summaryrefslogtreecommitdiff
path: root/addons/web/static/tests/widgets/dropdown_menu_tests.js
diff options
context:
space:
mode:
authorGéry Debongnie <ged@odoo.com>2018-12-06 12:39:06 +0000
committerGéry Debongnie <ged@odoo.com>2018-12-07 13:16:06 +0000
commit40dd121938552d3f88289d2e5fcd1d57a0dd01bb (patch)
tree4830c8ffdea1e10d35c7ddf096f536bd8999240f /addons/web/static/tests/widgets/dropdown_menu_tests.js
parent48a50b4bc011fc6dfc82a673f921fad941dc79cf (diff)
[REF] web: move ControlPanel inside controllers/actions
This branch introduces a large-scale reorganization of the component tree generated by the web client. The short version is that now, the control panel is a child of the view controller and no longer a sibling. Graphically (and simplified), we go from this: webClient / | \ ... ... actionManager / \ controlPanel viewController / \ to this: webClient / | \ ... ... actionManager | viewController / | \ ControlPanelController / \ CPRenderer CPModel The motivation is that this work moves the code where it should be. Before this commit, it was kind of weird to have code in the controllers to render buttons outside of their root node (in renderButtons). Also, the action manager had to take care of coordinating search view states between view transitions. So, this work simplifies the code. It also makes it easier to extend. We see day after day that Odoo needs to take care of more complex UI needs, and in many cases, these needs were quite difficult to implement (we prefer spaghettis in our plates, not in our code). The changes in this branch should open the way to implement these features. For example, - it will now be easy to add the possibility of views (for example, the search view or a new ControlPanel view) to add custom buttons (of type action or object) in the control panel. - Another need will be to serialize/ restore the state of the search view across action boundaries (needed by the dashboard). - Another example is the possibility for views to customize easily the presence/absence of sub menus (filters/groupbys/favorites/ time range/...) - Another need is an easier way for views/client action to customize their control panel. This commit also contains a large rewrite of the search view (so it is more inline with our architecture and easier to maintain). Part of task 1893568 Co-authored-by: Aaron Bohy <aab@odoo.com> Co-authored-by: Mathieu Duckerts-Antoine <dam@odoo.com> Co-authored-by: Martin Geubelle <mge@odoo.com>
Diffstat (limited to 'addons/web/static/tests/widgets/dropdown_menu_tests.js')
-rw-r--r--addons/web/static/tests/widgets/dropdown_menu_tests.js172
1 files changed, 79 insertions, 93 deletions
diff --git a/addons/web/static/tests/widgets/dropdown_menu_tests.js b/addons/web/static/tests/widgets/dropdown_menu_tests.js
index 83f5d3fecb7..709651c7cb1 100644
--- a/addons/web/static/tests/widgets/dropdown_menu_tests.js
+++ b/addons/web/static/tests/widgets/dropdown_menu_tests.js
@@ -4,10 +4,10 @@ odoo.define('web.dropdown_menu_tests', function (require) {
var DropdownMenu = require('web.DropdownMenu');
var testUtils = require('web.test_utils');
-function createDropdownMenu(dropdownTitle, groups, params) {
+function createDropdownMenu(items, params) {
params = params || {};
var target = params.debug ? document.body : $('#qunit-fixture');
- var menu = new DropdownMenu(null, dropdownTitle, groups);
+ var menu = new DropdownMenu(null, items);
testUtils.mock.addMockEnvironment(menu, params);
menu.appendTo(target);
return menu;
@@ -18,74 +18,69 @@ QUnit.module('Web', {
this.items = [
{
isActive: false,
- isOpen: false,
description: 'Some Item',
- itemId: 1,
+ id: 1,
groupId: 1,
+ groupNumber: 1,
},
{
isActive: true,
description: 'Some other Item',
- itemId: 2,
- options: [],
- isRemovable: true,
+ id: 2,
groupId: 2,
+ groupNumber: 2,
},
];
- this.dropdownHeader = {
- title: "Menu",
- icon: "fa fa-bars",
- };
},
}, function () {
QUnit.module('DropdownMenu');
QUnit.test('simple rendering', function (assert) {
- assert.expect(2);
+ assert.expect(4);
- var dropdownMenu = createDropdownMenu(this.dropdownHeader, this.items);
- assert.containsN(dropdownMenu, '.dropdown-divider, .dropdown-item, .dropdown-item-text', 4, 'should have 4 elements counting the dividers');
- assert.strictEqual(dropdownMenu.$('.dropdown-divider, .dropdown-item, .dropdown-item-text').eq(1).text().trim(), 'Some Item',
+ var dropdownMenu = createDropdownMenu(this.items);
+ assert.containsN(dropdownMenu, '.dropdown-divider, .dropdown-item, .dropdown-item-text', 4,
+ 'should have 4 elements counting the dividers');
+ assert.strictEqual(dropdownMenu.$('.o_menu_item').first().text().trim(), 'Some Item',
'first element should have "Some Item" description');
+ assert.ok(!dropdownMenu.$('.o_menu_item > .dropdown-item').eq(0).hasClass('selected'),
+ 'first element should not be selected');
+ assert.ok(dropdownMenu.$('.o_menu_item > .dropdown-item').eq(1).hasClass('selected'),
+ 'second element should be selected');
+
dropdownMenu.destroy();
});
- QUnit.test('click on an item should toggle item', function (assert) {
- assert.expect(9);
+ QUnit.test('click on an item without options should toggle it', function (assert) {
+ assert.expect(7);
- var eventNumber = 0;
-
- var dropdownMenu = createDropdownMenu(this.dropdownHeader, this.items, {
+ var self = this;
+ var dropdownMenu = createDropdownMenu(this.items, {
intercepts: {
- menu_item_toggled: function (ev) {
- eventNumber++;
- assert.strictEqual(ev.data.itemId, 1);
- if (eventNumber === 1) {
- assert.strictEqual(ev.data.isActive, true);
- } else {
- assert.strictEqual(ev.data.isActive, false);
- }
+ menu_item_clicked: function (ev) {
+ assert.strictEqual(ev.data.id, 1);
+ self.items[0].isActive = !self.items[0].isActive;
+ dropdownMenu.update(self.items);
},
},
});
testUtils.dom.click(dropdownMenu.$('button:first'));
- assert.doesNotHaveClass(dropdownMenu.$('.o_menu_item:first > .dropdown-item'), 'selected');
+ assert.doesNotHaveClass(dropdownMenu.$('.o_menu_item:first > .dropdown-item').first(), 'selected');
testUtils.dom.click(dropdownMenu.$('.o_menu_item a').first());
assert.hasClass(dropdownMenu.$('.o_menu_item:first > .dropdown-item'), 'selected');
assert.ok(dropdownMenu.$('.o_menu_item:first').is(':visible'),
'item should still be visible');
testUtils.dom.click(dropdownMenu.$('.o_menu_item a').first());
- assert.doesNotHaveClass(dropdownMenu.$('.o_menu_item:first > .dropdown-item'), 'selected');
+ assert.doesNotHaveClass(dropdownMenu.$('.o_menu_item:first > .dropdown-item').first(), 'selected');
assert.ok(dropdownMenu.$('.o_menu_item:first').is(':visible'),
'item should still be visible');
-
dropdownMenu.destroy();
});
QUnit.test('click on an item should not change url', function (assert) {
assert.expect(0);
- var dropdownMenu = createDropdownMenu(this.dropdownHeader, this.items);
+ var dropdownMenu = createDropdownMenu(this.items);
testUtils.dom.click(dropdownMenu.$('.o_dropdown_toggler_btn'));
dropdownMenu.$el.click(function () {
// we do not want a click to get out and change the url, for example
@@ -99,10 +94,12 @@ QUnit.module('Web', {
QUnit.test('options rendering', function (assert) {
assert.expect(3);
- this.items[0].options = [{optionId: 1, description: "First Option", groupId: 1}, {optionId: 2, description: "Second Option", groupId: 1}];
-
- var dropdownMenu = createDropdownMenu(this.dropdownHeader, this.items);
- // open dropdown
+ this.items[0].hasOptions = true;
+ this.items[0].options = [
+ {optionId: 1, description: "First Option", groupId: 1},
+ {optionId: 2, description: "Second Option", groupId: 1}
+ ];
+ var dropdownMenu = createDropdownMenu(this.items);
testUtils.dom.click(dropdownMenu.$('button:first'));
assert.containsN(dropdownMenu, '.dropdown-divider, .dropdown-item, .dropdown-item-text', 4);
// open options menu
@@ -115,12 +112,16 @@ QUnit.module('Web', {
dropdownMenu.destroy();
});
- QUnit.test('close menu closes also submenu', function (assert) {
+ QUnit.test('close menu closes also submenus', function (assert) {
assert.expect(2);
- this.items[0].options = [{optionId: 1, description: "First Option"}, {optionId: 2, description: "Second Option"}];
-
- var dropdownMenu = createDropdownMenu(this.dropdownHeader, this.items);
+ this.items[0].hasOptions = true;
+ this.items[0].options = [
+ {optionId: 1, description: "First Option"},
+ {optionId: 2, description: "Second Option"}
+ ];
+ var dropdownMenu = createDropdownMenu(this.items);
+ // open dropdown menu
testUtils.dom.click(dropdownMenu.$('button:first'));
// open options menu
testUtils.dom.click(dropdownMenu.$('span.fa-caret-right'));
@@ -132,74 +133,59 @@ QUnit.module('Web', {
dropdownMenu.destroy();
});
- QUnit.test('click on an option should toggle options and item states properly', function (assert) {
- assert.expect(22);
-
- this.items[0].options = [{optionId: 1, description: "First Option"}, {optionId: 2, description: "Second Option"}];
+ QUnit.test('click on an option should trigger the event "item_option_clicked" with appropriate data', function (assert) {
+ assert.expect(16);
+ var self = this;
var eventNumber = 0;
-
- var dropdownMenu = createDropdownMenu(this.dropdownHeader, this.items, {
+ this.items[0].hasOptions = true;
+ this.items[0].options = [
+ {optionId: 1, description: "First Option"},
+ {optionId: 2, description: "Second Option"}
+ ];
+ var dropdownMenu = createDropdownMenu(this.items, {
intercepts: {
- menu_item_toggled: function (ev) {
+ item_option_clicked: function (ev) {
eventNumber++;
+ assert.strictEqual(ev.data.id, 1);
if (eventNumber === 1) {
- assert.strictEqual(ev.data.itemId, 1);
- assert.strictEqual(ev.data.isActive, true);
assert.strictEqual(ev.data.optionId, 1);
- } else {
- assert.strictEqual(ev.data.itemId, 1);
- assert.strictEqual(ev.data.isActive, false);
- assert.strictEqual(ev.data.optionId, false);
+ self.items[0].isActive = true;
+ self.items[0].currentOptionId = 1;
}
- },
- item_option_changed: function (ev) {
- if (eventNumber === 1) {
- assert.strictEqual(ev.data.itemId, 1);
- assert.strictEqual(ev.data.isActive, true);
+ if (eventNumber === 2) {
+ assert.strictEqual(ev.data.optionId, 2);
+ self.items[0].currentOptionId = 2;
+ }
+ if (eventNumber === 3) {
assert.strictEqual(ev.data.optionId, 2);
+ self.items[0].isActive = false;
+ self.items[0].currentOptionId = false;
}
+ dropdownMenu.update(self.items);
},
},
});
// open dropdown menu
testUtils.dom.click(dropdownMenu.$('button:first'));
- // open options menu
- testUtils.dom.click(dropdownMenu.$('span.fa-caret-right'));
- assert.containsN(dropdownMenu, '.dropdown-divider, .dropdown-item, .dropdown-item-text', 7);
- // Don't forget there is a hidden li.divider element at first place among children
- assert.doesNotHaveClass(dropdownMenu.$('.o_menu_item:nth-child(2) > .dropdown-item'), 'selected');
- assert.doesNotHaveClass(dropdownMenu.$('.o_item_option:nth-child(2) > .dropdown-item'), 'selected');
- assert.doesNotHaveClass(dropdownMenu.$('.o_item_option:nth-child(3) > .dropdown-item'), 'selected');
- testUtils.dom.click(dropdownMenu.$('.o_item_option:first'));
- assert.hasClass(dropdownMenu.$('.o_menu_item:nth-child(2) > .dropdown-item'), 'selected');
- assert.hasClass(dropdownMenu.$('.o_item_option:nth-child(2) > .dropdown-item'), 'selected');
- assert.doesNotHaveClass(dropdownMenu.$('.o_item_option:nth-child(3) > .dropdown-item'), 'selected');
- testUtils.dom.click(dropdownMenu.$('.o_item_option:nth-child(3)'));
- assert.hasClass(dropdownMenu.$('.o_menu_item:nth-child(2) > .dropdown-item'), 'selected');
- assert.doesNotHaveClass(dropdownMenu.$('.o_item_option:nth-child(2) > .dropdown-item'), 'selected');
- assert.hasClass(dropdownMenu.$('.o_item_option:nth-child(3) > .dropdown-item'), 'selected');
- testUtils.dom.click(dropdownMenu.$('.o_item_option:nth-child(3)'));
- assert.doesNotHaveClass(dropdownMenu.$('.o_menu_item:nth-child(2) > .dropdown-item'), 'selected');
- assert.doesNotHaveClass(dropdownMenu.$('.o_item_option:nth-child(2) > .dropdown-item'), 'selected');
- assert.doesNotHaveClass(dropdownMenu.$('.o_item_option:nth-child(3) > .dropdown-item'), 'selected');
- dropdownMenu.destroy();
- });
+ assert.containsN(dropdownMenu, '.dropdown-divider, .o_menu_item', 4);
+ testUtils.dom.clickFirst(dropdownMenu.$('.o_menu_item'));
+ // click on first option
+ testUtils.dom.click(dropdownMenu.$('.o_item_option > .dropdown-item').eq(0));
+ assert.hasClass(dropdownMenu.$('.o_menu_item > .dropdown-item').first(), 'selected');
+ assert.hasClass(dropdownMenu.$('.o_item_option> .dropdown-item').eq(0),'selected');
+ assert.doesNotHaveClass(dropdownMenu.$('.o_item_option > .dropdown-item').eq(1), 'selected');
+ // click on second option
+ testUtils.dom.click($('.o_item_option > .dropdown-item').eq(1));
+ assert.hasClass(dropdownMenu.$('.o_menu_item > .dropdown-item').first(), 'selected');
+ assert.doesNotHaveClass(dropdownMenu.$('.o_item_option > .dropdown-item').eq(0), 'selected');
+ assert.hasClass(dropdownMenu.$('.o_item_option > .dropdown-item').eq(1), 'selected');
+ // click again on second option
+ testUtils.dom.click($('.o_item_option > .dropdown-item').eq(1));
+ assert.doesNotHaveClass(dropdownMenu.$('.o_menu_item > .dropdown-item').first(), 'selected');
+ assert.doesNotHaveClass(dropdownMenu.$('.o_item_option > .dropdown-item').eq(0), 'selected');
+ assert.doesNotHaveClass(dropdownMenu.$('.o_item_option > .dropdown-item').eq(1), 'selected');
- QUnit.test('trash an item should be possible', function (assert) {
- assert.expect(3);
-
- var dropdownMenu = createDropdownMenu(this.dropdownHeader, this.items, {
- intercepts: {
- menu_item_deleted: function (ev) {
- assert.strictEqual(ev.data.itemId, 2);
- },
- },
- });
- testUtils.dom.click(dropdownMenu.$('button:first'));
- assert.containsN(dropdownMenu, '.dropdown-divider, .dropdown-item, .dropdown-item-text', 4);
- testUtils.dom.click(dropdownMenu.$('span.o_trash_button'));
- assert.containsN(dropdownMenu, '.dropdown-divider, .dropdown-item, .dropdown-item-text', 2);
dropdownMenu.destroy();
});
});