The main aim of the present refactoring is twofold: - simplify the code that was largely complexified at the time of the introduction of comparisons in the pivot view (Time Ranges menu), - factorize the method expandHeader and _loadData that were too much complex. Along the way, the pivot model structure has been simplified and many tests have been added. Performances in mobile mode have been improved by avoiding unecessary operations due to useless column groupbys in that mode. It should now be easier to understand and modify the pivot view in future. Co-Authored-By: Aaron Bohy <aab@odoo.com> closes odoo/odoo#33615 Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
2200 lines
88 KiB
JavaScript
2200 lines
88 KiB
JavaScript
odoo.define('web.search_panel_tests', function (require) {
|
|
"use strict";
|
|
|
|
var AbstractStorageService = require('web.AbstractStorageService');
|
|
var FormView = require('web.FormView');
|
|
var KanbanView = require('web.KanbanView');
|
|
var RamStorage = require('web.RamStorage');
|
|
var testUtils = require('web.test_utils');
|
|
|
|
var createActionManager = testUtils.createActionManager;
|
|
var createView = testUtils.createView;
|
|
|
|
QUnit.module('Views', {
|
|
beforeEach: function () {
|
|
this.data = {
|
|
partner: {
|
|
fields: {
|
|
foo: {string: "Foo", type: 'char'},
|
|
bar: {string: "Bar", type: 'boolean'},
|
|
int_field: {string: "Int Field", type: 'integer', group_operator: 'sum'},
|
|
company_id: {string: "company", type: 'many2one', relation: 'company'},
|
|
category_id: { string: "category", type: 'many2one', relation: 'category' },
|
|
state: { string: "State", type: 'selection', selection: [['abc', "ABC"], ['def', "DEF"], ['ghi', "GHI"]]},
|
|
},
|
|
records: [
|
|
{id: 1, bar: true, foo: "yop", int_field: 1, company_id: 3, state: 'abc', category_id: 6},
|
|
{id: 2, bar: true, foo: "blip", int_field: 2, company_id: 5, state: 'def', category_id: 7},
|
|
{id: 3, bar: true, foo: "gnap", int_field: 4, company_id: 3, state: 'ghi', category_id: 7},
|
|
{id: 4, bar: false, foo: "blip", int_field: 8, company_id: 5, state: 'ghi', category_id: 7},
|
|
]
|
|
},
|
|
company: {
|
|
fields: {
|
|
name: {string: "Display Name", type: 'char'},
|
|
parent_id: {string: 'Parent company', type: 'many2one', relation: 'company'},
|
|
category_id: {string: 'Category', type: 'many2one', relation: 'category'},
|
|
},
|
|
records: [
|
|
{id: 3, name: "asustek", category_id: 6},
|
|
{id: 5, name: "agrolait", category_id: 7},
|
|
],
|
|
},
|
|
category: {
|
|
fields: {
|
|
name: {string: "Category Name", type: 'char'},
|
|
},
|
|
records: [
|
|
{id: 6, name: "gold"},
|
|
{id: 7, name: "silver"},
|
|
]
|
|
},
|
|
};
|
|
|
|
this.actions = [{
|
|
id: 1,
|
|
name: 'Partners',
|
|
res_model: 'partner',
|
|
type: 'ir.actions.act_window',
|
|
views: [[false, 'kanban'], [false, 'list'], [false, 'pivot'], [false, 'form']],
|
|
}, {
|
|
id: 2,
|
|
name: 'Partners',
|
|
res_model: 'partner',
|
|
type: 'ir.actions.act_window',
|
|
views: [[false, 'form']],
|
|
}];
|
|
|
|
this.archs = {
|
|
'partner,false,list': '<tree><field name="foo"/></tree>',
|
|
'partner,false,kanban':
|
|
`<kanban>
|
|
<templates><t t-name="kanban-box">
|
|
<div><field name="foo"/></div>
|
|
</t></templates>
|
|
</kanban>`,
|
|
'partner,false,form':
|
|
`<form>
|
|
<button name="1" type="action" string="multi view"/>
|
|
<field name="foo"/>
|
|
</form>`,
|
|
'partner,false,pivot': '<pivot><field name="int_field" type="measure"/></pivot>',
|
|
'partner,false,search':
|
|
`<search>
|
|
<searchpanel>
|
|
<field name="company_id"/>
|
|
<field select="multi" name="category_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
};
|
|
|
|
var RamStorageService = AbstractStorageService.extend({
|
|
storage: new RamStorage(),
|
|
});
|
|
this.services = {
|
|
local_storage: RamStorageService,
|
|
};
|
|
},
|
|
}, function () {
|
|
|
|
QUnit.module('SearchPanel');
|
|
|
|
QUnit.test('basic rendering', async function (assert) {
|
|
assert.expect(17);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
assert.step((args.method || route) + (args.model ? (' on ' + args.model) : ''));
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field name="company_id"/>
|
|
<field select="multi" name="category_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
});
|
|
|
|
assert.containsOnce(kanban, '.o_content.o_controller_with_searchpanel > .o_search_panel');
|
|
assert.containsOnce(kanban, '.o_content.o_controller_with_searchpanel > .o_kanban_view');
|
|
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
|
|
assert.containsN(kanban, '.o_search_panel_section', 2);
|
|
|
|
var $firstSection = kanban.$('.o_search_panel_section:first');
|
|
assert.hasClass($firstSection.find('.o_search_panel_section_header i'), 'fa-folder');
|
|
assert.containsOnce($firstSection, '.o_search_panel_section_header:contains(company)');
|
|
assert.containsN($firstSection, '.o_search_panel_category_value', 3);
|
|
assert.containsOnce($firstSection, '.o_search_panel_category_value:first .active');
|
|
assert.strictEqual($firstSection.find('.o_search_panel_category_value').text().replace(/\s/g, ''),
|
|
'Allasustekagrolait');
|
|
|
|
var $secondSection = kanban.$('.o_search_panel_section:nth(1)');
|
|
assert.hasClass($secondSection.find('.o_search_panel_section_header i'), 'fa-filter');
|
|
assert.containsOnce($secondSection, '.o_search_panel_section_header:contains(category)');
|
|
assert.containsN($secondSection, '.o_search_panel_filter_value', 2);
|
|
assert.strictEqual($secondSection.find('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'gold1silver3');
|
|
|
|
assert.verifySteps([
|
|
'search_panel_select_range on partner',
|
|
'search_panel_select_multi_range on partner',
|
|
'/web/dataset/search_read on partner',
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('sections with custom icon and color', async function (assert) {
|
|
assert.expect(4);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field name="company_id" icon="fa-car" color="blue"/>
|
|
<field select="multi" name="state" icon="fa-star" color="#000"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
});
|
|
|
|
assert.hasClass(kanban.$('.o_search_panel_section_header:first i'), 'fa-car');
|
|
assert.hasAttrValue(kanban.$('.o_search_panel_section_header:first i'), 'style="{color: blue}"');
|
|
assert.hasClass(kanban.$('.o_search_panel_section_header:nth(1) i'), 'fa-star');
|
|
assert.hasAttrValue(kanban.$('.o_search_panel_section_header:nth(1) i'), 'style="{color: #000}"');
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('sections with attr invisible="1" are ignored', async function (assert) {
|
|
// 'groups' attributes are converted server-side into invisible="1" when the user doesn't
|
|
// belong to the given group
|
|
assert.expect(4);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: this.services,
|
|
arch: `<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field name="company_id"/>
|
|
<field select="multi" invisible="1" name="state"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
mockRPC: function (route, args) {
|
|
assert.step(args.method || route);
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
});
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_section');
|
|
|
|
assert.verifySteps([
|
|
'search_panel_select_range',
|
|
'/web/dataset/search_read',
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('categories and filters order is kept', async function (assert) {
|
|
assert.expect(4);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field name="company_id"/>
|
|
<field select="multi" name="category_id"/>
|
|
<field name="state"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
}
|
|
});
|
|
|
|
assert.containsN(kanban, '.o_search_panel_section', 3);
|
|
assert.strictEqual(kanban.$('.o_search_panel_section_header:nth(0)').text().trim(),
|
|
'company');
|
|
assert.strictEqual(kanban.$('.o_search_panel_section_header:nth(1)').text().trim(),
|
|
'category');
|
|
assert.strictEqual(kanban.$('.o_search_panel_section_header:nth(2)').text().trim(),
|
|
'State');
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('specify active category value in context', async function (assert) {
|
|
assert.expect(1);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field name="company_id"/>
|
|
<field name="state"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.deepEqual(args.domain, [["state", "=", "ghi"]]);
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
context: {
|
|
searchpanel_default_company_id: false,
|
|
searchpanel_default_state: 'ghi',
|
|
},
|
|
});
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('use category (on many2one) to refine search', async function (assert) {
|
|
assert.expect(14);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.step(JSON.stringify(args.domain));
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field name="company_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
domain: [['bar', '=', true]],
|
|
});
|
|
|
|
// select 'asustek'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(1) header'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(1) .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 2);
|
|
|
|
// select 'agrolait'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(2) header'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(2) .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
// select 'All'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:first header'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:first .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
assert.verifySteps([
|
|
'[["bar","=",true]]',
|
|
'[["bar","=",true],["company_id","child_of",3]]',
|
|
'[["bar","=",true],["company_id","child_of",5]]',
|
|
'[["bar","=",true]]',
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('use category (on selection) to refine search', async function (assert) {
|
|
assert.expect(14);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.step(JSON.stringify(args.domain));
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `<search><searchpanel><field name="state"/></searchpanel></search>`,
|
|
},
|
|
});
|
|
|
|
// select 'abc'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(1) header'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(1) .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
// select 'ghi'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(3) header'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(3) .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 2);
|
|
|
|
// select 'All' again
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:first header'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:first .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
|
|
assert.verifySteps([
|
|
'[]',
|
|
'[["state","=","abc"]]',
|
|
'[["state","=","ghi"]]',
|
|
'[]',
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('store and retrieve active category value', async function (assert) {
|
|
assert.expect(8);
|
|
|
|
var Storage = RamStorage.extend({
|
|
getItem: function (key) {
|
|
assert.step('getItem ' + key);
|
|
return 3; // 'asustek'
|
|
},
|
|
setItem: function (key, value) {
|
|
assert.step('setItem ' + key + ' to ' + value);
|
|
},
|
|
});
|
|
var RamStorageService = AbstractStorageService.extend({
|
|
storage: new Storage(),
|
|
});
|
|
|
|
var expectedActiveId = 3;
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: {
|
|
local_storage: RamStorageService,
|
|
},
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<seasrch>
|
|
<searchpanel>
|
|
<field name="company_id"/>
|
|
</searchpanel>
|
|
</seasrch>`,
|
|
},
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.deepEqual(args.domain, [['company_id', 'child_of', expectedActiveId]]);
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
});
|
|
|
|
// 'asustek' should be selected by default
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(1) .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 2);
|
|
|
|
// select 'agrolait'
|
|
expectedActiveId = 5;
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(2) header'));
|
|
|
|
assert.verifySteps([
|
|
'getItem searchpanel_partner_company_id',
|
|
'setItem searchpanel_partner_company_id to 5',
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('retrieved category value does not exist', async function (assert) {
|
|
assert.expect(6);
|
|
|
|
var Storage = RamStorage.extend({
|
|
getItem: function (key) {
|
|
assert.step('getItem ' + key);
|
|
return 343; // this value doesn't exist
|
|
},
|
|
});
|
|
var RamStorageService = AbstractStorageService.extend({
|
|
storage: new Storage(),
|
|
});
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: {
|
|
local_storage: RamStorageService,
|
|
},
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `<search><searchpanel><field name="company_id"/></searchpanel></search>`,
|
|
},
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.deepEqual(args.domain, []);
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
});
|
|
|
|
// 'All' should be selected by default as the retrieved value does not exist
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:first .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
|
|
assert.verifySteps(['getItem searchpanel_partner_company_id']);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('use two categories to refine search', async function (assert) {
|
|
assert.expect(14);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.step(JSON.stringify(args.domain));
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field name="company_id"/>
|
|
<field name="state"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
domain: [['bar', '=', true]],
|
|
});
|
|
|
|
assert.containsN(kanban, '.o_search_panel_section', 2);
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
// select 'asustek'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value[data-id=3] header'));
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 2);
|
|
|
|
// select 'abc'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value[data-id=abc] header'));
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
// select 'ghi'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value[data-id=ghi] header'));
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
// select 'All' in first category (company_id)
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_section:first .o_search_panel_category_value:first header'));
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
// select 'All' in second category (state)
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_section:nth(1) .o_search_panel_category_value:first header'));
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
assert.verifySteps([
|
|
'[["bar","=",true]]',
|
|
'[["bar","=",true],["company_id","child_of",3]]',
|
|
'[["bar","=",true],["company_id","child_of",3],["state","=","abc"]]',
|
|
'[["bar","=",true],["company_id","child_of",3],["state","=","ghi"]]',
|
|
'[["bar","=",true],["state","=","ghi"]]',
|
|
'[["bar","=",true]]',
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('category with parent_field', async function (assert) {
|
|
assert.expect(28);
|
|
|
|
this.data.company.records.push({id: 40, name: 'child company 1', parent_id: 5});
|
|
this.data.company.records.push({id: 41, name: 'child company 2', parent_id: 5});
|
|
this.data.partner.records[1].company_id = 40;
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.step(JSON.stringify(args.domain));
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `<search><searchpanel><field name="company_id"/></searchpanel></search>`,
|
|
},
|
|
});
|
|
|
|
// 'All' is selected by default
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:first .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
assert.containsN(kanban, '.o_search_panel_category_value', 3);
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .o_toggle_fold');
|
|
|
|
// unfold parent category
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value .o_toggle_fold'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:first .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
assert.containsN(kanban, '.o_search_panel_category_value', 5);
|
|
assert.containsN(kanban, '.o_search_panel_category_value .o_search_panel_category_value', 2);
|
|
|
|
// click on first child company
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value .o_search_panel_category_value:first header'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .o_search_panel_category_value:first .active');
|
|
assert.containsOnce(kanban, '.o_kanban_record:not(.o_kanban_ghost)');
|
|
|
|
// click on parent company
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(2) > header'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(2) .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
// parent company should be folded
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(2) .active');
|
|
assert.containsN(kanban, '.o_search_panel_category_value', 3);
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
// fold category with children
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value .o_toggle_fold'));
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value .o_toggle_fold'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(2) .active');
|
|
assert.containsN(kanban, '.o_search_panel_category_value', 3);
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
assert.verifySteps([
|
|
'[]',
|
|
'[["company_id","child_of",40]]',
|
|
'[["company_id","child_of",5]]',
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('category with no parent_field', async function (assert) {
|
|
assert.expect(10);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.step(JSON.stringify(args.domain));
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `<search><searchpanel><field name="category_id"/></searchpanel></search>`,
|
|
},
|
|
});
|
|
|
|
// 'All' is selected by default
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:first .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
assert.containsN(kanban, '.o_search_panel_category_value', 3);
|
|
|
|
// click on 'gold' category
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(1) header'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(1) .active');
|
|
assert.containsOnce(kanban, '.o_kanban_record:not(.o_kanban_ghost)');
|
|
|
|
assert.verifySteps([
|
|
'[]',
|
|
'[["category_id","=",6]]', // must use '=' operator (instead of 'child_of')
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('can (un)fold parent category values', async function (assert) {
|
|
assert.expect(7);
|
|
|
|
this.data.company.records.push({id: 40, name: 'child company 1', parent_id: 5});
|
|
this.data.company.records.push({id: 41, name: 'child company 2', parent_id: 5});
|
|
this.data.partner.records[1].company_id = 40;
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `<search><searchpanel><field name="company_id"/></searchpanel></search>`,
|
|
},
|
|
});
|
|
|
|
assert.strictEqual(kanban.$('.o_search_panel_category_value:contains(agrolait) .o_toggle_fold').length, 1,
|
|
"'agrolait' should be displayed as a parent category value");
|
|
assert.hasClass(kanban.$('.o_search_panel_category_value:contains(agrolait) .o_toggle_fold'), 'fa-caret-left',
|
|
"'agrolait' should be folded");
|
|
assert.containsN(kanban, '.o_search_panel_category_value', 3);
|
|
|
|
// unfold agrolait
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:contains(agrolait) .o_toggle_fold'));
|
|
assert.hasClass(kanban.$('.o_search_panel_category_value:contains(agrolait) .o_toggle_fold'), 'fa-caret-down',
|
|
"'agrolait' should be open");
|
|
assert.containsN(kanban, '.o_search_panel_category_value', 5);
|
|
|
|
// fold agrolait
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:contains(agrolait) .o_toggle_fold'));
|
|
assert.hasClass(kanban.$('.o_search_panel_category_value:contains(agrolait) .o_toggle_fold'), 'fa-caret-left',
|
|
"'agrolait' should be folded");
|
|
assert.containsN(kanban, '.o_search_panel_category_value', 3);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('fold status is kept at reload', async function (assert) {
|
|
assert.expect(4);
|
|
|
|
this.data.company.records.push({id: 40, name: 'child company 1', parent_id: 5});
|
|
this.data.company.records.push({id: 41, name: 'child company 2', parent_id: 5});
|
|
this.data.partner.records[1].company_id = 40;
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `<search><searchpanel><field name="company_id"/></searchpanel></search>`,
|
|
},
|
|
});
|
|
|
|
// unfold agrolait
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:contains(agrolait) .o_toggle_fold'));
|
|
assert.hasClass(kanban.$('.o_search_panel_category_value:contains(agrolait) .o_toggle_fold'), 'fa-caret-down',
|
|
"'agrolait' should be open");
|
|
assert.containsN(kanban, '.o_search_panel_category_value', 5);
|
|
|
|
await kanban.reload({});
|
|
|
|
assert.hasClass(kanban.$('.o_search_panel_category_value:contains(agrolait) .o_toggle_fold'), 'fa-caret-down',
|
|
"'agrolait' should be open");
|
|
assert.containsN(kanban, '.o_search_panel_category_value', 5);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('concurrency: delayed search_reads', async function (assert) {
|
|
assert.expect(19);
|
|
|
|
var def;
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
var result = this._super.apply(this, arguments);
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.step(JSON.stringify(args.domain));
|
|
return Promise.resolve(def).then(_.constant(result));
|
|
}
|
|
return result;
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `<search><searchpanel><field name="company_id"/></searchpanel></search>`,
|
|
},
|
|
domain: [['bar', '=', true]],
|
|
});
|
|
|
|
// 'All' should be selected by default
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:first .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
// select 'asustek' (delay the reload)
|
|
def = testUtils.makeTestPromise();
|
|
var asustekDef = def;
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(1) header'));
|
|
|
|
// 'asustek' should be selected, but there should still be 3 records
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(1) .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
// select 'agrolait' (delay the reload)
|
|
def = testUtils.makeTestPromise();
|
|
var agrolaitDef = def;
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(2) header'));
|
|
|
|
// 'agrolait' should be selected, but there should still be 3 records
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(2) .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
// unlock asustek search (should be ignored, so there should still be 3 records)
|
|
asustekDef.resolve();
|
|
await testUtils.nextTick();
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(2) .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
// unlock agrolait search, there should now be 1 record
|
|
agrolaitDef.resolve();
|
|
await testUtils.nextTick();
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(2) .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
assert.verifySteps([
|
|
'[["bar","=",true]]',
|
|
'[["bar","=",true],["company_id","child_of",3]]',
|
|
'[["bar","=",true],["company_id","child_of",5]]',
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('concurrency: misordered get_filters', async function (assert) {
|
|
assert.expect(15);
|
|
|
|
var def;
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
var result = this._super.apply(this, arguments);
|
|
if (args.method === 'search_panel_select_multi_range') {
|
|
return Promise.resolve(def).then(_.constant(result));
|
|
}
|
|
return result;
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field name="state"/>
|
|
<field select="multi" name="company_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
});
|
|
|
|
// 'All' should be selected by default
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:first .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
|
|
// select 'abc' (delay the reload)
|
|
def = testUtils.makeTestPromise();
|
|
var abcDef = def;
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(1) header'));
|
|
|
|
// 'All' should still be selected, and there should still be 4 records
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:first .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
|
|
// select 'ghi' (delay the reload)
|
|
def = testUtils.makeTestPromise();
|
|
var ghiDef = def;
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(3) header'));
|
|
|
|
// 'All' should still be selected, and there should still be 4 records
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:first .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
|
|
// unlock ghi search
|
|
ghiDef.resolve();
|
|
await testUtils.nextTick();
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(3) .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 2);
|
|
|
|
// unlock abc search (should be ignored)
|
|
abcDef.resolve();
|
|
await testUtils.nextTick();
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(3) .active');
|
|
assert.containsN(kanban, '.o_kanban_record:not(.o_kanban_ghost)', 2);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('concurrency: delayed get_filter', async function (assert) {
|
|
assert.expect(3);
|
|
|
|
var def;
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
var result = this._super.apply(this, arguments);
|
|
if (args.method === 'search_panel_select_multi_range') {
|
|
return Promise.resolve(def).then(_.constant(result));
|
|
}
|
|
return result;
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field select="multi" name="company_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
});
|
|
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
|
|
// trigger a reload and delay the get_filter
|
|
def = testUtils.makeTestPromise();
|
|
kanban.reload({domain: [['id', '=', 1]]});
|
|
await testUtils.nextTick();
|
|
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
|
|
def.resolve();
|
|
await testUtils.nextTick();
|
|
|
|
assert.containsOnce(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)');
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('use filter (on many2one) to refine search', async function (assert) {
|
|
assert.expect(32);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
var result = this._super.apply(this, arguments);
|
|
if (args.method === 'search_panel_select_multi_range') {
|
|
// the following keys should have same value for all calls to this route
|
|
var keys = ['field_name', 'group_by', 'comodel_domain', 'search_domain', 'category_domain'];
|
|
assert.deepEqual(_.pick(args.kwargs, keys), {
|
|
group_by: false,
|
|
comodel_domain: [],
|
|
search_domain: [['bar', '=', true]],
|
|
category_domain: [],
|
|
});
|
|
// the filter_domain depends on the filter selection
|
|
assert.step(JSON.stringify(args.kwargs.filter_domain));
|
|
}
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.step(JSON.stringify(args.domain));
|
|
}
|
|
return result;
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field select="multi" name="company_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
domain: [['bar', '=', true]],
|
|
});
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_value', 2);
|
|
assert.containsNone(kanban, '.o_search_panel_filter_value input:checked');
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'asustek2agrolait1');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
// check 'asustek'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:first input'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_filter_value input:checked');
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'asustek2agrolait');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 2);
|
|
|
|
// check 'agrolait'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:nth(1) input'));
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_value input:checked', 2);
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'asustek2agrolait1');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
// uncheck 'asustek'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:first input'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_filter_value input:checked');
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'asustekagrolait1');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
// uncheck 'agrolait'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:nth(1) input'));
|
|
|
|
assert.containsNone(kanban, '.o_search_panel_filter_value input:checked');
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'asustek2agrolait1');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
assert.verifySteps([
|
|
// nothing checked
|
|
'[]',
|
|
'[["bar","=",true]]',
|
|
// 'asustek' checked
|
|
'[["company_id","in",[3]]]',
|
|
'[["bar","=",true],["company_id","in",[3]]]',
|
|
// 'asustek' and 'agrolait' checked
|
|
'[["company_id","in",[3,5]]]',
|
|
'[["bar","=",true],["company_id","in",[3,5]]]',
|
|
// 'agrolait' checked
|
|
'[["company_id","in",[5]]]',
|
|
'[["bar","=",true],["company_id","in",[5]]]',
|
|
// nothing checked
|
|
'[]',
|
|
'[["bar","=",true]]',
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('use filter (on selection) to refine search', async function (assert) {
|
|
assert.expect(32);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
var result = this._super.apply(this, arguments);
|
|
if (args.method === 'search_panel_select_multi_range') {
|
|
// the following keys should have same value for all calls to this route
|
|
var keys = ['group_by', 'comodel_domain', 'search_domain', 'category_domain'];
|
|
assert.deepEqual(_.pick(args.kwargs, keys), {
|
|
group_by: false,
|
|
comodel_domain: [],
|
|
search_domain: [['bar', '=', true]],
|
|
category_domain: [],
|
|
});
|
|
// the filter_domain depends on the filter selection
|
|
assert.step(JSON.stringify(args.kwargs.filter_domain));
|
|
}
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.step(JSON.stringify(args.domain));
|
|
}
|
|
return result;
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field select="multi" name="state"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
domain: [['bar', '=', true]],
|
|
});
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_value', 3);
|
|
assert.containsNone(kanban, '.o_search_panel_filter_value input:checked');
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'ABC1DEF1GHI1');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
// check 'abc'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:first input'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_filter_value input:checked');
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'ABC1DEFGHI');
|
|
assert.containsOnce(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
// check 'def'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:nth(1) input'));
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_value input:checked', 2);
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'ABC1DEF1GHI');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 2);
|
|
|
|
// uncheck 'abc'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:first input'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_filter_value input:checked');
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'ABCDEF1GHI');
|
|
assert.containsOnce(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)');
|
|
|
|
// uncheck 'def'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:nth(1) input'));
|
|
|
|
assert.containsNone(kanban, '.o_search_panel_filter_value input:checked');
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'ABC1DEF1GHI1');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
assert.verifySteps([
|
|
// nothing checked
|
|
'[]',
|
|
'[["bar","=",true]]',
|
|
// 'asustek' checked
|
|
'[["state","in",["abc"]]]',
|
|
'[["bar","=",true],["state","in",["abc"]]]',
|
|
// 'asustek' and 'agrolait' checked
|
|
'[["state","in",["abc","def"]]]',
|
|
'[["bar","=",true],["state","in",["abc","def"]]]',
|
|
// 'agrolait' checked
|
|
'[["state","in",["def"]]]',
|
|
'[["bar","=",true],["state","in",["def"]]]',
|
|
// nothing checked
|
|
'[]',
|
|
'[["bar","=",true]]',
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('only reload filters when domains change', async function (assert) {
|
|
assert.expect(11);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
assert.step(args.method || route);
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field name="state"/>
|
|
<field select="multi" name="company_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
viewOptions: {
|
|
limit: 2,
|
|
},
|
|
});
|
|
|
|
assert.verifySteps([
|
|
'search_panel_select_multi_range',
|
|
'/web/dataset/search_read',
|
|
]);
|
|
|
|
// go to page 2 (the domain doesn't change, so the filters should not be reloaded)
|
|
await testUtils.dom.click(kanban.$('.o_pager_next'));
|
|
|
|
assert.verifySteps([
|
|
'/web/dataset/search_read',
|
|
]);
|
|
|
|
// reload with another domain, so the filters should be reloaded
|
|
await kanban.reload({domain: [['id', '<', 5]]});
|
|
|
|
assert.verifySteps([
|
|
'search_panel_select_multi_range',
|
|
'/web/dataset/search_read',
|
|
]);
|
|
|
|
// change category value, so the filters should be reloaded
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(1) header'));
|
|
|
|
assert.verifySteps([
|
|
'search_panel_select_multi_range',
|
|
'/web/dataset/search_read',
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('filter with groupby', async function (assert) {
|
|
assert.expect(42);
|
|
|
|
this.data.company.records.push({id: 11, name: 'camptocamp', category_id: 7});
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
var result = this._super.apply(this, arguments);
|
|
if (args.method === 'search_panel_select_multi_range') {
|
|
// the following keys should have same value for all calls to this route
|
|
var keys = ['group_by', 'comodel_domain', 'search_domain', 'category_domain'];
|
|
assert.deepEqual(_.pick(args.kwargs, keys), {
|
|
group_by: 'category_id',
|
|
comodel_domain: [],
|
|
search_domain: [['bar', '=', true]],
|
|
category_domain: [],
|
|
});
|
|
// the filter_domain depends on the filter selection
|
|
assert.step(JSON.stringify(args.kwargs.filter_domain));
|
|
}
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.step(JSON.stringify(args.domain));
|
|
}
|
|
return result;
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field select="multi" name="company_id" groupby="category_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
domain: [['bar', '=', true]],
|
|
});
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_group', 2);
|
|
assert.containsOnce(kanban, '.o_search_panel_filter_group:first .o_search_panel_filter_value');
|
|
assert.containsN(kanban, '.o_search_panel_filter_group:nth(1) .o_search_panel_filter_value', 2);
|
|
assert.containsNone(kanban, '.o_search_panel_filter_value input:checked');
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_group > div > label').text().replace(/\s/g, ''),
|
|
'goldsilver');
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'asustek2agrolait1camptocamp');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 3);
|
|
|
|
// check 'asustek'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:first input'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_filter_value input:checked');
|
|
var firstGroupCheckbox = kanban.$('.o_search_panel_filter_group:first > div > input').get(0);
|
|
assert.strictEqual(firstGroupCheckbox.checked, true,
|
|
"first group checkbox should be checked");
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'asustek2agrolaitcamptocamp');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 2);
|
|
|
|
// check 'agrolait'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:nth(1) input'));
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_value input:checked', 2);
|
|
var secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
|
assert.strictEqual(secondGroupCheckbox.checked, false,
|
|
"second group checkbox should not be checked");
|
|
assert.strictEqual(secondGroupCheckbox.indeterminate, true,
|
|
"second group checkbox should be indeterminate");
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'asustekagrolaitcamptocamp');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 0);
|
|
|
|
// check 'camptocamp'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:nth(2) input'));
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_value input:checked', 3);
|
|
secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
|
assert.strictEqual(secondGroupCheckbox.checked, true,
|
|
"second group checkbox should be checked");
|
|
assert.strictEqual(secondGroupCheckbox.indeterminate, false,
|
|
"second group checkbox should not be indeterminate");
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'asustekagrolaitcamptocamp');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 0);
|
|
|
|
// uncheck second group
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_group:nth(1) > div > input'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_filter_value input:checked');
|
|
secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
|
assert.strictEqual(secondGroupCheckbox.checked, false,
|
|
"second group checkbox should not be checked");
|
|
assert.strictEqual(secondGroupCheckbox.indeterminate, false,
|
|
"second group checkbox should not be indeterminate");
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'asustek2agrolaitcamptocamp');
|
|
assert.containsN(kanban, '.o_kanban_view .o_kanban_record:not(.o_kanban_ghost)', 2);
|
|
|
|
assert.verifySteps([
|
|
// nothing checked
|
|
'[]',
|
|
'[["bar","=",true]]',
|
|
// 'asustek' checked
|
|
'[["company_id","in",[3]]]',
|
|
'[["bar","=",true],["company_id","in",[3]]]',
|
|
// 'asustek' and 'agrolait' checked
|
|
'[["company_id","in",[3]],["company_id","in",[5]]]',
|
|
'[["bar","=",true],["company_id","in",[3]],["company_id","in",[5]]]',
|
|
// 'asustek', 'agrolait' and 'camptocamp' checked
|
|
'[["company_id","in",[3]],["company_id","in",[5,11]]]',
|
|
'[["bar","=",true],["company_id","in",[3]],["company_id","in",[5,11]]]',
|
|
// 'asustek' checked
|
|
'[["company_id","in",[3]]]',
|
|
'[["bar","=",true],["company_id","in",[3]]]',
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('filter with domain', async function (assert) {
|
|
assert.expect(3);
|
|
|
|
this.data.company.records.push({id: 40, name: 'child company 1', parent_id: 3});
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
var result = this._super.apply(this, arguments);
|
|
if (args.method === 'search_panel_select_multi_range') {
|
|
assert.deepEqual(args.kwargs, {
|
|
group_by: false,
|
|
category_domain: [],
|
|
filter_domain: [],
|
|
search_domain: [],
|
|
comodel_domain: [['parent_id', '=', false]],
|
|
disable_counters: false,
|
|
});
|
|
}
|
|
return result;
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field select="multi" name="company_id" domain="[('parent_id','=',False)]"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
});
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_value', 2);
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
'asustek2agrolait2');
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('(un)fold filter group', async function (assert) {
|
|
assert.expect(13);
|
|
|
|
this.data.company.records.push({id: 11, name: 'camptocamp', category_id: 7});
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field select="multi" name="company_id" groupby="category_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
});
|
|
|
|
// groups are opened by default
|
|
assert.containsN(kanban, '.o_search_panel_filter_group', 2);
|
|
assert.containsN(kanban, '.o_search_panel_filter_value', 3);
|
|
|
|
// check 'agrolait'
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_value:nth(1) input'));
|
|
var secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
|
assert.strictEqual(secondGroupCheckbox.indeterminate, true);
|
|
assert.hasAttrValue(kanban.$('.o_search_panel_filter_value:nth(1) input'), 'checked', 'checked');
|
|
|
|
// fold second group
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_group:nth(1) .o_toggle_fold'));
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_group', 2);
|
|
assert.containsOnce(kanban, '.o_search_panel_filter_value');
|
|
secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
|
assert.strictEqual(secondGroupCheckbox.indeterminate, true);
|
|
|
|
// fold first group
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_group:first .o_toggle_fold'));
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_group', 2);
|
|
assert.containsNone(kanban, '.o_search_panel_filter_value');
|
|
|
|
// unfold second group
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter_group:nth(1) .o_toggle_fold'));
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_group', 2);
|
|
assert.containsN(kanban, '.o_search_panel_filter_value', 2);
|
|
secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
|
assert.strictEqual(secondGroupCheckbox.indeterminate, true);
|
|
assert.hasAttrValue(kanban.$('.o_search_panel_filter_value:first input'), 'checked', 'checked');
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('filter with domain depending on category', async function (assert) {
|
|
assert.expect(22);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
mockRPC: function (route, args) {
|
|
var result = this._super.apply(this, arguments);
|
|
if (args.method === 'search_panel_select_multi_range') {
|
|
// the following keys should have same value for all calls to this route
|
|
var keys = ['group_by', 'search_domain', 'filter_domain'];
|
|
assert.deepEqual(_.pick(args.kwargs, keys), {
|
|
group_by: false,
|
|
filter_domain: [],
|
|
search_domain: [],
|
|
});
|
|
assert.step(JSON.stringify(args.kwargs.category_domain));
|
|
assert.step(JSON.stringify(args.kwargs.comodel_domain));
|
|
}
|
|
return result;
|
|
},
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field name="category_id"/>
|
|
<field select="multi" name="company_id" domain="[['category_id', '=', category_id]]"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
});
|
|
|
|
// select 'gold' category
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(1) header'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(1) .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_filter_value');
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
"asustek1");
|
|
|
|
// select 'silver' category
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:nth(2) header'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:nth(2) .active');
|
|
assert.containsOnce(kanban, '.o_search_panel_filter_value');
|
|
assert.strictEqual(kanban.$('.o_search_panel_filter_value').text().replace(/\s/g, ''),
|
|
"agrolait2");
|
|
|
|
// select All
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_category_value:first header'));
|
|
|
|
assert.containsOnce(kanban, '.o_search_panel_category_value:first .active');
|
|
assert.containsNone(kanban, '.o_search_panel_filter_value');
|
|
|
|
assert.verifySteps([
|
|
'[]', // category_domain (All)
|
|
'[["category_id","=",false]]', // comodel_domain (All)
|
|
'[["category_id","=",6]]', // category_domain ('gold')
|
|
'[["category_id","=",6]]', // comodel_domain ('gold')
|
|
'[["category_id","=",7]]', // category_domain ('silver')
|
|
'[["category_id","=",7]]', // comodel_domain ('silver')
|
|
'[]', // category_domain (All)
|
|
'[["category_id","=",false]]', // comodel_domain (All)
|
|
]);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('specify active filter values in context', async function (assert) {
|
|
assert.expect(4);
|
|
|
|
var expectedDomain = [
|
|
['company_id', 'in', [5]],
|
|
['state', 'in', ['abc', 'ghi']],
|
|
];
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field select="multi" name="company_id"/>
|
|
<field select="multi" name="state"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.deepEqual(args.domain, expectedDomain);
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
context: {
|
|
searchpanel_default_company_id: [5],
|
|
searchpanel_default_state: ['abc', 'ghi'],
|
|
},
|
|
});
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_value input:checked', 3);
|
|
|
|
// manually untick a default value
|
|
expectedDomain = [['state', 'in', ['abc', 'ghi']]];
|
|
await testUtils.dom.click(kanban.$('.o_search_panel_filter:first .o_search_panel_filter_value:nth(1) input'));
|
|
|
|
assert.containsN(kanban, '.o_search_panel_filter_value input:checked', 2);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('retrieved filter value from context does not exist', async function (assert) {
|
|
assert.expect(1);
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field select="multi" name="company_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.deepEqual(args.domain, [["company_id", "in", [3]]]);
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
context: {
|
|
searchpanel_default_company_id: [1, 3],
|
|
},
|
|
});
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('filter with groupby and default values in context', async function (assert) {
|
|
assert.expect(2);
|
|
|
|
this.data.company.records.push({id: 11, name: 'camptocamp', category_id: 7});
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field select="multi" name="company_id" groupby="category_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.deepEqual(args.domain, [['company_id', 'in', [5]]]);
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
context: {
|
|
searchpanel_default_company_id: [5],
|
|
},
|
|
});
|
|
|
|
var secondGroupCheckbox = kanban.$('.o_search_panel_filter_group:nth(1) > div > input').get(0);
|
|
assert.strictEqual(secondGroupCheckbox.indeterminate, true);
|
|
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('tests conservation of category record order', async function (assert) {
|
|
assert.expect(1);
|
|
|
|
this.data.company.records.push({id: 56, name: 'highID', category_id: 6});
|
|
this.data.company.records.push({id: 2, name: 'lowID', category_id: 6});
|
|
|
|
var kanban = await createView({
|
|
View: KanbanView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
services: this.services,
|
|
arch: `
|
|
<kanban>
|
|
<templates>
|
|
<t t-name="kanban-box">
|
|
<div>
|
|
<field name="foo"/>
|
|
</div>
|
|
</t>
|
|
</templates>
|
|
</kanban>`,
|
|
archs: {
|
|
'partner,false,search': `
|
|
<search>
|
|
<searchpanel>
|
|
<field name="company_id"/>
|
|
<field select="multi" name="category_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
});
|
|
|
|
var $firstSection = kanban.$('.o_search_panel_section:first');
|
|
assert.strictEqual($firstSection.find('.o_search_panel_category_value').text().replace(/\s/g, ''),
|
|
'AllasustekagrolaithighIDlowID');
|
|
kanban.destroy();
|
|
});
|
|
|
|
QUnit.test('search panel is available on list and kanban by default', async function (assert) {
|
|
assert.expect(8);
|
|
|
|
var actionManager = await createActionManager({
|
|
actions: this.actions,
|
|
archs: this.archs,
|
|
data: this.data,
|
|
});
|
|
|
|
await actionManager.doAction(1);
|
|
assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_kanban_view');
|
|
assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_search_panel');
|
|
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_pivot'));
|
|
assert.containsOnce(actionManager, '.o_content .o_pivot');
|
|
assert.containsNone(actionManager, '.o_content .o_search_panel');
|
|
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_list'));
|
|
assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_list_view');
|
|
assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_search_panel');
|
|
|
|
await testUtils.dom.click(actionManager.$('.o_data_row .o_data_cell:first'));
|
|
assert.containsOnce(actionManager, '.o_content .o_form_view');
|
|
assert.containsNone(actionManager, '.o_content .o_search_panel');
|
|
|
|
actionManager.destroy();
|
|
});
|
|
|
|
QUnit.test('search panel with view_types attribute', async function (assert) {
|
|
assert.expect(6);
|
|
|
|
this.archs['partner,false,search'] =
|
|
`<search>
|
|
<searchpanel view_types="kanban,pivot">
|
|
<field name="company_id"/>
|
|
<field select="multi" name="category_id"/>
|
|
</searchpanel>
|
|
</search>`;
|
|
|
|
|
|
var actionManager = await createActionManager({
|
|
actions: this.actions,
|
|
archs: this.archs,
|
|
data: this.data,
|
|
});
|
|
|
|
await actionManager.doAction(1);
|
|
assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_kanban_view');
|
|
assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_search_panel');
|
|
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_list'));
|
|
assert.containsOnce(actionManager, '.o_content .o_list_view');
|
|
assert.containsNone(actionManager, '.o_content .o_search_panel');
|
|
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_pivot'));
|
|
assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_pivot');
|
|
assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_search_panel');
|
|
|
|
actionManager.destroy();
|
|
});
|
|
|
|
QUnit.test('search panel state is shared between views', async function (assert) {
|
|
assert.expect(16);
|
|
|
|
var actionManager = await createActionManager({
|
|
actions: this.actions,
|
|
archs: this.archs,
|
|
data: this.data,
|
|
services: this.services,
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.step(JSON.stringify(args.domain));
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
});
|
|
|
|
await actionManager.doAction(1);
|
|
assert.hasClass(actionManager.$('.o_search_panel_category_value:first header'), 'active');
|
|
assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
|
|
// select 'asustek' company
|
|
await testUtils.dom.click(actionManager.$('.o_search_panel_category_value:nth(1) header'));
|
|
assert.hasClass(actionManager.$('.o_search_panel_category_value:nth(1) header'), 'active');
|
|
assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 2);
|
|
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_list'));
|
|
assert.hasClass(actionManager.$('.o_search_panel_category_value:nth(1) header'), 'active');
|
|
assert.containsN(actionManager, '.o_data_row', 2);
|
|
|
|
// select 'agrolait' company
|
|
await testUtils.dom.click(actionManager.$('.o_search_panel_category_value:nth(2) header'));
|
|
assert.hasClass(actionManager.$('.o_search_panel_category_value:nth(2) header'), 'active');
|
|
assert.containsN(actionManager, '.o_data_row', 2);
|
|
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_kanban'));
|
|
assert.hasClass(actionManager.$('.o_search_panel_category_value:nth(2) header'), 'active');
|
|
assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 2);
|
|
|
|
assert.verifySteps([
|
|
'[]', // initial search_read
|
|
'[["company_id","child_of",3]]', // kanban, after selecting the first company
|
|
'[["company_id","child_of",3]]', // list
|
|
'[["company_id","child_of",5]]', // list, after selecting the other company
|
|
'[["company_id","child_of",5]]', // kanban
|
|
]);
|
|
|
|
actionManager.destroy();
|
|
});
|
|
|
|
QUnit.test('search panel filters are kept between switch views', async function (assert) {
|
|
assert.expect(16);
|
|
|
|
var actionManager = await createActionManager({
|
|
actions: this.actions,
|
|
archs: this.archs,
|
|
data: this.data,
|
|
services: this.services,
|
|
mockRPC: function (route, args) {
|
|
if (route === '/web/dataset/search_read') {
|
|
assert.step(JSON.stringify(args.domain));
|
|
}
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
});
|
|
|
|
await actionManager.doAction(1);
|
|
assert.containsNone(actionManager, '.o_search_panel_filter_value input:checked');
|
|
assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
|
|
// select gold filter
|
|
await testUtils.dom.click(actionManager.$('.o_search_panel_filter input[type="checkbox"]:nth(0)'));
|
|
assert.containsOnce(actionManager, '.o_search_panel_filter_value input:checked');
|
|
assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_list'));
|
|
assert.containsOnce(actionManager, '.o_search_panel_filter_value input:checked');
|
|
assert.containsN(actionManager, '.o_data_row', 1);
|
|
|
|
// select silver filter
|
|
await testUtils.dom.click(actionManager.$('.o_search_panel_filter input[type="checkbox"]:nth(1)'));
|
|
assert.containsN(actionManager, '.o_search_panel_filter_value input:checked', 2);
|
|
assert.containsN(actionManager, '.o_data_row', 4);
|
|
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_kanban'));
|
|
assert.containsN(actionManager, '.o_search_panel_filter_value input:checked', 2);
|
|
assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
|
|
assert.verifySteps([
|
|
'[]', // initial search_read
|
|
'[["category_id","in",[6]]]', // kanban, after selecting the gold filter
|
|
'[["category_id","in",[6]]]', // list
|
|
'[["category_id","in",[6,7]]]', // list, after selecting the silver filter
|
|
'[["category_id","in",[6,7]]]', // kanban
|
|
]);
|
|
|
|
actionManager.destroy();
|
|
});
|
|
|
|
QUnit.test('search panel filters are kept when switching to a view with no search panel', async function (assert) {
|
|
assert.expect(13);
|
|
|
|
var actionManager = await createActionManager({
|
|
actions: this.actions,
|
|
archs: this.archs,
|
|
data: this.data,
|
|
});
|
|
|
|
await actionManager.doAction(1);
|
|
assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_kanban_view');
|
|
assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_search_panel');
|
|
assert.containsNone(actionManager, '.o_search_panel_filter_value input:checked');
|
|
assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 4);
|
|
|
|
// select gold filter
|
|
await testUtils.dom.click(actionManager.$('.o_search_panel_filter input[type="checkbox"]:nth(0)'));
|
|
assert.containsOnce(actionManager, '.o_search_panel_filter_value input:checked');
|
|
assert.containsN(actionManager, '.o_kanban_record:not(.o_kanban_ghost)', 1);
|
|
|
|
// switch to pivot
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_pivot'));
|
|
assert.containsOnce(actionManager, '.o_content .o_pivot');
|
|
assert.containsNone(actionManager, '.o_content .o_search_panel');
|
|
assert.strictEqual(actionManager.$('.o_pivot_cell_value').text(), '15');
|
|
|
|
// switch to list
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_list'));
|
|
assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_list_view');
|
|
assert.containsOnce(actionManager, '.o_content.o_controller_with_searchpanel .o_search_panel');
|
|
assert.containsOnce(actionManager, '.o_search_panel_filter_value input:checked');
|
|
assert.containsN(actionManager, '.o_data_row', 1);
|
|
|
|
actionManager.destroy();
|
|
});
|
|
|
|
QUnit.test('disable search panel onExecuteAction', async function (assert) {
|
|
assert.expect(6);
|
|
|
|
var actionManager = await createActionManager({
|
|
actions: this.actions,
|
|
archs: this.archs,
|
|
data: this.data,
|
|
services: this.services,
|
|
});
|
|
|
|
await actionManager.doAction(2);
|
|
|
|
await testUtils.dom.click(actionManager.$('.o_form_view button:contains("multi view")'));
|
|
assert.containsOnce(actionManager, '.o_kanban_view');
|
|
assert.containsNone(actionManager, '.o_search_panel');
|
|
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_list'));
|
|
assert.containsOnce(actionManager, '.o_list_view');
|
|
assert.containsNone(actionManager, '.o_search_panel');
|
|
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_kanban'));
|
|
assert.containsOnce(actionManager, '.o_kanban_view');
|
|
assert.containsNone(actionManager, '.o_search_panel');
|
|
|
|
actionManager.destroy();
|
|
});
|
|
|
|
QUnit.test('categories and filters are not reloaded when switching between views', async function (assert) {
|
|
assert.expect(8);
|
|
|
|
var actionManager = await createActionManager({
|
|
actions: this.actions,
|
|
archs: this.archs,
|
|
data: this.data,
|
|
services: this.services,
|
|
mockRPC: function (route, args) {
|
|
assert.step(args.method || route);
|
|
return this._super.apply(this, arguments);
|
|
},
|
|
});
|
|
|
|
await actionManager.doAction(1);
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_list'));
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_kanban'));
|
|
|
|
assert.verifySteps([
|
|
'/web/action/load',
|
|
'load_views',
|
|
'search_panel_select_range', // kanban: categories
|
|
'search_panel_select_multi_range', // kanban: filters
|
|
'/web/dataset/search_read', // kanban: records
|
|
'/web/dataset/search_read', // list: records
|
|
'/web/dataset/search_read', // kanban: records
|
|
]);
|
|
|
|
actionManager.destroy();
|
|
});
|
|
|
|
QUnit.test('scroll position is kept when switching between controllers', async function (assert) {
|
|
assert.expect(6);
|
|
|
|
for (var i = 10; i < 20; i++) {
|
|
this.data.category.records.push({id: i, name: "Cat " + i});
|
|
}
|
|
|
|
var actionManager = await createActionManager({
|
|
actions: this.actions,
|
|
archs: this.archs,
|
|
data: this.data,
|
|
services: this.services,
|
|
});
|
|
actionManager.$el.css('max-height', 300);
|
|
|
|
await actionManager.doAction(1);
|
|
assert.containsOnce(actionManager, '.o_content .o_kanban_view');
|
|
assert.strictEqual(actionManager.$('.o_search_panel').scrollTop(), 0);
|
|
|
|
// simulate a scroll in the search panel and switch into list
|
|
actionManager.$('.o_search_panel').scrollTop(50);
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_list'));
|
|
assert.containsOnce(actionManager, '.o_content .o_list_view');
|
|
assert.strictEqual(actionManager.$('.o_search_panel').scrollTop(), 50);
|
|
|
|
// simulate another scroll and switch back to kanban
|
|
actionManager.$('.o_search_panel').scrollTop(30);
|
|
await testUtils.dom.click(actionManager.$('.o_cp_switch_kanban'));
|
|
assert.containsOnce(actionManager, '.o_content .o_kanban_view');
|
|
assert.strictEqual(actionManager.$('.o_search_panel').scrollTop(), 30);
|
|
|
|
actionManager.destroy();
|
|
});
|
|
|
|
QUnit.test('search panel is not instantiated in dialogs', async function (assert) {
|
|
assert.expect(2);
|
|
|
|
this.data.company.records = [
|
|
{id: 1, name: 'Company1'},
|
|
{id: 2, name: 'Company2'},
|
|
{id: 3, name: 'Company3'},
|
|
{id: 4, name: 'Company4'},
|
|
{id: 5, name: 'Company5'},
|
|
{id: 6, name: 'Company6'},
|
|
{id: 7, name: 'Company7'},
|
|
{id: 8, name: 'Company8'},
|
|
];
|
|
|
|
var form = await createView({
|
|
View: FormView,
|
|
model: 'partner',
|
|
data: this.data,
|
|
arch: '<form><field name="company_id"/></form>',
|
|
archs: {
|
|
'company,false,list': '<tree><field name="name"/></tree>',
|
|
'company,false,search':
|
|
`<search>
|
|
<field name="name"/>
|
|
<searchpanel>
|
|
<field name="category_id"/>
|
|
</searchpanel>
|
|
</search>`,
|
|
},
|
|
});
|
|
|
|
await testUtils.fields.many2one.clickOpenDropdown('company_id');
|
|
await testUtils.fields.many2one.clickItem('company_id', 'Search More');
|
|
|
|
assert.containsOnce(document.body, '.modal .o_list_view');
|
|
assert.containsNone(document.body, '.modal .o_search_panel');
|
|
|
|
form.destroy();
|
|
});
|
|
});
|
|
});
|