Add unit and integration test suites

- Shared: link building, feed ordering, input schemas, API client
- API unit: track matching, private-address blocking, token crypto,
  plan expiry, provider response parsing
- API integration against Postgres and Redis: auth, follows and pins,
  now-playing state, webhooks, OAuth return URLs, realtime, rate limits
- Tests use a dedicated *_test database and Redis DB, and refuse to wipe
  anything else; fetch is stubbed so they never hit the network
- Pin Node to 22.13+ (.nvmrc), which Vite's native bindings require

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MzFywujuH9TiuXbr9vjoX8
This commit is contained in:
2026-10-03 11:28:17 -04:00
co-authored by Claude Opus 5.5
parent 95cd740e51
commit fe503307df
29 changed files with 3281 additions and 10 deletions
+20
View File
@@ -0,0 +1,20 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { timeAgo } from './time';
describe('timeAgo', () => {
beforeEach(() => {
vi.useFakeTimers();
vi.setSystemTime(new Date('2026-10-03T12:00:00Z'));
});
afterEach(() => vi.useRealTimers());
it.each([
['2026-10-03T11:59:30Z', 'just now'],
['2026-10-03T11:55:00Z', '5m ago'],
['2026-10-03T09:00:00Z', '3h ago'],
['2026-09-30T12:00:00Z', '3d ago'],
['2026-10-03T12:00:10Z', 'just now'], // slight clock skew into the future
])('%s → %s', (iso, expected) => {
expect(timeAgo(iso)).toBe(expected);
});
});