UNPKG

@luigi-project/testing-utilities

Version:

Luigi testing utilities for standalone testing of microfrontends

236 lines (235 loc) • 9.38 kB
export class LuigiMockUtil { constructor(browser, win) { this.sessionStorageItemName = 'luigiMockData'; this.visualizationContainerId = 'luigi-debug-vis-cnt'; this.messages = []; this.browser = browser; this.win = win; } /** * Parses the elements added by LuigiMockModule into the DOM and assigns them to the local this.messages variable * @returns {Promise<void>} - A Promise that resolves when parsing is complete. */ async parseLuigiMockedMessages() { const window = this.getGlobalThis(); const getTextNodeValues = () => { const debugCtn = window.getElementById(this.visualizationContainerId); return Array.from((debugCtn === null || debugCtn === void 0 ? void 0 : debugCtn.childNodes) || []).map((item) => item.textContent || ''); }; let textElements; try { switch (true) { case 'evaluate' in this.browser: this.browser.evaluate(getTextNodeValues); break; case 'execute' in this.browser: this.browser.execute(getTextNodeValues); break; case 'executeScript' in this.browser: this.browser.executeScript(getTextNodeValues); break; default: this.browser(getTextNodeValues); break; } this.messages = textElements .map((item) => { try { return JSON.parse(item); } catch (error) { return undefined; } }) .filter(item => item !== undefined); } catch (error) { console.debug('Failed to parse luigi mocked messages: ', error); } } /** * Mocks the context by sending luigi context messages with the desired mocked context as parameter. * @param mockContext an object representing the context to be mocked */ mockContext(mockContext) { const window = this.getGlobalThis(); const postMessageToLuigi = (context) => { window.postMessage({ msg: 'luigi.get-context', context }, '*'); return Object.assign(Object.assign({}, context), { windowMessage: 'isPosted' }); }; try { switch (true) { case 'evaluate' in this.browser: this.browser.evaluate(postMessageToLuigi, mockContext); break; case 'execute' in this.browser: this.browser.execute(postMessageToLuigi, mockContext); break; case 'executeScript' in this.browser: this.browser.executeScript(postMessageToLuigi, mockContext); break; default: this.browser(postMessageToLuigi.bind(this, mockContext)); break; } } catch (error) { console.debug('Failed to mock context: ', error); } } /** * This method serves as a mock for the luigi client pathExists() function. * It is used in e2e tests when component being tested utilizes a call to `LuigiClient.linkManager().pathExists()` * * @param path the path to check * @param exists mocked boolean representing if path should exist or not * @example For the following call in your angular component: * `LuigiClient.linkManager().pathExists('pathToCheck')` * * // You need to call the following to mock pathExists() returning `true` for a given 'pathToCheck': * await mockPathExists('pathToCheck', true); * * // You need to call the following to mock pathExists() returning `false` for a given 'pathToCheck': * await mockPathExists('pathToCheck', false); * */ mockPathExists(path, exists) { const window = this.getGlobalThis(); const mockContext = { path, exists }; /** * Sets the path exists mock data in sessionStorage. * @param {string} path - The path for which mock data is to be set. * @param {boolean} exists - Boolean indicating whether the path exists. * @returns {Object} - Object indicating session storage item. */ const setPathExistsMockData = (context) => { window.sessionStorage.clear(); const pathExistsMockData = { pathExists: { [context['path']]: context['exists'] } }; window.sessionStorage.setItem(this.sessionStorageItemName, JSON.stringify(pathExistsMockData)); return Object.assign(Object.assign({}, pathExistsMockData), { sessionItem: 'isStored' }); }; try { switch (true) { case 'evaluate' in this.browser: this.browser.evaluate(setPathExistsMockData, mockContext); break; case 'execute' in this.browser: this.browser.execute(setPathExistsMockData, mockContext); break; case 'executeScript' in this.browser: this.browser.executeScript(setPathExistsMockData, mockContext); break; default: this.browser(setPathExistsMockData.bind(this, mockContext)); break; } } catch (error) { console.debug('Failed to mock path exists: ', error); } } /** * Checks on the printed DOM Luigi message responses for a modal with given title * having been opened. In such a case a message would be printed containing a modal.title. * Returns false if not such element was found. * @param title the title of the modal * @example * Format of the targeted message example: * { * msg: 'luigi.navigation.open', * sessionId: 0, * params: { * preserveView: true, * nodeParams: { mode: 'modal' }, * errorSkipNavigation: false, * fromContext: null, * fromClosestContext: false, * fromVirtualTreeRoot: false, * fromParent: true, * relative: true, * link: 'templates', * intent: false, * modal: { title: 'Create Component from Template' } // element to check * } * } * */ async modalOpenedWithTitle(title) { // parse messages into a readable array await this.parseLuigiMockedMessages(); // traverse the array and find the modal message response // check if its modal option has the title const indexFoundModalMessageWTitle = this.messages.findIndex(message => { const msgExists = message.msg && message.msg === 'luigi.navigation.open' && message.params && message.params.modal && message.params.modal.title; if (msgExists) { return message.params.modal.title === title; } return false; }); if (indexFoundModalMessageWTitle >= 0) { return true; } console.debug('Could not find modal with title: ', title); return false; } /** * Returns output of 'mockContext' method with given data. * @param {Object} context - Object representing the context to be mocked. * @returns {string} - Stringified output of 'mockContext' method. */ getMockedContextOutput(context) { return `{"msg":"luigi.get-context","context":${JSON.stringify(context)}}`; } /** * Returns output of 'mockPathExists' method with given arguments. * @param {string} path - The path for which mock data is to be set. * @param {boolean} exists - Boolean indicating whether the path exists. * @returns {string} - Stringified output of 'mockPathExists' method. */ getMockedPathExistsOutput(path, exists) { return JSON.stringify({ [this.sessionStorageItemName]: { pathExists: { [path]: exists } } }).slice(1, -1); } /** * Returns parsed session storage data used for testing. * @param {Object} data - Object or string representing the data to be cleaned. * @returns {string} - Stringified session storage data. */ getCleanSessionStorageData(data) { if (typeof data === 'string') { data = JSON.parse(data); } return JSON.stringify(data) .replace(/\\/g, '') .replace(/"{/g, '{') .replace(/}"/g, '}'); } /** * Returns ID of Luigi visualization container added in the DOM for testing. * @returns {string} - ID of Luigi visualization container. */ getVisualizationContainerId() { return this.visualizationContainerId; } /** * Returns list of messages, representing message elements added in the DOM for testing. * @returns {Array} - Array of message elements. */ getMSG() { return this.messages; } /** * Returns the global window object. * @returns the global win object */ getGlobalThis() { return this.win || globalThis; } }