odoo.define('web.groupby_menu_tests', function (require) { "use strict"; const testUtils = require('web.test_utils'); const cpHelpers = testUtils.controlPanel; const { createControlPanel } = testUtils; const searchMenuTypes = ['groupBy']; QUnit.module('Components', { beforeEach: function () { this.fields = { bar: { string: "Bar", type: "many2one", relation: 'partner' }, birthday: { string: "Birthday", type: "date", store: true, sortable: true }, date_field: { string: "Date", type: "date", store: true, sortable: true }, float_field: { string: "Float", type: "float", group_operator: 'sum' }, foo: { string: "Foo", type: "char", store: true, sortable: true }, }; }, }, function () { QUnit.module('GroupByMenu'); QUnit.test('simple rendering with neither groupbys nor groupable fields', async function (assert) { assert.expect(1); const params = { cpModelConfig: { searchMenuTypes }, cpProps: { fields: {}, searchMenuTypes }, }; const controlPanel = await createControlPanel(params); assert.containsNone(controlPanel, '.o_menu_item, .dropdown-divider, div.o_generator_menu'); controlPanel.destroy(); }); QUnit.test('simple rendering with no groupby', async function (assert) { assert.expect(5); const params = { cpModelConfig: { searchMenuTypes }, cpProps: { fields: this.fields, searchMenuTypes }, }; const controlPanel = await createControlPanel(params); await cpHelpers.toggleGroupByMenu(controlPanel); assert.containsNone(controlPanel, '.o_menu_item, .dropdown-divider'); assert.containsOnce(controlPanel, 'div.o_generator_menu'); await cpHelpers.toggleAddCustomGroup(controlPanel); const optionEls = controlPanel.el.querySelectorAll('div.o_generator_menu select.o_group_by_selector option'); assert.strictEqual(optionEls[0].innerText.trim(), 'Birthday'); assert.strictEqual(optionEls[1].innerText.trim(), 'Date'); assert.strictEqual(optionEls[2].innerText.trim(), 'Foo'); controlPanel.destroy(); }); QUnit.test('simple rendering with a single groupby', async function (assert) { assert.expect(4); const arch = ` `; const params = { cpModelConfig: { arch, fields: this.fields, searchMenuTypes }, cpProps: { fields: this.fields, searchMenuTypes }, }; const controlPanel = await createControlPanel(params); await cpHelpers.toggleGroupByMenu(controlPanel); assert.containsOnce(controlPanel, '.o_menu_item'); assert.strictEqual(controlPanel.el.querySelector('.o_menu_item').innerText.trim(), "Groupby Foo"); assert.containsOnce(controlPanel, '.dropdown-divider'); assert.containsOnce(controlPanel, 'div.o_generator_menu'); controlPanel.destroy(); }); QUnit.test('toggle a "simple" groupby in groupby menu works', async function (assert) { assert.expect(9); const groupBys = [['foo'], []]; const arch = ` `; const params = { cpModelConfig: {arch, fields: this.fields, searchMenuTypes }, cpProps: { fields: this.fields, searchMenuTypes }, search: function (searchQuery) { const { groupBy } = searchQuery; assert.deepEqual(groupBy, groupBys.shift()); }, }; const controlPanel = await createControlPanel(params); await cpHelpers.toggleGroupByMenu(controlPanel); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), []); assert.notOk(cpHelpers.isItemSelected(controlPanel, 0)); await cpHelpers.toggleMenuItem(controlPanel, 0); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Groupby Foo']); assert.containsOnce(controlPanel.el.querySelector('.o_searchview .o_searchview_facet'), 'span.fa.fa-bars.o_searchview_facet_label'); assert.ok(cpHelpers.isItemSelected(controlPanel, 0)); await cpHelpers.toggleMenuItem(controlPanel, 0); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), []); assert.notOk(cpHelpers.isItemSelected(controlPanel, 0)); controlPanel.destroy(); }); QUnit.test('toggle a "simple" groupby quickly does not crash', async function (assert) { assert.expect(1); const arch = ` `; const params = { cpModelConfig: { arch, fields: this.fields, searchMenuTypes }, cpProps: { fields: this.fields, searchMenuTypes }, }; const controlPanel = await createControlPanel(params); await cpHelpers.toggleGroupByMenu(controlPanel); cpHelpers.toggleMenuItem(controlPanel, 0); cpHelpers.toggleMenuItem(controlPanel, 0); assert.ok(true); controlPanel.destroy(); }); QUnit.test('remove a "Group By" facet properly unchecks groupbys in groupby menu', async function (assert) { assert.expect(5); const arch = ` `; const params = { cpModelConfig: { arch, fields: this.fields, searchMenuTypes, context: { search_default_gb_foo: 1 } }, cpProps: { fields: this.fields, searchMenuTypes }, search: function (searchQuery) { const { groupBy } = searchQuery; assert.deepEqual(groupBy, []); }, }; const controlPanel = await createControlPanel(params); await cpHelpers.toggleGroupByMenu(controlPanel); const facetEl = controlPanel.el.querySelector('.o_searchview .o_searchview_facet'); assert.strictEqual(facetEl.innerText.trim(), "Groupby Foo"); assert.ok(cpHelpers.isItemSelected(controlPanel, 0)); await testUtils.dom.click(facetEl.querySelector('i.o_facet_remove')); assert.containsNone(controlPanel, '.o_searchview .o_searchview_facet'); await cpHelpers.toggleGroupByMenu(controlPanel); assert.notOk(cpHelpers.isItemSelected(controlPanel, 0)); controlPanel.destroy(); }); QUnit.test('group by a date field using interval works', async function (assert) { assert.expect(21); const groupBys = [ ['date_field:year', 'date_field:week' ], ['date_field:year', 'date_field:month', 'date_field:week'], ['date_field:year', 'date_field:month'], ['date_field:year'], [] ]; const arch = ` `; const params = { cpModelConfig: { arch, fields: this.fields, searchMenuTypes, context: { search_default_date: 1 } }, cpProps: { fields: this.fields, searchMenuTypes }, search: function (searchQuery) { const { groupBy } = searchQuery; assert.deepEqual(groupBy, groupBys.shift()); }, }; const controlPanel = await createControlPanel(params); await cpHelpers.toggleGroupByMenu(controlPanel); await cpHelpers.toggleMenuItem(controlPanel, 0); const optionEls = controlPanel.el.querySelectorAll('ul.o_menu_item_options > li.o_item_option > a'); // default groupby should be activated with the default inteval 'week' const { groupBy } = controlPanel.getQuery(); assert.deepEqual(groupBy, ['date_field:week']); assert.ok(cpHelpers.isOptionSelected(controlPanel, 0, 3)); // check option descriptions const optionDescriptions = [...optionEls].map(e => e.innerText.trim()); const expectedDescriptions = ['Year', 'Quarter', 'Month', 'Week', 'Day']; assert.deepEqual(optionDescriptions, expectedDescriptions); const steps = [ { description: 'Year', facetContent: 'Date: Year>Date: Week', selectedoptions: [0, 3] }, { description: 'Month', facetContent: 'Date: Year>Date: Month>Date: Week', selectedoptions: [0, 2, 3] }, { description: 'Week', facetContent: 'Date: Year>Date: Month', selectedoptions: [0, 2] }, { description: 'Month', facetContent: 'Date: Year', selectedoptions: [0] }, { description: 'Year', selectedoptions: [] }, ]; for (const s of steps) { const index = expectedDescriptions.indexOf(s.description); await cpHelpers.toggleMenuItemOption(controlPanel, 0, index); if (s.facetContent) { assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), [s.facetContent]); } else { assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), []); } s.selectedoptions.forEach(index => { assert.ok(cpHelpers.isOptionSelected(controlPanel, 0, index)); }); } controlPanel.destroy(); }); QUnit.test('interval options are correctly grouped and ordered', async function (assert) { assert.expect(8); const arch = ` `; const params = { cpModelConfig: { arch, fields: this.fields, searchMenuTypes, context: { search_default_bar: 1 } }, cpProps: { fields: this.fields, searchMenuTypes }, }; const controlPanel = await createControlPanel(params); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Bar']); // open menu 'Group By' await cpHelpers.toggleGroupByMenu(controlPanel); // Open the groupby 'Date' await cpHelpers.toggleMenuItem(controlPanel, 'Date'); // select option 'week' await cpHelpers.toggleMenuItemOption(controlPanel, 'Date', 'Week'); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Bar>Date: Week']); // select option 'day' await cpHelpers.toggleMenuItemOption(controlPanel, 'Date', 'Day'); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Bar>Date: Week>Date: Day']); // select option 'year' await cpHelpers.toggleMenuItemOption(controlPanel, 'Date', 'Year'); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Bar>Date: Year>Date: Week>Date: Day']); // select 'Foo' await cpHelpers.toggleMenuItem(controlPanel, 'Foo'); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Bar>Date: Year>Date: Week>Date: Day>Foo']); // select option 'quarter' await cpHelpers.toggleMenuItem(controlPanel, 'Date'); await cpHelpers.toggleMenuItemOption(controlPanel, 'Date', 'Quarter'); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Bar>Date: Year>Date: Quarter>Date: Week>Date: Day>Foo']); // unselect 'Bar' await cpHelpers.toggleMenuItem(controlPanel, 'Bar'); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Date: Year>Date: Quarter>Date: Week>Date: Day>Foo']); // unselect option 'week' await cpHelpers.toggleMenuItem(controlPanel, 'Date'); await cpHelpers.toggleMenuItemOption(controlPanel, 'Date', 'Week'); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Date: Year>Date: Quarter>Date: Day>Foo']); controlPanel.destroy(); }); QUnit.test('the ID field should not be proposed in "Add Custom Group" menu', async function (assert) { assert.expect(2); const fields = { foo: { string: "Foo", type: "char", store: true, sortable: true }, id: { sortable: true, string: 'ID', type: 'integer' } }; const params = { cpModelConfig: { searchMenuTypes }, cpProps: { fields, searchMenuTypes }, }; const controlPanel = await createControlPanel(params); await cpHelpers.toggleGroupByMenu(controlPanel); await cpHelpers.toggleAddCustomGroup(controlPanel); const optionEls = controlPanel.el.querySelectorAll('div.o_generator_menu select.o_group_by_selector option'); assert.strictEqual(optionEls.length, 1); assert.strictEqual(optionEls[0].innerText.trim(), "Foo"); controlPanel.destroy(); }); QUnit.test('add a date field in "Add Custome Group" activate a groupby with global default option "month"', async function (assert) { assert.expect(4); const fields = { date_field: { string: "Date", type: "date", store: true, sortable: true }, id: { sortable: true, string: 'ID', type: 'integer' } }; const params = { cpModelConfig: { fields, searchMenuTypes }, cpProps: { fields, searchMenuTypes }, search: function (searchQuery) { const { groupBy } = searchQuery; assert.deepEqual(groupBy, ['date_field:month']); } }; const controlPanel = await createControlPanel(params); await cpHelpers.toggleGroupByMenu(controlPanel); await cpHelpers.toggleAddCustomGroup(controlPanel); await cpHelpers.applyGroup(controlPanel); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Date: Month']); assert.ok(cpHelpers.isItemSelected(controlPanel, "Date")); await cpHelpers.toggleMenuItem(controlPanel, "Date"); assert.ok(cpHelpers.isOptionSelected(controlPanel, "Date", "Month")); controlPanel.destroy(); }); QUnit.test('default groupbys can be ordered', async function (assert) { assert.expect(2); const arch = ` `; const params = { cpModelConfig: { arch, fields: this.fields, searchMenuTypes, context: { search_default_birthday: 2, search_default_date: 1 } }, cpProps: { fields: this.fields, searchMenuTypes }, }; const controlPanel = await createControlPanel(params); // the defautl groupbys should be activated in the right order const { groupBy } = controlPanel.getQuery(); assert.deepEqual(groupBy, ['date_field:week', 'birthday:month']); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Date: Week>Birthday: Month']); controlPanel.destroy(); }); QUnit.test('a separator in groupbys does not cause problems', async function (assert) { assert.expect(23); const arch = ` `; const params = { cpModelConfig: { arch, fields: this.fields, searchMenuTypes, }, cpProps: { fields: this.fields, searchMenuTypes }, }; const controlPanel = await createControlPanel(params); await cpHelpers.toggleGroupByMenu(controlPanel); await cpHelpers.toggleMenuItem(controlPanel, 0); await cpHelpers.toggleMenuItemOption(controlPanel, 0, 4); assert.ok(cpHelpers.isItemSelected(controlPanel, 0)); assert.notOk(cpHelpers.isItemSelected(controlPanel, 1)); assert.ok(cpHelpers.isOptionSelected(controlPanel, 0, 4), 'selected'); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Date: Day']); await cpHelpers.toggleMenuItem(controlPanel, 1); await cpHelpers.toggleMenuItem(controlPanel, 0); assert.ok(cpHelpers.isItemSelected(controlPanel, 0)); assert.ok(cpHelpers.isItemSelected(controlPanel, 1)); assert.ok(cpHelpers.isOptionSelected(controlPanel, 0, 4), 'selected'); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Date: Day>Bar']); await cpHelpers.toggleMenuItemOption(controlPanel, 0, 1); assert.ok(cpHelpers.isItemSelected(controlPanel, 0)); assert.ok(cpHelpers.isItemSelected(controlPanel, 1)); assert.ok(cpHelpers.isOptionSelected(controlPanel, 0, 1), 'selected'); assert.ok(cpHelpers.isOptionSelected(controlPanel, 0, 4), 'selected'); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Date: Quarter>Date: Day>Bar']); await cpHelpers.toggleMenuItem(controlPanel, 1); await cpHelpers.toggleMenuItem(controlPanel, 0); assert.ok(cpHelpers.isItemSelected(controlPanel, 0)); assert.notOk(cpHelpers.isItemSelected(controlPanel, 1)); assert.ok(cpHelpers.isOptionSelected(controlPanel, 0, 1), 'selected'); assert.ok(cpHelpers.isOptionSelected(controlPanel, 0, 4), 'selected'); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), ['Date: Quarter>Date: Day']); await cpHelpers.removeFacet(controlPanel); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), []); await cpHelpers.toggleGroupByMenu(controlPanel); await cpHelpers.toggleMenuItem(controlPanel, 0); assert.notOk(cpHelpers.isItemSelected(controlPanel, 0)); assert.notOk(cpHelpers.isItemSelected(controlPanel, 1)); assert.notOk(cpHelpers.isOptionSelected(controlPanel, 0, 1), 'selected'); assert.notOk(cpHelpers.isOptionSelected(controlPanel, 0, 4), 'selected'); controlPanel.destroy(); }); QUnit.test('falsy search default groupbys are not activated', async function (assert) { assert.expect(2); const arch = ` `; const params = { cpModelConfig: { arch, fields: this.fields, searchMenuTypes, context: { search_default_birthday: false, search_default_foo: 0 } }, cpProps: { fields: this.fields, searchMenuTypes }, }; const controlPanel = await createControlPanel(params); const { groupBy } = controlPanel.getQuery(); assert.deepEqual(groupBy, []); assert.deepEqual(cpHelpers.getFacetTexts(controlPanel), []); controlPanel.destroy(); }); }); });