mirror of
https://github.com/ruvnet/RuView.git
synced 2026-08-28 19:16:38 +00:00
The web UI had persistent 404 errors on model, recording, and training endpoints, and the sensing WebSocket never connected on Dashboard/Live Demo tabs because sensingService.start() was only called lazily on Sensing tab visit. Server (main.rs): - Add 14 fully-functional Axum handlers: model CRUD (7), recording lifecycle (4), training control (3) - Scan data/models/ and data/recordings/ at startup - Recording writes CSI frames to .jsonl via tokio background task - Model load/unload lifecycle with state tracking Web UI (app.js): - Import and start sensingService early in initializeServices() so Dashboard and Live Demo tabs connect to /ws/sensing immediately Mobile (ws.service.ts): - Fix WebSocket URL builder to use same-origin port instead of hardcoded port 3001 Mobile (jest.config.js): - Fix testPathIgnorePatterns that was ignoring the entire test directory Mobile (25 test files): - Replace all it.todo() placeholder tests with real implementations covering components, services, stores, hooks, screens, and utils ADR-043 documents all changes. Co-Authored-By: claude-flow <ruv@ruv.net>
148 lines
4.0 KiB
TypeScript
148 lines
4.0 KiB
TypeScript
import { RingBuffer } from '@/utils/ringBuffer';
|
|
|
|
describe('RingBuffer', () => {
|
|
describe('constructor', () => {
|
|
it('creates a buffer with the given capacity', () => {
|
|
const buf = new RingBuffer<number>(5);
|
|
expect(buf.toArray()).toEqual([]);
|
|
});
|
|
|
|
it('floors fractional capacity', () => {
|
|
const buf = new RingBuffer<number>(3.9);
|
|
buf.push(1);
|
|
buf.push(2);
|
|
buf.push(3);
|
|
buf.push(4);
|
|
// capacity is 3 (floored), so oldest is evicted
|
|
expect(buf.toArray()).toEqual([2, 3, 4]);
|
|
});
|
|
|
|
it('throws on zero capacity', () => {
|
|
expect(() => new RingBuffer<number>(0)).toThrow('capacity must be greater than 0');
|
|
});
|
|
|
|
it('throws on negative capacity', () => {
|
|
expect(() => new RingBuffer<number>(-1)).toThrow('capacity must be greater than 0');
|
|
});
|
|
|
|
it('throws on NaN capacity', () => {
|
|
expect(() => new RingBuffer<number>(NaN)).toThrow('capacity must be greater than 0');
|
|
});
|
|
|
|
it('throws on Infinity capacity', () => {
|
|
expect(() => new RingBuffer<number>(Infinity)).toThrow('capacity must be greater than 0');
|
|
});
|
|
});
|
|
|
|
describe('push', () => {
|
|
it('adds values in order', () => {
|
|
const buf = new RingBuffer<number>(5);
|
|
buf.push(10);
|
|
buf.push(20);
|
|
buf.push(30);
|
|
expect(buf.toArray()).toEqual([10, 20, 30]);
|
|
});
|
|
|
|
it('evicts oldest when capacity is exceeded', () => {
|
|
const buf = new RingBuffer<number>(3);
|
|
buf.push(1);
|
|
buf.push(2);
|
|
buf.push(3);
|
|
buf.push(4);
|
|
expect(buf.toArray()).toEqual([2, 3, 4]);
|
|
});
|
|
|
|
it('evicts multiple oldest values over time', () => {
|
|
const buf = new RingBuffer<number>(2);
|
|
buf.push(1);
|
|
buf.push(2);
|
|
buf.push(3);
|
|
buf.push(4);
|
|
buf.push(5);
|
|
expect(buf.toArray()).toEqual([4, 5]);
|
|
});
|
|
});
|
|
|
|
describe('toArray', () => {
|
|
it('returns a copy of the internal array', () => {
|
|
const buf = new RingBuffer<number>(5);
|
|
buf.push(1);
|
|
buf.push(2);
|
|
const arr = buf.toArray();
|
|
arr.push(99);
|
|
expect(buf.toArray()).toEqual([1, 2]);
|
|
});
|
|
|
|
it('returns an empty array when buffer is empty', () => {
|
|
const buf = new RingBuffer<number>(5);
|
|
expect(buf.toArray()).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('clear', () => {
|
|
it('empties the buffer', () => {
|
|
const buf = new RingBuffer<number>(5);
|
|
buf.push(1);
|
|
buf.push(2);
|
|
buf.clear();
|
|
expect(buf.toArray()).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe('max', () => {
|
|
it('returns null on empty buffer', () => {
|
|
const buf = new RingBuffer<number>(5, (a, b) => a - b);
|
|
expect(buf.max).toBeNull();
|
|
});
|
|
|
|
it('throws without comparator', () => {
|
|
const buf = new RingBuffer<number>(5);
|
|
buf.push(1);
|
|
expect(() => buf.max).toThrow('Comparator required for max()');
|
|
});
|
|
|
|
it('returns the maximum value', () => {
|
|
const buf = new RingBuffer<number>(5, (a, b) => a - b);
|
|
buf.push(3);
|
|
buf.push(1);
|
|
buf.push(5);
|
|
buf.push(2);
|
|
expect(buf.max).toBe(5);
|
|
});
|
|
|
|
it('returns the maximum with a single element', () => {
|
|
const buf = new RingBuffer<number>(5, (a, b) => a - b);
|
|
buf.push(42);
|
|
expect(buf.max).toBe(42);
|
|
});
|
|
});
|
|
|
|
describe('min', () => {
|
|
it('returns null on empty buffer', () => {
|
|
const buf = new RingBuffer<number>(5, (a, b) => a - b);
|
|
expect(buf.min).toBeNull();
|
|
});
|
|
|
|
it('throws without comparator', () => {
|
|
const buf = new RingBuffer<number>(5);
|
|
buf.push(1);
|
|
expect(() => buf.min).toThrow('Comparator required for min()');
|
|
});
|
|
|
|
it('returns the minimum value', () => {
|
|
const buf = new RingBuffer<number>(5, (a, b) => a - b);
|
|
buf.push(3);
|
|
buf.push(1);
|
|
buf.push(5);
|
|
buf.push(2);
|
|
expect(buf.min).toBe(1);
|
|
});
|
|
|
|
it('returns the minimum with a single element', () => {
|
|
const buf = new RingBuffer<number>(5, (a, b) => a - b);
|
|
buf.push(42);
|
|
expect(buf.min).toBe(42);
|
|
});
|
|
});
|
|
});
|