svg-spritemap-webpack-plugin
Version:
Generates symbol-based SVG spritemap from all .svg files in a directory
162 lines (161 loc) • 7.33 kB
JavaScript
import path from 'node:path';
import assert from 'node:assert';
import webpack from 'webpack';
import { rimraf } from 'rimraf';
import { describe, it, afterEach } from 'node:test';
import SVGSpritemapPlugin from './index.js'; // eslint-disable-line @onefinity/eslint-config/import-grouping
afterEach(() => {
rimraf.sync(path.resolve(import.meta.dirname, '../dist/'));
});
describe('Options', () => {
const options = {
entry: 'data:text/javascript,',
mode: 'development'
};
it('does not generate spritemap when no sprites are found', (context, done) => {
webpack(Object.assign(Object.assign({}, options), { plugins: [
new SVGSpritemapPlugin('no-matches/**/*.svg')
] }), (errors, stats) => {
assert.strictEqual(errors, null);
assert.strictEqual(stats === null || stats === void 0 ? void 0 : stats.compilation.emittedAssets.size, 1);
done();
});
});
it('generates spritemap when sprites are found', (context, done) => {
webpack(Object.assign(Object.assign({}, options), { plugins: [
new SVGSpritemapPlugin([
'tests/input/svg/single.svg',
'tests/input/svg/title-tag.svg'
])
] }), (errors, stats) => {
assert.strictEqual(errors, null);
assert.ok(stats === null || stats === void 0 ? void 0 : stats.compilation.emittedAssets.has('spritemap.svg'));
done();
});
});
it('removes sprite prefix when sprite.prefix option is set to false', (context, done) => {
webpack(Object.assign(Object.assign({}, options), { plugins: [
new SVGSpritemapPlugin('tests/input/svg/single.svg', {
sprite: {
prefix: false
}
})
] }), (errors, stats) => {
var _a;
if (!stats) {
return;
}
(_a = stats.compilation.compiler.outputFileSystem) === null || _a === void 0 ? void 0 : _a.readFile(path.join(stats.compilation.outputOptions.path, 'spritemap.svg'), (error, data) => {
var _a;
if (error) {
throw error;
}
assert.match((_a = data === null || data === void 0 ? void 0 : data.toString()) !== null && _a !== void 0 ? _a : '', /id="single"/);
done();
});
});
});
[{
filename: 'sprite.scss',
expected: /'single':\s*"data:/
}, {
filename: 'sprite.css',
expected: /\.single \{ background-image: url\(['"]?data:/
}, {
filename: 'sprite.less',
expected: /@single:\s*['"]?data:/
}].forEach(({ filename, expected }) => {
it(`generates ${filename} containing ${expected}`, (context, done) => {
webpack(Object.assign(Object.assign({}, options), { plugins: [
new SVGSpritemapPlugin('tests/input/svg/single.svg', {
styles: {
filename
}
})
] }), (errors, stats) => {
var _a;
assert.strictEqual(errors, null);
(_a = stats === null || stats === void 0 ? void 0 : stats.compilation.compiler.outputFileSystem) === null || _a === void 0 ? void 0 : _a.readFile(path.join(stats.compilation.outputOptions.path, filename), (error, data) => {
var _a;
assert.match((_a = data === null || data === void 0 ? void 0 : data.toString()) !== null && _a !== void 0 ? _a : '', expected);
done();
});
});
});
});
it('throws on invalid options', () => {
assert.throws(() => {
webpack(Object.assign(Object.assign({}, options), { plugins: [
new SVGSpritemapPlugin('tests/input/svg/single.svg', {
output: {
// @ts-expect-error - Invalid options
filename: 123
}
})
] }));
});
});
it('adds the svg4everybody helper to each entry', (context, done) => {
webpack(Object.assign(Object.assign({}, options), { entry: {
a: 'data:text/javascript,',
b: 'data:text/javascript,'
}, plugins: [
new SVGSpritemapPlugin('tests/input/svg/single.svg', {
output: {
svg4everybody: true
}
})
] }), (errors, stats) => {
assert.strictEqual(errors, null);
stats === null || stats === void 0 ? void 0 : stats.compilation.entries.forEach((entry) => {
var _a, _b;
assert.match((_b = (_a = entry.dependencies.at(1)) === null || _a === void 0 ? void 0 : _a.getResourceIdentifier()) !== null && _b !== void 0 ? _b : '', /data:text\/javascript,.*svg4everybody/);
});
done();
});
});
it('adds spritemap to named chunk', (context, done) => {
webpack(Object.assign(Object.assign({}, options), { plugins: [
new SVGSpritemapPlugin('tests/input/svg/single.svg', {
output: {
chunk: {
name: 'icons'
}
},
sprite: {
prefix: false
}
})
] }), (errors, stats) => {
var _a;
assert.strictEqual(errors, null);
assert.ok((_a = stats === null || stats === void 0 ? void 0 : stats.compilation.namedChunks.get('icons')) === null || _a === void 0 ? void 0 : _a.files.has('spritemap.svg'), 'spritemap.svg should be in icons chunk');
done();
});
});
it('reuses existing chunk instead of creating duplicates', (context, done) => {
webpack(Object.assign(Object.assign({}, options), { plugins: [{
apply(compiler) {
compiler.hooks.thisCompilation.tap('TestPlugin', (compilation) => {
compilation.hooks.processAssets.tap({
name: 'TestPlugin',
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
}, () => {
compilation.addChunk('icons');
});
});
}
}, new SVGSpritemapPlugin('tests/input/svg/single.svg', {
output: {
chunk: {
name: 'icons'
}
}
})] }), (errors, stats) => {
var _a;
assert.strictEqual(errors, null);
assert.ok((_a = stats === null || stats === void 0 ? void 0 : stats.compilation.namedChunks.get('icons')) === null || _a === void 0 ? void 0 : _a.files.has('spritemap.svg'), 'spritemap.svg should be in icons chunk');
done();
});
});
});