mirror of
https://github.com/iconify/iconify.git
synced 2024-09-14 14:29:04 +00:00
Move version 2 to a big monorepo
This commit is contained in:
commit
58d4cf3d49
9
.editorconfig
Normal file
9
.editorconfig
Normal file
@ -0,0 +1,9 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.DS_Store
|
||||
node_modules
|
8
.prettierrc
Normal file
8
.prettierrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"singleQuote": true,
|
||||
"useTabs": true,
|
||||
"semi": true,
|
||||
"quoteProps": "consistent",
|
||||
"endOfLine": "lf"
|
||||
}
|
10
.vscode/settings.json
vendored
Normal file
10
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"spellright.language": [
|
||||
"en"
|
||||
],
|
||||
"spellright.documentTypes": [
|
||||
"markdown",
|
||||
"latex",
|
||||
"plaintext"
|
||||
]
|
||||
}
|
69
README.md
Normal file
69
README.md
Normal file
@ -0,0 +1,69 @@
|
||||
### What is Iconify?
|
||||
|
||||
Iconify is the most versatile icon framework.
|
||||
|
||||
- Unified icon framework that can be used with any icon library.
|
||||
- Out of the box includes 60+ icon sets with 50,000 icons.
|
||||
- Embed icons in HTML with SVG framework or components for front-end frameworks.
|
||||
- Embed icons in designs with plug-ins for Figma, Sketch and Adobe XD.
|
||||
- Add icon search to your applications with Iconify Icon Finder.
|
||||
|
||||
For more information visit [https://iconify.design/](https://iconify.design/).
|
||||
|
||||
## This repository
|
||||
|
||||
This repository is a big monorepo that contains several implementations of Iconify icon framework.
|
||||
|
||||
There are two types of Iconify implementations:
|
||||
|
||||
- Implementations that rely on icon packages.
|
||||
- Implementations that rely on Iconify API.
|
||||
|
||||
### Implementations: without API
|
||||
|
||||
These Iconify implementations require the developer to provide icon data and expect that icon data to be included in the bundle.
|
||||
|
||||
Examples: Iconify for React, Iconify for Vue.
|
||||
|
||||
They are easy to use and do not require an internet connection to work, similar to other React/Vue components.
|
||||
|
||||
### Implementations: with API
|
||||
|
||||
Iconify is designed to be easy to use. One of the main features is the Iconify API.
|
||||
|
||||
Iconify API provides data for over 50,000 icons! API is hosted on publicly available servers, spread out geographically to make sure visitors from all over the world have the fastest possible connection with redundancies in place to make sure it is always online.
|
||||
|
||||
#### Why is API needed?
|
||||
|
||||
When you use an icon font, each visitor loads an entire font, even if your page only uses a few icons. This is a major downside of using icon fonts. That limits developers to one or two fonts or icon sets.
|
||||
|
||||
Unlike icon fonts, Iconify implementations that use API do not load the entire icon set. Unlike fonts and SVG frameworks, Iconify only loads icons that are used on the current page instead of loading entire icon sets. Iconify API provides icon data to Iconify SVG framework and other implementations that rely on Iconify API.
|
||||
|
||||
## Available packages
|
||||
|
||||
There are several Iconify implementations included in this repository:
|
||||
|
||||
| Implementation | Usage | with API | without API |
|
||||
| ------------------------------------ | ----- | :------: | :---------: |
|
||||
| [SVG Framework](./packages/iconify/) | HTML | + | + |
|
||||
| [React component](./packages/react/) | React | - | + |
|
||||
| [Vue component](./packages/vue/) | Vue | - | + |
|
||||
|
||||
Other packages:
|
||||
|
||||
- [Iconify types](./packages/types/) - TypeScript types used by various implementations.
|
||||
- [Iconify core](./packages/core/) - common files used by various implementations.
|
||||
- [React demo](./packages/react-demo/) - demo for React component. Run `npm start` to start demo.
|
||||
- [Vue demo](./packages/vue-demo/) - demo for Vue component. Run `npm serve` to start demo.
|
||||
- [Browser tests](./packages/browser-tests/) - unit tests for SVG framework. Must be ran in browser.
|
||||
|
||||
## License
|
||||
|
||||
Iconify is dual-licensed under Apache 2.0 and GPL 2.0 license. You may select, at your option, one of the above-listed licenses.
|
||||
|
||||
`SPDX-License-Identifier: Apache-2.0 OR GPL-2.0`
|
||||
|
||||
This license does not apply to icons. Icons are released under different licenses, see each icon set for details.
|
||||
Icons available by default are all licensed under some kind of open-source or free license.
|
||||
|
||||
© 2020 Vjacheslav Trushkin
|
7
lerna.json
Normal file
7
lerna.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": "independent",
|
||||
"npmClient": "npm",
|
||||
"packages": [
|
||||
"packages/*"
|
||||
]
|
||||
}
|
6590
package-lock.json
generated
Normal file
6590
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
package.json
Normal file
25
package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "iconify",
|
||||
"private": true,
|
||||
"description": "The most versatile icon framework",
|
||||
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
|
||||
"license": "(Apache-2.0 OR GPL-2.0)",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"bugs": "https://github.com/iconify/iconify/issues",
|
||||
"homepage": "https://iconify.design/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/iconify/iconify.git"
|
||||
},
|
||||
"scripts": {
|
||||
"bootstrap": "lerna bootstrap --force-local",
|
||||
"clean": "lerna clean",
|
||||
"link": "lerna link --force-local",
|
||||
"setup": "npm run clean && npm run bootstrap"
|
||||
},
|
||||
"devDependencies": {
|
||||
"lerna": "^3.20.2"
|
||||
}
|
||||
}
|
0
packages/.gitignore
vendored
Normal file
0
packages/.gitignore
vendored
Normal file
4
packages/browser-tests/.gitignore
vendored
Normal file
4
packages/browser-tests/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
lib
|
||||
dist
|
97
packages/browser-tests/build.js
Normal file
97
packages/browser-tests/build.js
Normal file
@ -0,0 +1,97 @@
|
||||
const path = require('path');
|
||||
const child_process = require('child_process');
|
||||
|
||||
// List of commands to run
|
||||
const commands = [];
|
||||
|
||||
// Parse command line
|
||||
const compile = {
|
||||
core: false,
|
||||
iconify: false,
|
||||
lib: true,
|
||||
dist: true,
|
||||
};
|
||||
process.argv.slice(2).forEach(cmd => {
|
||||
if (cmd.slice(0, 2) !== '--') {
|
||||
return;
|
||||
}
|
||||
const parts = cmd.slice(2).split('-');
|
||||
if (parts.length === 2) {
|
||||
// Parse 2 part commands like --with-lib
|
||||
const key = parts.pop();
|
||||
if (compile[key] === void 0) {
|
||||
return;
|
||||
}
|
||||
switch (parts.shift()) {
|
||||
case 'with':
|
||||
// enable module
|
||||
compile[key] = true;
|
||||
break;
|
||||
|
||||
case 'without':
|
||||
// disable module
|
||||
compile[key] = false;
|
||||
break;
|
||||
|
||||
case 'only':
|
||||
// disable other modules
|
||||
Object.keys(compile).forEach(key2 => {
|
||||
compile[key2] = key2 === key;
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Compile core before compiling this package
|
||||
if (compile.core) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build'],
|
||||
cwd: path.dirname(__dirname) + '/core',
|
||||
});
|
||||
}
|
||||
|
||||
if (compile.iconify || compile.core) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build'],
|
||||
cwd: path.dirname(__dirname) + '/iconify',
|
||||
});
|
||||
}
|
||||
|
||||
// Compile other packages
|
||||
Object.keys(compile).forEach(key => {
|
||||
if (key !== 'core' && key !== 'iconify' && compile[key]) {
|
||||
commands.push({
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build:' + key],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Run next command
|
||||
*/
|
||||
const next = () => {
|
||||
const item = commands.shift();
|
||||
if (item === void 0) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (item.cwd === void 0) {
|
||||
item.cwd = __dirname;
|
||||
}
|
||||
|
||||
const result = child_process.spawnSync(item.cmd, item.args, {
|
||||
cwd: item.cwd,
|
||||
stdio: 'inherit',
|
||||
});
|
||||
|
||||
if (result.status === 0) {
|
||||
process.nextTick(next);
|
||||
} else {
|
||||
process.exit(result.status);
|
||||
}
|
||||
};
|
||||
next();
|
1139
packages/browser-tests/package-lock.json
generated
Normal file
1139
packages/browser-tests/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
35
packages/browser-tests/package.json
Normal file
35
packages/browser-tests/package.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@iconify/iconify-browser-tests",
|
||||
"private": true,
|
||||
"description": "Browser tests for @iconify/iconify package",
|
||||
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
|
||||
"version": "2.0.0-dev",
|
||||
"license": "(Apache-2.0 OR GPL-2.0)",
|
||||
"bugs": "https://github.com/iconify/iconify/issues",
|
||||
"homepage": "https://iconify.design/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/iconify/iconify.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node build",
|
||||
"build:lib": "tsc -b",
|
||||
"build:dist": "rollup -c rollup.config.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cyberalien/redundancy": "^1.0.0",
|
||||
"@iconify/core": "^1.0.0-beta.0",
|
||||
"@iconify/iconify": "^2.0.0-beta.0",
|
||||
"@iconify/types": "^1.0.1",
|
||||
"@rollup/plugin-buble": "^0.21.1",
|
||||
"@rollup/plugin-commonjs": "^11.0.2",
|
||||
"@rollup/plugin-node-resolve": "^7.1.1",
|
||||
"@types/chai": "^4.2.8",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"chai": "^4.2.0",
|
||||
"mocha": "^6.2.2",
|
||||
"rollup": "^1.32.0",
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
54
packages/browser-tests/rollup.config.js
Normal file
54
packages/browser-tests/rollup.config.js
Normal file
@ -0,0 +1,54 @@
|
||||
import fs from 'fs';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import buble from '@rollup/plugin-buble';
|
||||
|
||||
const match = '-test.ts';
|
||||
const files = fs
|
||||
.readdirSync('tests')
|
||||
.sort()
|
||||
.filter(file => file.slice(0 - match.length) === match)
|
||||
.map(file => file.slice(0, file.length - match.length));
|
||||
|
||||
// Get config files
|
||||
const tests = [];
|
||||
const config = files.map(file => {
|
||||
tests.push(file + '.js');
|
||||
return {
|
||||
input: 'lib/' + file + match.replace('.ts', '.js'),
|
||||
output: {
|
||||
file: 'dist/' + file + '.js',
|
||||
format: 'iife',
|
||||
globals: {
|
||||
mocha: 'mocha',
|
||||
chai: 'chai',
|
||||
},
|
||||
},
|
||||
external: ['mocha', 'chai'],
|
||||
plugins: [
|
||||
resolve({
|
||||
browser: true,
|
||||
extensions: ['.js'],
|
||||
}),
|
||||
commonjs(),
|
||||
buble(),
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
// Write tests.html
|
||||
let content = fs.readFileSync(__dirname + '/tests/tests.html', 'utf8');
|
||||
content = content.replace(
|
||||
'<!-- tests -->',
|
||||
tests
|
||||
.map(file => {
|
||||
return '<script src="./' + file + '"></script>';
|
||||
})
|
||||
.join('')
|
||||
);
|
||||
try {
|
||||
fs.mkdirSync(__dirname + '/dist', 0o755);
|
||||
} catch (err) {}
|
||||
fs.writeFileSync(__dirname + '/dist/tests.html', content, 'utf8');
|
||||
|
||||
export default config;
|
199
packages/browser-tests/tests/10-fake-api-test.ts
Normal file
199
packages/browser-tests/tests/10-fake-api-test.ts
Normal file
@ -0,0 +1,199 @@
|
||||
import mocha from 'mocha';
|
||||
import chai from 'chai';
|
||||
import { FakeData, setFakeData, prepareQuery, sendQuery } from './fake-api';
|
||||
import { API } from '@iconify/core/lib/api/';
|
||||
import { setAPIModule } from '@iconify/core/lib/api/modules';
|
||||
import { setAPIConfig } from '@iconify/core/lib/api/config';
|
||||
import { coreModules } from '@iconify/core/lib/modules';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
// Set API
|
||||
setAPIModule({
|
||||
prepare: prepareQuery,
|
||||
send: sendQuery,
|
||||
});
|
||||
coreModules.api = API;
|
||||
|
||||
let prefixCounter = 0;
|
||||
function nextPrefix(): string {
|
||||
return 'fake-api-' + prefixCounter++;
|
||||
}
|
||||
|
||||
describe('Testing fake API', () => {
|
||||
it('Loading results', done => {
|
||||
const prefix = nextPrefix();
|
||||
const data: FakeData = {
|
||||
icons: ['icon1', 'icon2'],
|
||||
data: {
|
||||
prefix,
|
||||
icons: {
|
||||
icon1: {
|
||||
body:
|
||||
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
|
||||
},
|
||||
icon2: {
|
||||
body:
|
||||
'<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
},
|
||||
};
|
||||
setAPIConfig(
|
||||
{
|
||||
resources: ['https://api1.local', 'https://api2.local'],
|
||||
},
|
||||
prefix
|
||||
);
|
||||
setFakeData(prefix, data);
|
||||
|
||||
// Attempt to load icons
|
||||
API.loadIcons(
|
||||
[prefix + ':icon1', prefix + ':icon2'],
|
||||
(loaded, missing, pending) => {
|
||||
expect(loaded).to.be.eql([
|
||||
{
|
||||
prefix,
|
||||
name: 'icon1',
|
||||
},
|
||||
{
|
||||
prefix,
|
||||
name: 'icon2',
|
||||
},
|
||||
]);
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('Loading results with delay', done => {
|
||||
const prefix = nextPrefix();
|
||||
const data: FakeData = {
|
||||
icons: ['icon1', 'icon2'],
|
||||
delay: 100,
|
||||
data: {
|
||||
prefix,
|
||||
icons: {
|
||||
icon1: {
|
||||
body:
|
||||
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
|
||||
},
|
||||
icon2: {
|
||||
body:
|
||||
'<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
},
|
||||
};
|
||||
setAPIConfig(
|
||||
{
|
||||
resources: ['https://api1.local', 'https://api2.local'],
|
||||
},
|
||||
prefix
|
||||
);
|
||||
setFakeData(prefix, data);
|
||||
|
||||
// Attempt to load icons
|
||||
const start = Date.now();
|
||||
API.loadIcons(
|
||||
[
|
||||
{
|
||||
prefix,
|
||||
name: 'icon1',
|
||||
},
|
||||
{
|
||||
prefix,
|
||||
name: 'icon2',
|
||||
},
|
||||
],
|
||||
(loaded, missing, pending) => {
|
||||
expect(loaded).to.be.eql([
|
||||
{
|
||||
prefix,
|
||||
name: 'icon1',
|
||||
},
|
||||
{
|
||||
prefix,
|
||||
name: 'icon2',
|
||||
},
|
||||
]);
|
||||
const end = Date.now();
|
||||
expect(end - start).to.be.at.least(50);
|
||||
expect(end - start).to.be.at.most(150);
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('Loading partial results', done => {
|
||||
const prefix = nextPrefix();
|
||||
const data: FakeData = {
|
||||
icons: ['icon1'],
|
||||
delay: 20,
|
||||
data: {
|
||||
prefix,
|
||||
icons: {
|
||||
icon1: {
|
||||
body:
|
||||
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
},
|
||||
};
|
||||
setAPIConfig(
|
||||
{
|
||||
resources: ['https://api1.local', 'https://api2.local'],
|
||||
rotate: 20,
|
||||
timeout: 100,
|
||||
limit: 1,
|
||||
},
|
||||
prefix
|
||||
);
|
||||
setFakeData(prefix, data);
|
||||
|
||||
// Attempt to load icons
|
||||
let counter = 0;
|
||||
API.loadIcons(
|
||||
[prefix + ':icon1', prefix + ':icon2'],
|
||||
(loaded, missing, pending) => {
|
||||
try {
|
||||
counter++;
|
||||
switch (counter) {
|
||||
case 1:
|
||||
// Loaded icon1
|
||||
expect(loaded).to.be.eql([
|
||||
{
|
||||
prefix,
|
||||
name: 'icon1',
|
||||
},
|
||||
]);
|
||||
expect(pending).to.be.eql([
|
||||
{
|
||||
prefix,
|
||||
name: 'icon2',
|
||||
},
|
||||
]);
|
||||
expect(missing).to.be.eql([]);
|
||||
done();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
done(
|
||||
'Callback should not be called ' +
|
||||
counter +
|
||||
' times.'
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
done(err);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
344
packages/browser-tests/tests/10-finder-iconify-test.ts
Normal file
344
packages/browser-tests/tests/10-finder-iconify-test.ts
Normal file
@ -0,0 +1,344 @@
|
||||
import mocha from 'mocha';
|
||||
import chai from 'chai';
|
||||
|
||||
import { getNode } from './node';
|
||||
import { finder } from '@iconify/iconify/lib/finders/iconify';
|
||||
import { IconifyElement } from '@iconify/iconify/lib/element';
|
||||
import { IconifyIconCustomisations } from '@iconify/core/lib/customisations';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('Testing Iconify finder', () => {
|
||||
it('Finding nodes and getting node name', () => {
|
||||
const node = getNode('iconify-finder');
|
||||
node.innerHTML =
|
||||
'<div><p>List of <span>icons</span></p><ul>' +
|
||||
'<li>Valid icons: <span class="iconify" data-icon="mdi:home"></span><i class="iconify-inline" data-icon="mdi:account"></i></li>' +
|
||||
'<li>Icon without name: <span class="iconify"></span></li>' +
|
||||
'<li>Icon with extra classes: <i class="iconify iconify--mdi" data-icon="mdi:home"></i></li>' +
|
||||
'<li>Icon within icon: <span class="iconify" data-icon="mdi:alert:invalid"><i class="iconify" data-icon="mdi:question">text</i></span></li>' +
|
||||
'<li>Icon with wrong tag: <p class="iconify" data-icon="mdi:alert"></p></li>' +
|
||||
'</ul></div>';
|
||||
|
||||
// Get icons, convert to array
|
||||
const results = finder.find(node);
|
||||
const list: Element[] = Array.prototype.slice.call(results, 0);
|
||||
|
||||
// Test valid icons
|
||||
let element = list.shift();
|
||||
expect(element).to.not.be.equal(void 0);
|
||||
expect(element.tagName).to.be.equal('SPAN');
|
||||
expect(element.getAttribute('data-icon')).to.be.equal('mdi:home');
|
||||
expect(finder.name(element as IconifyElement)).to.be.equal('mdi:home');
|
||||
|
||||
element = list.shift();
|
||||
expect(element).to.not.be.equal(void 0);
|
||||
expect(element.tagName).to.be.equal('I');
|
||||
expect(element.getAttribute('data-icon')).to.be.equal('mdi:account');
|
||||
expect(finder.name(element as IconifyElement)).to.be.equal(
|
||||
'mdi:account'
|
||||
);
|
||||
|
||||
// Icon without name
|
||||
element = list.shift();
|
||||
expect(element).to.not.be.equal(void 0);
|
||||
expect(element.tagName).to.be.equal('SPAN');
|
||||
expect(element.getAttribute('data-icon')).to.be.equal(null);
|
||||
expect(finder.name(element as IconifyElement)).to.be.equal(null);
|
||||
|
||||
// Icon with extra classes
|
||||
element = list.shift();
|
||||
expect(element).to.not.be.equal(void 0);
|
||||
expect(element.tagName).to.be.equal('I');
|
||||
expect(element.getAttribute('data-icon')).to.be.equal('mdi:home');
|
||||
expect(finder.name(element as IconifyElement)).to.be.equal('mdi:home');
|
||||
|
||||
// Icon within icon
|
||||
element = list.shift();
|
||||
expect(element).to.not.be.equal(void 0);
|
||||
expect(element.tagName).to.be.equal('SPAN');
|
||||
expect(element.getAttribute('data-icon')).to.be.equal(
|
||||
'mdi:alert:invalid'
|
||||
);
|
||||
expect(finder.name(element as IconifyElement)).to.be.equal(
|
||||
'mdi:alert:invalid' // Validation is done in finder.ts, not in finder instance
|
||||
);
|
||||
|
||||
element = list.shift();
|
||||
expect(element).to.not.be.equal(void 0);
|
||||
expect(element.tagName).to.be.equal('I');
|
||||
expect(element.getAttribute('data-icon')).to.be.equal('mdi:question');
|
||||
expect(finder.name(element as IconifyElement)).to.be.equal(
|
||||
'mdi:question'
|
||||
);
|
||||
|
||||
// No more icons
|
||||
element = list.shift();
|
||||
expect(element).to.be.equal(void 0);
|
||||
});
|
||||
|
||||
it('Transformations and inline/block', () => {
|
||||
const node = getNode('iconify-finder');
|
||||
node.innerHTML =
|
||||
'Block icon:' +
|
||||
' <span class="iconify-inline" data-icon="mdi:home" data-inline="false"></span>' +
|
||||
'Inline rotated icons:' +
|
||||
' <span class="iconify-inline" data-icon="mdi:account" data-rotate="90deg"></span>' +
|
||||
' <span class="iconify iconify-inline" data-icon="mdi:account-circle" data-rotate="2"></span>' +
|
||||
'Block rotated icons:' +
|
||||
' <span class="iconify" data-icon="mdi:account-box" data-rotate="175%"></span>' +
|
||||
// Invalid rotation
|
||||
' <span class="iconify" data-icon="mdi:user" data-rotate="30%"></span>' +
|
||||
'Flip:' +
|
||||
' <span class="iconify" data-icon="ic:baseline-account" data-flip="horizontal,vertical"></span>' +
|
||||
// Double 'horizontal' flip: second entry should not change anything
|
||||
' <span class="iconify" data-icon="ic:twotone-account" data-flip="horizontal,vertical,horizontal"></span>' +
|
||||
' <span class="iconify" data-icon="ic:round-account" data-hFlip="true"></span>' +
|
||||
' <span class="iconify" data-icon="ic:sharp-account" data-vFlip="true"></span>' +
|
||||
' <span class="iconify" data-icon="ic:box-account" data-vFlip="false"></span>' +
|
||||
// Invalid value
|
||||
' <span class="iconify" data-icon="ic:outline-account" data-hFlip="invalid"></span>' +
|
||||
'';
|
||||
|
||||
// Get icons, convert to array
|
||||
const results = finder.find(node);
|
||||
const list: Element[] = Array.prototype.slice.call(results, 0);
|
||||
|
||||
function testElement(
|
||||
name: string,
|
||||
expected: IconifyIconCustomisations
|
||||
): void {
|
||||
let element = list.shift();
|
||||
expect(element).to.not.be.equal(void 0);
|
||||
expect(element.getAttribute('data-icon')).to.be.equal(name);
|
||||
expect(finder.customisations(element as IconifyElement)).to.be.eql(
|
||||
expected
|
||||
);
|
||||
}
|
||||
|
||||
// Block icon
|
||||
let element = list.shift();
|
||||
expect(element).to.not.be.equal(void 0);
|
||||
expect(element.tagName).to.be.equal('SPAN');
|
||||
expect(element.getAttribute('data-icon')).to.be.equal('mdi:home');
|
||||
const expected: IconifyIconCustomisations = {
|
||||
inline: false,
|
||||
};
|
||||
expect(finder.customisations(element as IconifyElement)).to.be.eql(
|
||||
expected
|
||||
);
|
||||
|
||||
// Rotated icons
|
||||
testElement('mdi:account', {
|
||||
inline: true,
|
||||
rotate: 1,
|
||||
});
|
||||
|
||||
testElement('mdi:account-circle', {
|
||||
inline: true,
|
||||
rotate: 2,
|
||||
});
|
||||
|
||||
testElement('mdi:account-box', {
|
||||
inline: false,
|
||||
rotate: 3,
|
||||
});
|
||||
|
||||
testElement('mdi:user', {
|
||||
inline: false,
|
||||
// No rotation because 30% is not a valid value
|
||||
});
|
||||
|
||||
// Flip
|
||||
testElement('ic:baseline-account', {
|
||||
inline: false,
|
||||
hFlip: true,
|
||||
vFlip: true,
|
||||
});
|
||||
|
||||
testElement('ic:twotone-account', {
|
||||
inline: false,
|
||||
hFlip: true,
|
||||
vFlip: true,
|
||||
});
|
||||
|
||||
testElement('ic:round-account', {
|
||||
inline: false,
|
||||
hFlip: true,
|
||||
});
|
||||
|
||||
testElement('ic:sharp-account', {
|
||||
inline: false,
|
||||
vFlip: true,
|
||||
});
|
||||
|
||||
testElement('ic:box-account', {
|
||||
inline: false,
|
||||
vFlip: false,
|
||||
});
|
||||
|
||||
testElement('ic:outline-account', {
|
||||
inline: false,
|
||||
});
|
||||
|
||||
// No more icons
|
||||
element = list.shift();
|
||||
expect(element).to.be.equal(void 0);
|
||||
});
|
||||
|
||||
it('Dimensions', () => {
|
||||
const node = getNode('iconify-finder');
|
||||
node.innerHTML =
|
||||
'Block icon:' +
|
||||
' <span class="iconify iconify-inline" data-icon="mdi:home" data-inline="false"></span>' +
|
||||
'Width and height:' +
|
||||
' <span class="iconify" data-icon="mdi:account" data-width="24" data-height="24"></span>' +
|
||||
' <span class="iconify" data-icon="mdi:account-box" data-width="100%" data-height="100%"></span>' +
|
||||
'Width:' +
|
||||
' <span class="iconify" data-icon="mdi:account-twotone" data-width="32" data-inline="true"></span>' +
|
||||
' <span class="iconify" data-icon="mdi:account-outline" data-width="auto" data-height=""></span>' +
|
||||
'Height:' +
|
||||
' <span class="iconify-inline" data-icon="mdi:account-sharp" data-height="2em" data-inline="false"></span>' +
|
||||
' <span class="iconify-inline" data-icon="mdi:account-square" data-height="auto" data-width=""></span>' +
|
||||
'';
|
||||
|
||||
// Get icons, convert to array
|
||||
const results = finder.find(node);
|
||||
const list: Element[] = Array.prototype.slice.call(results, 0);
|
||||
|
||||
function testElement(
|
||||
name: string,
|
||||
expected: IconifyIconCustomisations
|
||||
): void {
|
||||
let element = list.shift();
|
||||
expect(element).to.not.be.equal(void 0);
|
||||
expect(element.getAttribute('data-icon')).to.be.equal(name);
|
||||
expect(finder.customisations(element as IconifyElement)).to.be.eql(
|
||||
expected
|
||||
);
|
||||
}
|
||||
|
||||
// Block icon
|
||||
let element = list.shift();
|
||||
expect(element).to.not.be.equal(void 0);
|
||||
expect(element.tagName).to.be.equal('SPAN');
|
||||
expect(element.getAttribute('data-icon')).to.be.equal('mdi:home');
|
||||
const expected: IconifyIconCustomisations = {
|
||||
inline: false,
|
||||
};
|
||||
expect(finder.customisations(element as IconifyElement)).to.be.eql(
|
||||
expected
|
||||
);
|
||||
|
||||
// Width and height
|
||||
testElement('mdi:account', {
|
||||
inline: false,
|
||||
width: '24',
|
||||
height: '24',
|
||||
});
|
||||
|
||||
testElement('mdi:account-box', {
|
||||
inline: false,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
});
|
||||
|
||||
// Width only
|
||||
testElement('mdi:account-twotone', {
|
||||
inline: true,
|
||||
width: '32',
|
||||
});
|
||||
|
||||
testElement('mdi:account-outline', {
|
||||
inline: false,
|
||||
width: 'auto',
|
||||
});
|
||||
|
||||
// Height only
|
||||
testElement('mdi:account-sharp', {
|
||||
inline: false,
|
||||
height: '2em',
|
||||
});
|
||||
|
||||
testElement('mdi:account-square', {
|
||||
inline: true,
|
||||
height: 'auto',
|
||||
});
|
||||
|
||||
// No more icons
|
||||
element = list.shift();
|
||||
expect(element).to.be.equal(void 0);
|
||||
});
|
||||
|
||||
it('Alignment', () => {
|
||||
const node = getNode('iconify-finder');
|
||||
node.innerHTML =
|
||||
'Inline icon:' +
|
||||
' <i class="iconify" data-icon="mdi:home" data-inline="true"></i>' +
|
||||
'Alignment:' +
|
||||
' <i class="iconify" data-icon="mdi:account" data-align="left,top"></i>' +
|
||||
' <i class="iconify" data-icon="mdi:account-box" data-align="right,slice"></i>' +
|
||||
// 'bottom' overrides 'top', 'center' overrides 'right', extra comma
|
||||
' <i class="iconify-inline" data-icon="mdi:account-outline" data-align="top,right,bottom,meet,center,"></i>' +
|
||||
// spaces instead of comma, 'middle' overrides 'bottom'
|
||||
' <i class="iconify iconify-inline" data-icon="mdi:account-twotone" data-align="bottom middle"></i>' +
|
||||
'';
|
||||
|
||||
// Get icons, convert to array
|
||||
const results = finder.find(node);
|
||||
const list: Element[] = Array.prototype.slice.call(results, 0);
|
||||
|
||||
function testElement(
|
||||
name: string,
|
||||
expected: IconifyIconCustomisations
|
||||
): void {
|
||||
let element = list.shift();
|
||||
expect(element).to.not.be.equal(void 0);
|
||||
expect(element.getAttribute('data-icon')).to.be.equal(name);
|
||||
expect(finder.customisations(element as IconifyElement)).to.be.eql(
|
||||
expected
|
||||
);
|
||||
}
|
||||
|
||||
// First icon
|
||||
let element = list.shift();
|
||||
expect(element).to.not.be.equal(void 0);
|
||||
expect(element.tagName).to.be.equal('I');
|
||||
expect(element.getAttribute('data-icon')).to.be.equal('mdi:home');
|
||||
const expected: IconifyIconCustomisations = {
|
||||
inline: true,
|
||||
};
|
||||
expect(finder.customisations(element as IconifyElement)).to.be.eql(
|
||||
expected
|
||||
);
|
||||
|
||||
// Alignment
|
||||
testElement('mdi:account', {
|
||||
inline: false,
|
||||
hAlign: 'left',
|
||||
vAlign: 'top',
|
||||
});
|
||||
|
||||
testElement('mdi:account-box', {
|
||||
inline: false,
|
||||
hAlign: 'right',
|
||||
slice: true,
|
||||
});
|
||||
|
||||
testElement('mdi:account-outline', {
|
||||
inline: true,
|
||||
hAlign: 'center',
|
||||
vAlign: 'bottom',
|
||||
slice: false,
|
||||
});
|
||||
|
||||
testElement('mdi:account-twotone', {
|
||||
inline: true,
|
||||
vAlign: 'middle',
|
||||
});
|
||||
|
||||
// No more icons
|
||||
element = list.shift();
|
||||
expect(element).to.be.equal(void 0);
|
||||
});
|
||||
});
|
74
packages/browser-tests/tests/10-finder-v1-test.ts
Normal file
74
packages/browser-tests/tests/10-finder-v1-test.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import mocha from 'mocha';
|
||||
import chai from 'chai';
|
||||
|
||||
import { getNode } from './node';
|
||||
import { addFinder, findPlaceholders } from '@iconify/iconify/lib/finder';
|
||||
import { IconifyFinder } from '@iconify/iconify/lib/interfaces/finder';
|
||||
import { finder as iconifyFinder } from '@iconify/iconify/lib/finders/iconify-v1';
|
||||
import { finder as iconifyIconFinder } from '@iconify/iconify/lib/finders/iconify-v1-icon';
|
||||
import { IconifyIconName } from '@iconify/core/lib/icon/name';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
// Add finders
|
||||
addFinder(iconifyFinder);
|
||||
addFinder(iconifyIconFinder);
|
||||
|
||||
describe('Testing legacy finder', () => {
|
||||
it('Finding nodes', () => {
|
||||
const node = getNode('finder');
|
||||
node.innerHTML =
|
||||
'<div><p>List of <span>icons</span></p><ul>' +
|
||||
'<li>Valid icons:' +
|
||||
' <span class="iconify" data-icon="mdi:home"></span>' +
|
||||
' <i class="iconify" data-icon="mdi:account"></i>' +
|
||||
'</li>' +
|
||||
'<li>Icon without name:' +
|
||||
' <span class="iconify"></span>' +
|
||||
'</li>' +
|
||||
'<li>Block icon:' +
|
||||
' <iconify-icon data-icon="ic:baseline-account"></iconify-icon>' +
|
||||
'</li>' +
|
||||
'<li>Icon with wrong tag: <p class="iconify" data-icon="mdi:alert"></p></li>' +
|
||||
'</ul></div>';
|
||||
|
||||
const items = findPlaceholders(node);
|
||||
|
||||
function testIcon(
|
||||
name: IconifyIconName | null,
|
||||
expectedFinder: IconifyFinder
|
||||
): void {
|
||||
const item = items.shift();
|
||||
expect(item.name).to.be.eql(name);
|
||||
expect(item.finder).to.be.equal(expectedFinder);
|
||||
}
|
||||
|
||||
// Test all icons
|
||||
testIcon(
|
||||
{
|
||||
prefix: 'mdi',
|
||||
name: 'home',
|
||||
},
|
||||
iconifyFinder
|
||||
);
|
||||
|
||||
testIcon(
|
||||
{
|
||||
prefix: 'mdi',
|
||||
name: 'account',
|
||||
},
|
||||
iconifyFinder
|
||||
);
|
||||
|
||||
testIcon(
|
||||
{
|
||||
prefix: 'ic',
|
||||
name: 'baseline-account',
|
||||
},
|
||||
iconifyIconFinder
|
||||
);
|
||||
|
||||
// End of list
|
||||
expect(items.shift()).to.be.equal(void 0);
|
||||
});
|
||||
});
|
74
packages/browser-tests/tests/10-finder-v2-test.ts
Normal file
74
packages/browser-tests/tests/10-finder-v2-test.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import mocha from 'mocha';
|
||||
import chai from 'chai';
|
||||
|
||||
import { getNode } from './node';
|
||||
import { addFinder, findPlaceholders } from '@iconify/iconify/lib/finder';
|
||||
import { IconifyFinder } from '@iconify/iconify/lib/interfaces/finder';
|
||||
import { finder as iconifyFinder } from '@iconify/iconify/lib/finders/iconify';
|
||||
import { finder as iconifyIconFinder } from '@iconify/iconify/lib/finders/iconify-icon';
|
||||
import { IconifyIconName } from '@iconify/core/lib/icon/name';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
// Add finders
|
||||
addFinder(iconifyFinder);
|
||||
addFinder(iconifyIconFinder);
|
||||
|
||||
describe('Testing finder', () => {
|
||||
it('Finding nodes', () => {
|
||||
const node = getNode('finder');
|
||||
node.innerHTML =
|
||||
'<div><p>List of <span>icons</span></p><ul>' +
|
||||
'<li>Valid icons:' +
|
||||
' <span class="iconify" data-icon="mdi:home"></span>' +
|
||||
' <i class="iconify" data-icon="mdi:account"></i>' +
|
||||
'</li>' +
|
||||
'<li>Icon without name:' +
|
||||
' <span class="iconify"></span>' +
|
||||
'</li>' +
|
||||
'<li>Block icon:' +
|
||||
' <iconify-icon data-icon="ic:baseline-account"></iconify-icon>' +
|
||||
'</li>' +
|
||||
'<li>Icon with wrong tag: <p class="iconify" data-icon="mdi:alert"></p></li>' +
|
||||
'</ul></div>';
|
||||
|
||||
const items = findPlaceholders(node);
|
||||
|
||||
function testIcon(
|
||||
name: IconifyIconName | null,
|
||||
expectedFinder: IconifyFinder
|
||||
): void {
|
||||
const item = items.shift();
|
||||
expect(item.name).to.be.eql(name);
|
||||
expect(item.finder).to.be.equal(expectedFinder);
|
||||
}
|
||||
|
||||
// Test all icons
|
||||
testIcon(
|
||||
{
|
||||
prefix: 'mdi',
|
||||
name: 'home',
|
||||
},
|
||||
iconifyFinder
|
||||
);
|
||||
|
||||
testIcon(
|
||||
{
|
||||
prefix: 'mdi',
|
||||
name: 'account',
|
||||
},
|
||||
iconifyFinder
|
||||
);
|
||||
|
||||
testIcon(
|
||||
{
|
||||
prefix: 'ic',
|
||||
name: 'baseline-account',
|
||||
},
|
||||
iconifyIconFinder
|
||||
);
|
||||
|
||||
// End of list
|
||||
expect(items.shift()).to.be.equal(void 0);
|
||||
});
|
||||
});
|
219
packages/browser-tests/tests/10-node-attributes-test.ts
Normal file
219
packages/browser-tests/tests/10-node-attributes-test.ts
Normal file
@ -0,0 +1,219 @@
|
||||
import mocha from 'mocha';
|
||||
import chai from 'chai';
|
||||
|
||||
import { getNode } from './node';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
// Dummy svgAttributes variable
|
||||
const svgAttributes: Record<string, unknown> = {};
|
||||
|
||||
/**
|
||||
* Copy attributes from placeholder to SVG.
|
||||
*
|
||||
* This is similar to code used in render.ts
|
||||
*
|
||||
* @param placeholderElement
|
||||
* @param svg
|
||||
*/
|
||||
function copyData(placeholderElement, svg) {
|
||||
const svgStyle = svg.style;
|
||||
|
||||
// Copy attributes from placeholder
|
||||
const placeholderAttributes = placeholderElement.attributes;
|
||||
for (let i = 0; i < placeholderAttributes.length; i++) {
|
||||
const item = placeholderAttributes.item(i);
|
||||
if (item) {
|
||||
const name = item.name;
|
||||
if (
|
||||
name !== 'class' &&
|
||||
name !== 'style' &&
|
||||
svgAttributes[name] === void 0
|
||||
) {
|
||||
try {
|
||||
svg.setAttribute(name, item.value);
|
||||
} catch (err) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy styles from placeholder
|
||||
const placeholderStyle = placeholderElement.style;
|
||||
for (let i = 0; i < placeholderStyle.length; i++) {
|
||||
const attr = placeholderStyle[i];
|
||||
const value = placeholderStyle[attr];
|
||||
if (value !== '') {
|
||||
svgStyle[attr] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe('Testing copying node data', () => {
|
||||
it('Inline attributes', () => {
|
||||
const node = getNode('node-attributes');
|
||||
node.innerHTML = '<p title="Testing" data-foo="bar">Test</p>';
|
||||
|
||||
const source = node.querySelector('p');
|
||||
const target = document.createElement('span');
|
||||
copyData(source, target);
|
||||
|
||||
// Test title
|
||||
expect(source.getAttribute('title')).to.be.equal(
|
||||
'Testing',
|
||||
'Source title should be set'
|
||||
);
|
||||
expect(target.getAttribute('title')).to.be.equal(
|
||||
'Testing',
|
||||
'Target title should be set'
|
||||
);
|
||||
|
||||
// Test data-*
|
||||
expect(source.getAttribute('data-foo')).to.be.equal(
|
||||
'bar',
|
||||
'Source data-foo should be set'
|
||||
);
|
||||
expect(target.getAttribute('data-foo')).to.be.equal(
|
||||
'bar',
|
||||
'Target data-foo should be set'
|
||||
);
|
||||
});
|
||||
|
||||
it('Inline style', () => {
|
||||
const node = getNode('node-attributes');
|
||||
node.innerHTML =
|
||||
'<p style="color: red; border: 1px solid green; vertical-align: -.1em">Test</p>';
|
||||
|
||||
const source = node.querySelector('p');
|
||||
const target = document.createElement('span');
|
||||
copyData(source, target);
|
||||
|
||||
// Test color
|
||||
expect(source.style.color).to.be.equal(
|
||||
'red',
|
||||
'Source color should be red'
|
||||
);
|
||||
expect(target.style.color).to.be.equal(
|
||||
'red',
|
||||
'Target color should be red'
|
||||
);
|
||||
|
||||
// Test border width
|
||||
expect(source.style.borderWidth).to.be.equal(
|
||||
'1px',
|
||||
'Source border width should be 1px'
|
||||
);
|
||||
expect(target.style.borderWidth).to.be.equal(
|
||||
'1px',
|
||||
'Target border width should be 1px'
|
||||
);
|
||||
|
||||
// Test background color
|
||||
expect(source.style.backgroundColor).to.be.equal(
|
||||
'',
|
||||
'Source background color should not be set'
|
||||
);
|
||||
expect(target.style.backgroundColor).to.be.equal(
|
||||
'',
|
||||
'Target background color should not be set'
|
||||
);
|
||||
});
|
||||
|
||||
it('DOM style', () => {
|
||||
const node = getNode('node-attributes');
|
||||
node.innerHTML = '<p>Test</p>';
|
||||
|
||||
const source = node.querySelector('p');
|
||||
source.style.color = 'green';
|
||||
source.style.border = '2px solid blue';
|
||||
|
||||
const target = document.createElement('span');
|
||||
copyData(source, target);
|
||||
|
||||
// Test color
|
||||
expect(source.style.color).to.be.equal(
|
||||
'green',
|
||||
'Source color should be green'
|
||||
);
|
||||
expect(target.style.color).to.be.equal(
|
||||
'green',
|
||||
'Target color should be green'
|
||||
);
|
||||
|
||||
// Test border width
|
||||
expect(source.style.borderWidth).to.be.equal(
|
||||
'2px',
|
||||
'Source border width should be 2px'
|
||||
);
|
||||
expect(target.style.borderWidth).to.be.equal(
|
||||
'2px',
|
||||
'Target border width should be 2px'
|
||||
);
|
||||
|
||||
// Test background color
|
||||
expect(source.style.backgroundColor).to.be.equal(
|
||||
'',
|
||||
'Source background color should not be set'
|
||||
);
|
||||
expect(target.style.backgroundColor).to.be.equal(
|
||||
'',
|
||||
'Target background color should not be set'
|
||||
);
|
||||
});
|
||||
|
||||
it('Overwriting source style before copy', () => {
|
||||
const node = getNode('node-attributes');
|
||||
node.innerHTML = '<p style="color: blue">Test</p>';
|
||||
|
||||
const source = node.querySelector('p');
|
||||
|
||||
// Overwrite inline style
|
||||
source.style.color = 'purple';
|
||||
|
||||
const target = document.createElement('span');
|
||||
copyData(source, target);
|
||||
|
||||
// Test color
|
||||
expect(source.style.color).to.be.equal(
|
||||
'purple',
|
||||
'Source color should be purple'
|
||||
);
|
||||
expect(target.style.color).to.be.equal(
|
||||
'purple',
|
||||
'Target color should be purple'
|
||||
);
|
||||
});
|
||||
|
||||
it('Overwriting target style during copy', () => {
|
||||
const node = getNode('node-attributes');
|
||||
node.innerHTML = '<p style="color: blue">Test</p>';
|
||||
|
||||
const source = node.querySelector('p');
|
||||
const target = document.createElement('span');
|
||||
|
||||
// Set target style
|
||||
target.style.color = 'purple';
|
||||
target.style.verticalAlign = '-0.2em';
|
||||
|
||||
copyData(source, target);
|
||||
|
||||
// Test color
|
||||
expect(source.style.color).to.be.equal(
|
||||
'blue',
|
||||
'Source color should be blue'
|
||||
);
|
||||
expect(target.style.color).to.be.equal(
|
||||
'blue',
|
||||
'Target color should be blue'
|
||||
);
|
||||
|
||||
// Test vertical-align
|
||||
expect(source.style.verticalAlign).to.be.equal(
|
||||
'',
|
||||
'Source vartical-align should not be set'
|
||||
);
|
||||
expect(target.style.verticalAlign).to.be.equal(
|
||||
'-0.2em',
|
||||
'Target vertical-align should be set'
|
||||
);
|
||||
});
|
||||
});
|
40
packages/browser-tests/tests/10-observer-creation-test.ts
Normal file
40
packages/browser-tests/tests/10-observer-creation-test.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import mocha from 'mocha';
|
||||
import chai from 'chai';
|
||||
|
||||
import { getNode } from './node';
|
||||
import { browserModules } from '@iconify/iconify/lib/modules';
|
||||
import { observer } from '@iconify/iconify/lib/modules/observer';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('Testing observer creation', () => {
|
||||
it('Creating observer and triggering event', done => {
|
||||
const node = getNode('observer-creation');
|
||||
browserModules.root = node;
|
||||
|
||||
let counter = 0;
|
||||
|
||||
node.innerHTML = '<div></div><ul><li>test</li><li>test2</li></ul>';
|
||||
observer.init(root => {
|
||||
expect(root).to.be.equal(node);
|
||||
|
||||
counter++;
|
||||
|
||||
// Should be called only once
|
||||
expect(counter).to.be.equal(1);
|
||||
|
||||
expect(observer.isPaused()).to.be.equal(false);
|
||||
|
||||
// Pause observer
|
||||
observer.pause();
|
||||
expect(observer.isPaused()).to.be.equal(true);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
// Add few nodes to trigger observer
|
||||
expect(observer.isPaused()).to.be.equal(false);
|
||||
node.querySelector('div').innerHTML =
|
||||
'<span class="test">Some text</span><i>!</i>';
|
||||
});
|
||||
});
|
110
packages/browser-tests/tests/10-observer-manipulation-test.ts
Normal file
110
packages/browser-tests/tests/10-observer-manipulation-test.ts
Normal file
@ -0,0 +1,110 @@
|
||||
import mocha from 'mocha';
|
||||
import chai from 'chai';
|
||||
|
||||
import { getNode } from './node';
|
||||
import { elementFinderProperty } from '@iconify/iconify/lib/element';
|
||||
import { browserModules } from '@iconify/iconify/lib/modules';
|
||||
import { observer } from '@iconify/iconify/lib/modules/observer';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
describe('Testing observer with DOM manipulation', () => {
|
||||
it('Series of events', (done) => {
|
||||
const node = getNode('observer-manipulation');
|
||||
browserModules.root = node;
|
||||
|
||||
let counter = 0;
|
||||
let waitingCallback: string | boolean = true;
|
||||
|
||||
node.innerHTML =
|
||||
'<div></div><ul><li>test</li><li>test2</li></ul><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" role="img" width="1em" height="1em" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg); vertical-align: -0.125em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24" data-icon="mdi-home" data-inline="false" class="iconify"><path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"></path></svg>';
|
||||
observer.init((root) => {
|
||||
expect(root).to.be.equal(node);
|
||||
expect(waitingCallback).to.be.equal(true);
|
||||
|
||||
counter++;
|
||||
|
||||
switch (counter) {
|
||||
case 1:
|
||||
// Added few nodes
|
||||
// Remove few nodes. It should not trigger event listener
|
||||
waitingCallback = 'removing nodes';
|
||||
(() => {
|
||||
const item = node.querySelector('ul > li:last-child');
|
||||
const parent = item.parentNode;
|
||||
parent.removeChild(item);
|
||||
|
||||
// Set timer for next step to make sure callback is not called
|
||||
setTimeout(() => {
|
||||
// Add node. This should trigger callback
|
||||
const newItem = document.createElement('li');
|
||||
parent.appendChild(newItem);
|
||||
waitingCallback = true;
|
||||
}, 50);
|
||||
})();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Added one list item
|
||||
// Pause observer
|
||||
waitingCallback = 'pause test';
|
||||
(() => {
|
||||
const item = node.querySelector('ul > li:last-child');
|
||||
observer.pause();
|
||||
item.innerHTML = '<string>Strong</strong> text!';
|
||||
|
||||
// Set timer for next step to make sure callback is not called
|
||||
setTimeout(() => {
|
||||
// Resume observer and wait a bit. Resuming observer should not trigger update
|
||||
waitingCallback = 'resume test';
|
||||
observer.resume();
|
||||
|
||||
setTimeout(() => {
|
||||
// Change text of item: should remove <strong> and add new text node
|
||||
waitingCallback = true;
|
||||
item.innerHTML = 'Weak text!';
|
||||
}, 50);
|
||||
}, 50);
|
||||
})();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
waitingCallback = 'attributes on ul';
|
||||
(() => {
|
||||
const item = node.querySelector('ul');
|
||||
item.setAttribute('data-foo', 'bar');
|
||||
|
||||
// Set timer for next step to make sure callback is not called
|
||||
setTimeout(() => {
|
||||
waitingCallback = true;
|
||||
const item = node.querySelector('svg');
|
||||
item[elementFinderProperty] = true; // Add fake finder property to trigger update
|
||||
item.setAttribute('data-icon', 'mdi-account');
|
||||
item.setAttribute('data-rotate', '2');
|
||||
}, 50);
|
||||
})();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
(() => {
|
||||
// Test removing attribute from SVG
|
||||
const item = node.querySelector('svg');
|
||||
item.removeAttribute('data-rotate');
|
||||
})();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
done();
|
||||
break;
|
||||
|
||||
default:
|
||||
done('Unexpected callback call!');
|
||||
}
|
||||
});
|
||||
|
||||
// Add few nodes to trigger observer
|
||||
expect(observer.isPaused()).to.be.equal(false);
|
||||
node.querySelector('div').innerHTML =
|
||||
'<span class="test">Some text</span><i>!</i>';
|
||||
});
|
||||
});
|
991
packages/browser-tests/tests/20-renderer-v1-test.ts
Normal file
991
packages/browser-tests/tests/20-renderer-v1-test.ts
Normal file
@ -0,0 +1,991 @@
|
||||
import mocha from 'mocha';
|
||||
import chai from 'chai';
|
||||
|
||||
import { getNode } from './node';
|
||||
import { addFinder, findPlaceholders } from '@iconify/iconify/lib/finder';
|
||||
import { finder as iconifyFinder } from '@iconify/iconify/lib/finders/iconify-v1';
|
||||
import { finder as iconifyIconFinder } from '@iconify/iconify/lib/finders/iconify-v1-icon';
|
||||
import { getStorage, addIconSet, getIcon } from '@iconify/core/lib/storage';
|
||||
import { renderIcon } from '@iconify/iconify/lib/render';
|
||||
import { stringToIcon } from '@iconify/core/lib/icon/name';
|
||||
|
||||
const expect = chai.expect;
|
||||
|
||||
// Add finders
|
||||
addFinder(iconifyIconFinder);
|
||||
addFinder(iconifyFinder);
|
||||
|
||||
describe('Testing legacy renderer', () => {
|
||||
// Add mentioned icons to storage
|
||||
const storage = getStorage('mdi');
|
||||
addIconSet(storage, {
|
||||
prefix: 'mdi',
|
||||
icons: {
|
||||
'account-box': {
|
||||
body:
|
||||
'<path d="M6 17c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6m9-9a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3a3 3 0 0 1 3 3M3 5v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2z" fill="currentColor"/>',
|
||||
},
|
||||
'account-cash': {
|
||||
body:
|
||||
'<path d="M11 8c0 2.21-1.79 4-4 4s-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4m0 6.72V20H0v-2c0-2.21 3.13-4 7-4c1.5 0 2.87.27 4 .72M24 20H13V3h11v17m-8-8.5a2.5 2.5 0 0 1 5 0a2.5 2.5 0 0 1-5 0M22 7a2 2 0 0 1-2-2h-3c0 1.11-.89 2-2 2v9a2 2 0 0 1 2 2h3c0-1.1.9-2 2-2V7z" fill="currentColor"/>',
|
||||
},
|
||||
'account': {
|
||||
body:
|
||||
'<path d="M12 4a4 4 0 0 1 4 4a4 4 0 0 1-4 4a4 4 0 0 1-4-4a4 4 0 0 1 4-4m0 10c4.42 0 8 1.79 8 4v2H4v-2c0-2.21 3.58-4 8-4z" fill="currentColor"/>',
|
||||
},
|
||||
'home': {
|
||||
body:
|
||||
'<path d="M10 20v-6h4v6h5v-8h3L12 3L2 12h3v8h5z" fill="currentColor"/>',
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
});
|
||||
|
||||
it('Convert placeholders to SVG', () => {
|
||||
const node = getNode('renderer');
|
||||
node.innerHTML =
|
||||
'<div><p>Testing renderer v1</p><ul>' +
|
||||
'<li>Inline icons:<br />' +
|
||||
' Red icon with red border: <span class="iconify" data-icon="mdi:home" style="color: red; border: 1px solid red;"></span><br />' +
|
||||
' No vertical-align, green border: <i class="iconify test-icon iconify--mdi-account" data-icon="mdi:account" style="vertical-align: 0;" data-flip="horizontal" aria-hidden="false"></i>' +
|
||||
'</li>' +
|
||||
'<li>Block icons:' +
|
||||
' <iconify-icon data-icon="mdi-account-cash" title="<Cash>!"></iconify-icon>' +
|
||||
' <span class="iconify-icon" data-icon="mdi:account" data-flip="vertical" data-width="auto"></span>' +
|
||||
'</li>' +
|
||||
'<li>Changed by attribute:' +
|
||||
' <iconify-icon data-icon="mdi:account-box" data-inline="true" data-rotate="2" data-width="42"></iconify-icon>' +
|
||||
'</li>' +
|
||||
'<li>Mix of classes:' +
|
||||
' <i class="iconify iconify-icon should-be-block" data-icon="mdi:home"></i>' +
|
||||
'</li>' +
|
||||
'</ul></div>';
|
||||
|
||||
// Get items
|
||||
const items = findPlaceholders(node);
|
||||
expect(items.length).to.be.equal(6);
|
||||
|
||||
// Test finders to make sure icons are in correct order
|
||||
expect(items[0].finder).to.be.equal(iconifyIconFinder);
|
||||
expect(items[1].finder).to.be.equal(iconifyIconFinder);
|
||||
expect(items[2< |