'Scan Now' triggers POST /api/devices/scan from the band header. '+ Add by MAC' renamed '+ Manual Add' with an optional IP field (addBody/addManual accept ip) and a MAC input that auto-inserts colons as you type. Frontend test 4/4; DB-backed api/repo tests written (run with the suite — skipped locally to avoid colliding with a concurrent test run on void_test). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
81 lines
3.7 KiB
JavaScript
81 lines
3.7 KiB
JavaScript
// tests/frontend/devices_band.test.js
|
|
import { describe, it, expect, vi, beforeAll, afterAll } from 'vitest';
|
|
import { JSDOM } from 'jsdom';
|
|
|
|
vi.mock('../../public/api.js', () => ({
|
|
api: {
|
|
get: vi.fn(async (p) => {
|
|
if (p === '/api/devices') return { groups: [ { name: 'Network', devices: [
|
|
{ mac: 'bc:a5:11:3e:06:88', ip: '192.168.1.13', name: 'Orbi Satellite', grp: 'Network', vendor: 'Netgear', randomized: false, present: true } ] } ] };
|
|
if (p === '/api/devices/discovered') return [
|
|
{ mac: '24:4b:fe:8e:09:a4', ip: '192.168.1.15', vendor: 'ASUSTek', randomized: false, present: true } ];
|
|
return {};
|
|
}),
|
|
patch: vi.fn(async () => ({})),
|
|
post: vi.fn(async () => ({})),
|
|
del: vi.fn(async () => ({}))
|
|
}
|
|
}));
|
|
|
|
import { api } from '../../public/api.js';
|
|
|
|
let renderDevicesBand;
|
|
beforeAll(async () => {
|
|
const dom = new JSDOM('<!doctype html><html><body><div id="h"></div></body></html>', { url: 'http://localhost/' });
|
|
global.window = dom.window; global.document = dom.window.document; global.Node = dom.window.Node;
|
|
({ renderDevicesBand } = await import('../../public/views/devices_band.js'));
|
|
});
|
|
afterAll(() => { delete global.window; delete global.document; delete global.Node; });
|
|
|
|
describe('devices band', () => {
|
|
it('renders known devices from the API with MAC, and a discovered count', async () => {
|
|
const host = document.getElementById('h');
|
|
await renderDevicesBand(host);
|
|
await new Promise(r => setTimeout(r, 0));
|
|
expect(host.textContent).toContain('Orbi Satellite');
|
|
expect(host.querySelector('.dv-mac').textContent).toBe('bc:a5:11:3e:06:88');
|
|
expect(host.querySelector('.dv-discovered')).not.toBeNull(); // review affordance present
|
|
expect(host.textContent).toMatch(/Discovered/i);
|
|
});
|
|
|
|
it('lets you edit a known device (✎ → name/group → Save patches)', async () => {
|
|
const host = document.getElementById('h');
|
|
await renderDevicesBand(host);
|
|
await new Promise(r => setTimeout(r, 0));
|
|
const t = host.querySelector('.dv-tile');
|
|
t.querySelector('.dv-edit-btn').click();
|
|
const nameI = t.querySelector('.dv-edit-name');
|
|
expect(nameI.value).toBe('Orbi Satellite');
|
|
nameI.value = 'Orbi RBS50';
|
|
t.querySelector('.dv-add').click(); // Save
|
|
await new Promise(r => setTimeout(r, 0));
|
|
expect(api.patch).toHaveBeenCalledWith('/api/devices/bc:a5:11:3e:06:88',
|
|
expect.objectContaining({ name: 'Orbi RBS50', grp: 'Network' }));
|
|
});
|
|
|
|
it('Manual Add reveals a form (with IP) and POSTs the new device; MAC field auto-inserts colons', async () => {
|
|
const host = document.getElementById('h');
|
|
await renderDevicesBand(host);
|
|
await new Promise(r => setTimeout(r, 0));
|
|
expect(host.querySelector('.dv-addtoggle').textContent).toBe('+ Manual Add');
|
|
host.querySelector('.dv-addtoggle').click(); // reveal the form
|
|
const [macI, ipI] = host.querySelectorAll('.dv-addform .dv-edit-name');
|
|
macI.value = 'aabbccddeeff';
|
|
macI.dispatchEvent(new window.Event('input')); // colon-mask
|
|
expect(macI.value).toBe('aa:bb:cc:dd:ee:ff');
|
|
ipI.value = '192.168.1.50';
|
|
host.querySelector('.dv-addform .dv-add').click();
|
|
await new Promise(r => setTimeout(r, 0));
|
|
expect(api.post).toHaveBeenCalledWith('/api/devices', expect.objectContaining({ mac: 'aa:bb:cc:dd:ee:ff', ip: '192.168.1.50' }));
|
|
});
|
|
|
|
it('Scan Now triggers the scheduled scan', async () => {
|
|
const host = document.getElementById('h');
|
|
await renderDevicesBand(host);
|
|
await new Promise(r => setTimeout(r, 0));
|
|
host.querySelector('.dv-scanbtn').click();
|
|
await new Promise(r => setTimeout(r, 0));
|
|
expect(api.post).toHaveBeenCalledWith('/api/devices/scan');
|
|
});
|
|
});
|