Preserve device inventory across unavailable observations
This commit is contained in:
@@ -116,7 +116,7 @@ test('malformed persisted devices and remote observations cannot enter canonical
|
||||
]);
|
||||
});
|
||||
|
||||
test('device inventory discovers, merges, persists metadata and expires anonymous devices', async (t) => {
|
||||
test('device inventory discovers, merges, persists metadata and expires devices after 30 days', async (t) => {
|
||||
const directory = fs.mkdtempSync(path.join(os.tmpdir(), 'harbor-devices-'));
|
||||
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
|
||||
const store = createJsonStore({ filePath: path.join(directory, 'devices.json'), defaultValue: {} });
|
||||
@@ -169,6 +169,7 @@ test('device inventory discovers, merges, persists metadata and expires anonymou
|
||||
snapshot = await service.refresh();
|
||||
assert.equal(snapshot.devices.length, 1);
|
||||
assert.equal(snapshot.devices[0].confidence, 'ambiguous');
|
||||
assert.equal(snapshot.devices[0].ip, '192.168.50.10');
|
||||
|
||||
current = new Date('2026-07-01T10:05:00.000Z');
|
||||
observation = {
|
||||
@@ -229,19 +230,23 @@ test('device inventory discovers, merges, persists metadata and expires anonymou
|
||||
(error) => error.code === 'REQUEST_INVALID',
|
||||
);
|
||||
const persisted = createDeviceInventoryService({ store, observe: async () => observation, vendor, now: () => current });
|
||||
assert.equal(persisted.snapshot().devices.find(({ id }) => id === namedId).deprioritized, true);
|
||||
snapshot = persisted.snapshot();
|
||||
assert.equal(snapshot.devices.find(({ id }) => id === namedId).deprioritized, true);
|
||||
snapshot = persisted.update(replacement.id, { pinned: true }, snapshot.revision);
|
||||
assert.equal(snapshot.devices.find(({ id }) => id === replacement.id).pinned, true);
|
||||
|
||||
observation = { observedAt: current.toISOString(), observations: [], error: 'source unavailable' };
|
||||
snapshot = await persisted.refresh();
|
||||
assert.equal(snapshot.devices.length, 2);
|
||||
assert.equal(snapshot.source.error, 'source unavailable');
|
||||
|
||||
snapshot = persisted.update(namedId, { alias: '' }, snapshot.revision);
|
||||
current = new Date('2026-08-02T10:00:00.000Z');
|
||||
observation = { observedAt: current.toISOString(), observations: [], error: null };
|
||||
observation = { observedAt: current.toISOString(), observations: [], error: 'source unavailable' };
|
||||
snapshot = await persisted.refresh();
|
||||
assert.deepEqual(snapshot.devices.map(({ id }) => id), [namedId]);
|
||||
snapshot = persisted.update(namedId, { deprioritized: false }, snapshot.revision);
|
||||
assert.equal(snapshot.devices.length, 2);
|
||||
assert.equal(snapshot.source.error, 'source unavailable');
|
||||
|
||||
observation = { observedAt: current.toISOString(), observations: [], error: null };
|
||||
snapshot = await persisted.refresh();
|
||||
assert.equal(snapshot.devices.length, 0);
|
||||
|
||||
|
||||
@@ -117,10 +117,10 @@ test('Gateway device inventory uses the existing accessible responsive drawer',
|
||||
assert.match(panel, /aria-pressed=\{device\.pinned\}/);
|
||||
assert.match(panel, /const \[pinCollapses, setPinCollapses\][\s\S]*animationDone[\s\S]*result: saved \? 'saved' : 'failed'/);
|
||||
assert.match(panel, /const compact = deprioritized && !collapsing[\s\S]*const expanded = device\.pinned && !collapsing[\s\S]*const showDetails = !compact && \(device\.pinned \|\| collapsing\)[\s\S]*pinned=\{showDetails\}[\s\S]*onCollapseEnd=/);
|
||||
assert.match(panel, /Закреплённые[\s\S]*Убраны вниз[\s\S]*Остальные/);
|
||||
assert.match(panel, /Закреплённые[\s\S]*Фоновые[\s\S]*Остальные/);
|
||||
assert.match(panel, /client-device-group-heading[\s\S]*role=\{groupStart \? 'heading' : undefined\}[\s\S]*aria-level=\{groupStart \? 3 : undefined\}/);
|
||||
assert.match(panel, /toggleDeprioritized[\s\S]*deprioritized: !deprioritized[\s\S]*deprioritized: true/);
|
||||
assert.match(panel, /client-device-deprioritize[\s\S]*aria-pressed=\{deprioritized\}[\s\S]*Вернуть \$\{title\} в основной список[\s\S]*Убрать \$\{title\} вниз/);
|
||||
assert.match(panel, /client-device-deprioritize[\s\S]*aria-pressed=\{deprioritized\}[\s\S]*Вернуть \$\{title\} в основной список[\s\S]*Убрать \$\{title\} в фон/);
|
||||
assert.match(panel, /\{!compact && <TrafficChart/);
|
||||
assert.doesNotMatch(panel, /Закрепите устройство, чтобы изменить маршрут|Сначала верните маршрут через Gateway/);
|
||||
assert.match(panel, /maxLength=\{64\}[\s\S]*autoFocus/);
|
||||
|
||||
Reference in New Issue
Block a user