import { cleanupGlobals, expectedBlock, expectedInline, setupDOM, } from './helpers'; import { defineIconifyIcon, IconifyIconHTMLElement } from '../src/component'; import type { IconState } from '../src/state'; export declare interface DebugIconifyIconHTMLElement extends IconifyIconHTMLElement { // Internal stuff, used for debugging _shadowRoot: ShadowRoot; _state: IconState; } describe('Testing icon component', () => { afterEach(cleanupGlobals); it('Registering component', () => { // Setup DOM const doc = setupDOM('').window.document; // Make sure component does not exist and registry is available expect(window.customElements).toBeDefined(); expect(window.customElements.get('iconify-icon')).toBeUndefined(); // Define component const IconifyIcon = defineIconifyIcon(); expect(IconifyIcon).toBeDefined(); expect(window.customElements.get('iconify-icon')).toBeDefined(); // Create element const node = document.createElement( 'iconify-icon' ) as DebugIconifyIconHTMLElement; expect(node instanceof IconifyIcon).toBe(true); // Define component again (should return previous class) const IconifyIcon2 = defineIconifyIcon(); expect(IconifyIcon2).toBe(IconifyIcon); // Create another element const node2 = document.createElement( 'iconify-icon' ) as DebugIconifyIconHTMLElement; expect(node2 instanceof IconifyIcon).toBe(true); }); it('Creating component instance, changing properties', () => { // Setup DOM const doc = setupDOM('').window.document; // Make sure component does not exist and registry is available expect(window.customElements).toBeDefined(); expect(window.customElements.get('iconify-icon')).toBeUndefined(); // Define component const IconifyIcon = defineIconifyIcon(); expect(IconifyIcon).toBeDefined(); expect(window.customElements.get('iconify-icon')).toBeDefined(); // Create element const node = document.createElement( 'iconify-icon' ) as DebugIconifyIconHTMLElement; // Should be empty expect(node._shadowRoot.innerHTML).toBe( `` ); // Check for dynamically added methods expect(typeof node.loadIcon).toBe('function'); expect(typeof IconifyIcon.loadIcon).toBe('function'); // Set icon node.icon = { body: '', }; expect(node.icon).toEqual({ body: '', }); expect(node.getAttribute('icon')).toBe( JSON.stringify({ body: '', }) ); // Should render SVG const blankSVG = ''; expect(node._shadowRoot.innerHTML).toBe( `${blankSVG}` ); // Check inline attribute expect(node.inline).toBe(false); expect(node.getAttribute('inline')).toBe(null); // Change inline node.inline = true; expect(node.inline).toBe(true); expect(node.getAttribute('inline')).toBe('true'); expect(node._shadowRoot.innerHTML).toBe( `${blankSVG}` ); }); it('Testing changes to inline', () => { // Setup DOM const doc = setupDOM('').window.document; // Make sure component does not exist and registry is available expect(window.customElements).toBeDefined(); expect(window.customElements.get('iconify-icon')).toBeUndefined(); // Define component const IconifyIcon = defineIconifyIcon(); expect(IconifyIcon).toBeDefined(); expect(window.customElements.get('iconify-icon')).toBeDefined(); // Create element const node = document.createElement( 'iconify-icon' ) as DebugIconifyIconHTMLElement; // Should be empty with block style expect(node._shadowRoot.innerHTML).toBe( `` ); // Check inline expect(node.inline).toBe(false); expect(node.hasAttribute('inline')).toBe(false); expect(node.getAttribute('inline')).toBeFalsy(); // Change to inline via property node.inline = true; expect(node._shadowRoot.innerHTML).toBe( `` ); expect(node.inline).toBe(true); expect(node.hasAttribute('inline')).toBe(true); expect(node.getAttribute('inline')).toBeTruthy(); // Change to block by removing attribute node.removeAttribute('inline'); expect(node._shadowRoot.innerHTML).toBe( `` ); expect(node.inline).toBe(false); expect(node.hasAttribute('inline')).toBe(false); expect(node.getAttribute('inline')).toBeFalsy(); // Change to inline by setting attribute node.setAttribute('inline', 'inline'); expect(node._shadowRoot.innerHTML).toBe( `` ); expect(node.inline).toBe(true); expect(node.hasAttribute('inline')).toBe(true); expect(node.getAttribute('inline')).toBeTruthy(); }); it('Restarting animation', async () => { // Setup DOM const doc = setupDOM('').window.document; // Make sure component does not exist and registry is available expect(window.customElements).toBeDefined(); expect(window.customElements.get('iconify-icon')).toBeUndefined(); // Define component expect(defineIconifyIcon()).toBeDefined(); expect(window.customElements.get('iconify-icon')).toBeDefined(); // Create element const node = document.createElement( 'iconify-icon' ) as DebugIconifyIconHTMLElement; // Set icon const body = ''; node.icon = { body, }; expect(node.icon).toEqual({ body, }); expect(node.getAttribute('icon')).toBe( JSON.stringify({ body, }) ); // Should render SPAN, with comment const renderedIconWithComment = ""; const html1 = node._shadowRoot.innerHTML; expect(html1.replace(/-- [0-9]+ --/, '-- --')).toBe( `${renderedIconWithComment}` ); // Restart animation, test icon again node.restartAnimation(); const html2 = node._shadowRoot.innerHTML; expect(html2).not.toBe(html1); expect(html2.replace(/-- [0-9]+ --/, '-- --')).toBe( `${renderedIconWithComment}` ); // Small delay to make sure timer is increased to get new number await new Promise((fulfill) => { setTimeout(fulfill, 10); }); // Restart animation again, test icon again node.restartAnimation(); const html3 = node._shadowRoot.innerHTML; expect(html3.replace(/-- [0-9]+ --/, '-- --')).toBe( `${renderedIconWithComment}` ); expect(html3).not.toBe(html1); expect(html3).not.toBe(html2); }); it('Restarting animation for SVG', () => { // Setup DOM const doc = setupDOM('').window.document; // Make sure component does not exist and registry is available expect(window.customElements).toBeDefined(); expect(window.customElements.get('iconify-icon')).toBeUndefined(); // Define component expect(defineIconifyIcon()).toBeDefined(); expect(window.customElements.get('iconify-icon')).toBeDefined(); // Create element const node = document.createElement( 'iconify-icon' ) as DebugIconifyIconHTMLElement; // Set icon const body = ''; node.mode = 'svg'; node.icon = { body, }; expect(node.icon).toEqual({ body, }); expect(node.getAttribute('icon')).toBe( JSON.stringify({ body, }) ); // Should render SVG const renderedIcon = ''; const html1 = node._shadowRoot.innerHTML; const svg1 = node._shadowRoot.lastChild as SVGSVGElement; const setCurrentTimeSupported = !!svg1.setCurrentTime; expect(html1).toBe(`${renderedIcon}`); expect(svg1.outerHTML).toBe(renderedIcon); // Restart animation, test icon again node.restartAnimation(); const html2 = node._shadowRoot.innerHTML; const svg2 = node._shadowRoot.lastChild as SVGSVGElement; expect(html2).toBe(html1); expect(svg2.outerHTML).toBe(renderedIcon); // Node should be different because JSDOM does not support setCurrentTime(), but that might change in future if (setCurrentTimeSupported) { expect(svg2).toBe(svg1); } else { expect(svg2).not.toBe(svg1); } }); });