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 = `
`;
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: ` `,
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 = `
`;
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 = ``;
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();
});
});
});