mirror of
https://github.com/iconify/iconify.git
synced 2024-12-12 05:37:49 +00:00
chore: migrate react tests to vitest, publish react component update
This commit is contained in:
parent
ad3ffb793f
commit
17a46f6a75
@ -1,3 +0,0 @@
|
||||
{
|
||||
"presets": ["@babel/preset-env", "@babel/preset-react"]
|
||||
}
|
@ -7,7 +7,9 @@
|
||||
"@cyberalien/redundancy",
|
||||
"@iconify/api-redundancy"
|
||||
],
|
||||
"compiler": {},
|
||||
"compiler": {
|
||||
"tsconfigFilePath": "<projectFolder>/tsconfig.src.json"
|
||||
},
|
||||
"apiReport": {
|
||||
"enabled": false
|
||||
},
|
||||
|
@ -3,7 +3,7 @@
|
||||
"description": "Iconify icon component for React.",
|
||||
"author": "Vjacheslav Trushkin",
|
||||
"type": "module",
|
||||
"version": "5.0.1",
|
||||
"version": "5.0.2",
|
||||
"license": "MIT",
|
||||
"bugs": "https://github.com/iconify/iconify/issues",
|
||||
"homepage": "https://iconify.design/",
|
||||
@ -17,12 +17,12 @@
|
||||
"clean": "rimraf lib dist tsconfig.tsbuildinfo",
|
||||
"prebuild": "pnpm run clean",
|
||||
"build": "node build",
|
||||
"build:lib": "tsc -b",
|
||||
"build:lib": "tsc -b tsconfig.src.json",
|
||||
"build:dist": "rollup -c rollup.config.js",
|
||||
"prebuild:api": "api-extractor run --local --verbose --config api-extractor.offline.json",
|
||||
"build:api": "api-extractor run --local --verbose --config api-extractor.iconify.json",
|
||||
"build:cleanup": "node cleanup",
|
||||
"test": "jest --runInBand"
|
||||
"test": "vitest"
|
||||
},
|
||||
"main": "dist/iconify.js",
|
||||
"types": "dist/iconify.d.ts",
|
||||
@ -51,20 +51,20 @@
|
||||
"@iconify/types": "workspace:^"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.24.8",
|
||||
"@babel/preset-react": "^7.24.7",
|
||||
"@iconify/core": "workspace:^",
|
||||
"@iconify/utils": "workspace:^",
|
||||
"@microsoft/api-extractor": "^7.47.2",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@testing-library/jest-dom": "^6.4.6",
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@types/react": "^18.3.3",
|
||||
"babel-jest": "^29.7.0",
|
||||
"jest": "^29.7.0",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"jsdom": "^24.1.1",
|
||||
"react": "^18.3.1",
|
||||
"react-test-renderer": "^18.3.1",
|
||||
"rimraf": "^4.4.1",
|
||||
"rollup": "^3.29.4",
|
||||
"typescript": "^5.5.3"
|
||||
"typescript": "^5.5.3",
|
||||
"vitest": "^2.0.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16"
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { loadIcons, iconExists } from '../../dist/iconify';
|
||||
import { mockAPIData } from '@iconify/core/lib/api/modules/mock';
|
||||
import { provider, nextPrefix } from './load';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
|
||||
describe('Testing fake API', () => {
|
||||
test('using fake API to load icon', () => {
|
@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { Icon, loadIcons, iconExists } from '../../dist/iconify';
|
||||
import { mockAPIData } from '@iconify/core/lib/api/modules/mock';
|
||||
import { provider, nextPrefix } from './load';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
@ -12,11 +13,11 @@ const iconData = {
|
||||
|
||||
describe('Rendering icon', () => {
|
||||
test('rendering icon after loading it', () => {
|
||||
return new Promise((fulfill) => {
|
||||
return new Promise((resolve) => {
|
||||
const prefix = nextPrefix();
|
||||
const name = 'render-test';
|
||||
const iconName = `@${provider}:${prefix}:${name}`;
|
||||
const className = `iconify iconify--${prefix} iconify--${provider}`;
|
||||
const className = `iconify iconify--${provider} iconify--${prefix}`;
|
||||
let onLoadCalled = false;
|
||||
|
||||
mockAPIData({
|
||||
@ -49,7 +50,7 @@ describe('Rendering icon', () => {
|
||||
expect(iconExists(iconName)).toEqual(true);
|
||||
|
||||
// Render component
|
||||
const component = renderer.create(
|
||||
const renderResult = render(
|
||||
<Icon
|
||||
icon={iconName}
|
||||
onLoad={(name) => {
|
||||
@ -59,42 +60,24 @@ describe('Rendering icon', () => {
|
||||
}}
|
||||
/>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink': 'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox':
|
||||
'0 0 ' + iconData.width + ' ' + iconData.height,
|
||||
className,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
expect(renderResult.container.innerHTML).toEqual(
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="${className}" width="1em" height="1em" viewBox="0 0 24 24"><path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"></path></svg>`
|
||||
);
|
||||
|
||||
// Make sure onLoad has been called
|
||||
expect(onLoadCalled).toEqual(true);
|
||||
|
||||
fulfill(true);
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('rendering icon before loading it', () => {
|
||||
return new Promise((fulfill) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const prefix = nextPrefix();
|
||||
const name = 'mock-test';
|
||||
const iconName = `@${provider}:${prefix}:${name}`;
|
||||
const className = `iconify iconify--${prefix} iconify--${provider}`;
|
||||
const className = `iconify iconify--${provider} iconify--${prefix}`;
|
||||
let onLoadCalled = false;
|
||||
|
||||
mockAPIData({
|
||||
@ -120,42 +103,32 @@ describe('Rendering icon', () => {
|
||||
// Test it again
|
||||
expect(iconExists(iconName)).toEqual(true);
|
||||
|
||||
// Check if state was changed
|
||||
// Wrapped in double setTimeout() because re-render takes 2 ticks
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
const tree = component.toJSON();
|
||||
// Check if state was changed in next few ticks
|
||||
let counter = 0;
|
||||
const timer = setInterval(() => {
|
||||
counter++;
|
||||
const html = renderResult.container.innerHTML;
|
||||
if (html.includes('<span')) {
|
||||
// Not rendered yet
|
||||
if (counter > 5) {
|
||||
clearInterval(timer);
|
||||
reject(new Error('Icon not rendered'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink':
|
||||
'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox':
|
||||
'0 0 ' +
|
||||
iconData.width +
|
||||
' ' +
|
||||
iconData.height,
|
||||
'className': 'test ' + className,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
// Should be rendered: test it
|
||||
clearInterval(timer);
|
||||
|
||||
// onLoad should have been called
|
||||
expect(onLoadCalled).toEqual(true);
|
||||
expect(html).toEqual(
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="${className} test" width="1em" height="1em" viewBox="0 0 24 24"><path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"></path></svg>`
|
||||
);
|
||||
|
||||
fulfill(true);
|
||||
}, 0);
|
||||
}, 0);
|
||||
// onLoad should have been called
|
||||
expect(onLoadCalled).toEqual(true);
|
||||
|
||||
resolve(true);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -163,7 +136,7 @@ describe('Rendering icon', () => {
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Render component
|
||||
const component = renderer.create(
|
||||
const renderResult = render(
|
||||
<Icon
|
||||
icon={iconName}
|
||||
className="test"
|
||||
@ -174,14 +147,9 @@ describe('Rendering icon', () => {
|
||||
}}
|
||||
/>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
// Should render placeholder
|
||||
expect(tree).toMatchObject({
|
||||
type: 'span',
|
||||
props: {},
|
||||
children: null,
|
||||
});
|
||||
expect(renderResult.container.innerHTML).toEqual('<span></span>');
|
||||
|
||||
// onLoad should not have been called yet
|
||||
expect(onLoadCalled).toEqual(false);
|
||||
@ -189,7 +157,7 @@ describe('Rendering icon', () => {
|
||||
});
|
||||
|
||||
test('missing icon', () => {
|
||||
return new Promise((fulfill) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const prefix = nextPrefix();
|
||||
const name = 'missing-icon';
|
||||
const iconName = `@${provider}:${prefix}:${name}`;
|
||||
@ -208,21 +176,30 @@ describe('Rendering icon', () => {
|
||||
// Test it again
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Check if state was changed
|
||||
// Wrapped in double setTimeout() because re-render takes 2 ticks
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
const tree = component.toJSON();
|
||||
// Check if state was changed in next few ticks
|
||||
let counter = 0;
|
||||
const timer = setInterval(() => {
|
||||
counter++;
|
||||
const html = renderResult.container.innerHTML;
|
||||
if (html.includes('<span')) {
|
||||
// Not rendered yet
|
||||
if (counter > 5) {
|
||||
// Success
|
||||
clearInterval(timer);
|
||||
resolve(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'span',
|
||||
props: {},
|
||||
children: null,
|
||||
});
|
||||
|
||||
fulfill(true);
|
||||
}, 0);
|
||||
}, 0);
|
||||
// Content changed???
|
||||
clearInterval(timer);
|
||||
reject(
|
||||
new Error(
|
||||
'Bad icon content: ' +
|
||||
renderResult.container.innerHTML
|
||||
)
|
||||
);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -230,7 +207,7 @@ describe('Rendering icon', () => {
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Render component
|
||||
const component = renderer.create(
|
||||
const renderResult = render(
|
||||
<Icon
|
||||
icon={iconName}
|
||||
onLoad={() => {
|
||||
@ -238,14 +215,9 @@ describe('Rendering icon', () => {
|
||||
}}
|
||||
></Icon>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
// Should render placeholder
|
||||
expect(tree).toMatchObject({
|
||||
type: 'span',
|
||||
props: {},
|
||||
children: null,
|
||||
});
|
||||
expect(renderResult.container.innerHTML).toEqual('<span></span>');
|
||||
});
|
||||
});
|
||||
});
|
@ -1,414 +0,0 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { Icon, iconExists } from '../../dist/iconify';
|
||||
import { mockAPIData } from '@iconify/core/lib/api/modules/mock';
|
||||
import { provider, nextPrefix } from './load';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
const iconData2 = {
|
||||
body: '<path d="M19.031 4.281l-11 11l-.687.719l.687.719l11 11l1.438-1.438L10.187 16L20.47 5.719z" fill="currentColor"/>',
|
||||
width: 32,
|
||||
height: 32,
|
||||
};
|
||||
|
||||
describe('Rendering icon', () => {
|
||||
test('changing icon property', () => {
|
||||
return new Promise((fulfill) => {
|
||||
const prefix = nextPrefix();
|
||||
const name = 'changing-prop';
|
||||
const name2 = 'changing-prop2';
|
||||
const iconName = `@${provider}:${prefix}:${name}`;
|
||||
const iconName2 = `@${provider}:${prefix}:${name2}`;
|
||||
const className = `iconify iconify--${prefix} iconify--${provider}`;
|
||||
let onLoadCalled = ''; // Name of icon from last onLoad call
|
||||
|
||||
const onLoad = (name) => {
|
||||
// onLoad should be called only once per icon
|
||||
switch (name) {
|
||||
// First onLoad call
|
||||
case iconName:
|
||||
expect(onLoadCalled).toEqual('');
|
||||
break;
|
||||
|
||||
// Second onLoad call
|
||||
case iconName2:
|
||||
expect(onLoadCalled).toEqual(iconName);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unexpected onLoad('${name}') call`);
|
||||
}
|
||||
onLoadCalled = name;
|
||||
};
|
||||
|
||||
mockAPIData({
|
||||
type: 'icons',
|
||||
provider,
|
||||
prefix,
|
||||
response: {
|
||||
prefix,
|
||||
icons: {
|
||||
[name]: iconData,
|
||||
},
|
||||
},
|
||||
delay: (next) => {
|
||||
// Icon should not have loaded yet
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// onLoad should not have been called yet
|
||||
expect(onLoadCalled).toEqual('');
|
||||
|
||||
// Send icon data
|
||||
next();
|
||||
|
||||
// Test it again
|
||||
expect(iconExists(iconName)).toEqual(true);
|
||||
|
||||
// Check if state was changed
|
||||
// Wrapped in double setTimeout() because re-render takes 2 ticks
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink':
|
||||
'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox':
|
||||
'0 0 ' +
|
||||
iconData.width +
|
||||
' ' +
|
||||
iconData.height,
|
||||
className,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
|
||||
// onLoad should have been called
|
||||
expect(onLoadCalled).toEqual(iconName);
|
||||
|
||||
// Change property
|
||||
component.update(
|
||||
<Icon icon={iconName2} onLoad={onLoad} />
|
||||
);
|
||||
}, 0);
|
||||
}, 0);
|
||||
},
|
||||
});
|
||||
|
||||
mockAPIData({
|
||||
type: 'icons',
|
||||
provider,
|
||||
prefix,
|
||||
response: {
|
||||
prefix,
|
||||
icons: {
|
||||
[name2]: iconData2,
|
||||
},
|
||||
},
|
||||
delay: (next) => {
|
||||
// Icon should not have loaded yet
|
||||
expect(iconExists(iconName2)).toEqual(false);
|
||||
|
||||
// Send icon data
|
||||
next();
|
||||
|
||||
// Test it again
|
||||
expect(iconExists(iconName2)).toEqual(true);
|
||||
|
||||
// Check if state was changed
|
||||
// Wrapped in double setTimeout() because re-render takes 2 ticks
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink':
|
||||
'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData2.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox':
|
||||
'0 0 ' +
|
||||
iconData2.width +
|
||||
' ' +
|
||||
iconData2.height,
|
||||
className,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
|
||||
// onLoad should have been called for second icon
|
||||
expect(onLoadCalled).toEqual(iconName2);
|
||||
|
||||
fulfill(true);
|
||||
}, 0);
|
||||
}, 0);
|
||||
},
|
||||
});
|
||||
|
||||
// Check if icon has been loaded
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Render component
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconName} onLoad={onLoad} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
// Should render placeholder
|
||||
expect(tree).toMatchObject({
|
||||
type: 'span',
|
||||
props: {},
|
||||
children: null,
|
||||
});
|
||||
|
||||
// onLoad should not have been called yet
|
||||
expect(onLoadCalled).toEqual('');
|
||||
});
|
||||
});
|
||||
|
||||
test('changing icon property while loading', () => {
|
||||
return new Promise((fulfill) => {
|
||||
const prefix = nextPrefix();
|
||||
const name = 'changing-prop';
|
||||
const name2 = 'changing-prop2';
|
||||
const iconName = `@${provider}:${prefix}:${name}`;
|
||||
const iconName2 = `@${provider}:${prefix}:${name2}`;
|
||||
const className = `iconify iconify--${prefix} iconify--${provider}`;
|
||||
let isSync = true;
|
||||
|
||||
mockAPIData({
|
||||
type: 'icons',
|
||||
provider,
|
||||
prefix,
|
||||
response: {
|
||||
prefix,
|
||||
icons: {
|
||||
[name]: iconData,
|
||||
},
|
||||
},
|
||||
delay: (next) => {
|
||||
// Should have been called asynchronously, which means icon name has changed
|
||||
expect(isSync).toEqual(false);
|
||||
|
||||
// Send icon data
|
||||
next();
|
||||
},
|
||||
});
|
||||
|
||||
mockAPIData({
|
||||
type: 'icons',
|
||||
provider,
|
||||
prefix,
|
||||
response: {
|
||||
prefix,
|
||||
icons: {
|
||||
[name2]: iconData2,
|
||||
},
|
||||
},
|
||||
delay: (next) => {
|
||||
// Should have been called asynchronously
|
||||
expect(isSync).toEqual(false);
|
||||
|
||||
// Icon should not have loaded yet
|
||||
expect(iconExists(iconName2)).toEqual(false);
|
||||
|
||||
// Send icon data
|
||||
next();
|
||||
|
||||
// Test it again
|
||||
expect(iconExists(iconName2)).toEqual(true);
|
||||
|
||||
// Check if state was changed
|
||||
// Wrapped in double setTimeout() because re-render takes 2 ticks
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink':
|
||||
'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData2.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox':
|
||||
'0 0 ' +
|
||||
iconData2.width +
|
||||
' ' +
|
||||
iconData2.height,
|
||||
className,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
|
||||
fulfill(true);
|
||||
}, 0);
|
||||
}, 0);
|
||||
},
|
||||
});
|
||||
|
||||
// Check if icon has been loaded
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Render component
|
||||
const component = renderer.create(<Icon icon={iconName} />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
// Should render placeholder
|
||||
expect(tree).toMatchObject({
|
||||
type: 'span',
|
||||
props: {},
|
||||
children: null,
|
||||
});
|
||||
|
||||
// Change icon name
|
||||
component.update(<Icon icon={iconName2} />);
|
||||
|
||||
// Async
|
||||
isSync = false;
|
||||
});
|
||||
});
|
||||
|
||||
test('changing multiple properties', () => {
|
||||
return new Promise((fulfill) => {
|
||||
const prefix = nextPrefix();
|
||||
const name = 'multiple-props';
|
||||
const iconName = `@${provider}:${prefix}:${name}`;
|
||||
const className = `iconify iconify--${prefix} iconify--${provider}`;
|
||||
|
||||
mockAPIData({
|
||||
type: 'icons',
|
||||
provider,
|
||||
prefix,
|
||||
response: {
|
||||
prefix,
|
||||
icons: {
|
||||
[name]: iconData,
|
||||
},
|
||||
},
|
||||
delay: (next) => {
|
||||
// Icon should not have loaded yet
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Send icon data
|
||||
next();
|
||||
|
||||
// Test it again
|
||||
expect(iconExists(iconName)).toEqual(true);
|
||||
|
||||
// Check if state was changed
|
||||
// Wrapped in double setTimeout() because re-render takes 2 ticks
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
let tree = component.toJSON();
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink':
|
||||
'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox':
|
||||
'0 0 ' +
|
||||
iconData.width +
|
||||
' ' +
|
||||
iconData.height,
|
||||
className,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
|
||||
// Add horizontal flip and style
|
||||
component.update(
|
||||
<Icon
|
||||
icon={iconName}
|
||||
hFlip={true}
|
||||
style={{ color: 'red' }}
|
||||
/>
|
||||
);
|
||||
|
||||
tree = component.toJSON();
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink':
|
||||
'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {
|
||||
color: 'red',
|
||||
},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: `<g transform="translate(${iconData.width} 0) scale(-1 1)">${iconData.body}</g>`,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox':
|
||||
'0 0 ' +
|
||||
iconData.width +
|
||||
' ' +
|
||||
iconData.height,
|
||||
className,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
fulfill(true);
|
||||
}, 0);
|
||||
}, 0);
|
||||
},
|
||||
});
|
||||
|
||||
// Check if icon has been loaded
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Render component with placeholder text
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconName}>loading...</Icon>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
// Should render placeholder
|
||||
expect(tree).toEqual('loading...');
|
||||
});
|
||||
});
|
||||
});
|
344
components/react/tests/api/30-changing-props.test.tsx
Normal file
344
components/react/tests/api/30-changing-props.test.tsx
Normal file
@ -0,0 +1,344 @@
|
||||
import React from 'react';
|
||||
import { Icon, iconExists } from '../../dist/iconify';
|
||||
import { mockAPIData } from '@iconify/core/lib/api/modules/mock';
|
||||
import { provider, nextPrefix } from './load';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const path1 = 'M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z';
|
||||
const iconData = {
|
||||
body: `<path d="${path1}" fill="currentColor"/>`,
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
const path2 =
|
||||
'M19.031 4.281l-11 11l-.687.719l.687.719l11 11l1.438-1.438L10.187 16L20.47 5.719z';
|
||||
const iconData2 = {
|
||||
body: `<path d="${path2}" fill="currentColor"/>`,
|
||||
width: 32,
|
||||
height: 32,
|
||||
};
|
||||
|
||||
describe('Rendering icon', () => {
|
||||
test('changing icon property', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const prefix = nextPrefix();
|
||||
const name = 'changing-prop';
|
||||
const name2 = 'changing-prop2';
|
||||
const iconName = `@${provider}:${prefix}:${name}`;
|
||||
const iconName2 = `@${provider}:${prefix}:${name2}`;
|
||||
let onLoadCalled = ''; // Name of icon from last onLoad call
|
||||
|
||||
const onLoad = (name) => {
|
||||
// onLoad should be called only once per icon
|
||||
switch (name) {
|
||||
// First onLoad call
|
||||
case iconName:
|
||||
expect(onLoadCalled).toEqual('');
|
||||
break;
|
||||
|
||||
// Second onLoad call
|
||||
case iconName2:
|
||||
expect(onLoadCalled).toEqual(iconName);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error(`Unexpected onLoad('${name}') call`);
|
||||
}
|
||||
onLoadCalled = name;
|
||||
};
|
||||
|
||||
mockAPIData({
|
||||
type: 'icons',
|
||||
provider,
|
||||
prefix,
|
||||
response: {
|
||||
prefix,
|
||||
icons: {
|
||||
[name]: iconData,
|
||||
},
|
||||
},
|
||||
delay: (next) => {
|
||||
// Icon should not have loaded yet
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// onLoad should not have been called yet
|
||||
expect(onLoadCalled).toEqual('');
|
||||
|
||||
// Send icon data
|
||||
next();
|
||||
|
||||
// Test it again
|
||||
expect(iconExists(iconName)).toEqual(true);
|
||||
|
||||
// Check if state was changed in next few ticks
|
||||
let counter = 0;
|
||||
const timer = setInterval(() => {
|
||||
counter++;
|
||||
const html = renderResult.container.innerHTML;
|
||||
if (html.includes('<span')) {
|
||||
// Not rendered yet
|
||||
if (counter > 5) {
|
||||
clearInterval(timer);
|
||||
reject(new Error('Icon not rendered'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Should be rendered: test it
|
||||
clearInterval(timer);
|
||||
|
||||
expect(html).toContain(path1);
|
||||
|
||||
// onLoad should have been called
|
||||
expect(onLoadCalled).toEqual(iconName);
|
||||
|
||||
// Change property
|
||||
renderResult.rerender(
|
||||
<Icon icon={iconName2} onLoad={onLoad} />
|
||||
);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
mockAPIData({
|
||||
type: 'icons',
|
||||
provider,
|
||||
prefix,
|
||||
response: {
|
||||
prefix,
|
||||
icons: {
|
||||
[name2]: iconData2,
|
||||
},
|
||||
},
|
||||
delay: (next) => {
|
||||
// Icon should not have loaded yet
|
||||
expect(iconExists(iconName2)).toEqual(false);
|
||||
|
||||
// Send icon data
|
||||
next();
|
||||
|
||||
// Test it again
|
||||
expect(iconExists(iconName2)).toEqual(true);
|
||||
|
||||
// Check if state was changed in next few ticks
|
||||
let counter = 0;
|
||||
const timer = setInterval(() => {
|
||||
counter++;
|
||||
const html = renderResult.container.innerHTML;
|
||||
if (html.includes('<span')) {
|
||||
// Not rendered yet
|
||||
if (counter > 5) {
|
||||
clearInterval(timer);
|
||||
reject(new Error('Icon was not updated'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Should be rendered: test it
|
||||
clearInterval(timer);
|
||||
|
||||
expect(html).toContain(path2);
|
||||
|
||||
// onLoad should have been called for second icon
|
||||
expect(onLoadCalled).toEqual(iconName2);
|
||||
|
||||
resolve(true);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// Check if icon has been loaded
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Render component
|
||||
const renderResult = render(
|
||||
<Icon icon={iconName} onLoad={onLoad} />
|
||||
);
|
||||
|
||||
// Should render placeholder
|
||||
expect(renderResult.container.innerHTML).toEqual('<span></span>');
|
||||
|
||||
// onLoad should not have been called yet
|
||||
expect(onLoadCalled).toEqual('');
|
||||
});
|
||||
});
|
||||
|
||||
test('changing icon property while loading', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const prefix = nextPrefix();
|
||||
const name = 'changing-prop';
|
||||
const name2 = 'changing-prop2';
|
||||
const iconName = `@${provider}:${prefix}:${name}`;
|
||||
const iconName2 = `@${provider}:${prefix}:${name2}`;
|
||||
let isSync = true;
|
||||
|
||||
mockAPIData({
|
||||
type: 'icons',
|
||||
provider,
|
||||
prefix,
|
||||
response: {
|
||||
prefix,
|
||||
icons: {
|
||||
[name]: iconData,
|
||||
},
|
||||
},
|
||||
delay: (next) => {
|
||||
// Should have been called asynchronously, which means icon name has changed
|
||||
expect(isSync).toEqual(false);
|
||||
|
||||
// Send icon data
|
||||
next();
|
||||
},
|
||||
});
|
||||
|
||||
mockAPIData({
|
||||
type: 'icons',
|
||||
provider,
|
||||
prefix,
|
||||
response: {
|
||||
prefix,
|
||||
icons: {
|
||||
[name2]: iconData2,
|
||||
},
|
||||
},
|
||||
delay: (next) => {
|
||||
// Should have been called asynchronously
|
||||
expect(isSync).toEqual(false);
|
||||
|
||||
// Icon should not have loaded yet
|
||||
expect(iconExists(iconName2)).toEqual(false);
|
||||
|
||||
// Send icon data
|
||||
next();
|
||||
|
||||
// Test it again
|
||||
expect(iconExists(iconName2)).toEqual(true);
|
||||
|
||||
// Check if state was changed in next few ticks
|
||||
let counter = 0;
|
||||
const timer = setInterval(() => {
|
||||
counter++;
|
||||
const html = renderResult.container.innerHTML;
|
||||
if (html.includes('<span')) {
|
||||
// Not rendered yet
|
||||
if (counter > 5) {
|
||||
clearInterval(timer);
|
||||
reject(new Error('Icon not rendered'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Should be rendered: test it
|
||||
clearInterval(timer);
|
||||
|
||||
expect(html).toContain(path2);
|
||||
|
||||
resolve(true);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// Check if icon has been loaded
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Render component
|
||||
const renderResult = render(<Icon icon={iconName} />);
|
||||
|
||||
// Should render placeholder
|
||||
expect(renderResult.container.innerHTML).toEqual('<span></span>');
|
||||
|
||||
// Change icon name
|
||||
renderResult.rerender(<Icon icon={iconName2} />);
|
||||
|
||||
// Async
|
||||
isSync = false;
|
||||
});
|
||||
});
|
||||
|
||||
test('changing multiple properties', () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const prefix = nextPrefix();
|
||||
const name = 'multiple-props';
|
||||
const iconName = `@${provider}:${prefix}:${name}`;
|
||||
const className = `iconify iconify--${prefix} iconify--${provider}`;
|
||||
|
||||
mockAPIData({
|
||||
type: 'icons',
|
||||
provider,
|
||||
prefix,
|
||||
response: {
|
||||
prefix,
|
||||
icons: {
|
||||
[name]: iconData,
|
||||
},
|
||||
},
|
||||
delay: (next) => {
|
||||
// Icon should not have loaded yet
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Send icon data
|
||||
next();
|
||||
|
||||
// Test it again
|
||||
expect(iconExists(iconName)).toEqual(true);
|
||||
|
||||
// Check if state was changed in next few ticks
|
||||
let counter = 0;
|
||||
const timer = setInterval(() => {
|
||||
counter++;
|
||||
const html = renderResult.container.innerHTML;
|
||||
if (!html.includes('<svg')) {
|
||||
// Not rendered yet
|
||||
if (counter > 5) {
|
||||
clearInterval(timer);
|
||||
reject(new Error('Icon not rendered'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Should be rendered: test it
|
||||
clearInterval(timer);
|
||||
|
||||
expect(html).toContain(path1);
|
||||
expect(html).not.toContain(
|
||||
`<g transform="translate(${iconData.width} 0) scale(-1 1)">`
|
||||
);
|
||||
expect(html).not.toContain('style="color: red;"');
|
||||
|
||||
// Add horizontal flip and style
|
||||
renderResult.rerender(
|
||||
<Icon
|
||||
icon={iconName}
|
||||
hFlip={true}
|
||||
style={{ color: 'red' }}
|
||||
/>
|
||||
);
|
||||
|
||||
// Should be updated immediately
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
`<g transform="translate(${iconData.width} 0) scale(-1 1)">`
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'style="color: red;"'
|
||||
);
|
||||
|
||||
resolve(true);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// Check if icon has been loaded
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Render component with placeholder text
|
||||
const renderResult = render(
|
||||
<Icon icon={iconName}>loading...</Icon>
|
||||
);
|
||||
|
||||
// Should render placeholder
|
||||
expect(renderResult.container.innerHTML).toEqual('loading...');
|
||||
});
|
||||
});
|
||||
});
|
@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { Icon, InlineIcon, loadIcons, iconExists } from '../../dist/iconify';
|
||||
import { mockAPIData } from '@iconify/core/lib/api/modules/mock';
|
||||
import { provider, nextPrefix } from './load';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
@ -12,7 +13,7 @@ const iconData = {
|
||||
|
||||
describe('Testing references', () => {
|
||||
test('reference for preloaded icon', () => {
|
||||
return new Promise((fulfill) => {
|
||||
return new Promise((resolve) => {
|
||||
const prefix = nextPrefix();
|
||||
const name = 'render-test';
|
||||
const iconName = `@${provider}:${prefix}:${name}`;
|
||||
@ -50,7 +51,7 @@ describe('Testing references', () => {
|
||||
expect(iconExists(iconName)).toEqual(true);
|
||||
|
||||
// Render components
|
||||
renderer.create(
|
||||
render(
|
||||
<Icon
|
||||
icon={iconName}
|
||||
ref={(element) => {
|
||||
@ -59,7 +60,7 @@ describe('Testing references', () => {
|
||||
/>
|
||||
);
|
||||
|
||||
renderer.create(
|
||||
render(
|
||||
<InlineIcon
|
||||
icon={iconName}
|
||||
ref={(element) => {
|
||||
@ -72,13 +73,13 @@ describe('Testing references', () => {
|
||||
expect(gotRef).toEqual(true);
|
||||
expect(gotInlineRef).toEqual(true);
|
||||
|
||||
fulfill(true);
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('reference to pending icon', () => {
|
||||
return new Promise((fulfill) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const prefix = nextPrefix();
|
||||
const name = 'mock-test';
|
||||
const iconName = `@${provider}:${prefix}:${name}`;
|
||||
@ -108,15 +109,23 @@ describe('Testing references', () => {
|
||||
expect(iconExists(iconName)).toEqual(true);
|
||||
expect(gotRef).toEqual(false);
|
||||
|
||||
// Check if state was changed
|
||||
// Wrapped in double setTimeout() because re-render takes 2 ticks
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
expect(gotRef).toEqual(true);
|
||||
// Check if state was changed in next few ticks
|
||||
let counter = 0;
|
||||
const timer = setInterval(() => {
|
||||
counter++;
|
||||
if (!gotRef) {
|
||||
// Test again
|
||||
if (counter > 5) {
|
||||
clearInterval(timer);
|
||||
reject(new Error('Icon reference was not set'));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
fulfill(true);
|
||||
}, 0);
|
||||
}, 0);
|
||||
// Success!
|
||||
clearInterval(timer);
|
||||
resolve(true);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -124,7 +133,7 @@ describe('Testing references', () => {
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Render component
|
||||
renderer.create(
|
||||
render(
|
||||
<Icon
|
||||
icon={iconName}
|
||||
ref={(element) => {
|
||||
@ -139,7 +148,7 @@ describe('Testing references', () => {
|
||||
});
|
||||
|
||||
test('missing icon', () => {
|
||||
return new Promise((fulfill) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const prefix = nextPrefix();
|
||||
const name = 'missing-icon';
|
||||
const iconName = `@${provider}:${prefix}:${name}`;
|
||||
@ -164,16 +173,23 @@ describe('Testing references', () => {
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
expect(gotRef).toEqual(false);
|
||||
|
||||
// Check if state was changed
|
||||
// Wrapped in double setTimeout() because re-render takes 2 ticks
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
// Reference should not have been called
|
||||
expect(gotRef).toEqual(false);
|
||||
// Check if state was changed in next few ticks
|
||||
let counter = 0;
|
||||
const timer = setInterval(() => {
|
||||
counter++;
|
||||
if (gotRef) {
|
||||
// Failed!
|
||||
clearInterval(timer);
|
||||
reject(new Error('Icon reference was set'));
|
||||
return;
|
||||
}
|
||||
|
||||
fulfill(true);
|
||||
}, 0);
|
||||
}, 0);
|
||||
if (counter > 5) {
|
||||
// Waited enough. Success
|
||||
clearInterval(timer);
|
||||
resolve(true);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -181,7 +197,7 @@ describe('Testing references', () => {
|
||||
expect(iconExists(iconName)).toEqual(false);
|
||||
|
||||
// Render component
|
||||
const component = renderer.create(
|
||||
render(
|
||||
<Icon
|
||||
icon={iconName}
|
||||
ref={(element) => {
|
@ -1,67 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Creating component using object', () => {
|
||||
test('basic icon', () => {
|
||||
const component = renderer.create(
|
||||
<Icon
|
||||
icon={iconData}
|
||||
onLoad={() => {
|
||||
// Should be called only for icons loaded from API
|
||||
throw new Error('onLoad called for object!');
|
||||
}}
|
||||
/>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink': 'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox': '0 0 ' + iconData.width + ' ' + iconData.height,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('inline icon', () => {
|
||||
const component = renderer.create(<InlineIcon icon={iconData} />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink': 'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {
|
||||
verticalAlign: '-0.125em',
|
||||
},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox': '0 0 ' + iconData.width + ' ' + iconData.height,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
});
|
35
components/react/tests/iconify/10-basic.test.tsx
Normal file
35
components/react/tests/iconify/10-basic.test.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/iconify';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Creating component using object', () => {
|
||||
test('basic icon', () => {
|
||||
const renderResult = render(
|
||||
<Icon
|
||||
icon={iconData}
|
||||
onLoad={() => {
|
||||
// Should be called only for icons loaded from API
|
||||
throw new Error('onLoad called for object!');
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(renderResult.container.innerHTML).toEqual(
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" viewBox="0 0 24 24"><path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"></path></svg>'
|
||||
);
|
||||
});
|
||||
|
||||
test('inline icon', () => {
|
||||
const renderResult = render(<InlineIcon icon={iconData} />);
|
||||
expect(renderResult.container.innerHTML).toEqual(
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" style="vertical-align: -0.125em;" width="1em" height="1em" viewBox="0 0 24 24"><path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"></path></svg>'
|
||||
);
|
||||
});
|
||||
});
|
@ -1,57 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
describe('Empty icon', () => {
|
||||
test('basic test', () => {
|
||||
const component = renderer.create(<Icon />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'span',
|
||||
props: {},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('with child node', () => {
|
||||
const component = renderer.create(
|
||||
<Icon>
|
||||
<i class="fa fa-home" />
|
||||
</Icon>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'i',
|
||||
props: {},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('with text child node', () => {
|
||||
const component = renderer.create(<Icon>icon</Icon>);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatch('icon');
|
||||
});
|
||||
|
||||
test('with multiple childen', () => {
|
||||
const component = renderer.create(
|
||||
<Icon>
|
||||
<i class="fa fa-home" />
|
||||
Home
|
||||
</Icon>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject([
|
||||
{
|
||||
type: 'i',
|
||||
props: {},
|
||||
children: null,
|
||||
},
|
||||
'Home',
|
||||
]);
|
||||
});
|
||||
});
|
46
components/react/tests/iconify/10-empty.test.tsx
Normal file
46
components/react/tests/iconify/10-empty.test.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/iconify';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
describe('Empty icon', () => {
|
||||
test('basic test', () => {
|
||||
// @ts-expect-error
|
||||
const renderResult = render(<Icon />);
|
||||
|
||||
expect(renderResult.container.innerHTML).toEqual('<span></span>');
|
||||
});
|
||||
test('with child node', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<Icon>
|
||||
<i className="fa fa-home" />
|
||||
</Icon>
|
||||
);
|
||||
|
||||
expect(renderResult.container.innerHTML).toEqual(
|
||||
'<i class="fa fa-home"></i>'
|
||||
);
|
||||
});
|
||||
|
||||
test('with text child node', () => {
|
||||
// @ts-expect-error
|
||||
const renderResult = render(<Icon>icon</Icon>);
|
||||
|
||||
expect(renderResult.container.innerHTML).toEqual('icon');
|
||||
});
|
||||
|
||||
test('with multiple childen', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<Icon>
|
||||
<i className="fa fa-home" />
|
||||
Home
|
||||
</Icon>
|
||||
);
|
||||
|
||||
expect(renderResult.container.innerHTML).toEqual(
|
||||
'<i class="fa fa-home"></i>Home'
|
||||
);
|
||||
});
|
||||
});
|
@ -1,81 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Rendering as span', () => {
|
||||
test('basic icon', () => {
|
||||
const component = renderer.create(
|
||||
<Icon
|
||||
icon={iconData}
|
||||
mode="style"
|
||||
onLoad={() => {
|
||||
// Should be called only for icons loaded from API
|
||||
throw new Error('onLoad called for object!');
|
||||
}}
|
||||
/>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'span',
|
||||
props: {
|
||||
style: {
|
||||
'--svg': `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z' fill='currentColor'/%3E%3C/svg%3E")`,
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'display': 'inline-block',
|
||||
'backgroundColor': 'currentColor',
|
||||
// 'webkitMaskImage': 'var(--svg)',
|
||||
// 'webkitMaskRepeat': 'no-repeat',
|
||||
// 'webkitMaskSize': '100% 100%',
|
||||
'maskImage': 'var(--svg)',
|
||||
'maskRepeat': 'no-repeat',
|
||||
'maskSize': '100% 100%',
|
||||
},
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('custom dimensions', () => {
|
||||
const component = renderer.create(
|
||||
<Icon
|
||||
icon={iconData}
|
||||
mode="style"
|
||||
width="32"
|
||||
height={48}
|
||||
onLoad={() => {
|
||||
// Should be called only for icons loaded from API
|
||||
throw new Error('onLoad called for object!');
|
||||
}}
|
||||
/>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'span',
|
||||
props: {
|
||||
style: {
|
||||
'--svg': `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z' fill='currentColor'/%3E%3C/svg%3E")`,
|
||||
'width': '32px',
|
||||
'height': '48px',
|
||||
'display': 'inline-block',
|
||||
'backgroundColor': 'currentColor',
|
||||
// 'webkitMaskImage': 'var(--svg)',
|
||||
// 'webkitMaskRepeat': 'no-repeat',
|
||||
// 'webkitMaskSize': '100% 100%',
|
||||
'maskImage': 'var(--svg)',
|
||||
'maskRepeat': 'no-repeat',
|
||||
'maskSize': '100% 100%',
|
||||
},
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
});
|
48
components/react/tests/iconify/10-style-mode.test.tsx
Normal file
48
components/react/tests/iconify/10-style-mode.test.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/iconify';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Rendering as span', () => {
|
||||
test('basic icon', () => {
|
||||
const renderResult = render(
|
||||
<Icon
|
||||
icon={iconData}
|
||||
mode="style"
|
||||
onLoad={() => {
|
||||
// Should be called only for icons loaded from API
|
||||
throw new Error('onLoad called for object!');
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(renderResult.container.innerHTML).toEqual(
|
||||
`<span style="--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z' fill='currentColor'/%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>`
|
||||
);
|
||||
});
|
||||
|
||||
test('custom dimensions', () => {
|
||||
const renderResult = render(
|
||||
<Icon
|
||||
icon={iconData}
|
||||
mode="style"
|
||||
width="32"
|
||||
height={48}
|
||||
onLoad={() => {
|
||||
// Should be called only for icons loaded from API
|
||||
throw new Error('onLoad called for object!');
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(renderResult.container.innerHTML).toEqual(
|
||||
`<span style="--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z' fill='currentColor'/%3E%3C/svg%3E"); width: 32px; height: 48px; display: inline-block; background-color: currentColor; mask-image: var(--svg); mask-repeat: no-repeat; mask-size: 100% 100%;"></span>`
|
||||
);
|
||||
});
|
||||
});
|
@ -1,83 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Passing attributes', () => {
|
||||
test('title', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} title="Icon!" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.title).toStrictEqual('Icon!');
|
||||
});
|
||||
|
||||
test('aria-hidden', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} aria-hidden="false" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props['aria-hidden']).toStrictEqual(void 0);
|
||||
});
|
||||
|
||||
test('ariaHidden', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} ariaHidden="false" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props['aria-hidden']).toStrictEqual(void 0);
|
||||
});
|
||||
|
||||
test('style', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon
|
||||
icon={iconData}
|
||||
style={{ verticalAlign: '0', color: 'red' }}
|
||||
/>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style).toMatchObject({
|
||||
verticalAlign: '0',
|
||||
color: 'red',
|
||||
});
|
||||
});
|
||||
|
||||
test('color', () => {
|
||||
const component = renderer.create(<Icon icon={iconData} color="red" />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style).toMatchObject({
|
||||
color: 'red',
|
||||
});
|
||||
});
|
||||
|
||||
test('color with style', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} color="red" style={{ color: 'green' }} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
// `style` overrides `color`
|
||||
expect(tree.props.style).toMatchObject({
|
||||
color: 'green',
|
||||
});
|
||||
});
|
||||
|
||||
test('attributes that cannot change', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} viewBox="0 0 0 0" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.viewBox).toStrictEqual('0 0 24 24');
|
||||
});
|
||||
});
|
75
components/react/tests/iconify/20-attributes.test.tsx
Normal file
75
components/react/tests/iconify/20-attributes.test.tsx
Normal file
@ -0,0 +1,75 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/iconify';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Passing attributes', () => {
|
||||
test('title', () => {
|
||||
// @ts-expect-error
|
||||
const renderResult = render(<Icon icon={iconData} title="Icon!" />);
|
||||
expect(renderResult.container.innerHTML).toContain('title="Icon!"');
|
||||
});
|
||||
|
||||
test('aria-hidden', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} aria-hidden="false" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('aria-hidden');
|
||||
});
|
||||
|
||||
test('ariaHidden', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<InlineIcon icon={iconData} ariaHidden="false" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('aria-hidden');
|
||||
});
|
||||
|
||||
test('style', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon
|
||||
icon={iconData}
|
||||
style={{ verticalAlign: '0', color: 'red' }}
|
||||
/>
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'style="vertical-align: 0; color: red;"'
|
||||
);
|
||||
});
|
||||
|
||||
test('color', () => {
|
||||
const renderResult = render(<Icon icon={iconData} color="red" />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'style="color: red;"'
|
||||
);
|
||||
});
|
||||
|
||||
test('color with style', () => {
|
||||
const renderResult = render(
|
||||
<Icon icon={iconData} color="red" style={{ color: 'green' }} />
|
||||
);
|
||||
|
||||
// `style` overrides `color`
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'style="color: green;"'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('red');
|
||||
});
|
||||
|
||||
test('attributes that cannot change', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} viewBox="0 0 0 0" />
|
||||
);
|
||||
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'viewBox="0 0 24 24"'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('0 0 0 0');
|
||||
});
|
||||
});
|
@ -1,51 +0,0 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Dimensions', () => {
|
||||
test('height', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} height="48" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.height).toStrictEqual('48');
|
||||
expect(tree.props.width).toStrictEqual('48');
|
||||
});
|
||||
|
||||
test('width and height', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} width={32} height="48" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.height).toStrictEqual('48');
|
||||
expect(tree.props.width).toStrictEqual('32');
|
||||
});
|
||||
|
||||
test('auto', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} height="auto" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.height).toStrictEqual('24');
|
||||
expect(tree.props.width).toStrictEqual('24');
|
||||
});
|
||||
|
||||
test('unset', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} height="unset" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.height).toStrictEqual(void 0);
|
||||
expect(tree.props.width).toStrictEqual(void 0);
|
||||
});
|
||||
});
|
48
components/react/tests/iconify/20-dimensions.test.tsx
Normal file
48
components/react/tests/iconify/20-dimensions.test.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '../../dist/iconify';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Dimensions', () => {
|
||||
test('height', () => {
|
||||
const renderResult = render(<InlineIcon icon={iconData} height="48" />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'width="48" height="48"'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('1em');
|
||||
});
|
||||
|
||||
test('width and height', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} width={32} height="48" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'width="32" height="48"'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('1em');
|
||||
});
|
||||
|
||||
test('auto', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} height="auto" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'width="24" height="24"'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('1em');
|
||||
});
|
||||
|
||||
test('unset', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} height="unset" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('width=');
|
||||
expect(renderResult.container.innerHTML).not.toContain('height=');
|
||||
});
|
||||
});
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconDataWithID = {
|
||||
body: '<defs><path id="ssvg-id-1st-place-medala" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medald" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medalf" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medalh" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medalj" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medalm" d="M.93.01h120.55v58.36H.93z"/><path d="M52.849 78.373v-3.908c3.681-.359 6.25-.958 7.703-1.798c1.454-.84 2.54-2.828 3.257-5.962h4.021v40.385h-5.437V78.373h-9.544z" id="ssvg-id-1st-place-medalp"/><linearGradient x1="49.998%" y1="-13.249%" x2="49.998%" y2="90.002%" id="ssvg-id-1st-place-medalb"><stop stop-color="#1E88E5" offset="13.55%"/><stop stop-color="#1565C0" offset="93.8%"/></linearGradient><linearGradient x1="26.648%" y1="2.735%" x2="77.654%" y2="105.978%" id="ssvg-id-1st-place-medalk"><stop stop-color="#64B5F6" offset="13.55%"/><stop stop-color="#2196F3" offset="94.62%"/></linearGradient><radialGradient cx="22.368%" cy="12.5%" fx="22.368%" fy="12.5%" r="95.496%" id="ssvg-id-1st-place-medalo"><stop stop-color="#FFEB3B" offset="29.72%"/><stop stop-color="#FBC02D" offset="95.44%"/></radialGradient></defs><g fill="none" fill-rule="evenodd"><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medalc" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medala"/></mask><path fill="url(#ssvg-id-1st-place-medalb)" fill-rule="nonzero" mask="url(#ssvg-id-1st-place-medalc)" d="M45.44 42.18h31.43l30-48.43H75.44z"/></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medale" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medald"/></mask><g opacity=".2" mask="url(#ssvg-id-1st-place-medale)" fill="#424242" fill-rule="nonzero"><path d="M101.23-3L75.2 39H50.85L77.11-3h24.12zm5.64-3H75.44l-30 48h31.42l30.01-48z"/></g></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medalg" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medalf"/></mask><path d="M79 30H43c-4.42 0-8 3.58-8 8v16.04c0 2.17 1.8 3.95 4.02 3.96h.01c2.23-.01 4.97-1.75 4.97-3.96V44c0-1.1.9-2 2-2h30c1.1 0 2 .9 2 2v9.93c0 1.98 2.35 3.68 4.22 4.04c.26.05.52.08.78.08c2.21 0 4-1.79 4-4V38c0-4.42-3.58-8-8-8z" fill="#FDD835" fill-rule="nonzero" mask="url(#ssvg-id-1st-place-medalg)"/></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medali" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medalh"/></mask><g opacity=".2" mask="url(#ssvg-id-1st-place-medali)" fill="#424242" fill-rule="nonzero"><path d="M79 32c3.31 0 6 2.69 6 6v16.04A2.006 2.006 0 0 1 82.59 56c-1.18-.23-2.59-1.35-2.59-2.07V44c0-2.21-1.79-4-4-4H46c-2.21 0-4 1.79-4 4v10.04c0 .88-1.64 1.96-2.97 1.96c-1.12-.01-2.03-.89-2.03-1.96V38c0-3.31 2.69-6 6-6h36zm0-2H43c-4.42 0-8 3.58-8 8v16.04c0 2.17 1.8 3.95 4.02 3.96h.01c2.23-.01 4.97-1.75 4.97-3.96V44c0-1.1.9-2 2-2h30c1.1 0 2 .9 2 2v9.93c0 1.98 2.35 3.68 4.22 4.04c.26.05.52.08.78.08c2.21 0 4-1.79 4-4V38c0-4.42-3.58-8-8-8z"/></g></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medall" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medalj"/></mask><path fill="url(#ssvg-id-1st-place-medalk)" fill-rule="nonzero" mask="url(#ssvg-id-1st-place-medall)" d="M76.87 42.18H45.44l-30-48.43h31.43z"/></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medaln" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medalm"/></mask><g opacity=".2" mask="url(#ssvg-id-1st-place-medaln)" fill="#424242" fill-rule="nonzero"><path d="M45.1-3l26.35 42H47.1L20.86-3H45.1zm1.77-3H15.44l30 48h31.42L46.87-6z"/></g></g><circle fill="url(#ssvg-id-1st-place-medalo)" fill-rule="nonzero" cx="64" cy="86" r="38"/><path d="M64 51c19.3 0 35 15.7 35 35s-15.7 35-35 35s-35-15.7-35-35s15.7-35 35-35zm0-3c-20.99 0-38 17.01-38 38s17.01 38 38 38s38-17.01 38-38s-17.01-38-38-38z" opacity=".2" fill="#424242" fill-rule="nonzero"/><path d="M47.3 63.59h33.4v44.4H47.3z"/><use fill="#000" xlink:href="#ssvg-id-1st-place-medalp"/><use fill="#FFA000" xlink:href="#ssvg-id-1st-place-medalp"/></g>',
|
||||
@ -10,47 +11,18 @@ const iconDataWithID = {
|
||||
|
||||
describe('Replacing IDs', () => {
|
||||
test('default behavior', () => {
|
||||
const component = renderer.create(<Icon icon={iconDataWithID} />);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconDataWithID.body);
|
||||
const renderResult = render(<Icon icon={iconDataWithID} />);
|
||||
expect(renderResult.container.innerHTML).not.toContain(
|
||||
'ssvg-id-1st-place-medal'
|
||||
);
|
||||
});
|
||||
|
||||
test('custom generator', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconDataWithID} id="test" />
|
||||
const renderResult = render(<Icon icon={iconDataWithID} id="test" />);
|
||||
expect(renderResult.container.innerHTML).not.toContain(
|
||||
'ssvg-id-1st-place-medal'
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
// Generate expected body
|
||||
let expected = iconDataWithID.body;
|
||||
const replacements = {
|
||||
'ssvg-id-1st-place-medala': 'testID0',
|
||||
'ssvg-id-1st-place-medald': 'testID1',
|
||||
'ssvg-id-1st-place-medalf': 'testID2',
|
||||
'ssvg-id-1st-place-medalh': 'testID3',
|
||||
'ssvg-id-1st-place-medalj': 'testID4',
|
||||
'ssvg-id-1st-place-medalm': 'testID5',
|
||||
'ssvg-id-1st-place-medalp': 'testID6',
|
||||
'ssvg-id-1st-place-medalb': 'testID7',
|
||||
'ssvg-id-1st-place-medalk': 'testID8',
|
||||
'ssvg-id-1st-place-medalo': 'testID9',
|
||||
'ssvg-id-1st-place-medalc': 'testID10',
|
||||
'ssvg-id-1st-place-medale': 'testID11',
|
||||
'ssvg-id-1st-place-medalg': 'testID12',
|
||||
'ssvg-id-1st-place-medali': 'testID13',
|
||||
'ssvg-id-1st-place-medall': 'testID14',
|
||||
'ssvg-id-1st-place-medaln': 'testID15',
|
||||
};
|
||||
Object.keys(replacements).forEach((search) => {
|
||||
expected = expected.replace(
|
||||
new RegExp(search, 'g'),
|
||||
replacements[search]
|
||||
);
|
||||
});
|
||||
|
||||
expect(body).toStrictEqual(expected);
|
||||
expect(renderResult.container.innerHTML).toContain('id="testID0"');
|
||||
expect(renderResult.container.innerHTML).toContain('id="testID10"');
|
||||
});
|
||||
});
|
@ -1,30 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Inline attribute', () => {
|
||||
test('string', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} inline="true" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style.verticalAlign).toStrictEqual('-0.125em');
|
||||
});
|
||||
|
||||
test('false string', () => {
|
||||
// "false" should be ignored
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} inline="false" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style.verticalAlign).toEqual(void 0);
|
||||
});
|
||||
});
|
43
components/react/tests/iconify/20-inline.test.tsx
Normal file
43
components/react/tests/iconify/20-inline.test.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/iconify';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Inline attribute', () => {
|
||||
test('boolean true', () => {
|
||||
const renderResult = render(<Icon icon={iconData} inline={true} />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'style="vertical-align: -0.125em;"'
|
||||
);
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
// @ts-expect-error
|
||||
const renderResult = render(<Icon icon={iconData} inline="true" />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'style="vertical-align: -0.125em;"'
|
||||
);
|
||||
});
|
||||
|
||||
test('false', () => {
|
||||
const renderResult = render(<Icon icon={iconData} inline={false} />);
|
||||
expect(renderResult.container.innerHTML).not.toContain(
|
||||
'vertical-align'
|
||||
);
|
||||
});
|
||||
|
||||
test('false string', () => {
|
||||
// "false" should be ignored
|
||||
// @ts-expect-error
|
||||
const renderResult = render(<Icon icon={iconData} inline="false" />);
|
||||
expect(renderResult.container.innerHTML).not.toContain(
|
||||
'vertical-align'
|
||||
);
|
||||
});
|
||||
});
|
@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body:
|
||||
'<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
@ -12,7 +12,7 @@ const iconData = {
|
||||
describe('Testing references', () => {
|
||||
test('basic icon reference', () => {
|
||||
let gotRef = false;
|
||||
const component = renderer.create(
|
||||
render(
|
||||
<Icon
|
||||
icon={iconData}
|
||||
ref={(element) => {
|
||||
@ -27,7 +27,7 @@ describe('Testing references', () => {
|
||||
|
||||
test('inline icon reference', () => {
|
||||
let gotRef = false;
|
||||
const component = renderer.create(
|
||||
render(
|
||||
<InlineIcon
|
||||
icon={iconData}
|
||||
ref={(element) => {
|
||||
@ -42,7 +42,8 @@ describe('Testing references', () => {
|
||||
|
||||
test('placeholder reference', () => {
|
||||
let gotRef = false;
|
||||
const component = renderer.create(
|
||||
render(
|
||||
// @ts-expect-error
|
||||
<Icon
|
||||
ref={(element) => {
|
||||
gotRef = true;
|
@ -1,114 +0,0 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Rotation', () => {
|
||||
test('number', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} rotate={1} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('rotate(90 ');
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} rotate="180deg" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('rotate(180 ');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Flip', () => {
|
||||
test('boolean', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} hFlip={true} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('scale(-1 1)');
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} flip="vertical" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('scale(1 -1)');
|
||||
});
|
||||
|
||||
test('string and boolean', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} flip="horizontal" vFlip={true} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
// horizontal + vertical = 180deg rotation
|
||||
expect(body).toMatch('rotate(180 ');
|
||||
});
|
||||
|
||||
test('string for boolean attribute', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} hFlip="true" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('scale(-1 1)');
|
||||
});
|
||||
|
||||
test('shorthand and boolean', () => {
|
||||
// 'flip' is processed after 'hFlip' because of order of elements in object, overwriting value
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} hFlip={false} flip="horizontal" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('scale(-1 1)');
|
||||
});
|
||||
|
||||
test('shorthand and boolean as string', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} flip="vertical" hFlip="true" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
// horizontal + vertical = 180deg rotation
|
||||
expect(body).toMatch('rotate(180 ');
|
||||
});
|
||||
|
||||
test('wrong case', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} vflip={true} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toMatch('scale(');
|
||||
});
|
||||
});
|
100
components/react/tests/iconify/20-transformations.test.tsx
Normal file
100
components/react/tests/iconify/20-transformations.test.tsx
Normal file
@ -0,0 +1,100 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '../../dist/iconify';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Rotation', () => {
|
||||
test('number', () => {
|
||||
const renderResult = render(<InlineIcon icon={iconData} rotate={1} />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="rotate(90 12 12)">'
|
||||
);
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<InlineIcon icon={iconData} rotate="180deg" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="rotate(180 12 12)">'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Flip', () => {
|
||||
test('boolean', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} hFlip={true} />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="translate(24 0) scale(-1 1)">'
|
||||
);
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} flip="vertical" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="translate(0 24) scale(1 -1)">'
|
||||
);
|
||||
});
|
||||
|
||||
test('string and boolean', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} flip="horizontal" vFlip={true} />
|
||||
);
|
||||
// horizontal + vertical = 180deg rotation
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="rotate(180 12 12)">'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('scale');
|
||||
});
|
||||
|
||||
test('string for boolean attribute', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<InlineIcon icon={iconData} hFlip="true" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="translate(24 0) scale(-1 1)">'
|
||||
);
|
||||
});
|
||||
|
||||
test('shorthand and boolean', () => {
|
||||
// 'flip' is processed after 'hFlip' because of order of elements in object, overwriting value
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} hFlip={false} flip="horizontal" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="translate(24 0) scale(-1 1)">'
|
||||
);
|
||||
});
|
||||
|
||||
test('shorthand and boolean as string', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<InlineIcon icon={iconData} flip="vertical" hFlip="true" />
|
||||
);
|
||||
// horizontal + vertical = 180deg rotation
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="rotate(180 12 12)">'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('scale');
|
||||
});
|
||||
|
||||
test('wrong case', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<InlineIcon icon={iconData} vflip={true} />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('transform');
|
||||
});
|
||||
});
|
@ -1,59 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/offline';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Creating component', () => {
|
||||
test('basic icon', () => {
|
||||
const component = renderer.create(<Icon icon={iconData} />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink': 'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox': '0 0 ' + iconData.width + ' ' + iconData.height,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('inline icon', () => {
|
||||
const component = renderer.create(<InlineIcon icon={iconData} />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink': 'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {
|
||||
verticalAlign: '-0.125em',
|
||||
},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox': '0 0 ' + iconData.width + ' ' + iconData.height,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
});
|
23
components/react/tests/offline/10-basic.test.tsx
Normal file
23
components/react/tests/offline/10-basic.test.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/offline';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Creating component', () => {
|
||||
test('basic icon', () => {
|
||||
const renderResult = render(<Icon icon={iconData} />);
|
||||
});
|
||||
|
||||
test('inline icon', () => {
|
||||
const renderResult = render(<InlineIcon icon={iconData} />);
|
||||
expect(renderResult.container.innerHTML).toEqual(
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" style="vertical-align: -0.125em;" width="1em" height="1em" viewBox="0 0 24 24"><path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"></path></svg>'
|
||||
);
|
||||
});
|
||||
});
|
@ -1,57 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/offline';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
describe('Empty icon', () => {
|
||||
test('basic test', () => {
|
||||
const component = renderer.create(<Icon />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'span',
|
||||
props: {},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('with child node', () => {
|
||||
const component = renderer.create(
|
||||
<Icon>
|
||||
<i class="fa fa-home" />
|
||||
</Icon>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'i',
|
||||
props: {},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('with text child node', () => {
|
||||
const component = renderer.create(<Icon>icon</Icon>);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatch('icon');
|
||||
});
|
||||
|
||||
test('with multiple childen', () => {
|
||||
const component = renderer.create(
|
||||
<Icon>
|
||||
<i class="fa fa-home" />
|
||||
Home
|
||||
</Icon>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject([
|
||||
{
|
||||
type: 'i',
|
||||
props: {},
|
||||
children: null,
|
||||
},
|
||||
'Home',
|
||||
]);
|
||||
});
|
||||
});
|
47
components/react/tests/offline/10-empty.test.tsx
Normal file
47
components/react/tests/offline/10-empty.test.tsx
Normal file
@ -0,0 +1,47 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/offline';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
describe('Empty icon', () => {
|
||||
test('basic test', () => {
|
||||
// @ts-expect-error
|
||||
const renderResult = render(<Icon />);
|
||||
|
||||
expect(renderResult.container.innerHTML).toEqual('<span></span>');
|
||||
});
|
||||
|
||||
test('with child node', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<Icon>
|
||||
<i className="fa fa-home" />
|
||||
</Icon>
|
||||
);
|
||||
|
||||
expect(renderResult.container.innerHTML).toEqual(
|
||||
'<i class="fa fa-home"></i>'
|
||||
);
|
||||
});
|
||||
|
||||
test('with text child node', () => {
|
||||
// @ts-expect-error
|
||||
const renderResult = render(<Icon>icon</Icon>);
|
||||
|
||||
expect(renderResult.container.innerHTML).toEqual('icon');
|
||||
});
|
||||
|
||||
test('with multiple childen', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<Icon>
|
||||
<i className="fa fa-home" />
|
||||
Home
|
||||
</Icon>
|
||||
);
|
||||
|
||||
expect(renderResult.container.innerHTML).toEqual(
|
||||
'<i class="fa fa-home"></i>Home'
|
||||
);
|
||||
});
|
||||
});
|
@ -1,85 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/offline';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Passing attributes', () => {
|
||||
test('title', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} title="Icon!" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.title).toStrictEqual('Icon!');
|
||||
});
|
||||
|
||||
test('aria-hidden', () => {
|
||||
// dashes, string value
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} aria-hidden="false" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props['aria-hidden']).toStrictEqual(void 0);
|
||||
});
|
||||
|
||||
test('ariaHidden', () => {
|
||||
// camelCase, boolean value
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} ariaHidden={false} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props['aria-hidden']).toStrictEqual(void 0);
|
||||
});
|
||||
|
||||
test('style', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon
|
||||
icon={iconData}
|
||||
style={{ verticalAlign: '0', color: 'red' }}
|
||||
/>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style).toMatchObject({
|
||||
verticalAlign: '0',
|
||||
color: 'red',
|
||||
});
|
||||
});
|
||||
|
||||
test('color', () => {
|
||||
const component = renderer.create(<Icon icon={iconData} color="red" />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style).toMatchObject({
|
||||
color: 'red',
|
||||
});
|
||||
});
|
||||
|
||||
test('color with style', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} color="red" style={{ color: 'green' }} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
// `style` overrides `color`
|
||||
expect(tree.props.style).toMatchObject({
|
||||
color: 'green',
|
||||
});
|
||||
});
|
||||
|
||||
test('attributes that cannot change', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} viewBox="0 0 0 0" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.viewBox).toStrictEqual('0 0 24 24');
|
||||
});
|
||||
});
|
77
components/react/tests/offline/20-attributes.test.tsx
Normal file
77
components/react/tests/offline/20-attributes.test.tsx
Normal file
@ -0,0 +1,77 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/offline';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Passing attributes', () => {
|
||||
test('title', () => {
|
||||
// @ts-expect-error
|
||||
const renderResult = render(<Icon icon={iconData} title="Icon!" />);
|
||||
expect(renderResult.container.innerHTML).toContain('title="Icon!"');
|
||||
});
|
||||
|
||||
test('aria-hidden', () => {
|
||||
// dashes, string value
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} aria-hidden="false" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('aria-hidden');
|
||||
});
|
||||
|
||||
test('ariaHidden', () => {
|
||||
// camelCase, boolean value
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<InlineIcon icon={iconData} ariaHidden="false" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('aria-hidden');
|
||||
});
|
||||
|
||||
test('style', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon
|
||||
icon={iconData}
|
||||
style={{ verticalAlign: '0', color: 'red' }}
|
||||
/>
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'style="vertical-align: 0; color: red;"'
|
||||
);
|
||||
});
|
||||
|
||||
test('color', () => {
|
||||
const renderResult = render(<Icon icon={iconData} color="red" />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'style="color: red;"'
|
||||
);
|
||||
});
|
||||
|
||||
test('color with style', () => {
|
||||
const renderResult = render(
|
||||
<Icon icon={iconData} color="red" style={{ color: 'green' }} />
|
||||
);
|
||||
|
||||
// `style` overrides `color`
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'style="color: green;"'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('red');
|
||||
});
|
||||
|
||||
test('attributes that cannot change', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} viewBox="0 0 0 0" />
|
||||
);
|
||||
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'viewBox="0 0 24 24"'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('0 0 0 0');
|
||||
});
|
||||
});
|
@ -1,51 +0,0 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '../../dist/offline';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Dimensions', () => {
|
||||
test('height', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} height="48" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.height).toStrictEqual('48');
|
||||
expect(tree.props.width).toStrictEqual('48');
|
||||
});
|
||||
|
||||
test('width and height', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} width={32} height="48" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.height).toStrictEqual('48');
|
||||
expect(tree.props.width).toStrictEqual('32');
|
||||
});
|
||||
|
||||
test('auto', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} height="auto" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.height).toStrictEqual('24');
|
||||
expect(tree.props.width).toStrictEqual('24');
|
||||
});
|
||||
|
||||
test('undefined', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} height="undefined" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.height).toStrictEqual(void 0);
|
||||
expect(tree.props.width).toStrictEqual(void 0);
|
||||
});
|
||||
});
|
48
components/react/tests/offline/20-dimensions.test.tsx
Normal file
48
components/react/tests/offline/20-dimensions.test.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '../../dist/offline';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Dimensions', () => {
|
||||
test('height', () => {
|
||||
const renderResult = render(<InlineIcon icon={iconData} height="48" />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'width="48" height="48"'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('1em');
|
||||
});
|
||||
|
||||
test('width and height', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} width={32} height="48" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'width="32" height="48"'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('1em');
|
||||
});
|
||||
|
||||
test('auto', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} height="auto" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'width="24" height="24"'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('1em');
|
||||
});
|
||||
|
||||
test('unset', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} height="unset" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('width=');
|
||||
expect(renderResult.container.innerHTML).not.toContain('height=');
|
||||
});
|
||||
});
|
@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/offline';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconDataWithID = {
|
||||
body: '<defs><path id="ssvg-id-1st-place-medala" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medald" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medalf" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medalh" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medalj" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medalm" d="M.93.01h120.55v58.36H.93z"/><path d="M52.849 78.373v-3.908c3.681-.359 6.25-.958 7.703-1.798c1.454-.84 2.54-2.828 3.257-5.962h4.021v40.385h-5.437V78.373h-9.544z" id="ssvg-id-1st-place-medalp"/><linearGradient x1="49.998%" y1="-13.249%" x2="49.998%" y2="90.002%" id="ssvg-id-1st-place-medalb"><stop stop-color="#1E88E5" offset="13.55%"/><stop stop-color="#1565C0" offset="93.8%"/></linearGradient><linearGradient x1="26.648%" y1="2.735%" x2="77.654%" y2="105.978%" id="ssvg-id-1st-place-medalk"><stop stop-color="#64B5F6" offset="13.55%"/><stop stop-color="#2196F3" offset="94.62%"/></linearGradient><radialGradient cx="22.368%" cy="12.5%" fx="22.368%" fy="12.5%" r="95.496%" id="ssvg-id-1st-place-medalo"><stop stop-color="#FFEB3B" offset="29.72%"/><stop stop-color="#FBC02D" offset="95.44%"/></radialGradient></defs><g fill="none" fill-rule="evenodd"><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medalc" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medala"/></mask><path fill="url(#ssvg-id-1st-place-medalb)" fill-rule="nonzero" mask="url(#ssvg-id-1st-place-medalc)" d="M45.44 42.18h31.43l30-48.43H75.44z"/></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medale" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medald"/></mask><g opacity=".2" mask="url(#ssvg-id-1st-place-medale)" fill="#424242" fill-rule="nonzero"><path d="M101.23-3L75.2 39H50.85L77.11-3h24.12zm5.64-3H75.44l-30 48h31.42l30.01-48z"/></g></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medalg" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medalf"/></mask><path d="M79 30H43c-4.42 0-8 3.58-8 8v16.04c0 2.17 1.8 3.95 4.02 3.96h.01c2.23-.01 4.97-1.75 4.97-3.96V44c0-1.1.9-2 2-2h30c1.1 0 2 .9 2 2v9.93c0 1.98 2.35 3.68 4.22 4.04c.26.05.52.08.78.08c2.21 0 4-1.79 4-4V38c0-4.42-3.58-8-8-8z" fill="#FDD835" fill-rule="nonzero" mask="url(#ssvg-id-1st-place-medalg)"/></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medali" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medalh"/></mask><g opacity=".2" mask="url(#ssvg-id-1st-place-medali)" fill="#424242" fill-rule="nonzero"><path d="M79 32c3.31 0 6 2.69 6 6v16.04A2.006 2.006 0 0 1 82.59 56c-1.18-.23-2.59-1.35-2.59-2.07V44c0-2.21-1.79-4-4-4H46c-2.21 0-4 1.79-4 4v10.04c0 .88-1.64 1.96-2.97 1.96c-1.12-.01-2.03-.89-2.03-1.96V38c0-3.31 2.69-6 6-6h36zm0-2H43c-4.42 0-8 3.58-8 8v16.04c0 2.17 1.8 3.95 4.02 3.96h.01c2.23-.01 4.97-1.75 4.97-3.96V44c0-1.1.9-2 2-2h30c1.1 0 2 .9 2 2v9.93c0 1.98 2.35 3.68 4.22 4.04c.26.05.52.08.78.08c2.21 0 4-1.79 4-4V38c0-4.42-3.58-8-8-8z"/></g></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medall" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medalj"/></mask><path fill="url(#ssvg-id-1st-place-medalk)" fill-rule="nonzero" mask="url(#ssvg-id-1st-place-medall)" d="M76.87 42.18H45.44l-30-48.43h31.43z"/></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medaln" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medalm"/></mask><g opacity=".2" mask="url(#ssvg-id-1st-place-medaln)" fill="#424242" fill-rule="nonzero"><path d="M45.1-3l26.35 42H47.1L20.86-3H45.1zm1.77-3H15.44l30 48h31.42L46.87-6z"/></g></g><circle fill="url(#ssvg-id-1st-place-medalo)" fill-rule="nonzero" cx="64" cy="86" r="38"/><path d="M64 51c19.3 0 35 15.7 35 35s-15.7 35-35 35s-35-15.7-35-35s15.7-35 35-35zm0-3c-20.99 0-38 17.01-38 38s17.01 38 38 38s38-17.01 38-38s-17.01-38-38-38z" opacity=".2" fill="#424242" fill-rule="nonzero"/><path d="M47.3 63.59h33.4v44.4H47.3z"/><use fill="#000" xlink:href="#ssvg-id-1st-place-medalp"/><use fill="#FFA000" xlink:href="#ssvg-id-1st-place-medalp"/></g>',
|
||||
@ -10,48 +11,18 @@ const iconDataWithID = {
|
||||
|
||||
describe('Replacing IDs', () => {
|
||||
test('default behavior', () => {
|
||||
const component = renderer.create(<Icon icon={iconDataWithID} />);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
// Check that default id doesn't exist
|
||||
expect(body.indexOf('ssvg-id-1st-place-medala')).toEqual(-1);
|
||||
const renderResult = render(<Icon icon={iconDataWithID} />);
|
||||
expect(renderResult.container.innerHTML).not.toContain(
|
||||
'ssvg-id-1st-place-medal'
|
||||
);
|
||||
});
|
||||
|
||||
test('custom generator', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconDataWithID} id="test" />
|
||||
const renderResult = render(<Icon icon={iconDataWithID} id="test" />);
|
||||
expect(renderResult.container.innerHTML).not.toContain(
|
||||
'ssvg-id-1st-place-medal'
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
// Generate expected body
|
||||
let expected = iconDataWithID.body;
|
||||
const replacements = {
|
||||
'ssvg-id-1st-place-medala': 'testID0',
|
||||
'ssvg-id-1st-place-medald': 'testID1',
|
||||
'ssvg-id-1st-place-medalf': 'testID2',
|
||||
'ssvg-id-1st-place-medalh': 'testID3',
|
||||
'ssvg-id-1st-place-medalj': 'testID4',
|
||||
'ssvg-id-1st-place-medalm': 'testID5',
|
||||
'ssvg-id-1st-place-medalp': 'testID6',
|
||||
'ssvg-id-1st-place-medalb': 'testID7',
|
||||
'ssvg-id-1st-place-medalk': 'testID8',
|
||||
'ssvg-id-1st-place-medalo': 'testID9',
|
||||
'ssvg-id-1st-place-medalc': 'testID10',
|
||||
'ssvg-id-1st-place-medale': 'testID11',
|
||||
'ssvg-id-1st-place-medalg': 'testID12',
|
||||
'ssvg-id-1st-place-medali': 'testID13',
|
||||
'ssvg-id-1st-place-medall': 'testID14',
|
||||
'ssvg-id-1st-place-medaln': 'testID15',
|
||||
};
|
||||
Object.keys(replacements).forEach((search) => {
|
||||
expected = expected.replace(
|
||||
new RegExp(search, 'g'),
|
||||
replacements[search]
|
||||
);
|
||||
});
|
||||
|
||||
expect(body).toStrictEqual(expected);
|
||||
expect(renderResult.container.innerHTML).toContain('id="testID0"');
|
||||
expect(renderResult.container.innerHTML).toContain('id="testID10"');
|
||||
});
|
||||
});
|
@ -1,48 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/offline';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Inline attribute', () => {
|
||||
test('boolean true', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} inline={true} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style.verticalAlign).toStrictEqual('-0.125em');
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} inline="true" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style.verticalAlign).toStrictEqual('-0.125em');
|
||||
});
|
||||
|
||||
test('false', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} inline={false} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style.verticalAlign).toEqual(void 0);
|
||||
});
|
||||
|
||||
test('false string', () => {
|
||||
// "false" should be ignored
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} inline="false" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style.verticalAlign).toEqual(void 0);
|
||||
});
|
||||
});
|
43
components/react/tests/offline/20-inline.test.tsx
Normal file
43
components/react/tests/offline/20-inline.test.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/offline';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Inline attribute', () => {
|
||||
test('boolean true', () => {
|
||||
const renderResult = render(<Icon icon={iconData} inline={true} />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'style="vertical-align: -0.125em;"'
|
||||
);
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
// @ts-expect-error
|
||||
const renderResult = render(<Icon icon={iconData} inline="true" />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'style="vertical-align: -0.125em;"'
|
||||
);
|
||||
});
|
||||
|
||||
test('false', () => {
|
||||
const renderResult = render(<Icon icon={iconData} inline={false} />);
|
||||
expect(renderResult.container.innerHTML).not.toContain(
|
||||
'vertical-align'
|
||||
);
|
||||
});
|
||||
|
||||
test('false string', () => {
|
||||
// "false" should be ignored
|
||||
// @ts-expect-error
|
||||
const renderResult = render(<Icon icon={iconData} inline="false" />);
|
||||
expect(renderResult.container.innerHTML).not.toContain(
|
||||
'vertical-align'
|
||||
);
|
||||
});
|
||||
});
|
@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/offline';
|
||||
import renderer from 'react-test-renderer';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body:
|
||||
'<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
@ -12,7 +12,7 @@ const iconData = {
|
||||
describe('Testing references', () => {
|
||||
test('basic icon reference', () => {
|
||||
let gotRef = false;
|
||||
const component = renderer.create(
|
||||
render(
|
||||
<Icon
|
||||
icon={iconData}
|
||||
ref={(element) => {
|
||||
@ -27,7 +27,7 @@ describe('Testing references', () => {
|
||||
|
||||
test('inline icon reference', () => {
|
||||
let gotRef = false;
|
||||
const component = renderer.create(
|
||||
render(
|
||||
<InlineIcon
|
||||
icon={iconData}
|
||||
ref={(element) => {
|
||||
@ -42,7 +42,8 @@ describe('Testing references', () => {
|
||||
|
||||
test('placeholder reference', () => {
|
||||
let gotRef = false;
|
||||
const component = renderer.create(
|
||||
render(
|
||||
// @ts-expect-error
|
||||
<Icon
|
||||
ref={(element) => {
|
||||
gotRef = true;
|
@ -1,122 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Icon, addIcon, addCollection } from '../../dist/offline';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Using storage', () => {
|
||||
test('using storage', () => {
|
||||
addIcon('test-icon', iconData);
|
||||
const component = renderer.create(<Icon icon="test-icon" />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink': 'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox': '0 0 ' + iconData.width + ' ' + iconData.height,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('using storage with icon set', () => {
|
||||
const iconSet = {
|
||||
prefix: 'mdi-light',
|
||||
icons: {
|
||||
account: {
|
||||
body: '<path d="M11.5 14c4.142 0 7.5 1.567 7.5 3.5V20H4v-2.5c0-1.933 3.358-3.5 7.5-3.5zm6.5 3.5c0-1.38-2.91-2.5-6.5-2.5S5 16.12 5 17.5V19h13v-1.5zM11.5 5a3.5 3.5 0 1 1 0 7a3.5 3.5 0 0 1 0-7zm0 1a2.5 2.5 0 1 0 0 5a2.5 2.5 0 0 0 0-5z" fill="currentColor"/>',
|
||||
},
|
||||
home: {
|
||||
body: '<path d="M16 8.414l-4.5-4.5L4.414 11H6v8h3v-6h5v6h3v-8h1.586L17 9.414V6h-1v2.414zM2 12l9.5-9.5L15 6V5h3v4l3 3h-3v7.998h-5v-6h-3v6H5V12H2z" fill="currentColor"/>',
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
addCollection(iconSet);
|
||||
const component = renderer.create(<Icon icon="mdi-light:account" />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink': 'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconSet.icons.account.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox': '0 0 ' + iconSet.width + ' ' + iconSet.height,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('using storage with icon set with custom prefix', () => {
|
||||
const iconSet = {
|
||||
prefix: 'mdi-light',
|
||||
icons: {
|
||||
'account-alert': {
|
||||
body: '<path d="M10.5 14c4.142 0 7.5 1.567 7.5 3.5V20H3v-2.5c0-1.933 3.358-3.5 7.5-3.5zm6.5 3.5c0-1.38-2.91-2.5-6.5-2.5S4 16.12 4 17.5V19h13v-1.5zM10.5 5a3.5 3.5 0 1 1 0 7a3.5 3.5 0 0 1 0-7zm0 1a2.5 2.5 0 1 0 0 5a2.5 2.5 0 0 0 0-5zM20 16v-1h1v1h-1zm0-3V7h1v6h-1z" fill="currentColor"/>',
|
||||
},
|
||||
'link': {
|
||||
body: '<path d="M8 13v-1h7v1H8zm7.5-6a5.5 5.5 0 1 1 0 11H13v-1h2.5a4.5 4.5 0 1 0 0-9H13V7h2.5zm-8 11a5.5 5.5 0 1 1 0-11H10v1H7.5a4.5 4.5 0 1 0 0 9H10v1H7.5z" fill="currentColor"/>',
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
addCollection(iconSet, 'custom-');
|
||||
const component = renderer.create(<Icon icon="custom-link" />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink': 'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconSet.icons.link.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'viewBox': '0 0 ' + iconSet.width + ' ' + iconSet.height,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('missing icon from storage', () => {
|
||||
const component = renderer.create(<Icon icon="missing-icon" />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'span',
|
||||
props: {},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
});
|
70
components/react/tests/offline/20-storage.test.tsx
Normal file
70
components/react/tests/offline/20-storage.test.tsx
Normal file
@ -0,0 +1,70 @@
|
||||
import React from 'react';
|
||||
import { Icon, addIcon, addCollection } from '../../dist/offline';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Using storage', () => {
|
||||
test('using storage', () => {
|
||||
addIcon('test-icon', iconData);
|
||||
|
||||
const renderResult = render(<Icon icon="test-icon" />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z'
|
||||
);
|
||||
});
|
||||
|
||||
test('using storage with icon set', () => {
|
||||
const iconSet = {
|
||||
prefix: 'mdi-light',
|
||||
icons: {
|
||||
account: {
|
||||
body: '<path d="M11.5 14c4.142 0 7.5 1.567 7.5 3.5V20H4v-2.5c0-1.933 3.358-3.5 7.5-3.5zm6.5 3.5c0-1.38-2.91-2.5-6.5-2.5S5 16.12 5 17.5V19h13v-1.5zM11.5 5a3.5 3.5 0 1 1 0 7a3.5 3.5 0 0 1 0-7zm0 1a2.5 2.5 0 1 0 0 5a2.5 2.5 0 0 0 0-5z" fill="currentColor"/>',
|
||||
},
|
||||
home: {
|
||||
body: '<path d="M16 8.414l-4.5-4.5L4.414 11H6v8h3v-6h5v6h3v-8h1.586L17 9.414V6h-1v2.414zM2 12l9.5-9.5L15 6V5h3v4l3 3h-3v7.998h-5v-6h-3v6H5V12H2z" fill="currentColor"/>',
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
addCollection(iconSet);
|
||||
|
||||
const renderResult = render(<Icon icon="mdi-light:account" />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'"M11.5 14c4.142 0 7.5 1.567 7.5 3.5V20'
|
||||
);
|
||||
});
|
||||
|
||||
test('using storage with icon set with custom prefix', () => {
|
||||
const iconSet = {
|
||||
prefix: 'mdi-light',
|
||||
icons: {
|
||||
'account-alert': {
|
||||
body: '<path d="M10.5 14c4.142 0 7.5 1.567 7.5 3.5V20H3v-2.5c0-1.933 3.358-3.5 7.5-3.5zm6.5 3.5c0-1.38-2.91-2.5-6.5-2.5S4 16.12 4 17.5V19h13v-1.5zM10.5 5a3.5 3.5 0 1 1 0 7a3.5 3.5 0 0 1 0-7zm0 1a2.5 2.5 0 1 0 0 5a2.5 2.5 0 0 0 0-5zM20 16v-1h1v1h-1zm0-3V7h1v6h-1z" fill="currentColor"/>',
|
||||
},
|
||||
'link': {
|
||||
body: '<path d="M8 13v-1h7v1H8zm7.5-6a5.5 5.5 0 1 1 0 11H13v-1h2.5a4.5 4.5 0 1 0 0-9H13V7h2.5zm-8 11a5.5 5.5 0 1 1 0-11H10v1H7.5a4.5 4.5 0 1 0 0 9H10v1H7.5z" fill="currentColor"/>',
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
addCollection(iconSet, 'custom-');
|
||||
|
||||
const renderResult = render(<Icon icon="custom-link" />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'M8 13v-1h7v1H8zm7.5-6a5.5 5.5 0 1 1 0 11H13v-1h2.5'
|
||||
);
|
||||
});
|
||||
|
||||
test('missing icon from storage', () => {
|
||||
const renderResult = render(<Icon icon="missing-icon" />);
|
||||
expect(renderResult.container.innerHTML).toEqual('<span></span>');
|
||||
});
|
||||
});
|
@ -1,114 +0,0 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '../../dist/offline';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 32,
|
||||
};
|
||||
|
||||
describe('Rotation', () => {
|
||||
test('number', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} rotate={1} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('rotate(90 ');
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} rotate="180deg" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('rotate(180 ');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Flip', () => {
|
||||
test('boolean', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} hFlip={true} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('scale(-1 1)');
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} flip="vertical" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('scale(1 -1)');
|
||||
});
|
||||
|
||||
test('string and boolean', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} flip="horizontal" vFlip={true} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
// horizontal + vertical = 180deg rotation
|
||||
expect(body).toMatch('rotate(180 ');
|
||||
});
|
||||
|
||||
test('string for boolean attribute', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} hFlip="true" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('scale(-1 1)');
|
||||
});
|
||||
|
||||
test('shorthand and boolean', () => {
|
||||
// 'flip' is processed after 'hFlip' because of order of elements in object, overwriting value
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} hFlip={false} flip="horizontal" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('scale(-1 1)');
|
||||
});
|
||||
|
||||
test('shorthand and boolean as string', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} flip="vertical" hFlip="true" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
// horizontal + vertical = 180deg rotation
|
||||
expect(body).toMatch('rotate(180 ');
|
||||
});
|
||||
|
||||
test('wrong case', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} vflip={true} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toMatch('scale(');
|
||||
});
|
||||
});
|
100
components/react/tests/offline/20-transformations.test.tsx
Normal file
100
components/react/tests/offline/20-transformations.test.tsx
Normal file
@ -0,0 +1,100 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '../../dist/offline';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const iconData = {
|
||||
body: '<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Rotation', () => {
|
||||
test('number', () => {
|
||||
const renderResult = render(<InlineIcon icon={iconData} rotate={1} />);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="rotate(90 12 12)">'
|
||||
);
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<InlineIcon icon={iconData} rotate="180deg" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="rotate(180 12 12)">'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Flip', () => {
|
||||
test('boolean', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} hFlip={true} />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="translate(24 0) scale(-1 1)">'
|
||||
);
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} flip="vertical" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="translate(0 24) scale(1 -1)">'
|
||||
);
|
||||
});
|
||||
|
||||
test('string and boolean', () => {
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} flip="horizontal" vFlip={true} />
|
||||
);
|
||||
// horizontal + vertical = 180deg rotation
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="rotate(180 12 12)">'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('scale');
|
||||
});
|
||||
|
||||
test('string for boolean attribute', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<InlineIcon icon={iconData} hFlip="true" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="translate(24 0) scale(-1 1)">'
|
||||
);
|
||||
});
|
||||
|
||||
test('shorthand and boolean', () => {
|
||||
// 'flip' is processed after 'hFlip' because of order of elements in object, overwriting value
|
||||
const renderResult = render(
|
||||
<InlineIcon icon={iconData} hFlip={false} flip="horizontal" />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="translate(24 0) scale(-1 1)">'
|
||||
);
|
||||
});
|
||||
|
||||
test('shorthand and boolean as string', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<InlineIcon icon={iconData} flip="vertical" hFlip="true" />
|
||||
);
|
||||
// horizontal + vertical = 180deg rotation
|
||||
expect(renderResult.container.innerHTML).toContain(
|
||||
'<g transform="rotate(180 12 12)">'
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('scale');
|
||||
});
|
||||
|
||||
test('wrong case', () => {
|
||||
const renderResult = render(
|
||||
// @ts-expect-error
|
||||
<InlineIcon icon={iconData} vflip={true} />
|
||||
);
|
||||
expect(renderResult.container.innerHTML).not.toContain('transform');
|
||||
});
|
||||
});
|
@ -1,15 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"target": "ES2019",
|
||||
"module": "ESNext",
|
||||
"declaration": true,
|
||||
"sourceMap": false,
|
||||
"strict": false,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.src.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.tests.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
17
components/react/tsconfig.src.json
Normal file
17
components/react/tsconfig.src.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["tests/**/*"],
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"target": "ES2019",
|
||||
"module": "ESNext",
|
||||
"declaration": true,
|
||||
"sourceMap": false,
|
||||
"strict": false,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
18
components/react/tsconfig.tests.json
Normal file
18
components/react/tsconfig.tests.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"include": ["tests/**/*", "tests/**/*.tsx"],
|
||||
"exclude": ["src/*"],
|
||||
"compilerOptions": {
|
||||
"rootDir": "./tests",
|
||||
"target": "ES2019",
|
||||
"module": "ESNext",
|
||||
"declaration": false,
|
||||
"sourceMap": false,
|
||||
"strict": false,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"skipLibCheck": true,
|
||||
"jsx": "react",
|
||||
"noEmit": true
|
||||
}
|
||||
}
|
8
components/react/vitest.config.ts
Normal file
8
components/react/vitest.config.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
},
|
||||
});
|
1106
pnpm-lock.yaml
1106
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user