odoo.define('web.search_panel_tests', function (require) {
"use strict";
var AbstractStorageService = require('web.AbstractStorageService');
var KanbanView = require('web.KanbanView');
var RamStorage = require('web.RamStorage');
var testUtils = require('web.test_utils');
var createView = testUtils.createView;
QUnit.module('Views', {
beforeEach: function () {
this.data = {
partner: {
fields: {
foo: {string: "Foo", type: 'char'},
bar: {string: "Bar", type: 'boolean'},
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", company_id: 3, state: 'abc', category_id: 6},
{id: 2, bar: true, foo: "blip", company_id: 5, state: 'def', category_id: 7},
{id: 3, bar: true, foo: "gnap", company_id: 3, state: 'ghi', category_id: 7},
{id: 4, bar: false, foo: "blip", 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"},
]
},
};
var RamStorageService = AbstractStorageService.extend({
storage: new RamStorage(),
});
this.services = {
local_storage: RamStorageService,
};
},
}, function () {
QUnit.module('SearchPanel in Kanban views');
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'' +
'',
});
assert.containsOnce(kanban, '.o_content.o_kanban_with_searchpanel > .o_search_panel');
assert.containsOnce(kanban, '.o_content.o_kanban_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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'' +
'',
});
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'' +
'',
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'' +
'' +
'',
});
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'' +
'',
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
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","=",3]]',
'[["bar","=",true],["company_id","=",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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
});
// 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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
mockRPC: function (route, args) {
if (route === '/web/dataset/search_read') {
assert.deepEqual(args.domain, [['company_id', '=', 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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'' +
'',
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","=",3]]',
'[["bar","=",true],["company_id","=",3],["state","=","abc"]]',
'[["bar","=",true],["company_id","=",3],["state","=","ghi"]]',
'[["bar","=",true],["state","=","ghi"]]',
'[["bar","=",true]]',
]);
kanban.destroy();
});
QUnit.test('category with parent_field', async function (assert) {
assert.expect(24);
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
});
// '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);
// fold category with children
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","=",40]]',
'[["company_id","=",5]]',
]);
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
});
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
});
// 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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
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","=",3]]',
'[["bar","=",true],["company_id","=",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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'' +
'',
});
// '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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
});
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'' +
'',
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
});
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
});
// 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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'' +
'',
});
// 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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'' +
'',
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
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: '' +
'' +
'' +
'' +
'
' +
'' +
'' +
'' +
'' +
'',
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();
});
});
});