import { aTimeout, elementUpdated, expect, fixture, html, oneEvent } from '@open-wc/testing';
import { registerIconLibrary } from '../../../dist/shoelace.js';
import type { SlErrorEvent } from '../../events/sl-error.js';
import type { SlLoadEvent } from '../../events/sl-load.js';
import type SlIcon from './icon.js';
const testLibraryIcons = {
'test-icon1': `
`,
'test-icon2': `
`,
'bad-icon': `
`
};
describe('', () => {
before(() => {
registerIconLibrary('test-library', {
resolver: (name: keyof typeof testLibraryIcons) => {
// only for testing a bad request
if (name === ('bad-request' as keyof typeof testLibraryIcons)) {
return `data:image/svg+xml`;
}
if (name in testLibraryIcons) {
return `data:image/svg+xml,${encodeURIComponent(testLibraryIcons[name])}`;
}
return '';
},
mutator: (svg: SVGElement) => svg.setAttribute('fill', 'currentColor')
});
});
describe('defaults ', () => {
it('default properties', async () => {
const el = await fixture(html` `);
expect(el.name).to.be.undefined;
expect(el.src).to.be.undefined;
expect(el.label).to.equal('');
expect(el.library).to.equal('default');
});
it('renders pre-loaded system icons and emits sl-load event', async () => {
const el = await fixture(html` `);
const listener = oneEvent(el, 'sl-load') as Promise;
el.name = 'check';
const ev = await listener;
await elementUpdated(el);
expect(el.shadowRoot?.querySelector('svg')).to.exist;
expect(ev).to.exist;
});
it('the icon is accessible', async () => {
const el = await fixture(html` `);
await expect(el).to.be.accessible();
});
it('the icon has the correct default aria attributes', async () => {
const el = await fixture(html` `);
expect(el.getAttribute('role')).to.be.null;
expect(el.getAttribute('aria-label')).to.be.null;
expect(el.getAttribute('aria-hidden')).to.equal('true');
});
});
describe('when a label is provided', () => {
it('the icon has the correct default aria attributes', async () => {
const fakeLabel = 'a label';
const el = await fixture(html` `);
expect(el.getAttribute('role')).to.equal('img');
expect(el.getAttribute('aria-label')).to.equal(fakeLabel);
expect(el.getAttribute('aria-hidden')).to.be.null;
});
});
describe('when a valid src is provided', () => {
it('the svg is rendered', async () => {
const fakeId = 'test-src';
const el = await fixture(html` `);
const listener = oneEvent(el, 'sl-load');
el.src = `data:image/svg+xml,${encodeURIComponent(``)}`;
await listener;
await elementUpdated(el);
expect(el.shadowRoot?.querySelector('svg')).to.exist;
expect(el.shadowRoot?.querySelector('svg')?.part.contains('svg')).to.be.true;
expect(el.shadowRoot?.querySelector('svg')?.getAttribute('id')).to.equal(fakeId);
});
});
describe('new library', () => {
it('renders icons from the new library and emits sl-load event', async () => {
const el = await fixture(html` `);
const listener = oneEvent(el, 'sl-load') as Promise;
el.name = 'test-icon1';
const ev = await listener;
await elementUpdated(el);
expect(el.shadowRoot?.querySelector('svg')).to.exist;
expect(ev.isTrusted).to.exist;
});
it('runs mutator from new library', async () => {
const el = await fixture(html` `);
await elementUpdated(el);
const svg = el.shadowRoot?.querySelector('svg');
expect(svg?.getAttribute('fill')).to.equal('currentColor');
});
});
describe('negative cases', () => {
// using new library so we can test for malformed icons when registered
it("svg not rendered with an icon that doesn't exist in the library", async () => {
const el = await fixture(html` `);
expect(el.shadowRoot?.querySelector('svg')).to.be.null;
});
it('emits sl-error when the file cant be retrieved', async () => {
const el = await fixture(html` `);
const listener = oneEvent(el, 'sl-error') as Promise;
el.name = 'bad-request';
const ev = await listener;
await elementUpdated(el);
expect(el.shadowRoot?.querySelector('svg')).to.be.null;
expect(ev).to.exist;
});
it("emits sl-error when there isn't an svg element in the registered icon", async () => {
const el = await fixture(html` `);
const listener = oneEvent(el, 'sl-error') as Promise;
el.name = 'bad-icon';
const ev = await listener;
await elementUpdated(el);
expect(el.shadowRoot?.querySelector('svg')).to.be.null;
expect(ev).to.exist;
});
});
describe('svg sprite sheets', () => {
// For some reason ESLint wants to fail in CI here, but works locally.
/* eslint-disable */
it('Should properly grab an SVG and render it from bootstrap icons', async () => {
registerIconLibrary('sprite', {
resolver: name => `/docs/assets/images/sprite.svg#${name}`,
mutator: svg => svg.setAttribute('fill', 'currentColor'),
spriteSheet: true
});
const el = await fixture(html``);
await elementUpdated(el);
const svg = el.shadowRoot?.querySelector("svg[part='svg']");
const use = svg?.querySelector(`use[href='/docs/assets/images/sprite.svg#arrow-left']`);
expect(svg).to.be.instanceof(SVGElement);
expect(use).to.be.instanceof(SVGUseElement);
// This is kind of hacky...but with no way to check "load", we just use a timeout
await aTimeout(1000);
// Theres no way to really test that the icon rendered properly. We just gotta trust the browser to do it's thing :)
// However, we can check the