test(api): Worker export/CSV — fill gaps + lifecycle test
Drove src/lib/csv.ts to 100% stmts/branch/funcs/lines (was 97.95%/55.55%): - added a null-fallback row test covering every ?? default (activityName, userName, insoleType→Kurk, pairCount→2, duration/paused→0) and the null end-time branch (line 65). - added CSV-escaping edge tests: commas, embedded quotes, and newlines inside a field stay inside the quoted cell. - added formatDuration edge (hours >99 → 100:00:00). - added a /api/export ordering-by-start-time behavior test and adopted resetDb per-test isolation in the export suite. No bugs found; CSV code behaves correctly. sessions.ts /api/export route already at 100%. Full api suite green (150 tests).
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import type { Hono } from 'hono';
|
||||
import { createApp } from '../src/app';
|
||||
import { db } from '../src/db/client';
|
||||
import { workSessions } from '../src/db/schema';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { quote, formatDuration } from '../src/lib/csv';
|
||||
import { authToken, bearer, seedActivity } from './helpers';
|
||||
import { authToken, bearer, seedActivity, resetDb } from './helpers';
|
||||
|
||||
// Start a session, backdate its start_time by `durationSeconds`, then stop it,
|
||||
// producing a completed session with an exact duration.
|
||||
@@ -31,6 +31,8 @@ async function completedSession(
|
||||
}
|
||||
|
||||
describe('csv export', () => {
|
||||
beforeEach(resetDb);
|
||||
|
||||
it('401s without a token', async () => {
|
||||
const app = createApp();
|
||||
const res = await app.request('/api/export');
|
||||
@@ -118,6 +120,32 @@ describe('csv export', () => {
|
||||
const lines = (await res.text()).split('\n');
|
||||
expect(lines).toHaveLength(2); // header + 1 completed row
|
||||
});
|
||||
|
||||
it('orders rows by start time ascending', async () => {
|
||||
const app = createApp();
|
||||
const token = await authToken(app, 'export-order@example.com');
|
||||
const frezenId = await seedActivity('Frezen');
|
||||
const slijpenId = await seedActivity('Slijpen');
|
||||
|
||||
// Two completed sessions; make Frezen clearly the older start.
|
||||
const older = await completedSession(app, token, frezenId, 'Kurk', 30);
|
||||
const newer = await completedSession(app, token, slijpenId, 'Berk', 30);
|
||||
await db
|
||||
.update(workSessions)
|
||||
.set({ startTime: new Date(Date.now() - 60000) })
|
||||
.where(eq(workSessions.id, older));
|
||||
await db
|
||||
.update(workSessions)
|
||||
.set({ startTime: new Date(Date.now() - 10000) })
|
||||
.where(eq(workSessions.id, newer));
|
||||
|
||||
const lines = (
|
||||
await (await app.request('/api/export', { headers: bearer(token) })).text()
|
||||
).split('\n');
|
||||
expect(lines).toHaveLength(3); // header + 2 rows
|
||||
expect(lines[1]).toContain('"Frezen"'); // oldest start first
|
||||
expect(lines[2]).toContain('"Slijpen"');
|
||||
});
|
||||
});
|
||||
|
||||
describe('csv helpers', () => {
|
||||
|
||||
Reference in New Issue
Block a user