mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-14 20:48:17 +08:00
118 lines
6.1 KiB
JavaScript
118 lines
6.1 KiB
JavaScript
'use strict';
|
|
const assert = require('node:assert/strict');
|
|
const test = require('node:test');
|
|
const { environment, loadModule, backend } = require('./helpers/runtime');
|
|
const mac = 'AA:BB:CC:11:22:33';
|
|
const snapshot = {
|
|
groups: [{ '.type': 'group', '.name': 'home', name: 'Home' }],
|
|
devices: [{ '.type': 'device', '.name': 'tv', mac, name: 'TV', group: 'home' }],
|
|
hints: { [mac]: { ipaddrs: ['192.168.1.20'] } },
|
|
neighbors: { neighbors: [{ mac, ip: '192.168.1.20', state: 'REACHABLE' }] },
|
|
errors: [], discoveryComplete: true
|
|
};
|
|
function context() {
|
|
const mocks = backend(), env = environment(mocks), cache = new Map();
|
|
return { env, mocks, load: name => loadModule(name, env, cache) };
|
|
}
|
|
function runTimer(env) {
|
|
const [id, timer] = Array.from(env.timeouts).find(([, value]) => value.delay === 0);
|
|
env.timeouts.delete(id);
|
|
return timer.callback();
|
|
}
|
|
|
|
test('a cache miss renders the full page before discovery and only the list waits for slow data', async () => {
|
|
const ctx = context(), service = ctx.load('device-manager.service');
|
|
let release, loads = 0;
|
|
service.load = () => { loads++; return new Promise(resolve => { release = resolve; }); };
|
|
ctx.env.window.localStorage.getItem = () => JSON.stringify({ tab: 'all', group: 'home', maskInfo: true });
|
|
const page = ctx.load('view.device-manager.devices');
|
|
const initial = await page.load();
|
|
assert.equal(initial.snapshot, null);
|
|
assert.equal(loads, 0);
|
|
assert.equal(ctx.mocks.state.calls.length, 0);
|
|
const node = page.render(initial), list = node.querySelector('#device_manager_tbody');
|
|
assert.ok(node.textContent.includes('LAN Device Management'));
|
|
assert.ok(node.querySelector('#dm-search-input'));
|
|
assert.equal(node.querySelectorAll('th').length, 8);
|
|
assert.match(list.textContent, /Loading list/);
|
|
assert.ok(!list.textContent.includes('No online devices'));
|
|
assert.ok(node.querySelectorAll('.dm-requires-data').every(button => button.disabled));
|
|
const pending = runTimer(ctx.env);
|
|
assert.equal(loads, 1);
|
|
assert.equal(page.refresh(), pending);
|
|
page.filterText = 'tv'; page.updateView();
|
|
assert.match(list.textContent, /Loading list/);
|
|
release(snapshot); await pending;
|
|
assert.ok(!list.textContent.includes('Loading list'));
|
|
assert.ok(list.textContent.includes('TV'));
|
|
assert.equal(page.activeGroup, 'home');
|
|
assert.equal(page.maskInfo, true);
|
|
assert.ok(node.querySelectorAll('.dm-requires-data').every(button => !button.disabled));
|
|
assert.equal(node.querySelector('#dm-cache-status').style.display, 'none');
|
|
});
|
|
|
|
test('an initial loading failure becomes a retry row and a retry replaces it with the device list', async () => {
|
|
const ctx = context(), service = ctx.load('device-manager.service');
|
|
service.load = () => Promise.reject(Error('router unavailable'));
|
|
const page = ctx.load('view.device-manager.devices'), node = page.render(await page.load());
|
|
await runTimer(ctx.env);
|
|
const list = node.querySelector('#device_manager_tbody');
|
|
assert.match(list.textContent, /Could not load the device list/);
|
|
const retry = list.querySelector('button');
|
|
assert.equal(retry.textContent, 'Retry');
|
|
service.load = () => Promise.resolve(snapshot);
|
|
await retry.click();
|
|
assert.equal(page.initialLoading, false);
|
|
assert.equal(page.loadFailed, false);
|
|
assert.ok(list.textContent.includes('TV'));
|
|
assert.ok(!list.textContent.includes('Retry'));
|
|
});
|
|
|
|
test('an expired snapshot shows the shell without starting or awaiting live discovery', async () => {
|
|
const ctx = context();
|
|
let now = 1000000;
|
|
ctx.env.Date = class extends Date { static now() { return now; } };
|
|
await ctx.load('device-manager.snapshot-cache').save(snapshot);
|
|
now += 300000;
|
|
const page = ctx.load('view.device-manager.devices'), initial = await page.load();
|
|
assert.equal(initial.snapshot, null);
|
|
assert.equal(initial.cached, false);
|
|
const node = page.render(initial);
|
|
assert.match(node.querySelector('#device_manager_tbody').textContent, /Loading list/);
|
|
assert.equal(ctx.mocks.state.calls.length, 0);
|
|
});
|
|
|
|
test('an empty cached online list stays loading until live discovery and Ping both finish', async () => {
|
|
for (const reachable of [true, false]) {
|
|
const ctx = context(), service = ctx.load('device-manager.service');
|
|
await ctx.load('device-manager.snapshot-cache').save({ groups: [], devices: [], errors: [], discoveryComplete: true });
|
|
let readDone, pingDone;
|
|
service.load = () => new Promise(resolve => { readDone = resolve; });
|
|
service.pingDevice = () => new Promise(resolve => { pingDone = resolve; });
|
|
const page = ctx.load('view.device-manager.devices'), node = page.render(await page.load());
|
|
const list = node.querySelector('#device_manager_tbody');
|
|
assert.match(list.textContent, /Loading list/);
|
|
assert.ok(!list.textContent.includes('No online devices'));
|
|
const reading = runTimer(ctx.env);
|
|
readDone(Object.assign({}, snapshot, { neighbors: { neighbors: [{ mac, ip: '192.168.1.20', state: 'STALE' }] } }));
|
|
await reading;
|
|
assert.match(list.textContent, /Loading list/);
|
|
const checking = runTimer(ctx.env);
|
|
await Promise.resolve(); await Promise.resolve(); await Promise.resolve();
|
|
assert.match(list.textContent, /Loading list/);
|
|
pingDone({ reachable }); await checking;
|
|
assert.ok(!list.textContent.includes('Loading list'));
|
|
assert.ok(list.textContent.includes(reachable ? 'TV' : 'No online devices'));
|
|
}
|
|
});
|
|
|
|
test('a completed empty discovery shows no online devices after its loading phase', async () => {
|
|
const ctx = context(), service = ctx.load('device-manager.service');
|
|
service.load = () => Promise.resolve({ groups: [], devices: [], errors: [], discoveryComplete: true });
|
|
const page = ctx.load('view.device-manager.devices'), node = page.render(await page.load());
|
|
const list = node.querySelector('#device_manager_tbody');
|
|
assert.match(list.textContent, /Loading list/);
|
|
await runTimer(ctx.env);
|
|
assert.equal(list.textContent, 'No online devices');
|
|
});
|