diff --git a/addons/web/static/src/core/domain_selector/domain_selector.js b/addons/web/static/src/core/domain_selector/domain_selector.js index 01fec1a50a2..f56d61e56a1 100644 --- a/addons/web/static/src/core/domain_selector/domain_selector.js +++ b/addons/web/static/src/core/domain_selector/domain_selector.js @@ -12,6 +12,7 @@ import { } from "@web/core/domain_selector/utils"; import { Component, onWillStart, onWillUpdateProps } from "@odoo/owl"; import { Domain } from "@web/core/domain"; +import { CheckBox } from "@web/core/checkbox/checkbox"; import { Dropdown } from "@web/core/dropdown/dropdown"; import { DropdownItem } from "@web/core/dropdown/dropdown_item"; import { getOperatorInfo, toOperator } from "@web/core/domain_selector/domain_selector_operators"; @@ -26,6 +27,8 @@ import { import { ModelFieldSelector } from "@web/core/model_field_selector/model_field_selector"; import { useLoadFieldInfo } from "@web/core/model_field_selector/utils"; import { formatValue } from "@web/core/domain_tree"; +import { deepEqual } from "@web/core/utils/objects"; +import { useService } from "@web/core/utils/hooks"; function collectDifferences(tree, otherTree) { // some differences shadow the other differences "below": @@ -92,6 +95,7 @@ export class DomainSelector extends Component { ModelFieldSelector, Editor, PathEditor, + CheckBox, }; static props = { domain: String, @@ -114,9 +118,18 @@ export class DomainSelector extends Component { setup() { this.getDefaultLeafDomain = useGetDefaultLeafDomain(); this.loadDisplayNames = useLoadDisplayNames(); - this.loadFieldInfo = useLoadFieldInfo(); + this.fieldService = useService("field"); + this.loadFieldInfo = useLoadFieldInfo(this.fieldService); this.tree = null; this.previousTree = null; + this.includeArchived = false; + this.archivedConnector = { + type: "condition", + value: [true, false], + negate: false, + path: "active", + operator: "in", + }; onWillStart(() => this.onPropsUpdated(this.props)); onWillUpdateProps((np) => this.onPropsUpdated(np)); } @@ -157,6 +170,7 @@ export class DomainSelector extends Component { const paths = new Set([ ...extractPathsFromDomain(domain), ...extractPathsFromDomain(defaultLeafDomain), + "active", ]); await this.loadFieldDefs(p.resModel, paths); @@ -177,6 +191,32 @@ export class DomainSelector extends Component { options ).children[0]; + this.showArchivedCheckbox = Boolean(this.fieldDefs.active); + this.includeArchived = false; + if (this.showArchivedCheckbox) { + if (this.tree.value === "&") { + this.tree.children = this.tree.children.filter((child) => { + if (deepEqual(child, this.archivedConnector)) { + this.includeArchived = true; + return false; + } + return true; + }); + if (this.tree.children.length === 1) { + if (this.tree.children[0].type !== "connector") { + this.tree.value = this.props.defaultConnector; + } else { + this.tree = this.tree.children[0]; + } + } + } else if ( + this.tree.children.length === 1 && + deepEqual(this.tree.children[0], this.archivedConnector) + ) { + this.includeArchived = true; + this.tree = buildDomainSelectorTree(new Domain(`[]`)); + } + } if (this.previousTree) { // find "first" difference restoreVirtualOperators(this.tree, this.previousTree); @@ -184,9 +224,17 @@ export class DomainSelector extends Component { } } + toggleIncludeArchived() { + this.includeArchived = !this.includeArchived; + this.notifyChanges(); + } + notifyChanges() { this.previousTree = cloneTree(this.tree); - const domain = this.tree ? buildDomain(this.tree) : `[]`; + const archiveDomain = this.includeArchived ? `[("active", "in", [True, False])]` : `[]`; + const domain = this.tree + ? Domain.and([buildDomain(this.tree), archiveDomain]).toString() + : archiveDomain; this.props.update(domain); } diff --git a/addons/web/static/src/core/domain_selector/domain_selector.xml b/addons/web/static/src/core/domain_selector/domain_selector.xml index f3a07370eec..6ba46c3b321 100644 --- a/addons/web/static/src/core/domain_selector/domain_selector.xml +++ b/addons/web/static/src/core/domain_selector/domain_selector.xml @@ -4,23 +4,31 @@
- - - Match all records - - - - - - Match records with - - of the following rules: - - - New Rule - + +
+
+ + Match all records + + + Match + + of the following rules: + +
+ + Include archived + +
+ + + New Rule diff --git a/addons/web/static/src/core/utils/objects.js b/addons/web/static/src/core/utils/objects.js index 20a5a0624c8..545e4c84c48 100644 --- a/addons/web/static/src/core/utils/objects.js +++ b/addons/web/static/src/core/utils/objects.js @@ -19,6 +19,15 @@ export function shallowEqual(obj1, obj2, comparisonFn = (a, b) => a === b) { ); } +/** + * Deeply compares two objects. + * + * @template {unknown} T + * @param {T} obj1 + * @param {T} obj2 + */ +export const deepEqual = (obj1, obj2) => shallowEqual(obj1, obj2, deepEqual); + /** * Deep copies an object. As it relies on JSON this function as some limitations * - no support for circular objects diff --git a/addons/web/static/tests/core/domain_selector_tests.js b/addons/web/static/tests/core/domain_selector_tests.js index 71e84cf02b3..2447f5486f7 100644 --- a/addons/web/static/tests/core/domain_selector_tests.js +++ b/addons/web/static/tests/core/domain_selector_tests.js @@ -172,17 +172,16 @@ QUnit.module("Components", (hooks) => { isDebugMode: true, }); - // As we gave an empty domain, there should be a visible button to add - // the first domain part + // When we have an empty domain, the "New Rule" button should be available assert.containsOnce( target, - ".o_domain_add_first_node_button", - "there should be a button to create first domain element" + "a[role=button]", + "there should be a button to create a domain element" ); // Clicking on the button should add a visible field selector in the // widget so that the user can change the field chain - await click(target, ".o_domain_add_first_node_button"); + await click(target, "a[role=button]"); assert.containsOnce(target, ".o_model_field_selector"); // Focusing the field selector input should open a field selector popover @@ -431,7 +430,7 @@ QUnit.module("Components", (hooks) => { }); // Clicking on the button should add a visible field selector in the // widget so that the user can change the field chain - await click(target, ".o_domain_add_first_node_button"); + await click(target, "a[role=button]"); }); QUnit.test("edit a domain with the debug textarea", async (assert) => { @@ -756,10 +755,10 @@ QUnit.module("Components", (hooks) => { await click(target, ".o_reset_domain_button"); assert.strictEqual( target.querySelector(".o_domain_selector").innerText.toLowerCase(), - "match all records add condition" + "match all records\nnew rule" ); assert.containsNone(target, ".o_reset_domain_button"); - assert.containsOnce(target, ".o_domain_add_first_node_button"); + assert.containsOnce(target, "a[role=button]"); assert.verifySteps(["[]"]); }); @@ -905,7 +904,7 @@ QUnit.module("Components", (hooks) => { }); assert.strictEqual( target.querySelector(".o_domain_selector").innerText, - `Match records with any of the following rules:\ncreate_date\nis between 2023-04-01 00:00:00 and 2023-04-30 23:59:59\n0\n= 1` + `Match any of the following rules:\ncreate_date\nis between 2023-04-01 00:00:00 and 2023-04-30 23:59:59\n0\n= 1` ); }); @@ -934,99 +933,99 @@ QUnit.module("Components", (hooks) => { const toTest = [ { domain: `["!", ("foo", "=", "abc")]`, - result: `Match records with all of the following rules:\nFoo\n!= abc`, + result: `Match all of the following rules:\nFoo\n!= abc`, }, { domain: `["!", "!", ("foo", "=", "abc")]`, - result: `Match records with all of the following rules:\nFoo\n= abc`, + result: `Match all of the following rules:\nFoo\n= abc`, }, { domain: `["!", "!", "!", ("foo", "=", "abc")]`, - result: `Match records with all of the following rules:\nFoo\n!= abc`, + result: `Match all of the following rules:\nFoo\n!= abc`, }, { domain: `["!", "&", ("foo", "=", "abc"), ("foo", "=", "def")]`, - result: `Match records with any of the following rules:\nFoo\n!= abc\nFoo\n!= def`, + result: `Match any of the following rules:\nFoo\n!= abc\nFoo\n!= def`, }, { domain: `["!", "|", ("foo", "=", "abc"), ("foo", "=", "def")]`, - result: `Match records with all of the following rules:\nFoo\n!= abc\nFoo\n!= def`, + result: `Match all of the following rules:\nFoo\n!= abc\nFoo\n!= def`, }, { domain: `["&", "!", ("foo", "=", "abc"), ("foo", "=", "def")]`, - result: `Match records with all of the following rules:\nFoo\n!= abc\nFoo\n= def`, + result: `Match all of the following rules:\nFoo\n!= abc\nFoo\n= def`, }, { domain: `["&", "!", "!", ("foo", "=", "abc"), ("foo", "=", "def")]`, - result: `Match records with all of the following rules:\nFoo\n= abc\nFoo\n= def`, + result: `Match all of the following rules:\nFoo\n= abc\nFoo\n= def`, }, { domain: `["&", ("foo", "=", "abc"), "!", ("foo", "=", "def")]`, - result: `Match records with all of the following rules:\nFoo\n= abc\nFoo\n!= def`, + result: `Match all of the following rules:\nFoo\n= abc\nFoo\n!= def`, }, { domain: `["&", ("foo", "=", "abc"), "!", "!", ("foo", "=", "def")]`, - result: `Match records with all of the following rules:\nFoo\n= abc\nFoo\n= def`, + result: `Match all of the following rules:\nFoo\n= abc\nFoo\n= def`, }, { domain: `["|", "!", ("foo", "=", "abc"), ("foo", "=", "def")]`, - result: `Match records with any of the following rules:\nFoo\n!= abc\nFoo\n= def`, + result: `Match any of the following rules:\nFoo\n!= abc\nFoo\n= def`, }, { domain: `["|", "!", "!", ("foo", "=", "abc"), ("foo", "=", "def")]`, - result: `Match records with any of the following rules:\nFoo\n= abc\nFoo\n= def`, + result: `Match any of the following rules:\nFoo\n= abc\nFoo\n= def`, }, { domain: `["|", ("foo", "=", "abc"), "!", ("foo", "=", "def")]`, - result: `Match records with any of the following rules:\nFoo\n= abc\nFoo\n!= def`, + result: `Match any of the following rules:\nFoo\n= abc\nFoo\n!= def`, }, { domain: `["|", ("foo", "=", "abc"), "!", "!", ("foo", "=", "def")]`, - result: `Match records with any of the following rules:\nFoo\n= abc\nFoo\n= def`, + result: `Match any of the following rules:\nFoo\n= abc\nFoo\n= def`, }, { domain: `["&", "!", "&", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with all of the following rules:\nany\nof:\nFoo\n!= abc\nFoo\n!= def\nFoo\n= ghi`, + result: `Match all of the following rules:\nany\nof:\nFoo\n!= abc\nFoo\n!= def\nFoo\n= ghi`, }, { domain: `["&", "!", "|", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with all of the following rules:\nFoo\n!= abc\nFoo\n!= def\nFoo\n= ghi`, + result: `Match all of the following rules:\nFoo\n!= abc\nFoo\n!= def\nFoo\n= ghi`, }, { domain: `["|", "!", "&", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with any of the following rules:\nFoo\n!= abc\nFoo\n!= def\nFoo\n= ghi`, + result: `Match any of the following rules:\nFoo\n!= abc\nFoo\n!= def\nFoo\n= ghi`, }, { domain: `["|", "!", "|", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with any of the following rules:\nall\nof:\nFoo\n!= abc\nFoo\n!= def\nFoo\n= ghi`, + result: `Match any of the following rules:\nall\nof:\nFoo\n!= abc\nFoo\n!= def\nFoo\n= ghi`, }, { domain: `["!", "&", "&", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with any of the following rules:\nFoo\n!= abc\nFoo\n!= def\nFoo\n!= ghi`, + result: `Match any of the following rules:\nFoo\n!= abc\nFoo\n!= def\nFoo\n!= ghi`, }, { domain: `["!", "|", "|", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with all of the following rules:\nFoo\n!= abc\nFoo\n!= def\nFoo\n!= ghi`, + result: `Match all of the following rules:\nFoo\n!= abc\nFoo\n!= def\nFoo\n!= ghi`, }, { domain: `["!", "&", "|", ("foo", "=", "abc"), "!", ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with any of the following rules:\nall\nof:\nFoo\n!= abc\nFoo\n= def\nFoo\n!= ghi`, + result: `Match any of the following rules:\nall\nof:\nFoo\n!= abc\nFoo\n= def\nFoo\n!= ghi`, }, { domain: `["!", "|", "&", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with all of the following rules:\nany\nof:\nFoo\n!= abc\nFoo\n!= def\nFoo\n!= ghi`, + result: `Match all of the following rules:\nany\nof:\nFoo\n!= abc\nFoo\n!= def\nFoo\n!= ghi`, }, { domain: `["!", "&", ("foo", "=", "abc"), "|", ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with any of the following rules:\nFoo\n!= abc\nall\nof:\nFoo\n!= def\nFoo\n!= ghi`, + result: `Match any of the following rules:\nFoo\n!= abc\nall\nof:\nFoo\n!= def\nFoo\n!= ghi`, }, { domain: `["!", "|", ("foo", "=", "abc"), "&", ("foo", "=", "def"), ("foo", "!=", "ghi")]`, - result: `Match records with all of the following rules:\nFoo\n!= abc\nany\nof:\nFoo\n!= def\nFoo\n= ghi`, + result: `Match all of the following rules:\nFoo\n!= abc\nany\nof:\nFoo\n!= def\nFoo\n= ghi`, }, { domain: `["!", "|", ("foo", "=", "abc"), "&", ("foo", "!=", "def"), "!", ("foo", "=", "ghi")]`, - result: `Match records with all of the following rules:\nFoo\n!= abc\nany\nof:\nFoo\n= def\nFoo\n= ghi`, + result: `Match all of the following rules:\nFoo\n!= abc\nany\nof:\nFoo\n= def\nFoo\n= ghi`, }, ]; @@ -1051,99 +1050,99 @@ QUnit.module("Components", (hooks) => { const toTest = [ { domain: `["!", ("foo", "=", "abc")]`, - result: `Match records with all of the following rules:\nFoo\n!= abc`, + result: `Match all of the following rules:\nFoo\n!= abc`, }, { domain: `["!", "!", ("foo", "=", "abc")]`, - result: `Match records with all of the following rules:\nFoo\n= abc`, + result: `Match all of the following rules:\nFoo\n= abc`, }, { domain: `["!", "!", "!", ("foo", "=", "abc")]`, - result: `Match records with all of the following rules:\nFoo\n!= abc`, + result: `Match all of the following rules:\nFoo\n!= abc`, }, { domain: `["!", "&", ("foo", "=", "abc"), ("foo", "=", "def")]`, - result: `Match records with not all of the following rules:\nFoo\n= abc\nFoo\n= def`, + result: `Match not all of the following rules:\nFoo\n= abc\nFoo\n= def`, }, { domain: `["!", "|", ("foo", "=", "abc"), ("foo", "=", "def")]`, - result: `Match records with none of the following rules:\nFoo\n= abc\nFoo\n= def`, + result: `Match none of the following rules:\nFoo\n= abc\nFoo\n= def`, }, { domain: `["&", "!", ("foo", "=", "abc"), ("foo", "=", "def")]`, - result: `Match records with all of the following rules:\nFoo\n!= abc\nFoo\n= def`, + result: `Match all of the following rules:\nFoo\n!= abc\nFoo\n= def`, }, { domain: `["&", "!", "!", ("foo", "=", "abc"), ("foo", "=", "def")]`, - result: `Match records with all of the following rules:\nFoo\n= abc\nFoo\n= def`, + result: `Match all of the following rules:\nFoo\n= abc\nFoo\n= def`, }, { domain: `["&", ("foo", "=", "abc"), "!", ("foo", "=", "def")]`, - result: `Match records with all of the following rules:\nFoo\n= abc\nFoo\n!= def`, + result: `Match all of the following rules:\nFoo\n= abc\nFoo\n!= def`, }, { domain: `["&", ("foo", "=", "abc"), "!", "!", ("foo", "=", "def")]`, - result: `Match records with all of the following rules:\nFoo\n= abc\nFoo\n= def`, + result: `Match all of the following rules:\nFoo\n= abc\nFoo\n= def`, }, { domain: `["|", "!", ("foo", "=", "abc"), ("foo", "=", "def")]`, - result: `Match records with any of the following rules:\nFoo\n!= abc\nFoo\n= def`, + result: `Match any of the following rules:\nFoo\n!= abc\nFoo\n= def`, }, { domain: `["|", "!", "!", ("foo", "=", "abc"), ("foo", "=", "def")]`, - result: `Match records with any of the following rules:\nFoo\n= abc\nFoo\n= def`, + result: `Match any of the following rules:\nFoo\n= abc\nFoo\n= def`, }, { domain: `["|", ("foo", "=", "abc"), "!", ("foo", "=", "def")]`, - result: `Match records with any of the following rules:\nFoo\n= abc\nFoo\n!= def`, + result: `Match any of the following rules:\nFoo\n= abc\nFoo\n!= def`, }, { domain: `["|", ("foo", "=", "abc"), "!", "!", ("foo", "=", "def")]`, - result: `Match records with any of the following rules:\nFoo\n= abc\nFoo\n= def`, + result: `Match any of the following rules:\nFoo\n= abc\nFoo\n= def`, }, { domain: `["&", "!", "&", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with all of the following rules:\nnot all\nof:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, + result: `Match all of the following rules:\nnot all\nof:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, }, { domain: `["&", "!", "|", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with all of the following rules:\nnone\nof:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, + result: `Match all of the following rules:\nnone\nof:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, }, { domain: `["|", "!", "&", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with any of the following rules:\nnot all\nof:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, + result: `Match any of the following rules:\nnot all\nof:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, }, { domain: `["|", "!", "|", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with any of the following rules:\nnone\nof:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, + result: `Match any of the following rules:\nnone\nof:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, }, { domain: `["!", "&", "&", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with not all of the following rules:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, + result: `Match not all of the following rules:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, }, { domain: `["!", "|", "|", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with none of the following rules:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, + result: `Match none of the following rules:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, }, { domain: `["!", "&", "|", ("foo", "=", "abc"), "!", ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with not all of the following rules:\nany\nof:\nFoo\n= abc\nFoo\n!= def\nFoo\n= ghi`, + result: `Match not all of the following rules:\nany\nof:\nFoo\n= abc\nFoo\n!= def\nFoo\n= ghi`, }, { domain: `["!", "|", "&", ("foo", "=", "abc"), ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with none of the following rules:\nall\nof:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, + result: `Match none of the following rules:\nall\nof:\nFoo\n= abc\nFoo\n= def\nFoo\n= ghi`, }, { domain: `["!", "&", ("foo", "=", "abc"), "|", ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with not all of the following rules:\nFoo\n= abc\nany\nof:\nFoo\n= def\nFoo\n= ghi`, + result: `Match not all of the following rules:\nFoo\n= abc\nany\nof:\nFoo\n= def\nFoo\n= ghi`, }, { domain: `["!", "|", ("foo", "=", "abc"), "&", ("foo", "=", "def"), ("foo", "=", "ghi")]`, - result: `Match records with none of the following rules:\nFoo\n= abc\nall\nof:\nFoo\n= def\nFoo\n= ghi`, + result: `Match none of the following rules:\nFoo\n= abc\nall\nof:\nFoo\n= def\nFoo\n= ghi`, }, { domain: `["!", "|", ("foo", "=", "abc"), "&", ("foo", "=", "def"), "!", ("foo", "=", "ghi")]`, - result: `Match records with none of the following rules:\nFoo\n= abc\nall\nof:\nFoo\n= def\nFoo\n!= ghi`, + result: `Match none of the following rules:\nFoo\n= abc\nall\nof:\nFoo\n= def\nFoo\n!= ghi`, }, ]; @@ -1268,17 +1267,14 @@ QUnit.module("Components", (hooks) => { QUnit.test("button 'New Rule' (edit mode)", async (assert) => { await makeDomainSelector(); assert.containsNone(target, ".o_domain_leaf"); - assert.containsOnce(target, ".o_domain_add_first_node_button"); - assert.containsNone(target, "a[role=button]"); + assert.containsOnce(target, "a[role=button]"); - await click(target, ".o_domain_add_first_node_button"); + await click(target, "a[role=button]"); assert.containsOnce(target, ".o_domain_leaf"); - assert.containsNone(target, ".o_domain_add_first_node_button"); assert.containsOnce(target, "a[role=button]"); await click(target, "a[role=button]"); assert.containsN(target, ".o_domain_leaf", 2); - assert.containsNone(target, ".o_domain_add_first_node_button"); assert.containsOnce(target, "a[role=button]"); }); @@ -2080,4 +2076,81 @@ QUnit.module("Components", (hooks) => { assert.containsNone(target, ".o_ds_value_cell"); assert.verifySteps([`[("product_ids", "!=", False)]`]); }); + + QUnit.test("Include archived button basic use", async (assert) => { + serverData.models.partner.fields.active = { + string: "Active", + type: "boolean", + searchable: true, + }; + await makeDomainSelector({ + isDebugMode: true, + domain: `["&", ("foo", "=", "test"), ("bar", "=", True)]`, + update(domain) { + assert.step(domain); + }, + }); + assert.containsN(target, ".o_domain_leaf", 2); + assert.containsOnce(target, '.form-switch label:contains("Include archived")'); + await click(target, ".form-switch"); + assert.containsN(target, ".o_domain_leaf", 2); + assert.verifySteps([ + '["&", "&", ("foo", "=", "test"), ("bar", "=", True), ("active", "in", [True, False])]', + ]); + await click(target, ".dropdown-toggle"); + await click(target, ".dropdown-menu span:nth-child(2)"); + assert.containsN(target, ".o_domain_leaf", 2); + assert.verifySteps([ + '["&", "|", ("foo", "=", "test"), ("bar", "=", True), ("active", "in", [True, False])]', + ]); + await click(target, ".form-switch"); + assert.containsN(target, ".o_domain_leaf", 2); + assert.verifySteps(['["|", ("foo", "=", "test"), ("bar", "=", True)]']); + }); + + QUnit.test("Include archived on empty tree", async (assert) => { + serverData.models.partner.fields.active = { + string: "Active", + type: "boolean", + searchable: true, + }; + await makeDomainSelector({ + isDebugMode: true, + domain: `[("foo", "=", "test")]`, + update(domain) { + assert.step(domain); + }, + }); + assert.containsOnce(target, ".o_domain_leaf"); + assert.containsOnce(target, '.form-switch label:contains("Include archived")'); + await click(target, ".form-switch"); + assert.containsOnce(target, ".o_domain_leaf"); + assert.verifySteps(['["&", ("foo", "=", "test"), ("active", "in", [True, False])]']); + await click(target, ".o_domain_delete_node_button"); + assert.containsNone(target, ".o_domain_leaf"); + assert.verifySteps(['[("active", "in", [True, False])]']); + await click(target, ".form-switch"); + assert.verifySteps(["[]"]); + await click(target, ".form-switch"); + assert.containsNone(target, ".o_domain_leaf"); + assert.verifySteps(['[("active", "in", [True, False])]']); + await click(target, "a[role=button]"); + assert.containsOnce(target, ".o_domain_leaf"); + assert.verifySteps(['["&", ("id", "=", 1), ("active", "in", [True, False])]']); + }); + + QUnit.test( + "Include archived not shown when model doesn't have the active field", + async (assert) => { + await makeDomainSelector({ + isDebugMode: true, + domain: `[("foo", "=", "test")]`, + update(domain) { + assert.step(domain); + }, + }); + assert.containsOnce(target, ".o_domain_leaf"); + assert.containsNone(target, '.form-switch label:contains("Include archived")'); + } + ); }); diff --git a/addons/web/static/tests/search/search_bar_tests.js b/addons/web/static/tests/search/search_bar_tests.js index b8e5142a820..f15d9f3a9fe 100644 --- a/addons/web/static/tests/search/search_bar_tests.js +++ b/addons/web/static/tests/search/search_bar_tests.js @@ -1476,7 +1476,7 @@ QUnit.module("Search", (hooks) => { assert.containsNone(target, ".o_domain_leaf"); assert.ok(target.querySelector(".modal footer button").disabled); - await click(target, ".modal .o_domain_add_first_node_button"); + await click(target, ".modal .o_domain_tree a[role=button]"); assert.containsOnce(target, ".o_domain_leaf"); assert.strictEqual(target.querySelector(".o_model_field_selector_value").innerText, "ID"); assert.strictEqual(target.querySelector(".o_domain_leaf_operator_select").value, "="); diff --git a/addons/web/static/tests/views/fields/domain_field_tests.js b/addons/web/static/tests/views/fields/domain_field_tests.js index 37605738101..fad92e86ae9 100644 --- a/addons/web/static/tests/views/fields/domain_field_tests.js +++ b/addons/web/static/tests/views/fields/domain_field_tests.js @@ -181,13 +181,12 @@ QUnit.module("Fields", (hooks) => { `, }); - // As the domain is empty, there should be a button to add the first - // domain part - assert.containsOnce(target, ".o_domain_add_first_node_button"); + // As the domain is empty, there should be a button to add a new rule + assert.containsOnce(target, ".o_domain_tree a[role=button]"); // Clicking on the button should add the [["id", "=", "1"]] domain, so // there should be a field selector in the DOM - await click(target, ".o_domain_add_first_node_button"); + await click(target, ".o_domain_tree a[role=button]"); assert.containsOnce(target, ".o_model_field_selector", "there should be a field selector"); // Focusing the field selector input should open the field selector @@ -242,7 +241,7 @@ QUnit.module("Fields", (hooks) => { `, }); - await click(target, ".o_domain_add_first_node_button"); + await click(target, ".o_domain_tree a[role=button]"); await click(target, ".o_model_field_selector"); await click( document.body.querySelector( @@ -930,7 +929,7 @@ QUnit.module("Fields", (hooks) => { assert.containsNone(target, ".modal"); await click(target, ".o_field_domain_dialog_button"); assert.containsOnce(target, ".modal"); - await click(target, ".modal .o_domain_add_first_node_button"); + await click(target, ".modal .o_domain_tree a[role=button]"); await click(target, ".modal-footer .btn-primary"); assert.containsOnce(target, ".o_domain_leaf"); assert.strictEqual(target.querySelector(".o_domain_leaf").textContent, "ID = 1"); @@ -957,7 +956,7 @@ QUnit.module("Fields", (hooks) => { await click(target, ".o_field_domain_dialog_button"); assert.containsOnce(target, ".modal"); - await click(target, ".modal .o_domain_add_first_node_button"); + await click(target, ".modal .o_domain_tree a[role=button]"); await editInput(target, ".o_domain_debug_input", "[(0, '=', expr)]"); await click(target, ".modal-footer .btn-primary"); assert.containsOnce(target, ".modal", "the domain is invalid: the dialog is not closed"); @@ -1027,13 +1026,12 @@ QUnit.module("Fields", (hooks) => { // Unfold the domain await click(target, ".o_field_domain > div > div"); - // As the domain is empty, there should be a button to add the first - // domain part - assert.containsOnce(target, ".o_domain_add_first_node_button"); + // As the domain is empty, there should be a button to add a new rule + assert.containsOnce(target, ".o_domain_tree a[role=button]"); // Clicking on the button should add the [["id", "=", "1"]] domain, so // there should be a field selector in the DOM - await click(target, ".o_domain_add_first_node_button"); + await click(target, ".o_domain_tree a[role=button]"); assert.containsOnce(target, ".o_model_field_selector"); // Focusing the field selector input should open the field selector