포털 중심 데이터 모델(core)과 영역 테스트 도우미
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
c7aea8d419
commit
8607f19e62
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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 } });
|
||||
Reference in New Issue
Block a user