Files
AriWeb-Suite/test/helpers.mjs

35 lines
3.3 KiB
JavaScript

/**
* test/helpers.mjs — 포털 영역 테스트 공통 도우미.
* makeDeps() 메모리 DB(모든 마이그레이션)·임시 보관소·작업 엔진·설정·가짜 어댑터를 묶은 deps
* seedGroup(deps, {...}) 사용자·그룹·구성원 한 벌 만들기 → { user, group }
* appFor(deps, areas, who) 지정 영역만 등록한 앱. who 를 주면 인증 미들웨어 없이 ctx.user/group/membership 을 주입(각 영역을 auth 없이 시험)
* call(app, method, path, body, who) invoke 래퍼(JSON 응답)
*/
import { openDb } from '../lib/db.mjs';
import { openVault } from '../lib/vault.mjs';
import { createJobEngine } from '../lib/jobs.mjs';
import { allMigrations } from '../portal/schema.mjs';
import { buildApp } from '../portal/app.mjs';
import { invoke } from '../lib/http.mjs';
import { newId, hashPassword } from '../lib/crypto.mjs';
import { tmpDir } from '../lib/test.mjs';
export async function makeDeps(extra = {}) {
const store = openDb(':memory:', await allMigrations()); const dir = tmpDir();
const vault = openVault(dir); const jobs = createJobEngine(store, { log: () => {}, workerId: 'test' });
const config = { dataDir: dir, publicUrl: 'https://my.example.test', halUrl: 'https://hal.example.test', webmakerUrl: 'https://webmaker.example.test', webmakerInternalUrl: 'http://127.0.0.1:1', arimailUrl: 'https://webmail.example.test', arimailInternalUrl: 'http://127.0.0.1:1', mailFrom: 'no-reply@example.test', values: {}, set(p) { Object.assign(this, p); } };
return { store, vault, jobs, config, log: () => {}, version: '0.1.1-test', ...extra };
}
export function seedGroup(deps, { email = 'owner@example.test', name = '테스트 그룹', kind = 'personal', role = 'owner', verified = true } = {}) {
const now = new Date().toISOString(); const uid = newId('u_'); const gid = newId('g_'); const { salt, hash } = hashPassword('pw-example-1');
deps.store.run('INSERT INTO users(id, email, email_verified_at, display_name, pass_hash, pass_salt, created_at, updated_at) VALUES(?,?,?,?,?,?,?,?)', uid, email, verified ? now : null, '테스트 사용자', hash, salt, now, now);
deps.store.run('INSERT INTO groups(id, name, kind, owner_user_id, created_at, updated_at) VALUES(?,?,?,?,?,?)', gid, name, kind, uid, now, now);
deps.store.run('INSERT INTO memberships(group_id, user_id, role, alias, joined_at) VALUES(?,?,?,?,?)', gid, uid, role, 'user-01', now);
return { user: deps.store.get('SELECT * FROM users WHERE id=?', uid), group: deps.store.get('SELECT * FROM groups WHERE id=?', gid), membership: deps.store.get('SELECT * FROM memberships WHERE group_id=? AND user_id=?', gid, uid) };
}
export async function appFor(deps, areas, who = null) {
const before = who ? (ctx) => { const w = typeof who === 'function' ? who(ctx) : who; if (!w) return; ctx.user = w.user; ctx.group = w.group; ctx.membership = w.membership; ctx.session = { id: 'test', csrf: 'test-csrf', data: { groupId: w.group?.id } }; ctx.sitePerms = (siteId, userId) => { const r = deps.store.get('SELECT perms_json FROM site_permissions WHERE site_id=? AND user_id=?', siteId, userId); return r ? JSON.parse(r.perms_json) : []; }; } : null;
return buildApp(deps, { areas: ['core', ...areas], before });
}
export const call = (app, method, path, body, headers = {}) => invoke(app, method, path, { body, headers: { 'x-csrf': 'test-csrf', ...headers } });