feat(web): rebuild fleet page with Hub-style identity guard and context actions
- Surface device identity state, carrier details and upstream link health. - Add fleet-level identity monitoring and restart/baseband context actions. - Apply consistent notification scoping across fleet views.
This commit is contained in:
@@ -277,4 +277,74 @@ describe('fleet table view model', () => {
|
||||
}).emptyReason,
|
||||
).toBe('filter');
|
||||
});
|
||||
|
||||
it('marks and searches the nodes the identity guard is holding', () => {
|
||||
const instances: FleetInstance[] = [
|
||||
{ id: 'held', name: 'Held', url: 'http://a', tags: [] },
|
||||
{ id: 'clear', name: 'Clear', url: 'http://b', tags: [] },
|
||||
{ id: 'blind', name: 'Blind', url: 'http://c', tags: [] },
|
||||
];
|
||||
const statuses = new Map<string, FleetStatus>([
|
||||
[
|
||||
'held',
|
||||
{
|
||||
reachable: true,
|
||||
identity: { tracked: true, status: 'pending', reasons: ['imei_claimed'] },
|
||||
},
|
||||
],
|
||||
['clear', { reachable: true, identity: { tracked: true, status: 'confirmed', reasons: [] } }],
|
||||
[
|
||||
'blind',
|
||||
{ reachable: true, identity: { tracked: false, status: 'confirmed', reasons: [] } },
|
||||
],
|
||||
]);
|
||||
|
||||
const rows = buildFleetTableViewModel(instances, statuses).rows;
|
||||
expect(rows.map((row) => [row.id, row.identityPending])).toEqual([
|
||||
['blind', false],
|
||||
['clear', false],
|
||||
['held', true],
|
||||
]);
|
||||
expect(
|
||||
buildFleetTableViewModel(instances, statuses, { query: '身份待确认' }).rows.map((r) => r.id),
|
||||
).toEqual(['held']);
|
||||
});
|
||||
|
||||
it('filters and searches by derived access method and reported IMEI', () => {
|
||||
const scoped: readonly FleetInstance[] = [
|
||||
{ id: 'local', name: 'Local', url: 'http://127.0.0.1:3000', tags: [] },
|
||||
{ id: 'lan', name: 'Lan', url: 'http://192.168.1.3', tags: [] },
|
||||
{ id: 'wan', name: 'Wan', url: 'https://wan.example', tags: [] },
|
||||
];
|
||||
const model = buildFleetTableViewModel(scoped, new Map(), { access: 'local' });
|
||||
expect(model.rows.map((row) => row.id)).toEqual(['local']);
|
||||
expect(buildFleetTableViewModel(instances, statuses, { access: 'lan' }).emptyReason).toBe(
|
||||
'filter',
|
||||
);
|
||||
expect(
|
||||
buildFleetTableViewModel(scoped, new Map(), { query: 'lan' }).rows.map((r) => r.id),
|
||||
).toEqual(['lan']);
|
||||
|
||||
const identified = new Map<string, FleetStatus>([
|
||||
[
|
||||
'alpha',
|
||||
{
|
||||
reachable: true,
|
||||
identity: {
|
||||
tracked: true,
|
||||
status: 'confirmed',
|
||||
reasons: [],
|
||||
imei: '860000000000001',
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(
|
||||
buildFleetTableViewModel(
|
||||
[{ id: 'alpha', name: 'Alpha', url: 'http://alpha.example', tags: [] }],
|
||||
identified,
|
||||
{ query: '860000000000001' },
|
||||
).rows.map((row) => row.id),
|
||||
).toEqual(['alpha']);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user