import * as React from 'react'; import { mocked } from 'jest-mock'; import { act, render } from '@testing-library/react'; import type { ExtensionDescriptor } from '@atlassian/clientside-extensions-registry'; import registry from '@atlassian/clientside-extensions-registry'; import { ErrorLevels } from '@atlassian/clientside-extensions-schema'; import type { Validator } from '@atlassian/clientside-extensions-schema'; import * as debug from '@atlassian/clientside-extensions-debug'; import ExtensionPoint from './ExtensionPoint'; jest.mock('@atlassian/clientside-extensions-registry'); debug.setLoggingEnabled(true); debug.setDebugEnabled(true); // avoid spamming the console with error/warn messages // eslint-disable-next-line no-underscore-dangle debug._deregisterDefaultLogger(); type MockSubjectPayload = { descriptors: ExtensionDescriptor[]; loadingState: boolean; }; type MockLocationObserver = (payload: MockSubjectPayload) => void; const supportedExtension: ExtensionDescriptor = { key: 'fake-1', location: 'fake-location', weight: 10, attributes: { label: 'a fake label', type: 'button' }, }; const unsupportedExtension: ExtensionDescriptor = { key: 'fake-2', location: 'fake-location', weight: 10, attributes: { label: 'a fake label' }, }; const validate: Validator = (input) => { const { type } = input as { type: string }; return type ? { errors: [], warnings: [], } : { errors: [ { error: 'error', severity: ErrorLevels.ERROR, }, ], warnings: [], }; }; /** * Only testing the runtime error of a wrong child provided and that the component is using the right hook. * The rest of the tests are in useExtensions.tests. */ describe('ExtensionPoint component', () => { it('should not render if the child provided is not a callback', async () => { const onDebugSpy = jest.fn(); debug.observeLogger(onDebugSpy); mocked(registry.getLocation).mockImplementation(() => ({ subscribe: () => { return { unsubscribe: () => {}, }; }, })); const TestComponent = () => { return ( // @ts-expect-error - forcing ts to ignore assigning a wrong child type to execute JS runtime validation Wrong child; ); }; const { container } = render(); expect(container.firstChild).toBe(null); // nothing rendered by the component expect(onDebugSpy).toHaveBeenCalledTimes(1); }); it('should provide all the extensions information to the child callback', () => { let locationObserver: MockLocationObserver; mocked(registry.getLocation).mockImplementation(() => ({ subscribe: (observer) => { locationObserver = observer; return { unsubscribe: () => {}, }; }, })); const TestComponent = () => { return ( {(supportedExtensions, unsupportedExtensions, isLoading) => ( <> {JSON.stringify(isLoading)} {JSON.stringify(supportedExtensions)} {JSON.stringify(unsupportedExtensions)} > )} ); }; const { asFragment } = render(); expect(asFragment()).toMatchSnapshot('loading state'); act(() => { locationObserver({ descriptors: [supportedExtension, unsupportedExtension], loadingState: false }); }); expect(asFragment()).toMatchSnapshot('with extensions state'); }); });
Wrong child
{JSON.stringify(isLoading)}
{JSON.stringify(supportedExtensions)}
{JSON.stringify(unsupportedExtensions)}