113 lines
4.2 KiB
JavaScript
113 lines
4.2 KiB
JavaScript
|
|
'use strict';
|
||
|
|
|
||
|
|
const test = require('node:test');
|
||
|
|
const assert = require('node:assert/strict');
|
||
|
|
|
||
|
|
const AssetResolver = require('../../src/registry/AssetResolver');
|
||
|
|
|
||
|
|
function fakeNs(name, entries) {
|
||
|
|
const map = new Map(entries.map(([k, v]) => [String(k).toLowerCase(), v]));
|
||
|
|
return {
|
||
|
|
name,
|
||
|
|
loadAll: () => new Map(map),
|
||
|
|
refresh: async () => new Map(map),
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
test('resolve() hits the cache on first call and is sync', () => {
|
||
|
|
const r = new AssetResolver([fakeNs('curves', [['m1', { foo: 1 }]])]);
|
||
|
|
assert.deepEqual(r.resolve('curves', 'm1'), { foo: 1 });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('resolve() is case-insensitive', () => {
|
||
|
|
const r = new AssetResolver([fakeNs('curves', [['MyModel', { ok: true }]])]);
|
||
|
|
assert.deepEqual(r.resolve('curves', 'mymodel'), { ok: true });
|
||
|
|
assert.deepEqual(r.resolve('curves', 'MYMODEL'), { ok: true });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('resolve() returns null for unknown id', () => {
|
||
|
|
const r = new AssetResolver([fakeNs('curves', [['m1', { foo: 1 }]])]);
|
||
|
|
assert.equal(r.resolve('curves', 'm999'), null);
|
||
|
|
assert.equal(r.resolve('curves', ''), null);
|
||
|
|
assert.equal(r.resolve('curves', null), null);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('resolve() throws on unknown namespace', () => {
|
||
|
|
const r = new AssetResolver([fakeNs('curves', [['m1', { foo: 1 }]])]);
|
||
|
|
assert.throws(() => r.resolve('nope', 'm1'), /unknown namespace/i);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('list() returns all ids in the namespace', () => {
|
||
|
|
const r = new AssetResolver([fakeNs('curves', [['a', 1], ['b', 2]])]);
|
||
|
|
assert.deepEqual(r.list('curves').sort(), ['a', 'b']);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('namespaces() lists every registered namespace', () => {
|
||
|
|
const r = new AssetResolver([
|
||
|
|
fakeNs('curves', []),
|
||
|
|
fakeNs('menu', []),
|
||
|
|
]);
|
||
|
|
assert.deepEqual(r.namespaces().sort(), ['curves', 'menu']);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('refresh(name) re-hydrates a single namespace', async () => {
|
||
|
|
let counter = 0;
|
||
|
|
const ns = {
|
||
|
|
name: 'curves',
|
||
|
|
loadAll: () => new Map([['m1', { v: ++counter }]]),
|
||
|
|
refresh: async () => new Map([['m1', { v: ++counter }]]),
|
||
|
|
};
|
||
|
|
const r = new AssetResolver([ns]);
|
||
|
|
assert.deepEqual(r.resolve('curves', 'm1'), { v: 1 });
|
||
|
|
await r.refresh('curves');
|
||
|
|
assert.deepEqual(r.resolve('curves', 'm1'), { v: 2 });
|
||
|
|
});
|
||
|
|
|
||
|
|
test('refresh() with no name re-hydrates every namespace', async () => {
|
||
|
|
let cA = 0, cB = 0;
|
||
|
|
const r = new AssetResolver([
|
||
|
|
{ name: 'a', loadAll: () => new Map([['x', { v: ++cA }]]), refresh: async () => new Map([['x', { v: ++cA }]]) },
|
||
|
|
{ name: 'b', loadAll: () => new Map([['y', { v: ++cB }]]), refresh: async () => new Map([['y', { v: ++cB }]]) },
|
||
|
|
]);
|
||
|
|
r.resolve('a', 'x');
|
||
|
|
r.resolve('b', 'y');
|
||
|
|
await r.refresh();
|
||
|
|
assert.equal(r.resolve('a', 'x').v, 2);
|
||
|
|
assert.equal(r.resolve('b', 'y').v, 2);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('constructor rejects malformed namespaces', () => {
|
||
|
|
assert.throws(() => new AssetResolver([{ name: 'x' }]), /loadAll/);
|
||
|
|
assert.throws(() => new AssetResolver([{ loadAll: () => {} }]), /name/);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('resolveAssetMetadata walks supplier→type→model and returns derived fields', () => {
|
||
|
|
const r = new AssetResolver([{
|
||
|
|
name: 'menu',
|
||
|
|
loadAll: () => new Map([['rotatingmachine', {
|
||
|
|
softwareType: 'rotatingmachine',
|
||
|
|
suppliers: [{
|
||
|
|
id: 'hidrostal', name: 'Hidrostal',
|
||
|
|
types: [{ id: 'pump-centrifugal', name: 'Centrifugal',
|
||
|
|
models: [{ id: 'm1', name: 'M-one', units: ['l/s', 'm3/h'] }],
|
||
|
|
}],
|
||
|
|
}],
|
||
|
|
}]]),
|
||
|
|
}]);
|
||
|
|
const meta = r.resolveAssetMetadata('rotatingmachine', 'm1');
|
||
|
|
assert.equal(meta.supplier, 'Hidrostal');
|
||
|
|
assert.equal(meta.type, 'Centrifugal');
|
||
|
|
assert.equal(meta.model, 'M-one');
|
||
|
|
assert.deepEqual(meta.units, ['l/s', 'm3/h']);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('resolveAssetMetadata returns null on missing model', () => {
|
||
|
|
const r = new AssetResolver([{
|
||
|
|
name: 'menu',
|
||
|
|
loadAll: () => new Map([['rotatingmachine', { suppliers: [] }]]),
|
||
|
|
}]);
|
||
|
|
assert.equal(r.resolveAssetMetadata('rotatingmachine', 'm-nope'), null);
|
||
|
|
assert.equal(r.resolveAssetMetadata('rotatingmachine', null), null);
|
||
|
|
assert.equal(r.resolveAssetMetadata(null, 'm1'), null);
|
||
|
|
});
|