Odoo18-Base/addons/web/static/tests/legacy/helpers/test_utils.js
2025-03-10 11:12:23 +07:00

278 lines
12 KiB
JavaScript

odoo.define('web.test_utils', async function (require) {
"use strict";
/**
* Test Utils
*
* In this module, we define various utility functions to help simulate a mock
* environment as close as possible as a real environment. The main function is
* certainly createView, which takes a bunch of parameters and give you back an
* instance of a view, appended in the dom, ready to be tested.
*/
const relationalFields = require('web.relational_fields');
const session = require('web.session');
const testUtilsCreate = require('web.test_utils_create');
const testUtilsControlPanel = require('web.test_utils_control_panel');
const testUtilsDom = require('web.test_utils_dom');
const testUtilsFields = require('web.test_utils_fields');
const testUtilsFile = require('web.test_utils_file');
const testUtilsForm = require('web.test_utils_form');
const testUtilsGraph = require('web.test_utils_graph');
const testUtilsKanban = require('web.test_utils_kanban');
const testUtilsMock = require('web.test_utils_mock');
const testUtilsModal = require('web.test_utils_modal');
const testUtilsPivot = require('web.test_utils_pivot');
const tools = require('web.tools');
function deprecated(fn, type) {
const msg = `Helper 'testUtils.${fn.name}' is deprecated. ` +
`Please use 'testUtils.${type}.${fn.name}' instead.`;
return tools.deprecated(fn, msg);
}
/**
* Helper function, make a promise with a public resolve function. Note that
* this is not standard and should not be used outside of tests...
*
* @returns {Promise + resolve and reject function}
*/
function makeTestPromise() {
let resolve;
let reject;
const promise = new Promise(function (_resolve, _reject) {
resolve = _resolve;
reject = _reject;
});
promise.resolve = function () {
resolve.apply(null, arguments);
return promise;
};
promise.reject = function () {
reject.apply(null, arguments);
return promise;
};
return promise;
}
/**
* Make a promise with public resolve and reject functions (see
* @makeTestPromise). Perform an assert.step when the promise is
* resolved/rejected.
*
* @param {Object} assert instance object with the assertion methods
* @param {function} assert.step
* @param {string} str message to pass to assert.step
* @returns {Promise + resolve and reject function}
*/
function makeTestPromiseWithAssert(assert, str) {
const prom = makeTestPromise();
prom.then(() => assert.step('ok ' + str)).catch(function () { });
prom.catch(() => assert.step('ko ' + str));
return prom;
}
/**
* Create a new promise that can be waited by the caller in order to execute
* code after the next microtask tick and before the next jobqueue tick.
*
* @return {Promise} an already fulfilled promise
*/
async function nextMicrotaskTick() {
return Promise.resolve();
}
/**
* Returns a promise that will be resolved after the tick after the
* nextAnimationFrame
*
* This is usefull to guarantee that OWL has had the time to render
*
* @returns {Promise}
*/
async function nextTick() {
return testUtilsDom.returnAfterNextAnimationFrame();
}
/**
* Awaits for an additionnal rendering frame initiated by the Owl
* compatibility layer processing.
*
* By default a simple "nextTick" will handle the rendering of any widget/
* component stuctures having at most 1 switch between the type of
* entities (Component > Widget or Widget > Component). However more time
* must be spent rendering in case we have additionnal switches. In such
* cases this function must be used (1 call for each additionnal switch)
* since it will be removed along with the compatiblity layer once the
* framework has been entirely converted, and using this helper will make
* it easier to wipe it from the code base.
*
* @returns {Promise}
*/
async function owlCompatibilityExtraNextTick() {
return testUtilsDom.returnAfterNextAnimationFrame();
}
// Loading static files cannot be properly simulated when their real content is
// really needed. This is the case for static XML files so we load them here,
// before starting the qunit test suite.
// (session.js is in charge of loading the static xml bundle and we also have
// to load xml files that are normally lazy loaded by specific widgets).
// Assets can also contain static xml files. They are loaded when the session
// is launched.
await session.is_bound;
setTimeout(function () {
// jquery autocomplete refines the search in a setTimeout() parameterized
// with a delay, so we force this delay to 0 s.t. the dropdown is filtered
// directly on the next tick
relationalFields.FieldMany2One.prototype.AUTOCOMPLETE_DELAY = 0;
}, 0);
return {
mock: {
addMockEnvironment: testUtilsMock.addMockEnvironment,
addMockEnvironmentOwl: testUtilsMock.addMockEnvironmentOwl,
intercept: testUtilsMock.intercept,
patch: testUtilsMock.patch,
patchDate: testUtilsMock.patchDate,
unpatch: testUtilsMock.unpatch,
getView: testUtilsMock.getView,
patchSetTimeout: testUtilsMock.patchSetTimeout,
},
controlPanel: {
// Generic interactions
toggleMenu: testUtilsControlPanel.toggleMenu,
toggleMenuItem: testUtilsControlPanel.toggleMenuItem,
toggleMenuItemOption: testUtilsControlPanel.toggleMenuItemOption,
isItemSelected: testUtilsControlPanel.isItemSelected,
isOptionSelected: testUtilsControlPanel.isOptionSelected,
getMenuItemTexts: testUtilsControlPanel.getMenuItemTexts,
// Button interactions
getButtons: testUtilsControlPanel.getButtons,
// FilterMenu interactions
toggleFilterMenu: testUtilsControlPanel.toggleFilterMenu,
toggleAddCustomFilter: testUtilsControlPanel.toggleAddCustomFilter,
applyFilter: testUtilsControlPanel.applyFilter,
addCondition: testUtilsControlPanel.addCondition,
// GroupByMenu interactions
toggleGroupByMenu: testUtilsControlPanel.toggleGroupByMenu,
toggleAddCustomGroup: testUtilsControlPanel.toggleAddCustomGroup,
selectGroup: testUtilsControlPanel.selectGroup,
applyGroup: testUtilsControlPanel.applyGroup,
// FavoriteMenu interactions
toggleFavoriteMenu: testUtilsControlPanel.toggleFavoriteMenu,
toggleSaveFavorite: testUtilsControlPanel.toggleSaveFavorite,
editFavoriteName: testUtilsControlPanel.editFavoriteName,
saveFavorite: testUtilsControlPanel.saveFavorite,
deleteFavorite: testUtilsControlPanel.deleteFavorite,
// ComparisonMenu interactions
toggleComparisonMenu: testUtilsControlPanel.toggleComparisonMenu,
// SearchBar interactions
getFacetTexts: testUtilsControlPanel.getFacetTexts,
removeFacet: testUtilsControlPanel.removeFacet,
editSearch: testUtilsControlPanel.editSearch,
validateSearch: testUtilsControlPanel.validateSearch,
// Action menus interactions
toggleActionMenu: testUtilsControlPanel.toggleActionMenu,
// Pager interactions
pagerPrevious: testUtilsControlPanel.pagerPrevious,
pagerNext: testUtilsControlPanel.pagerNext,
getPagerValue: testUtilsControlPanel.getPagerValue,
getPagerSize: testUtilsControlPanel.getPagerSize,
setPagerValue: testUtilsControlPanel.setPagerValue,
// View switcher
switchView: testUtilsControlPanel.switchView,
},
dom: {
triggerKeypressEvent: testUtilsDom.triggerKeypressEvent,
triggerMouseEvent: testUtilsDom.triggerMouseEvent,
triggerPositionalMouseEvent: testUtilsDom.triggerPositionalMouseEvent,
triggerPositionalTapEvents: testUtilsDom.triggerPositionalTapEvents,
dragAndDrop: testUtilsDom.dragAndDrop,
find: testUtilsDom.findItem,
getNode: testUtilsDom.getNode,
openDatepicker: testUtilsDom.openDatepicker,
click: testUtilsDom.click,
clickFirst: testUtilsDom.clickFirst,
clickLast: testUtilsDom.clickLast,
triggerEvents: testUtilsDom.triggerEvents,
triggerEvent: testUtilsDom.triggerEvent,
},
form: {
clickEdit: testUtilsForm.clickEdit,
clickSave: testUtilsForm.clickSave,
clickCreate: testUtilsForm.clickCreate,
clickDiscard: testUtilsForm.clickDiscard,
reload: testUtilsForm.reload,
},
graph: {
reload: testUtilsGraph.reload,
},
kanban: {
reload: testUtilsKanban.reload,
clickCreate: testUtilsKanban.clickCreate,
quickCreate: testUtilsKanban.quickCreate,
toggleGroupSettings: testUtilsKanban.toggleGroupSettings,
toggleRecordDropdown: testUtilsKanban.toggleRecordDropdown,
},
modal: {
clickButton: testUtilsModal.clickButton,
},
pivot: {
clickMeasure: testUtilsPivot.clickMeasure,
toggleMeasuresDropdown: testUtilsPivot.toggleMeasuresDropdown,
reload: testUtilsPivot.reload,
},
fields: {
many2one: {
createAndEdit: testUtilsFields.clickM2OCreateAndEdit,
clickOpenDropdown: testUtilsFields.clickOpenM2ODropdown,
clickHighlightedItem: testUtilsFields.clickM2OHighlightedItem,
clickItem: testUtilsFields.clickM2OItem,
searchAndClickItem: testUtilsFields.searchAndClickM2OItem,
},
editInput: testUtilsFields.editInput,
editSelect: testUtilsFields.editSelect,
editAndTrigger: testUtilsFields.editAndTrigger,
triggerKey: testUtilsFields.triggerKey,
triggerKeydown: testUtilsFields.triggerKeydown,
triggerKeyup: testUtilsFields.triggerKeyup,
},
file: {
createFile: testUtilsFile.createFile,
dragoverFile: testUtilsFile.dragoverFile,
dropFile: testUtilsFile.dropFile,
dropFiles: testUtilsFile.dropFiles,
inputFiles: testUtilsFile.inputFiles,
},
createComponent: testUtilsCreate.createComponent,
createControlPanel: testUtilsCreate.createControlPanel,
createAsyncView: testUtilsCreate.createView,
createCalendarView: testUtilsCreate.createCalendarView,
createView: testUtilsCreate.createView,
createModel: testUtilsCreate.createModel,
createParent: testUtilsCreate.createParent,
makeTestPromise: makeTestPromise,
makeTestPromiseWithAssert: makeTestPromiseWithAssert,
nextMicrotaskTick: nextMicrotaskTick,
nextTick: nextTick,
owlCompatibilityExtraNextTick,
prepareTarget: testUtilsCreate.prepareTarget,
returnAfterNextAnimationFrame: testUtilsDom.returnAfterNextAnimationFrame,
// backward-compatibility
addMockEnvironment: deprecated(testUtilsMock.addMockEnvironment, 'mock'),
dragAndDrop: deprecated(testUtilsDom.dragAndDrop, 'dom'),
getView: deprecated(testUtilsMock.getView, 'mock'),
intercept: deprecated(testUtilsMock.intercept, 'mock'),
openDatepicker: deprecated(testUtilsDom.openDatepicker, 'dom'),
patch: deprecated(testUtilsMock.patch, 'mock'),
patchDate: deprecated(testUtilsMock.patchDate, 'mock'),
triggerKeypressEvent: deprecated(testUtilsDom.triggerKeypressEvent, 'dom'),
triggerMouseEvent: deprecated(testUtilsDom.triggerMouseEvent, 'dom'),
triggerPositionalMouseEvent: deprecated(testUtilsDom.triggerPositionalMouseEvent, 'dom'),
unpatch: deprecated(testUtilsMock.unpatch, 'mock'),
};
});