111 lines
4.2 KiB
TypeScript
111 lines
4.2 KiB
TypeScript
import { afterEach, expect, it } from 'vitest';
|
|
import { flushSync, mount, unmount } from 'svelte';
|
|
import TemperatureChart from '../../src/lib/ui/components/capacity/TemperatureChart.svelte';
|
|
import type { CapacityHistory } from '../../src/lib/capacity.js';
|
|
|
|
let component: ReturnType<typeof mount> | undefined;
|
|
afterEach(async () => {
|
|
if (component) await unmount(component);
|
|
component = undefined;
|
|
document.body.replaceChildren();
|
|
});
|
|
function history(): CapacityHistory {
|
|
return {
|
|
range: '1h',
|
|
startAt: 1000,
|
|
endAt: 4000,
|
|
bucketMs: 1000,
|
|
points: [1000, 2000, 3000].map((at) => ({
|
|
at,
|
|
cpuCoresAvailable: null,
|
|
memoryBytesAvailable: null,
|
|
reportingHosts: 0,
|
|
expectedHosts: 1
|
|
})),
|
|
temperatures: [
|
|
{
|
|
id: 'host:cpu',
|
|
hostId: 'host',
|
|
label: 'CPU temperature',
|
|
kind: 'cpu',
|
|
points: [65, null, 67].map((celsius, i) => ({ at: 1000 + i * 1000, celsius }))
|
|
},
|
|
{
|
|
id: 'host:drive',
|
|
hostId: 'host',
|
|
label: 'NVMe drive 1',
|
|
kind: 'nvme',
|
|
points: [49, 50.9, 52].map((celsius, i) => ({ at: 1000 + i * 1000, celsius }))
|
|
}
|
|
]
|
|
};
|
|
}
|
|
function show(report = history()) {
|
|
component = mount(TemperatureChart, {
|
|
target: document.body,
|
|
props: { history: report, scope: 'ec-2' }
|
|
});
|
|
flushSync();
|
|
}
|
|
|
|
it('defaults to CPU and toggles device lines and readouts together', () => {
|
|
show();
|
|
const buttons = document.querySelectorAll<HTMLButtonElement>('.legend button');
|
|
expect(buttons[0].getAttribute('aria-pressed')).toBe('true');
|
|
expect(buttons[1].getAttribute('aria-pressed')).toBe('false');
|
|
expect(document.querySelectorAll('[data-series]')).toHaveLength(1);
|
|
// A missing middle bucket splits the CPU line into two isolated segments.
|
|
expect(document.querySelectorAll('[data-series="host:cpu"] path')).toHaveLength(2);
|
|
buttons[1].click();
|
|
flushSync();
|
|
expect(document.querySelectorAll('[data-series]')).toHaveLength(2);
|
|
expect(document.querySelector('.readout')?.textContent).toContain('52 °C');
|
|
buttons[0].click();
|
|
buttons[1].click();
|
|
flushSync();
|
|
expect(document.querySelectorAll('[data-series]')).toHaveLength(0);
|
|
expect(document.body.textContent).toContain('Select a sensor to show history');
|
|
expect(document.querySelector('.readout')).toBeNull();
|
|
});
|
|
|
|
it('supports keyboard and pointer inspection without turning missing readings into zero', () => {
|
|
show();
|
|
const plot = document.querySelector<HTMLElement>('[role="slider"]')!;
|
|
expect(plot.getAttribute('aria-valuenow')).toBe('2');
|
|
plot.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', bubbles: true }));
|
|
flushSync();
|
|
expect(plot.getAttribute('aria-valuetext')).toContain('65 °C');
|
|
plot.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
|
|
flushSync();
|
|
expect(plot.getAttribute('aria-valuetext')).toContain('Unavailable');
|
|
expect(document.querySelector('.readout')?.textContent).not.toContain('0 °C');
|
|
Object.defineProperty(plot, 'getBoundingClientRect', {
|
|
value: () => ({ left: 0, width: 1000 })
|
|
});
|
|
plot.dispatchEvent(
|
|
new PointerEvent('pointerdown', { clientX: 8, pointerType: 'touch', bubbles: true })
|
|
);
|
|
flushSync();
|
|
expect(plot.getAttribute('aria-valuenow')).toBe('0');
|
|
expect(document.querySelector('.readout')?.textContent).toContain('65 °C');
|
|
});
|
|
|
|
it('shows unsupported hosts as unavailable', () => {
|
|
const report = history();
|
|
report.temperatures[0].points = report.temperatures[0].points.map((point) => ({
|
|
...point,
|
|
celsius: null
|
|
}));
|
|
show(report);
|
|
expect(document.body.textContent).toContain('No temperature readings in this period');
|
|
expect(document.body.textContent).toContain('Unavailable');
|
|
});
|
|
|
|
it('plots a genuine zero-degree reading', () => {
|
|
const report = history();
|
|
report.temperatures[0].points[2].celsius = 0;
|
|
show(report);
|
|
expect(document.querySelector('.readout')?.textContent).toContain('0 °C');
|
|
expect(document.querySelector('.empty-chart')).toBeNull();
|
|
});
|