summaryrefslogtreecommitdiff
path: root/addons/web/static/tests/control_panel/control_panel_tests.js
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/web/static/tests/control_panel/control_panel_tests.js
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/web/static/tests/control_panel/control_panel_tests.js')
-rw-r--r--addons/web/static/tests/control_panel/control_panel_tests.js256
1 files changed, 256 insertions, 0 deletions
diff --git a/addons/web/static/tests/control_panel/control_panel_tests.js b/addons/web/static/tests/control_panel/control_panel_tests.js
new file mode 100644
index 00000000..c9e89387
--- /dev/null
+++ b/addons/web/static/tests/control_panel/control_panel_tests.js
@@ -0,0 +1,256 @@
+odoo.define('web.control_panel_tests', function (require) {
+ "use strict";
+
+ const testUtils = require('web.test_utils');
+
+ const cpHelpers = testUtils.controlPanel;
+ const { createControlPanel } = testUtils;
+
+ QUnit.module('ControlPanel', {
+ beforeEach() {
+ this.fields = {
+ display_name: { string: "Displayed name", type: 'char', searchable: true },
+ foo: { string: "Foo", type: "char", default: "My little Foo Value", store: true, sortable: true, searchable: true },
+ date_field: { string: "Date", type: "date", store: true, sortable: true, searchable: true },
+ float_field: { string: "Float", type: "float", searchable: true },
+ bar: { string: "Bar", type: "many2one", relation: 'partner', searchable: true },
+ };
+ }
+ }, function () {
+
+ QUnit.test('default field operator', async function (assert) {
+ assert.expect(2);
+
+ const fields = {
+ foo_op: { string: "Foo Op", type: "char", store: true, sortable: true, searchable: true },
+ foo: { string: "Foo", type: "char", store: true, sortable: true, searchable: true },
+ bar_op: { string: "Bar Op", type: "many2one", relation: 'partner', searchable: true },
+ bar: { string: "Bar", type: "many2one", relation: 'partner', searchable: true },
+ selec: { string: "Selec", type: "selection", selection: [['red', "Red"], ['black', "Black"]] },
+ };
+ const arch = `
+ <search>
+ <field name="bar"/>
+ <field name="bar_op" operator="child_of"/>
+ <field name="foo"/>
+ <field name="foo_op" operator="="/>
+ <field name="selec"/>
+ </search>`;
+ const searchMenuTypes = [];
+ const params = {
+ cpModelConfig: {
+ arch,
+ fields,
+ context: {
+ show_filterC: true,
+ search_default_bar: 10,
+ search_default_bar_op: 10,
+ search_default_foo: "foo",
+ search_default_foo_op: "foo_op",
+ search_default_selec: 'red',
+ },
+ searchMenuTypes,
+ },
+ cpProps: { fields, searchMenuTypes },
+ env: {
+ session: {
+ async rpc() {
+ return [[10, "Deco Addict"]];
+ },
+ },
+ },
+ };
+ const controlPanel = await createControlPanel(params);
+
+ assert.deepEqual(
+ cpHelpers.getFacetTexts(controlPanel).map(t => t.replace(/\s/g, "")),
+ [
+ "BarDecoAddict",
+ "BarOpDecoAddict",
+ "Foofoo",
+ "FooOpfoo_op",
+ "SelecRed"
+ ]
+ );
+ assert.deepEqual(
+ controlPanel.getQuery().domain,
+ [
+ "&", "&", "&", "&",
+ ["bar", "=", 10],
+ ["bar_op", "child_of", 10],
+ ["foo", "ilike", "foo"],
+ ["foo_op", "=", "foo_op"],
+ ["selec", "=", "red"],
+ ]
+ );
+
+ controlPanel.destroy();
+ });
+
+ QUnit.module('Keyboard navigation');
+
+ QUnit.test('remove a facet with backspace', async function (assert) {
+ assert.expect(2);
+
+ const params = {
+ cpModelConfig: {
+ arch: `<search> <field name="foo"/></search>`,
+ fields: this.fields,
+ context: { search_default_foo: "a" },
+ searchMenuTypes: ['filter'],
+ },
+ cpProps: { fields: this.fields },
+ };
+
+ const controlPanel = await createControlPanel(params);
+
+ assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Foo\na']);
+
+ // delete a facet
+ const searchInput = controlPanel.el.querySelector('input.o_searchview_input');
+ await testUtils.dom.triggerEvent(searchInput, 'keydown', { key: 'Backspace' });
+
+ assert.containsNone(controlPanel, 'div.o_searchview div.o_searchview_facet');
+
+ // delete nothing (should not crash)
+ await testUtils.dom.triggerEvent(searchInput, 'keydown', { key: 'Backspace' });
+
+ controlPanel.destroy();
+ });
+
+ QUnit.test('fields and filters with groups/invisible attribute', async function (assert) {
+ // navigation and automatic menu closure don't work here (i don't know why yet) -->
+ // should be tested separatly
+ assert.expect(16);
+
+ const arch = `
+ <search>
+ <field name="display_name" string="Foo B" invisible="1"/>
+ <field name="foo" string="Foo A"/>
+ <filter name="filterA" string="FA" domain="[]"/>
+ <filter name="filterB" string="FB" invisible="1" domain="[]"/>
+ <filter name="filterC" string="FC" invisible="not context.get('show_filterC')" domain="[]"/>
+ <filter name="groupByA" string="GA" context="{ 'group_by': 'date_field:day' }"/>
+ <filter name="groupByB" string="GB" context="{ 'group_by': 'date_field:day' }" invisible="1"/>
+ </search>`;
+ const searchMenuTypes = ['filter', 'groupBy'];
+ const params = {
+ cpModelConfig: {
+ arch,
+ fields: this.fields,
+ context: {
+ show_filterC: true,
+ search_default_display_name: 'value',
+ search_default_filterB: true,
+ search_default_groupByB: true
+ },
+ searchMenuTypes
+ },
+ cpProps: { fields: this.fields, searchMenuTypes },
+ };
+ const controlPanel = await createControlPanel(params);
+
+ function selectorContainsValue(selector, value, shouldContain) {
+ const elements = [...controlPanel.el.querySelectorAll(selector)];
+ const regExp = new RegExp(value);
+ const matches = elements.filter(el => regExp.test(el.innerText.replace(/\s/g, "")));
+ assert.strictEqual(matches.length, shouldContain ? 1 : 0,
+ `${selector} in the control panel should${shouldContain ? '' : ' not'} contain "${value}".`
+ );
+ }
+
+ // default filters/fields should be activated even if invisible
+ assert.containsN(controlPanel, 'div.o_searchview_facet', 3);
+ selectorContainsValue('.o_searchview_facet', "FooBvalue", true);
+ selectorContainsValue('.o_searchview_facet .o_facet_values', "FB", true);
+ selectorContainsValue('.o_searchview_facet .o_facet_values', "GB", true);
+
+ await cpHelpers.toggleFilterMenu(controlPanel);
+
+ selectorContainsValue('.o_menu_item a', "FA", true);
+ selectorContainsValue('.o_menu_item a', "FB", false);
+ selectorContainsValue('.o_menu_item a', "FC", true);
+
+ await cpHelpers.toggleGroupByMenu(controlPanel);
+
+ selectorContainsValue('.o_menu_item a', "GA", true);
+ selectorContainsValue('.o_menu_item a', "GB", false);
+
+ // 'a' to filter nothing on bar
+ await cpHelpers.editSearch(controlPanel, 'a');
+
+ // the only item in autocomplete menu should be FooA: a
+ selectorContainsValue('.o_searchview_autocomplete', "SearchFooAfor:a", true);
+ await cpHelpers.validateSearch(controlPanel);
+ selectorContainsValue('.o_searchview_facet', "FooAa", true);
+
+ // The items in the Filters menu and the Group By menu should be the same as before
+ await cpHelpers.toggleFilterMenu(controlPanel);
+
+ selectorContainsValue('.o_menu_item a', "FA", true);
+ selectorContainsValue('.o_menu_item a', "FB", false);
+ selectorContainsValue('.o_menu_item a', "FC", true);
+
+ await cpHelpers.toggleGroupByMenu(controlPanel);
+
+ selectorContainsValue('.o_menu_item a', "GA", true);
+ selectorContainsValue('.o_menu_item a', "GB", false);
+
+ controlPanel.destroy();
+ });
+
+ QUnit.test('invisible fields and filters with unknown related fields should not be rendered', async function (assert) {
+ assert.expect(2);
+
+ // This test case considers that the current user is not a member of
+ // the "base.group_system" group and both "bar" and "date_field" fields
+ // have field-level access control that limit access to them only from
+ // that group.
+ //
+ // As MockServer currently does not support "groups" access control, we:
+ //
+ // - emulate field-level access control of fields_get() by removing
+ // "bar" and "date_field" from the model fields
+ // - set filters with groups="base.group_system" as `invisible=1` in
+ // view to emulate the behavior of fields_view_get()
+ // [see ir.ui.view `_apply_group()`]
+
+ delete this.fields.bar;
+ delete this.fields.date_field;
+
+ const searchMenuTypes = [];
+ const params = {
+ cpProps: { fields: this.fields, searchMenuTypes },
+ };
+ const controlPanel = await createControlPanel(params);
+
+ assert.containsNone(controlPanel.el, 'div.o_search_options div.o_filter_menu',
+ "there should not be filter dropdown");
+ assert.containsNone(controlPanel.el, 'div.o_search_options div.o_group_by_menu',
+ "there should not be groupby dropdown");
+
+ controlPanel.destroy();
+ });
+
+ QUnit.test('groupby menu is not rendered if searchMenuTypes does not have groupBy', async function (assert) {
+ assert.expect(2);
+
+ const arch = `<search/>`;
+ const searchMenuTypes = ['filter'];
+ const params = {
+ cpModelConfig: {
+ arch,
+ fields: this.fields,
+ searchMenuTypes,
+ },
+ cpProps: { fields: this.fields, searchMenuTypes },
+ };
+ const controlPanel = await createControlPanel(params);
+
+ assert.containsOnce(controlPanel.el, 'div.o_search_options div.o_filter_menu');
+ assert.containsNone(controlPanel.el, 'div.o_search_options div.o_group_by_menu');
+
+ controlPanel.destroy();
+ });
+ });
+});