import { iconExists } from '@iconify/core/lib/storage/functions'; import { fakeAPI, nextPrefix, setupDOM, waitDOMReady, resetState, mockAPIData, awaitUntil, } from './helpers'; import { addBodyNode } from '../src/observer/root'; import { scanDOM } from '../src/scanner/index'; import { elementDataProperty } from '../src/scanner/config'; import { initObserver } from '../src/observer'; describe('Changing render modes', () => { const provider = nextPrefix(); beforeAll(() => { fakeAPI(provider); }); afterEach(resetState); it('Various background modes', async () => { const prefix = nextPrefix(); const iconName = `@${provider}:${prefix}:home`; // Add icon with API expect(iconExists(iconName)).toBe(false); mockAPIData({ type: 'icons', provider, prefix, response: { prefix, icons: { home: { body: '<g />', }, }, }, }); // Setup DOM and wait for it to be ready setupDOM( `<span class="iconify" data-icon="${iconName}" data-mode="style"></span>` ); await waitDOMReady(); // Observe body addBodyNode(); initObserver(scanDOM); // Check HTML and data expect(document.body.innerHTML).toBe( `<span class="iconify" data-icon="${iconName}" data-mode="style"></span>` ); // Wait for re-render const placeholder = document.body.childNodes[0] as HTMLSpanElement; const style = placeholder.style; await awaitUntil(() => !!style.getPropertyValue('--svg')); // Check HTML expect(document.body.innerHTML).toBe( `<span class="iconify iconify--${provider} iconify--${prefix}" data-icon="${iconName}" data-mode="style" style="--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cg /%3E%3C/svg%3E"); width: 1em; height: 1em; display: inline-block; background-color: transparent; background-repeat: no-repeat; background-size: 100% 100%;"></span>` ); let data = placeholder[elementDataProperty]; expect(data.addedStyles.indexOf('background-image') !== -1).toBe(true); expect(data.addedStyles.indexOf('mask-image') !== -1).toBe(false); expect(style.getPropertyValue('mask-image')).toBe(''); // Render as mask placeholder.setAttribute('data-mode', 'mask'); await awaitUntil(() => !!style.getPropertyValue('mask-image')); expect(document.body.innerHTML).toBe( `<span class="iconify iconify--${provider} iconify--${prefix}" data-icon="${iconName}" data-mode="mask" style="--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cg /%3E%3C/svg%3E"); width: 1em; height: 1em; display: inline-block; background-color: currentColor; mask-image: var(--svg); mask-repeat: no-repeat; mask-size: 100% 100%;"></span>` ); data = placeholder[elementDataProperty]; expect(data.addedStyles.indexOf('background-image') !== -1).toBe(false); expect(data.addedStyles.indexOf('mask-image') !== -1).toBe(true); expect(style.getPropertyValue('background-image')).toBe(''); // Re-render as background placeholder.setAttribute('data-mode', 'bg'); await awaitUntil(() => !style.getPropertyValue('mask-image')); expect(document.body.innerHTML).toBe( `<span class="iconify iconify--${provider} iconify--${prefix}" data-icon="${iconName}" data-mode="bg" style="--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cg /%3E%3C/svg%3E"); width: 1em; height: 1em; display: inline-block; background-color: transparent; background-repeat: no-repeat; background-size: 100% 100%;"></span>` ); data = placeholder[elementDataProperty]; expect(data.addedStyles.indexOf('background-image') !== -1).toBe(true); expect(data.addedStyles.indexOf('mask-image') !== -1).toBe(false); expect(style.getPropertyValue('mask-image')).toBe(''); // Re-render as SVG placeholder.setAttribute('data-mode', 'inline'); await awaitUntil(() => document.body.childNodes[0] !== placeholder); expect(document.body.innerHTML).toBe( `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" width="1em" height="1em" viewBox="0 0 16 16" data-icon="${iconName}" data-mode="inline" style="" class="iconify iconify--${provider} iconify--${prefix}"><g></g></svg>` ); const svgData = document.body.childNodes[0][elementDataProperty]; expect(svgData.mode).toBe('inline'); // Change to style (should not work!) placeholder.setAttribute('data-mode', 'bg'); await awaitUntil(() => svgData.mode !== 'bg'); expect(document.body.innerHTML).toBe( `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" width="1em" height="1em" viewBox="0 0 16 16" data-icon="${iconName}" data-mode="inline" style="" class="iconify iconify--${provider} iconify--${prefix}"><g></g></svg>` ); }); });