99 lines
3.6 KiB
TypeScript
99 lines
3.6 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import type { Notification } from '../../../src/config/schema/actions/types';
|
|
import { createLitElement, flushPromises } from '../../test-utils';
|
|
|
|
// @vitest-environment jsdom
|
|
describe('NotificationContextController', () => {
|
|
// Each test re-imports the controller after resetting the module registry so its
|
|
// module-level `js-yaml` singleton starts unloaded.
|
|
const loadController = async () => {
|
|
const module = await import(
|
|
'../../../src/components-lib/notification/notification-context-controller'
|
|
);
|
|
return module.NotificationContextController;
|
|
};
|
|
|
|
const createNotification = (context?: Notification['context']): Notification => ({
|
|
body: { text: 'oops' },
|
|
...(context && { context }),
|
|
});
|
|
|
|
beforeEach(() => {
|
|
vi.resetModules();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.restoreAllMocks();
|
|
vi.doUnmock('js-yaml');
|
|
});
|
|
|
|
it('should return an empty array when the notification has no context', async () => {
|
|
const NotificationContextController = await loadController();
|
|
const controller = new NotificationContextController(createLitElement());
|
|
|
|
expect(controller.getContext(createNotification())).toEqual([]);
|
|
});
|
|
|
|
it('should return string context items unchanged without loading the library', async () => {
|
|
const NotificationContextController = await loadController();
|
|
const host = createLitElement();
|
|
const controller = new NotificationContextController(host);
|
|
|
|
expect(controller.getContext(createNotification(['line one', 'line two']))).toEqual([
|
|
'line one',
|
|
'line two',
|
|
]);
|
|
expect(host.requestUpdate).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('should YAML-dump object context items once the library has loaded', async () => {
|
|
const NotificationContextController = await loadController();
|
|
const host = createLitElement();
|
|
const controller = new NotificationContextController(host);
|
|
const notification = createNotification([{ foo: 'bar' }]);
|
|
|
|
// The library is not yet loaded, so the first render defers.
|
|
expect(controller.getContext(notification)).toEqual([]);
|
|
|
|
await vi.waitFor(() => expect(host.requestUpdate).toHaveBeenCalled());
|
|
|
|
const result = controller.getContext(notification);
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0]).toContain('foo: bar');
|
|
});
|
|
|
|
it('should defer the whole context until the library loads when any item is an object', async () => {
|
|
const NotificationContextController = await loadController();
|
|
const host = createLitElement();
|
|
const controller = new NotificationContextController(host);
|
|
const notification = createNotification(['plain string', { foo: 'bar' }]);
|
|
|
|
expect(controller.getContext(notification)).toEqual([]);
|
|
|
|
await vi.waitFor(() => expect(host.requestUpdate).toHaveBeenCalled());
|
|
|
|
const result = controller.getContext(notification);
|
|
expect(result[0]).toBe('plain string');
|
|
expect(result[1]).toContain('foo: bar');
|
|
});
|
|
|
|
it('should swallow a failed library load and render without the dumped context', async () => {
|
|
vi.doMock('js-yaml', () => {
|
|
throw new Error('chunk load failed');
|
|
});
|
|
const NotificationContextController = await loadController();
|
|
const host = createLitElement();
|
|
const controller = new NotificationContextController(host);
|
|
const notification = createNotification([{ foo: 'bar' }]);
|
|
|
|
expect(controller.getContext(notification)).toEqual([]);
|
|
|
|
// Allow the rejected dynamic import to settle.
|
|
await flushPromises();
|
|
|
|
expect(host.requestUpdate).not.toHaveBeenCalled();
|
|
expect(controller.getContext(notification)).toEqual([]);
|
|
});
|
|
});
|