import { MfeStyleRegistry } from '../mfe-style-registry'; beforeAll(() => { if (!CSSStyleSheet.prototype.replaceSync) { CSSStyleSheet.prototype.replaceSync = jest.fn(); } }); describe('[web-components] MfeStyleRegistry', () => { const createRoot = () => { const root = document.createElement('div').attachShadow({ mode: 'open' }); root.adoptedStyleSheets = []; return root; }; beforeEach(() => { delete globalThis.__mfeStyles__; }); describe(MfeStyleRegistry.for.name, () => { test('initializes globalThis.__mfeStyles__', () => { MfeStyleRegistry.for('test-mfe'); expect(globalThis.__mfeStyles__).toBeDefined(); }); test('returns the same registry for the same component', () => { const a = MfeStyleRegistry.for('test-mfe'); const b = MfeStyleRegistry.for('test-mfe'); expect(a).toBe(b); }); test('returns different registries for different components', () => { const a = MfeStyleRegistry.for('mfe-a'); const b = MfeStyleRegistry.for('mfe-b'); expect(a).not.toBe(b); }); }); describe('injectSheet', () => { const defaultCss = '.foo { color: red; }'; const defaultSheetId = 'sheet-1'; let registry: MfeStyleRegistry; beforeEach(() => { registry = MfeStyleRegistry.for('test-mfe'); }); const subject = (sheetId = defaultSheetId, css = defaultCss) => registry.injectSheet(sheetId, css); test('creates a new CSSStyleSheet and stores it', () => { subject(); const sheet = registry.sheets.get('sheet-1'); expect(sheet).toBeInstanceOf(CSSStyleSheet); expect(sheet!.replaceSync).toHaveBeenCalledWith(defaultCss); }); test('adopts new sheets into observed roots', () => { const root = createRoot(); registry.observeRoot(root); subject(); expect(root.adoptedStyleSheets).toContain(registry.sheets.get('sheet-1')); }); describe('when sheet with the same ID already exists', () => { beforeEach(() => { subject(); }); test('updates existing sheet in place via replaceSync', () => { const sheet = registry.sheets.get(defaultSheetId)!; const newCSS = '.foo { color: blue; }'; subject(defaultSheetId, newCSS); expect(registry.sheets.get(defaultSheetId)).toBe(sheet); expect(sheet.replaceSync).toHaveBeenLastCalledWith(newCSS); }); }); }); describe('observeRoot', () => { let registry: MfeStyleRegistry; beforeEach(() => { registry = MfeStyleRegistry.for('test-mfe'); }); test('adds root to the roots set', () => { const root = createRoot(); registry.observeRoot(root); expect(registry.roots.has(root)).toBe(true); }); describe('when root is already observed', () => { let root: ShadowRoot; beforeEach(() => { registry.injectSheet('a', '.a {}'); root = createRoot(); registry.observeRoot(root); }); test('does not duplicate sheets', () => { registry.observeRoot(root); expect(root.adoptedStyleSheets).toHaveLength(1); }); }); test('adopts all existing sheets into the root', () => { registry.injectSheet('a', '.a {}'); registry.injectSheet('b', '.b {}'); const root = createRoot(); registry.observeRoot(root); expect(root.adoptedStyleSheets).toEqual([...registry.sheets.values()]); }); }); describe('unobserveRoot', () => { let registry: MfeStyleRegistry; let root: ShadowRoot; beforeEach(() => { registry = MfeStyleRegistry.for('test-mfe'); root = createRoot(); const defaultSheetId = 'sheet-1'; registry.injectSheet(defaultSheetId, '.foo {}'); registry.observeRoot(root); }); test('removes root from the roots set', () => { registry.unobserveRoot(root); expect(registry.roots.has(root)).toBe(false); }); test('removes adopted sheets from the root', () => { registry.unobserveRoot(root); expect(root.adoptedStyleSheets).toHaveLength(0); }); test('stops receiving newly adopted sheets', () => { registry.unobserveRoot(root); registry.injectSheet('sheet-2', '.bar {}'); expect(root.adoptedStyleSheets).toHaveLength(0); }); }); });