You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
5.6 KiB
TypeScript
167 lines
5.6 KiB
TypeScript
import { describe, it, expect, beforeAll, afterAll } from 'bun:test';
|
|
import { Database } from 'bun:sqlite';
|
|
import { mkdtempSync, rmSync } from 'fs';
|
|
import { tmpdir } from 'os';
|
|
import { join } from 'path';
|
|
import { startWebServer } from './helpers/server';
|
|
import { initializeDatabase, ensureUserExists } from '../../src/db';
|
|
|
|
async function sha256Hex(input: string): Promise<string> {
|
|
const enc = new TextEncoder().encode(input);
|
|
const buf = await crypto.subtle.digest('SHA-256', enc);
|
|
const bytes = new Uint8Array(buf);
|
|
return Array.from(bytes)
|
|
.map((b) => b.toString(16).padStart(2, '0'))
|
|
.join('');
|
|
}
|
|
|
|
function toIsoSql(d = new Date()): string {
|
|
return d.toISOString().replace('T', ' ').replace('Z', '');
|
|
}
|
|
|
|
describe('Web API - GET /api/me/preferences', () => {
|
|
const userId = '34600123456';
|
|
let dbPath: string;
|
|
let server: Awaited<ReturnType<typeof startWebServer>> | null = null;
|
|
let tmpDir: string;
|
|
|
|
beforeAll(async () => {
|
|
tmpDir = mkdtempSync(join(tmpdir(), 'webtest-'));
|
|
dbPath = join(tmpDir, 'tasks.db');
|
|
|
|
// Inicializar DB en archivo (como en prod)
|
|
const db = new Database(dbPath);
|
|
initializeDatabase(db);
|
|
ensureUserExists(userId, db);
|
|
|
|
// Crear sesión válida
|
|
const sid = 'sid-test-pref';
|
|
const hash = await sha256Hex(sid);
|
|
const now = new Date();
|
|
const nowIso = toIsoSql(now);
|
|
const expIso = toIsoSql(new Date(now.getTime() + 60 * 60 * 1000)); // +1h
|
|
|
|
db.prepare(`
|
|
INSERT INTO web_sessions (session_hash, user_id, created_at, last_seen_at, expires_at)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
`).run(hash, userId, nowIso, nowIso, expIso);
|
|
db.close();
|
|
|
|
// Arrancar web apuntando a este DB
|
|
server = await startWebServer({
|
|
port: 19100,
|
|
env: { DB_PATH: dbPath, TZ: 'UTC' }
|
|
});
|
|
|
|
// Probar que el endpoint responde (no asertivo aún)
|
|
const res = await fetch(`${server.baseUrl}/api/me/preferences`, {
|
|
headers: { Cookie: `sid=${sid}` }
|
|
});
|
|
expect(res.status).toBe(200);
|
|
});
|
|
|
|
afterAll(async () => {
|
|
try { await server?.stop(); } catch {}
|
|
try { rmSync(tmpDir, { recursive: true, force: true }); } catch {}
|
|
});
|
|
|
|
it('devuelve valores por defecto cuando no hay preferencias guardadas', async () => {
|
|
const sid = 'sid-test-pref';
|
|
const res = await fetch(`${server!.baseUrl}/api/me/preferences`, {
|
|
headers: { Cookie: `sid=${sid}` }
|
|
});
|
|
expect(res.status).toBe(200);
|
|
const json = await res.json();
|
|
expect(json).toEqual({ freq: 'off', time: '08:30' });
|
|
});
|
|
|
|
it('POST /api/me/preferences - flujo completo', async () => {
|
|
const sid = 'sid-test-pref';
|
|
const base = server!.baseUrl;
|
|
|
|
// 1) daily sin hora -> usa default '08:30'
|
|
let res = await fetch(`${base}/api/me/preferences`, {
|
|
method: 'POST',
|
|
headers: { 'content-type': 'application/json', Cookie: `sid=${sid}` },
|
|
body: JSON.stringify({ freq: 'daily' })
|
|
});
|
|
expect(res.status).toBe(200);
|
|
let json = await res.json();
|
|
expect(json).toEqual({ freq: 'daily', time: '08:30' });
|
|
|
|
// GET refleja lo guardado
|
|
res = await fetch(`${base}/api/me/preferences`, { headers: { Cookie: `sid=${sid}` } });
|
|
expect(res.status).toBe(200);
|
|
json = await res.json();
|
|
expect(json).toEqual({ freq: 'daily', time: '08:30' });
|
|
|
|
// 2) weekly con hora '7:5' → normaliza a '07:05'
|
|
res = await fetch(`${base}/api/me/preferences`, {
|
|
method: 'POST',
|
|
headers: { 'content-type': 'application/json', Cookie: `sid=${sid}` },
|
|
body: JSON.stringify({ freq: 'weekly', time: '7:5' })
|
|
});
|
|
expect(res.status).toBe(200);
|
|
json = await res.json();
|
|
expect(json).toEqual({ freq: 'weekly', time: '07:05' });
|
|
|
|
// 3) weekdays con hora inválida → 400
|
|
res = await fetch(`${base}/api/me/preferences`, {
|
|
method: 'POST',
|
|
headers: { 'content-type': 'application/json', Cookie: `sid=${sid}` },
|
|
body: JSON.stringify({ freq: 'weekdays', time: '25:00' })
|
|
});
|
|
expect(res.status).toBe(400);
|
|
|
|
// 4) freq inválida → 400
|
|
res = await fetch(`${base}/api/me/preferences`, {
|
|
method: 'POST',
|
|
headers: { 'content-type': 'application/json', Cookie: `sid=${sid}` },
|
|
body: JSON.stringify({ freq: 'foo', time: '08:00' })
|
|
});
|
|
expect(res.status).toBe(400);
|
|
|
|
// 5) off sin hora → conserva última ('07:05')
|
|
res = await fetch(`${base}/api/me/preferences`, {
|
|
method: 'POST',
|
|
headers: { 'content-type': 'application/json', Cookie: `sid=${sid}` },
|
|
body: JSON.stringify({ freq: 'off' })
|
|
});
|
|
expect(res.status).toBe(200);
|
|
json = await res.json();
|
|
expect(json).toEqual({ freq: 'off', time: '07:05' });
|
|
|
|
// GET refleja off con hora conservada
|
|
res = await fetch(`${base}/api/me/preferences`, { headers: { Cookie: `sid=${sid}` } });
|
|
expect(res.status).toBe(200);
|
|
json = await res.json();
|
|
expect(json).toEqual({ freq: 'off', time: '07:05' });
|
|
|
|
// 6) weekdays con hora válida
|
|
res = await fetch(`${base}/api/me/preferences`, {
|
|
method: 'POST',
|
|
headers: { 'content-type': 'application/json', Cookie: `sid=${sid}` },
|
|
body: JSON.stringify({ freq: 'weekdays', time: '18:45' })
|
|
});
|
|
expect(res.status).toBe(200);
|
|
json = await res.json();
|
|
expect(json).toEqual({ freq: 'weekdays', time: '18:45' });
|
|
|
|
// 7) daily con hora '6:7' -> normaliza '06:07'
|
|
res = await fetch(`${base}/api/me/preferences`, {
|
|
method: 'POST',
|
|
headers: { 'content-type': 'application/json', Cookie: `sid=${sid}` },
|
|
body: JSON.stringify({ freq: 'daily', time: '6:7' })
|
|
});
|
|
expect(res.status).toBe(200);
|
|
json = await res.json();
|
|
expect(json).toEqual({ freq: 'daily', time: '06:07' });
|
|
|
|
// GET final
|
|
res = await fetch(`${base}/api/me/preferences`, { headers: { Cookie: `sid=${sid}` } });
|
|
expect(res.status).toBe(200);
|
|
json = await res.json();
|
|
expect(json).toEqual({ freq: 'daily', time: '06:07' });
|
|
});
|
|
});
|