import '@testing-library/jest-dom'; import { render, waitFor } from '@testing-library/react'; import { Entries, IWebComponent } from '../common'; import { HeadlessCallback } from '../register-headless'; export function registerComponent( connectedCallback: HeadlessCallback, disconnectedCallback: HeadlessCallback, componentName: string | undefined ) { /* * This register can only happen once, unfortunately. So the connectedCallback and * disconnectedCallback need to work for all tests. If run more than once, * window.customElements.define will throw the error: * "NotSupportedError: This name has already been registered in the registry." * * Also note that there is no way to "unregister" a web component, so an afterAll * cannot be used. */ (global as any).WEB_COMPONENT_NAME = componentName; const { registerHeadless } = require('../register-headless'); registerHeadless(connectedCallback, disconnectedCallback); } describe('[web-components] registerHeadless', () => { const baseComponentName = 'mock-app'; const componentName = `${baseComponentName}-40b38a39`; const connectedCallback = jest.fn().mockName('connectedCallback'); const disconnectedCallback = jest.fn().mockName('disconnectedCallback'); const provideProps = { ldService: 'ld-service', logService: 'log-service', eventBus: 'event-bus', } as unknown as Entries; const mfeData = { foo: 'bar' }; const handleRef = (webComponent: IWebComponent | null) => { webComponent?.provide(provideProps); }; beforeAll(() => { registerComponent(connectedCallback, disconnectedCallback, componentName); }); const subject = (props: Record = {}, dataAttrs: Record = {}) => { jest.spyOn(console, 'error').mockImplementation(jest.fn()); // suppress "attempt to unmount root while rendering" error const data = props && { 'data-mfe-data': JSON.stringify(props) }; const Component: any = `headless-${componentName}`; const renderResult = render(); return renderResult; }; beforeEach(() => { jest.clearAllMocks(); }); [connectedCallback, disconnectedCallback].forEach(callback => { test(`calls ${callback.getMockName()} with mfeData`, async () => { const renderResult = subject({}, { 'data-mfe-data': JSON.stringify(mfeData) }); renderResult.unmount(); await waitFor(() => { expect(callback).toHaveBeenCalledWith( expect.objectContaining({ mfeData, }) ); }); }); }); [connectedCallback, disconnectedCallback].forEach(callback => { (['ldService', 'logService', 'eventBus'] as const).forEach(service => { test(`calls ${callback.getMockName()} with ${service}`, async () => { const renderResult = subject(); renderResult.unmount(); await waitFor(() => { expect(callback).toHaveBeenCalledWith( expect.objectContaining({ [service]: provideProps[service], }) ); }); }); }); }); test('logs an error when WEB_COMPONENT_NAME is not set', () => { const consoleSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn()); jest.isolateModules(() => { registerComponent(connectedCallback, disconnectedCallback, undefined); }); expect(consoleSpy).toHaveBeenCalledWith('"WEB_COMPONENT_NAME" is not defined!'); }); });