112 lines
6.0 KiB
JavaScript
112 lines
6.0 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
|
|
const {
|
|
buildFontFamilyFormats,
|
|
buildFontStylesheet,
|
|
collectFontLibrarySyncOperations
|
|
} = require('../src/web/lib/media/font-library');
|
|
|
|
test('buildFontFamilyFormats quotes multi-word font families for TinyMCE previews', () => {
|
|
const formats = buildFontFamilyFormats([
|
|
{ family: 'Old London', enabled: true },
|
|
{ family: 'My Custom Font', enabled: true }
|
|
]);
|
|
|
|
assert.match(formats, /Old London='Old London'/);
|
|
assert.match(formats, /My Custom Font='My Custom Font'/);
|
|
assert.match(formats, /Times New Roman='Times New Roman',Times,serif/);
|
|
assert.match(formats, /Lucida Sans Unicode='Lucida Sans Unicode','Lucida Grande',sans-serif/);
|
|
});
|
|
|
|
test('buildFontStylesheet keeps disabled fonts available for rendering', () => {
|
|
const stylesheet = buildFontStylesheet([
|
|
{ family: 'Enabled Font', fileName: 'enabled-font.ttf', format: 'truetype', enabled: true },
|
|
{ family: 'Disabled Font', fileName: 'disabled-font.ttf', format: 'truetype', enabled: false }
|
|
]);
|
|
|
|
assert.match(stylesheet, /Enabled Font/);
|
|
assert.match(stylesheet, /Disabled Font/);
|
|
assert.match(stylesheet, /\/media\/assets\/fonts\/enabled-font.ttf/);
|
|
});
|
|
|
|
test('legacy fonts and weather icons migrate into shared assets without losing metadata', async () => {
|
|
const root = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'pulse-assets-'));
|
|
try {
|
|
const fonts = path.join(root, 'fonts');
|
|
const weather = path.join(root, 'weather-icons', 'abc');
|
|
await fs.promises.mkdir(fonts, { recursive: true });
|
|
await fs.promises.mkdir(weather, { recursive: true });
|
|
await fs.promises.writeFile(path.join(fonts, 'custom.ttf'), 'font-data');
|
|
await fs.promises.writeFile(path.join(fonts, 'fonts.json'), JSON.stringify([{ id: 'custom', family: 'Custom', fileName: 'custom.ttf', enabled: false }]));
|
|
await fs.promises.writeFile(path.join(fonts, 'fonts.css'), "src:url('/media/fonts/custom.ttf')");
|
|
await fs.promises.writeFile(path.join(weather, 'clear-123abc.png'), 'icon-data');
|
|
await fs.promises.writeFile(path.join(root, 'weather-icons', 'sets.json'), JSON.stringify([{ id: 'abc', name: 'Custom', icons: { clear: '/media/weather-icons/abc/clear-123abc.png' } }]));
|
|
const library = require('../src/web/lib/media/font-library');
|
|
await library.ensureFontLibrary(path.join(root, 'uploads'));
|
|
const loaded = library.loadFontLibrary(root);
|
|
assert.equal(loaded.fonts[0].id, 'custom');
|
|
assert.equal(loaded.fonts[0].enabled, false);
|
|
assert.equal(loaded.manifestPath, path.join(root, 'assets', 'fonts.json'));
|
|
assert.equal(loaded.stylesheetPath, path.join(root, 'assets', 'fonts.css'));
|
|
assert.match(loaded.stylesheetHref, /^\/media\/assets\/fonts.css/);
|
|
assert.equal(fs.readFileSync(path.join(root, 'assets', 'fonts', 'custom.ttf'), 'utf8'), 'font-data');
|
|
assert.match(fs.readFileSync(loaded.stylesheetPath, 'utf8'), /\/media\/assets\/fonts\/custom.ttf/);
|
|
const weatherLibrary = require('../src/web/lib/media/weather-icon-library');
|
|
assert.equal(weatherLibrary.readWeatherIconSets(root)[0].icons.clear, '/media/assets/weather-icons/abc/clear-123abc.png');
|
|
assert.equal(weatherLibrary.getWeatherManifestPath(root), path.join(root, 'assets', 'weather.json'));
|
|
assert.equal(fs.existsSync(path.join(root, 'assets', 'weather-icons', 'sets.json')), false);
|
|
assert.equal(fs.readFileSync(path.join(root, 'assets', 'weather-icons', 'abc', 'clear-123abc.png'), 'utf8'), 'icon-data');
|
|
assert.equal(fs.existsSync(fonts), false);
|
|
assert.equal(fs.existsSync(path.join(root, 'weather-icons')), false);
|
|
await library.ensureFontLibrary(root);
|
|
assert.equal(library.loadFontLibrary(root).fonts.length, 1);
|
|
} finally {
|
|
await fs.promises.rm(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('shared assets migration tolerates simultaneous service startup', async () => {
|
|
const root = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'pulse-assets-race-'));
|
|
try {
|
|
const fonts = path.join(root, 'fonts');
|
|
await fs.promises.mkdir(fonts);
|
|
await fs.promises.writeFile(path.join(fonts, 'fonts.json'), '[]');
|
|
await fs.promises.writeFile(path.join(fonts, 'fonts.css'), "src:url('/media/fonts/custom.ttf')");
|
|
await Promise.all(Array.from({ length: 100 }, function (_unused, index) {
|
|
return fs.promises.writeFile(path.join(fonts, 'font-' + index + '.ttf'), 'font-data');
|
|
}));
|
|
const run = require('node:util').promisify(require('node:child_process').execFile);
|
|
const modulePath = require.resolve('../src/web/lib/media/assets-storage');
|
|
await Promise.all(Array.from({ length: 4 }, function () {
|
|
return run(process.execPath, ['-e', 'require(' + JSON.stringify(modulePath) + ').migrateLegacyAssets(' + JSON.stringify(root) + ')']);
|
|
}));
|
|
assert.equal(fs.existsSync(fonts), false);
|
|
assert.equal(fs.readdirSync(path.join(root, 'assets', 'fonts')).length, 100);
|
|
assert.equal(JSON.parse(fs.readFileSync(path.join(root, 'assets', 'fonts.json'))).length, 0);
|
|
} finally {
|
|
await fs.promises.rm(root, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test('collectFontLibrarySyncOperations keeps disabled fonts as puts', async () => {
|
|
const tempRoot = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'pulse-font-library-'));
|
|
const fontDir = path.join(tempRoot, 'fonts');
|
|
await fs.promises.mkdir(fontDir, { recursive: true });
|
|
await fs.promises.writeFile(path.join(fontDir, 'fonts.json'), JSON.stringify([
|
|
{ family: 'Enabled Font', fileName: 'enabled-font.ttf', enabled: true },
|
|
{ family: 'Disabled Font', fileName: 'disabled-font.ttf', enabled: false }
|
|
], null, 2));
|
|
|
|
const operations = collectFontLibrarySyncOperations(tempRoot);
|
|
const fontOps = operations.filter(function (operation) {
|
|
return String(operation.uploadPath || '').indexOf('/media/assets/fonts/') === 0 && /\.ttf$/.test(String(operation.uploadPath || ''));
|
|
});
|
|
|
|
assert.deepEqual(fontOps.map(function (operation) {
|
|
return operation.type;
|
|
}), ['put', 'put']);
|
|
}); |