Close the small residual branch gaps in five frontend modules

A second pass over modules whose own specs left only a handful of cold arms.
Counts are uncovered branches, module scoped, existing specs versus existing
plus new.

- diskResourceUtils 6 -> 0, the densest remaining gap in the frontend by
  ratio: missing capacity fields, absent SMART evidence and the no-candidate
  node arms.
- proxmoxPageModel 6 -> 0, availabilitySettingsModel 5 -> 0 and
  standalonePageModel 5 -> 0, all empty-collection guards, absent optional
  metadata and validation rejection arms.
- connectionsTableModel 8 -> 2 across eleven existing specs.

truenasPageModel was DISCARDED rather than committed: its remaining eight arms
measured no coverage gain and the agent correctly reported seven of them as
unreachable by construction, so there was nothing honest to land.

No source file is modified. Adversarial review returned no rejects and flagged
eight near-duplicate cases across four files; all eight were removed and the
module coverage re-measured as unchanged, proving they carried nothing.

PULSE_ALLOW_CONTRACT_NEUTRAL_COMMIT=test-only branch coverage, no source or contract change
This commit is contained in:
rcourtman
2026-07-25 00:27:00 +01:00
parent 6060936cb3
commit c483d2c014
5 changed files with 717 additions and 0 deletions
@@ -0,0 +1,122 @@
/**
* Branch-coverage tests for availabilitySettingsModel, targeting the arms left
* cold by availabilitySettingsModel.test.ts and availabilitySettingsModel.branchcov2.test.ts.
*
* Scoped coverage against those two existing specs leaves exactly five branches
* uncovered, all reachable from the public surface:
* - the 'udp' switch case in getAvailabilityTargetMethodLabel (both the
* with-port and without-port ternary arms inside it),
* - the `status.outcome === 'indeterminate'` consequent in
* getAvailabilityTargetStatusLabel ('Open or filtered'),
* - the `status.outcome === 'indeterminate'` consequent in
* getAvailabilityTargetStatusClass (amber badge),
* - the empty-targets consequent in getAvailabilityTargetsSummary
* ('No availability checks configured'),
* - the fall-through (no down, no indeterminate) to the final default return
* in getAvailabilityTargetsSummary ('N enabled · M total').
*
* Fixture builders and import style mirror the sibling branchcov2 file.
*/
import { describe, expect, it } from 'vitest';
import {
getAvailabilityTargetMethodLabel,
getAvailabilityTargetStatusClass,
getAvailabilityTargetStatusLabel,
getAvailabilityTargetsSummary,
} from '../availabilitySettingsModel';
import type { AvailabilityProbeStatus, AvailabilityTarget } from '@/api/availabilityTargets';
// ---- Fixtures ---------------------------------------------------------------
// Mirrors the sibling test factories so the three files stay consistent.
const target = (overrides: Partial<AvailabilityTarget> = {}): AvailabilityTarget => ({
id: 'mqtt-broker',
name: 'MQTT broker',
address: 'mqtt.local',
protocol: 'tcp',
port: 1883,
enabled: true,
...overrides,
});
const status = (overrides: Partial<AvailabilityProbeStatus> = {}): AvailabilityProbeStatus => ({
targetId: 'mqtt-broker',
name: 'MQTT broker',
address: 'mqtt.local',
protocol: 'tcp',
enabled: true,
available: true,
...overrides,
});
// ---- getAvailabilityTargetMethodLabel --------------------------------------
// The 'udp' switch case is the only protocol arm never entered by the sibling
// specs. Drive both ternary operands inside it (port present vs absent/0).
describe('getAvailabilityTargetMethodLabel (udp arm)', () => {
it("includes the port for a udp target with one ('UDP <port>' ternary arm)", () => {
expect(getAvailabilityTargetMethodLabel(target({ protocol: 'udp', port: 27015 }))).toBe(
'UDP 27015',
);
});
it("returns 'UDP port' for a udp target without a port (port falsy ternary arm)", () => {
expect(getAvailabilityTargetMethodLabel(target({ protocol: 'udp', port: undefined }))).toBe(
'UDP port',
);
});
});
// ---- getAvailabilityTargetStatusLabel --------------------------------------
// The indeterminate-outcome consequent short-circuits before the available /
// lastError arms and was never hit. outcome takes priority over `available`, so
// confirm it wins even when `available` is false.
describe('getAvailabilityTargetStatusLabel (indeterminate arm)', () => {
it("returns 'Open or filtered' when outcome is indeterminate (before the available branch)", () => {
expect(
getAvailabilityTargetStatusLabel(
target({
status: status({ available: false, outcome: 'indeterminate' }),
}),
),
).toBe('Open or filtered');
});
});
// ---- getAvailabilityTargetStatusClass --------------------------------------
// The indeterminate-outcome consequent returns the amber badge and was never
// hit. Like the label helper it is checked before the available branch.
describe('getAvailabilityTargetStatusClass (indeterminate arm)', () => {
it('returns the amber badge classes for an indeterminate outcome', () => {
expect(
getAvailabilityTargetStatusClass(
target({
status: status({ available: false, outcome: 'indeterminate' }),
}),
),
).toBe('bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300');
});
});
// ---- getAvailabilityTargetsSummary -----------------------------------------
// Two cold arms live here: the empty-input early return, and the final default
// return reached only when no target is down and none are indeterminate.
describe('getAvailabilityTargetsSummary (empty + all-healthy arms)', () => {
it("returns 'No availability checks configured' for an empty list (length === 0 arm)", () => {
expect(getAvailabilityTargetsSummary([])).toBe('No availability checks configured');
});
it("returns the default '<enabled> enabled · <total> total' when nothing is down or indeterminate (final fall-through arm)", () => {
// One online target and one paused target: enabled=1, down=0, indeterminate=0,
// total=2 -> falls through every guard to the default return.
expect(
getAvailabilityTargetsSummary([
target({ id: 'online', status: status({ targetId: 'online', available: true }) }),
target({ id: 'paused', enabled: false }),
]),
).toBe('1 enabled · 2 total');
});
});
@@ -0,0 +1,255 @@
import { describe, expect, it } from 'vitest';
import type {
Connection,
ConnectionAgentModuleStatus,
ConnectionFleetGovernance,
} from '@/api/connections';
import {
fleetGovernanceSignalsForConnection,
surfaceLabel,
visibleFleetGovernanceSignals,
type FleetGovernanceSignal,
type FleetGovernanceSignalKey,
} from '../connectionsTableModel';
// ---- Fixtures ---------------------------------------------------------------
// Mirrors the sibling coverage tests so the private signal builders below are
// driven through the single exported orchestrator (fleetGovernanceSignalsForConnection).
const connectionFixture = (overrides: Partial<Connection> = {}): Connection => ({
id: 'agent:host-1',
type: 'agent',
name: 'host-1',
address: 'host-1',
state: 'active',
stateReason: '',
enabled: true,
surfaces: ['host'],
scope: { host: true },
lastSeen: '2026-04-23T12:00:00Z',
lastError: null,
source: 'agent',
capabilities: { supportsPause: false, supportsScope: false, supportsTest: false },
...overrides,
});
const fleetFixture = (
overrides: Partial<ConnectionFleetGovernance> = {},
): ConnectionFleetGovernance => ({
enrollmentState: 'enrolled',
livenessState: 'active',
versionDrift: 'current',
adapterHealth: 'healthy',
configRollout: 'reported',
credentialStatus: 'verified',
updateStatus: 'current',
remoteControl: 'disabled',
...overrides,
});
const signalByKey = (
connection: Connection,
key: FleetGovernanceSignalKey,
): FleetGovernanceSignal | undefined =>
fleetGovernanceSignalsForConnection(connection).find((signal) => signal.key === key);
const agentModule = (
overrides: Partial<ConnectionAgentModuleStatus> = {},
): ConnectionAgentModuleStatus => ({
name: 'host',
enabled: true,
state: 'retrying',
updatedAt: '2026-07-09T12:00:00Z',
...overrides,
});
// ---- surfaceLabel (private fallback arm) ------------------------------------
//
// surfaceLabel returns SURFACE_LABELS[key] ?? key. The sibling suites exercise
// it only through the orchestrator paths with known keys; the cold arm is the
// `?? key` fallback for an unregistered surface.
describe('surfaceLabel', () => {
it('falls back to the raw key when the surface is unregistered (?? key arm)', () => {
expect(surfaceLabel('totallyUnknown')).toBe('totallyUnknown');
});
});
// ---- commandPolicyFromFleet (private) — remoteControl "disconnected" --------
//
// commandPolicyFromFleet switches on remoteControl when no explicit commandPolicy
// is present. The 'disconnected' arm was the only un-exercised case: it derives a
// blocked policy that commandPolicySignal then renders as 'Remote control blocked'.
describe('commandPolicyFromFleet (via fleetGovernanceSignalsForConnection)', () => {
it('derives a blocked command policy from remoteControl disconnected', () => {
const signal = signalByKey(
connectionFixture({ fleet: fleetFixture({ remoteControl: 'disconnected' }) }),
'command-policy',
);
expect(signal).toMatchObject({
key: 'command-policy',
label: 'Remote control blocked',
detail: 'The agent reports command execution enabled, but no command channel is connected.',
tone: 'critical',
});
});
});
// ---- commandPolicySignal (private) — explicit status "unknown" --------------
//
// commandPolicySignal first branches on enforcement (drifted/pending), then
// switches on status. The derived path can never produce status 'unknown' with a
// non-pending enforcement, so the switch's 'unknown' arm is only reachable
// through an explicit fleet.commandPolicy override whose enforcement is neither
// drifted nor pending.
describe('commandPolicySignal (via fleetGovernanceSignalsForConnection)', () => {
it('surfaces an explicit unknown command-policy status as a warning when enforcement is neutral', () => {
// enforcement is omitted (undefined) so neither the drifted nor pending
// short-circuit fires; the status switch reaches its 'unknown' arm.
const signal = signalByKey(
connectionFixture({
fleet: fleetFixture({
remoteControl: 'enabled',
commandPolicy: { status: 'unknown' },
}),
}),
'command-policy',
);
expect(signal).toMatchObject({
key: 'command-policy',
label: 'Remote control unknown',
detail: 'Pulse has not confirmed command-policy state yet.',
tone: 'warning',
});
});
});
// ---- updateSignal (private) — failed fallback detail ------------------------
//
// updateSignal's 'failed' arm uses `update?.lastError || <fallback>`. The
// sibling suite always supplies a populated agentUpdate.lastError for the failed
// case, so the `|| fallback` arm is cold. It fires when the agent has no update
// object at all, or when lastError is blank.
describe('updateSignal (via fleetGovernanceSignalsForConnection)', () => {
it('uses the generic update-failed detail when no agentUpdate object is present', () => {
const signal = signalByKey(
connectionFixture({ fleet: fleetFixture({ updateStatus: 'failed' }) }),
'updates',
);
expect(signal).toMatchObject({
key: 'updates',
label: 'Agent update failed',
detail: 'The agent could not complete its latest update check or update attempt.',
tone: 'critical',
});
});
it('falls back to the generic detail when agentUpdate.lastError is an empty string', () => {
const signal = signalByKey(
connectionFixture({
fleet: fleetFixture({ updateStatus: 'failed' }),
agentUpdate: { state: 'error', autoUpdate: false, lastError: '' },
}),
'updates',
);
expect(signal?.detail).toBe(
'The agent could not complete its latest update check or update attempt.',
);
});
});
// ---- moduleHealthSignal (private) — displayName ternary arms -----------------
//
// moduleHealthSignal maps module.name to a display name via a nested ternary
// (docker/kubernetes/host/<raw>). The sibling suites cover the docker and
// kubernetes names; the remaining arms (host + the raw fallback) are cold.
describe('moduleHealthSignal (via fleetGovernanceSignalsForConnection)', () => {
it('prettifies a failing host module to "Host" and uses the generic detail when lastError is absent', () => {
const signal = signalByKey(
connectionFixture({
agentModules: [agentModule({ name: 'host', state: 'retrying' })],
fleet: fleetFixture(),
}),
'module-health',
);
expect(signal).toMatchObject({
key: 'module-health',
label: 'Host module retrying',
tone: 'warning',
});
expect(signal?.detail).toBe('Host monitoring is enabled but the module is not running yet.');
});
it('uses the raw module name for a non-canonical module', () => {
const signal = signalByKey(
connectionFixture({
agentModules: [agentModule({ name: 'backup-collector', state: 'starting' })],
fleet: fleetFixture(),
}),
'module-health',
);
expect(signal?.label).toBe('backup-collector module starting');
expect(signal?.detail).toBe(
'backup-collector monitoring is enabled but the module is not running yet.',
);
});
});
// ---- isPassiveAgentRolloutConfirmationFallbackSignal (private) --------------
//
// This guard returns true for a rollout warning whose detail contains EITHER of
// two confirmation phrases, but only when a passive config-confirmation signal
// is also present. The sibling suites cover the first phrase
// ("staged rollout is waiting for confirmation"); the second phrase
// ("rollout state cannot be confirmed without comparable desired and applied
// agent config fingerprints") is cold. Driving it through
// visibleFleetGovernanceSignals asserts the observable effect: such a rollout
// signal is filtered out as a passive handshake.
describe('isPassiveAgentRolloutConfirmationFallbackSignal (via visibleFleetGovernanceSignals)', () => {
it('hides a rollout signal whose detail carries the second confirmation phrase', () => {
const signals: FleetGovernanceSignal[] = [
{
key: 'config-drift',
label: 'Config pending',
detail: 'Pulse has not received a comparable applied agent configuration fingerprint yet.',
tone: 'warning',
},
{
key: 'rollout',
label: 'Rollout pending',
detail:
'rollout state cannot be confirmed without comparable desired and applied agent config fingerprints',
tone: 'warning',
},
];
// Both signals are passive handshakes, so neither surfaces as a chip.
expect(visibleFleetGovernanceSignals(signals)).toEqual([]);
});
it('keeps a rollout warning visible when its detail matches neither confirmation phrase', () => {
const signals: FleetGovernanceSignal[] = [
{
key: 'config-drift',
label: 'Config pending',
detail: 'Pulse has not received a comparable applied agent configuration fingerprint yet.',
tone: 'warning',
},
{
key: 'rollout',
label: 'Rollout pending',
detail: 'The canary batch for this rollout is stalled.',
tone: 'warning',
},
];
// The config-drift handshake is hidden, but the rollout carries an
// actionable, non-handshake reason and must remain visible.
expect(visibleFleetGovernanceSignals(signals).map((signal) => signal.label)).toEqual([
'Rollout pending',
]);
});
});
@@ -0,0 +1,90 @@
import { describe, expect, it } from 'vitest';
import type { Resource } from '@/types/resource';
import {
getPhysicalDiskNodeIdentity,
matchesPhysicalDiskNode,
resolvePhysicalDiskMetricResourceId,
} from '@/components/Storage/diskResourceUtils';
const buildDisk = (overrides: Partial<Resource> = {}): Resource =>
({
id: 'disk-1',
type: 'physical_disk',
name: 'disk-1',
displayName: 'disk-1',
platformId: 'cluster-main',
platformType: 'proxmox-pve',
sourceType: 'api',
status: 'online',
lastSeen: Date.now(),
platformData: {
proxmox: { nodeName: 'tower', instance: 'cluster-main' },
physicalDisk: { devPath: '/dev/sda' },
},
identity: { hostname: 'tower' },
canonicalIdentity: { hostname: 'tower' },
...overrides,
}) as Resource;
describe('diskResourceUtils branch coverage', () => {
describe('getPhysicalDiskNodeIdentity node fallback chain', () => {
// L24: `resource.platformData || {}` right-hand fallback — platformData falsy.
it('falls back to an empty platformData record and resolves the node from identity', () => {
const disk = buildDisk({ platformData: undefined });
// No proxmox block survives the fallback, so identity.hostname is the
// only node evidence and the instance collapses to ''.
expect(getPhysicalDiskNodeIdentity(disk)).toEqual({ node: 'tower', instance: '' });
});
// L28: proxmox.nodeName absent -> identity?.hostname arm.
it('derives the node from resource identity hostname when proxmox omits it', () => {
const disk = buildDisk({
platformData: { physicalDisk: { devPath: '/dev/sda' } } as Resource['platformData'],
identity: { hostname: 'host-from-identity' },
});
expect(getPhysicalDiskNodeIdentity(disk)).toEqual({
node: 'host-from-identity',
instance: '',
});
});
// L28: proxmox.nodeName + identity absent -> canonicalIdentity?.hostname arm.
it('falls back to canonicalIdentity hostname when proxmox and identity are absent', () => {
const disk = buildDisk({
platformData: { physicalDisk: { devPath: '/dev/sda' } } as Resource['platformData'],
identity: undefined,
canonicalIdentity: { hostname: 'canon-host' },
});
expect(getPhysicalDiskNodeIdentity(disk)).toEqual({ node: 'canon-host', instance: '' });
});
// L28: every hostname source absent -> final `|| ''` arm.
it('returns an empty node when no hostname evidence exists anywhere', () => {
const disk = buildDisk({
platformData: { physicalDisk: { devPath: '/dev/sda' } } as Resource['platformData'],
identity: undefined,
canonicalIdentity: undefined,
});
expect(getPhysicalDiskNodeIdentity(disk)).toEqual({ node: '', instance: '' });
});
});
describe('matchesPhysicalDiskNode', () => {
// L40: `target.id && disk.parentId === target.id` -> early `return true`.
it('short-circuits to a match when the disk parentId equals the target id', () => {
// A name that would NOT match by node identity, proving the parentId
// early-return path is the one taken.
const disk = buildDisk({ parentId: 'node-1' });
expect(matchesPhysicalDiskNode(disk, { id: 'node-1', name: 'unrelated-node-name' })).toBe(
true,
);
});
});
describe('resolvePhysicalDiskMetricResourceId', () => {
// L82 ternary false arm + L84 `!agentId` early return: no candidate node.
it('returns null when the node collection is empty and no agent can be linked', () => {
expect(resolvePhysicalDiskMetricResourceId(buildDisk(), [], '/dev/sda')).toBeNull();
});
});
});
@@ -0,0 +1,135 @@
import { describe, expect, it } from 'vitest';
import type { Resource } from '@/types/resource';
import {
buildProxmoxPageModel,
getProxmoxProviderScope,
isProxmoxChildOfNode,
} from '../proxmoxPageModel';
// ---------------------------------------------------------------------------
// Fixture builder — mirrors the sibling proxmoxPageModel.test.ts factory so
// import style and default platform posture stay aligned.
// ---------------------------------------------------------------------------
const makeResource = (resource: Partial<Resource> & Pick<Resource, 'id' | 'type'>): Resource => ({
name: resource.id,
displayName: resource.id,
platformId: 'lab',
platformType: 'proxmox-pve',
sourceType: 'api',
status: 'online',
lastSeen: 1_700_000_000_000,
...resource,
});
// ===========================================================================
// getProxmoxProviderScope — the `||` fallback chain. The happy-path specs
// only ever exercise resources whose `proxmox.instance` (or, transitively,
// `platformId`) short-circuits the chain. The cold arms are the later
// operands: clusterId, parentId, and the final id fall-through.
// ===========================================================================
describe('getProxmoxProviderScope fallback chain', () => {
it('falls back to clusterId when proxmox.instance and platformId are absent', () => {
const resource = makeResource({
id: 'r',
type: 'agent',
platformId: '',
clusterId: 'cluster-9',
});
expect(getProxmoxProviderScope(resource)).toBe('cluster-9');
});
it('falls back to parentId when instance, platformId, and clusterId are absent', () => {
const resource = makeResource({
id: 'r',
type: 'agent',
platformId: '',
parentId: 'host-node',
});
expect(getProxmoxProviderScope(resource)).toBe('host-node');
});
it('returns resource.id as the final fallback when every scope field is absent', () => {
const resource = makeResource({ id: 'last-resort', type: 'agent', platformId: '' });
expect(getProxmoxProviderScope(resource)).toBe('last-resort');
});
});
// ===========================================================================
// isProxmoxChildOfNode — the parentId early-return guard. Existing specs
// relate guests to nodes via nodeName/scope only, so the
// `child.parentId && child.parentId === node.id` arm is never taken.
// ===========================================================================
describe('isProxmoxChildOfNode parentId early-return', () => {
it('returns true when child.parentId matches node.id without consulting node names', () => {
const node = makeResource({
id: 'node-1',
type: 'agent',
proxmox: { nodeName: 'node-1' },
});
// Deliberately mismatched nodeName to prove the parentId arm wins outright.
const child = makeResource({
id: 'vm-1',
type: 'vm',
parentId: 'node-1',
proxmox: { nodeName: 'unrelated-host', vmid: 101 },
});
expect(isProxmoxChildOfNode(child, node)).toBe(true);
});
it('does not early-return when child.parentId is set but differs from node.id', () => {
const node = makeResource({
id: 'node-1',
type: 'agent',
proxmox: { nodeName: 'node-1' },
});
const child = makeResource({
id: 'vm-2',
type: 'vm',
parentId: 'other-node',
proxmox: { nodeName: 'different-host', vmid: 102 },
});
expect(isProxmoxChildOfNode(child, node)).toBe(false);
});
});
// ===========================================================================
// buildProxmoxPageModel — the cluster-group sort comparator. The happy-path
// specs always insert named clusters before the standalone bucket, so V8's
// sort only ever calls the comparator with (standalone, non-standalone) pairs
// and only the `1` (consequent) arm fires. Inserting a standalone node FIRST
// makes the comparator receive (non-standalone, standalone) pairs and return
// the `-1` (alternate) arm.
// ===========================================================================
describe('buildProxmoxPageModel standalone-first sort comparator', () => {
it('exercises the -1 arm of the sort comparator when the standalone group is inserted first', () => {
// A node carrying no cluster hint resolves to 'Standalone'. Placed before a
// named-cluster node, the standalone bucket lands first in the insertion
// order, flipping the comparator argument direction.
const standaloneNode = makeResource({
id: 'solo-node',
type: 'agent',
proxmox: { nodeName: 'solo-node' },
});
const namedNode = makeResource({
id: 'named-node',
type: 'agent',
proxmox: { nodeName: 'named-node', clusterName: 'named' },
});
const model = buildProxmoxPageModel([standaloneNode, namedNode]);
// Standalone was inserted first; the sort still places named before standalone.
expect(model.clusterGroups.map((group) => group.label)).toEqual(['named', 'Standalone']);
expect(model.clusterGroups.map((group) => group.id)).toEqual([
'lab::named',
'lab::__standalone__',
]);
// The standalone bucket never counts as a real cluster.
expect(model.summary.clusterCount).toBe(1);
});
});
@@ -0,0 +1,115 @@
import { describe, expect, it } from 'vitest';
import type { Resource } from '@/types/resource';
import {
buildStandalonePostureSummary,
getStandaloneResourceStatusIndicator,
} from '../standalonePageModel';
const NOW_MS = Date.parse('2026-07-24T12:00:00Z');
const resource = (overrides: Partial<Resource>): Resource =>
({
id: overrides.id ?? 'agent-1',
name: overrides.name ?? overrides.id ?? 'agent-1',
displayName: overrides.displayName ?? overrides.name ?? overrides.id ?? 'agent-1',
type: overrides.type ?? 'agent',
platformId: overrides.platformId ?? 'agent-1',
platformType: overrides.platformType ?? 'agent',
sourceType: overrides.sourceType ?? 'agent',
status: overrides.status ?? 'online',
lastSeen: overrides.lastSeen ?? NOW_MS,
...overrides,
}) as Resource;
describe('standalonePageModel branch coverage', () => {
it('treats an ambiguous availability correlation with fresh evidence as an unresolved-identity warning', () => {
// Freshness is deliberately fresh (recent lastChecked + short poll
// interval keep it inside the freshness window) so the warning can only
// come from correlationState === 'ambiguous', and the label ternary falls
// through to 'Identity unresolved'.
const indicator = getStandaloneResourceStatusIndicator(
resource({
id: 'availability:ambiguous',
type: 'network-endpoint',
platformType: 'availability',
status: 'online',
availability: {
targetId: 'ambiguous',
correlationState: 'ambiguous',
available: true,
lastChecked: '2026-07-24T11:59:00Z',
pollIntervalSeconds: 60,
},
}),
NOW_MS,
);
expect(indicator).toEqual({ variant: 'warning', label: 'Identity unresolved' });
});
it('treats an unresolved availability correlation with fresh evidence as an unresolved-identity warning', () => {
const indicator = getStandaloneResourceStatusIndicator(
resource({
id: 'availability:unresolved',
type: 'network-endpoint',
platformType: 'availability',
status: 'online',
availability: {
targetId: 'unresolved',
correlationState: 'unresolved',
available: true,
lastChecked: '2026-07-24T11:59:00Z',
pollIntervalSeconds: 60,
},
}),
NOW_MS,
);
expect(indicator).toEqual({ variant: 'warning', label: 'Identity unresolved' });
});
it('treats an agent carrying the explicit stale flag as attention even when its last report is recent', () => {
// lastSeen is one minute before now, far inside the 5-minute stale
// window, so the time-based staleness expression cannot be the cause;
// only resource.agent?.stale === true forces the warning here.
const indicator = getStandaloneResourceStatusIndicator(
resource({
id: 'agent-flag-stale',
type: 'agent',
status: 'online',
lastSeen: NOW_MS - 60_000,
agent: { stale: true },
}),
NOW_MS,
);
expect(indicator).toEqual({ variant: 'warning', label: 'Stale' });
});
it('counts a status outside online/degraded/offline buckets as an unknown posture row', () => {
// 'paused' is not in OFFLINE/DEGRADED/online sets, so the base indicator
// resolves to the muted variant and the summary falls into the unknown
// else arm. lastSeen is non-positive so latestUpdateAt must stay unset.
const summary = buildStandalonePostureSummary(
[
resource({
id: 'paused-endpoint',
type: 'network-endpoint',
status: 'paused',
lastSeen: 0,
}),
],
NOW_MS,
);
expect(summary).toEqual({
attention: 0,
critical: 0,
normal: 0,
total: 1,
unknown: 1,
warning: 0,
});
expect(summary.latestUpdateAt).toBeUndefined();
});
});