odoo.define('web.control_panel_mobile_tests', function (require) {
"use strict";
const FormView = require('web.FormView');
const testUtils = require('web.test_utils');
const cpHelpers = require('@web/../tests/search/helpers');
const { browser } = require("@web/core/browser/browser");
const { patchWithCleanup, getFixture } = require("@web/../tests/helpers/utils");
const { createControlPanel, createView } = testUtils;
const { createWebClient, doAction, getActionManagerServerData } = require('@web/../tests/webclient/helpers');
let serverData;
let target;
QUnit.module('Control Panel', {
beforeEach: function () {
target = getFixture();
this.actions = [{
id: 1,
name: "Yes",
res_model: 'partner',
type: 'ir.actions.act_window',
views: [[false, 'list']],
}];
this.archs = {
'partner,false,list': '',
'partner,false,search': `
`,
};
this.data = {
partner: {
fields: {
foo: { string: "Foo", type: "char" },
boolean_field: { string: "I am a boolean", type: "boolean" },
},
records: [
{ id: 1, display_name: "First record", foo: "yop" },
],
},
};
const actions = {};
this.actions.forEach((act) => {
actions[act.xml_id || act.id] = act;
});
serverData = getActionManagerServerData();
Object.assign(serverData, { models: this.data, views: this.archs, actions });
patchWithCleanup(browser, {
setTimeout: (fn) => fn(),
clearTimeout: () => {},
});
},
}, function () {
QUnit.test('basic rendering', async function (assert) {
assert.expect(2);
const webClient = await createWebClient({serverData});
await doAction(webClient, 1);
assert.containsNone(target, '.o_control_panel .o_mobile_search',
"search options are hidden by default");
assert.containsOnce(target, '.o_control_panel .o_enable_searchview',
"should display a button to toggle the searchview");
});
QUnit.test("control panel appears at top on scroll event", async function (assert) {
assert.expect(12);
const MAX_HEIGHT = 800;
const MIDDLE_HEIGHT = 400;
const DELTA_TEST = 20;
const form = await createView({
View: FormView,
arch:
'
',
data: this.data,
model: 'partner',
res_id: 1,
});
const controlPanelEl = document.querySelector('.o_control_panel');
const controlPanelHeight = controlPanelEl.offsetHeight;
// Force container to have a scrollbar
controlPanelEl.parentElement.style.maxHeight = `${MAX_HEIGHT}px`;
const scrollAndAssert = async (targetHeight, expectedTopValue, hasStickyClass) => {
if (targetHeight !== null) {
controlPanelEl.parentElement.scrollTo(0, targetHeight);
await testUtils.nextTick();
}
const expectedPixelValue = `${expectedTopValue}px`;
assert.strictEqual(controlPanelEl.style.top, expectedPixelValue,
`Top must be ${expectedPixelValue} (after scroll to ${targetHeight})`);
if (hasStickyClass) {
assert.hasClass(controlPanelEl, 'o_mobile_sticky');
} else {
assert.doesNotHaveClass(controlPanelEl, 'o_mobile_sticky');
}
}
// Initial position (scrollTop: 0)
await scrollAndAssert(null, 0, false);
// Scroll down 800px (scrollTop: 800)
await scrollAndAssert(MAX_HEIGHT, -controlPanelHeight, true);
// Scoll up 20px (scrollTop: 780)
await scrollAndAssert(MAX_HEIGHT - DELTA_TEST, -controlPanelHeight + DELTA_TEST, true);
// Scroll up 380px (scrollTop: 400)
await scrollAndAssert(MIDDLE_HEIGHT, 0, true);
// Scroll down 200px (scrollTop: 800)
await scrollAndAssert(MAX_HEIGHT, -controlPanelHeight, true);
// Scroll up 400px (scrollTop: 0)
await scrollAndAssert(0, -controlPanelHeight, false);
form.destroy();
});
QUnit.test("mobile search: basic display", async function (assert) {
assert.expect(4);
const fields = {
birthday: { string: "Birthday", type: "date", store: true, sortable: true },
};
const searchMenuTypes = ["filter", "groupBy", "comparison", "favorite"];
const params = {
cpModelConfig: {
arch: `
`,
fields,
searchMenuTypes,
},
cpProps: { fields, searchMenuTypes },
};
const controlPanel = await createControlPanel(params);
// Toggle search bar controls
await testUtils.dom.click(controlPanel.el.querySelector("button.o_enable_searchview"));
// Open search view
await testUtils.dom.click(controlPanel.el.querySelector("button.o_toggle_searchview_full"));
// Toggle filter date
// Note: 'document.body' is used instead of 'controlPanel' because the
// search view is directly in the body.
await cpHelpers.toggleFilterMenu(document);
await cpHelpers.toggleMenuItem(document, "Birthday");
await cpHelpers.toggleMenuItemOption(document, "Birthday", 0);
assert.containsOnce(document.body, ".o_filter_menu");
assert.containsOnce(document.body, ".o_group_by_menu");
assert.containsOnce(document.body, ".o_comparison_menu");
assert.containsOnce(document.body, ".o_favorite_menu");
});
QUnit.test('mobile search: activate a filter through quick search', async function (assert) {
assert.expect(7);
let searchRPCFlag = false;
const mockRPC = (route, args) => {
if (searchRPCFlag && args.method === "web_search_read") {
assert.deepEqual(args.kwargs.domain, [['foo', 'ilike', 'A']],
"domain should have been properly transferred to list view");
}
};
const webClient = await createWebClient({serverData, mockRPC});
await doAction(webClient, 1);
assert.containsOnce(document.body, 'button.o_enable_searchview.oi-search',
"should display a button to open the searchview");
assert.containsNone(document.body, '.o_searchview_input_container',
"Quick search input should be hidden");
// open the search view
await testUtils.dom.click(document.querySelector('button.o_enable_searchview'));
assert.containsOnce(document.body, '.o_toggle_searchview_full',
"should display a button to expand the searchview");
assert.containsOnce(document.body, '.o_searchview_input_container',
"Quick search input should now be visible");
searchRPCFlag = true;
// use quick search input (search view is directly put in the body)
await cpHelpers.editSearch(document.body, "A");
await cpHelpers.validateSearch(document.body);
// close quick search
await testUtils.dom.click(document.querySelector('button.o_enable_searchview.fa-arrow-left'));
assert.containsNone(document.body, '.o_toggle_searchview_full',
"Expand icon shoud be hidden");
assert.containsNone(document.body, '.o_searchview_input_container',
"Quick search input should be hidden");
});
QUnit.test('mobile search: activate a filter in full screen search view', async function (assert) {
assert.expect(3);
const webClient = await createWebClient({ serverData });
await doAction(webClient, 1);
assert.containsNone(document.body, '.o_mobile_search');
// open the search view
await testUtils.dom.click(target.querySelector('button.o_enable_searchview'));
// open it in full screen
await testUtils.dom.click(target.querySelector('.o_toggle_searchview_full'));
assert.containsOnce(document.body, '.o_mobile_search');
await cpHelpers.toggleFilterMenu(document.body);
await cpHelpers.toggleMenuItem(document.body, "Active");
// closing search view
await testUtils.dom.click(
[...document.querySelectorAll('.o_mobile_search_button')].find(
e => e.innerText.trim() === "FILTER"
)
);
assert.containsNone(document.body, '.o_mobile_search');
});
});
});