Files
AriWeb-Suite/modules/arimail/test/_helpers.mjs
T

46 lines
4.3 KiB
JavaScript
Raw Normal View History

import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import { openDb, d1, migrate } from '../server/db.mjs';
import { hashPassword } from '../server/auth.mjs';
import { memoryRateStore } from '../server/util.mjs';
const HERE = dirname(fileURLToPath(import.meta.url));
export async function makeWwwDb({ login = 'arihakdang', password = 'admin-secret-12', email = 'admin@arihakdang.com', role = 'admin', status = 'active' } = {}) {
const db = openDb(':memory:');
db.exec('CREATE TABLE users(id TEXT PRIMARY KEY,email TEXT UNIQUE,login_id TEXT,name TEXT,role TEXT,status TEXT,password_hash TEXT)');
db.prepare('INSERT INTO users VALUES(?,?,?,?,?,?,?)').run('admin-1', email, login, '관리자', role, status, await hashPassword(password, 1000));
db.prepare('INSERT INTO users VALUES(?,?,?,?,?,?,?)').run('student-1', 'student@example.test', 'student', '학생', 'student', 'active', await hashPassword(password, 1000));
return db;
}
export async function makeEnv(over = {}) {
const db = openDb(':memory:'); migrate(db, join(HERE, '..', 'migrations'), { quiet: true });
return { DB: d1(db), RATE: memoryRateStore(), WWW_DB: await makeWwwDb(), MAILBOX: 'admin@arihakdang.com', RESEND_API_KEY: 'test', POP_AUTH_DELAY_MS: 0, ...over };
}
export function runner() {
let pass = 0, fail = 0;
const t = async (name, fn) => { try { await fn(); console.log(' ok ' + name); pass++; } catch (e) { console.log(' FAIL ' + name + ' — ' + (e.stack || e.message)); fail++; } };
const done = () => { console.log(`\n${pass} passed, ${fail} failed`); process.exit(fail ? 1 : 0); };
return { t, done };
}
export const eq = (a, b, m) => { if (a !== b) throw new Error(`${m}: ${JSON.stringify(a)} !== ${JSON.stringify(b)}`); };
export const ok = (v, m) => { if (!v) throw new Error(m); };
/** Resend 흉내: 수신 목록/상세/첨부/원본 다운로드/발송. */
export function fakeResend({ received = [], sent = [], raw = {}, attachments = {}, calls = [], failStatus = 0 } = {}) {
return async (url, options = {}) => {
const u = new URL(url), path = u.pathname; const method = options.method || 'GET';
calls.push({ path, method, body: options.body ? JSON.parse(options.body) : undefined, key: options.headers?.['Idempotency-Key'] });
if (failStatus) return Response.json({ message: 'API key is invalid' }, { status: failStatus });
if (path === '/domains') return Response.json({ data: [{ name: 'arihakdang.com', status: 'verified' }] });
if (path === '/emails' && method === 'POST') { const id = 'sent-' + calls.length; sent.push({ id, ...JSON.parse(options.body), created_at: new Date().toISOString() }); return Response.json({ id }); }
if (path === '/emails/receiving') return Response.json({ data: received.map(({ html, text, headers, ...s }) => s), has_more: false });
if (path === '/emails') return Response.json({ data: sent, has_more: false });
let m;
if ((m = path.match(/^\/emails\/receiving\/([^/]+)\/attachments$/))) return Response.json({ data: (attachments[m[1]] || []), has_more: false });
if ((m = path.match(/^\/emails\/receiving\/([^/]+)$/))) { const item = received.find((r) => r.id === m[1]); return item ? Response.json({ ...item, raw: raw[item.id] ? { download_url: 'https://files.test/raw/' + item.id, expires_at: '2099-01-01' } : null }) : Response.json({ message: 'not found' }, { status: 404 }); }
if ((m = path.match(/^\/emails\/([^/]+)$/))) { const item = sent.find((r) => r.id === m[1]); return item ? Response.json(item) : Response.json({}, { status: 404 }); }
if (u.hostname === 'files.test') { const id = path.split('/').pop(); if (path.startsWith('/raw/')) return new Response(raw[id]); const a = Object.values(attachments).flat().find((x) => x.id === id); return new Response(a?.bytes || 'file-bytes'); }
return Response.json({ data: [], has_more: false });
};
}
export const request = (path, cookie, method = 'GET', body, extraHeaders = {}) => new Request('https://mail.arihakdang.com/api/' + path, { method, headers: { ...(cookie ? { Cookie: cookie } : {}), ...(body instanceof FormData ? {} : { 'Content-Type': 'application/json' }), ...extraHeaders }, body: body instanceof FormData ? body : body === undefined ? undefined : typeof body === 'string' ? body : JSON.stringify(body) });
export const params = (path, ip = '127.0.0.1') => ({ path: path.split('?')[0].split('/').filter(Boolean), ip });