UNPKG

@luigi-project/testing-utilities

Version:

Luigi testing utilities for standalone testing of microfrontends

153 lines (152 loc) 7.74 kB
/* * This class mocks Luigi Core related functionality. * * Micro Frontends that use Luigi Client would usually communicate with Luigi Core * back and forth. When testing Luigi Client based components, Luigi Core might * not be present which leads into limitations on integration/e2e testing for standalone * microfrontends. * * This module adds a hook to the window postMessage API by adding an event listener to the * global message event of the window object and mocking the callback. * In the normal workflow this message would picked up by Luigi Core which then sends the response back. */ export class LuigiMockEngine { // Add a hook to the post message api to mock the LuigiCore response to the Client static initPostMessageHook() { return async () => { // Check if Luigi Client is running standalone if (window.parent === window) { console.debug('Detected standalone mode'); // Check and skip if Luigi environment is already mocked if (window.luigiMockEnvironment) { return; } // mock target origin if (window.LuigiClient) { window.LuigiClient.setTargetOrigin('*'); } window.luigiMockEnvironment = { msgListener: function (e) { if (e.data.msg && (e.data.msg.startsWith('luigi.') || e.data.msg === 'storage')) { if (e.data.msg === 'luigi.get-context') { window.postMessage({ msg: 'luigi.init', emulated: true, internal: { viewStackSize: 1 }, context: e.data.context }, '*'); } // vizualise retrieved event data LuigiMockEngine.visualize(JSON.stringify(e.data)); // Check and run mocked callback if it exists const mockListener = window.luigiMockEnvironment.mockListeners[e.data.msg]; if (mockListener) { mockListener(e); } } }, mockListeners: { 'luigi.navigation.pathExists': (event) => { const mockData = window.sessionStorage.getItem('luigiMockData'); let mockDataParsed = mockData ? JSON.parse(mockData) : undefined; const inputPath = event.data.data.link; const pathExists = mockDataParsed && mockDataParsed.pathExists && mockDataParsed.pathExists[inputPath]; const response = { msg: 'luigi.navigation.pathExists.answer', data: { correlationId: event.data.data.id, pathExists: pathExists ? pathExists : false }, emulated: true }; window.postMessage(response, '*'); }, //ux 'luigi.ux.confirmationModal.show': (event) => { const response = { msg: 'luigi.ux.confirmationModal.hide', data: event.data, emulated: true }; window.postMessage(response, '*'); }, 'luigi.ux.alert.show': (event) => { const response = { msg: 'luigi.ux.alert.hide', data: event.data, emulated: true }; window.postMessage(response, '*'); }, 'luigi.ux.set-current-locale': (event) => { const response = { msg: 'luigi.current-locale-changed', currentLocale: event.data.data.currentLocale, emulated: true }; window.postMessage(response, '*'); }, // linkManager 'luigi.navigation.open': (event) => { const response = { msg: 'luigi.navigate.ok', data: event.data, emulated: true }; window.postMessage(response, '*'); }, 'luigi.navigation.splitview.close': (event) => { const response = { msg: 'luigi.navigate.ok', data: event.data, emulated: true }; window.postMessage(response, '*'); }, 'luigi.navigation.splitview.collapse': (event) => { const response = { msg: 'luigi.navigate.ok', data: event.data, emulated: true }; window.postMessage(response, '*'); }, 'luigi.navigation.splitview.expand': (event) => { const response = { msg: 'luigi.navigate.ok', data: event.data, emulated: true }; window.postMessage(response, '*'); }, // storage storage: () => { } } }; // Listen to the global 'message' event of the window object window.addEventListener('message', window.luigiMockEnvironment.msgListener); } }; } /* * This method takes a data object of type 'any' and vizualizes a simple container * which holds data that is useful for e2e testing. */ static visualize(data) { const visualizationContainerId = 'luigi-debug-vis-cnt'; const dataWrapper = document.createElement('div'); let luigiVisualizationContainer = document.querySelector('#' + visualizationContainerId); // Construct element structure if not already constructed if (!luigiVisualizationContainer) { luigiVisualizationContainer = document.createElement('div'); luigiVisualizationContainer.setAttribute('id', visualizationContainerId); // Hide the added DOM element to avoid interferring/overlapping with other elements during testing. luigiVisualizationContainer.setAttribute('style', 'display:none'); document.body.appendChild(luigiVisualizationContainer); } dataWrapper.textContent = data; luigiVisualizationContainer.appendChild(dataWrapper); } }