import test from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import vm from 'node:vm'; const source = readFileSync(new URL('../egbim/app.js', import.meta.url), 'utf8'); const context = vm.createContext({ window: { QA_CONFIG: {}, location: { origin: 'https://qa.example.test' } }, document: { cookie: '', addEventListener() {} }, sessionStorage: { getItem() { return null; } }, localStorage: { getItem() { return null; } }, URL }); vm.runInContext(source.replace(/\}\)\(\);\s*$/, 'globalThis.testPage = { normalizeRemotePost, getPostCompanyLabel, normalizeAuthUser, isPostOwner }; })();'), context); const page = context.testPage; test('saved organization has priority over email-domain inference in list and detail', () => { const post = page.normalizeRemotePost({ id: 'fixture', requester_email: 'fixture@brsw.kr', requester_affiliation: '저장된 회사', requester_department: '저장된 부서' }); assert.equal(post.company, '저장된 회사'); assert.equal(post.department, '저장된 부서'); assert.equal(page.getPostCompanyLabel(post, { company: '현재 조회자 회사' }), '저장된 회사'); }); test('a matching tenant does not copy the current viewer company to an unrelated author', () => { const label = page.getPostCompanyLabel({ requesterTenantId: 'shared', raw: {} }, { tenantId: 'shared', company: '다른 작성자 회사' }); assert.notEqual(label, '다른 작성자 회사'); }); test('server organization has priority over stale browser custom attributes', () => { const user = page.normalizeAuthUser({ company: '서버 회사', department: '서버 부서', email: 'fixture@brsw.kr', customAttributes: { company: 'old', department: 'old' } }, {}); assert.equal(user.company, '서버 회사'); assert.equal(user.department, '서버 부서'); }); test('organization changes affect new author information without changing an existing post snapshot', () => { const post = page.normalizeRemotePost({ id: 'fixture', requester_affiliation: '작성 당시 회사', requester_department: '작성 당시 부서' }); const currentUser = page.normalizeAuthUser({ company: '전보 후 회사', department: '전보 후 부서' }, {}); assert.equal(currentUser.company, '전보 후 회사'); assert.equal(page.getPostCompanyLabel(post, currentUser), '작성 당시 회사'); assert.equal(post.department, '작성 당시 부서'); }); test('own-post filtering follows canonical identity even after company and department change', () => { const user = { requesterId: 'fixture-owner', company: '전보 후 회사', department: '전보 후 부서', name: '동명이인' }; assert.equal(page.isPostOwner({ requesterId: 'fixture-owner', company: '이전 회사' }, user), true); assert.equal(page.isPostOwner({ requesterId: 'another-owner', author: '동명이인', company: user.company }, user), false); }); test('a matching display name, login or email never grants post ownership without an author ID', () => { const user = { requesterId: 'fixture-owner', name: '동명이인', loginId: 'same@example.test', email: 'same@example.test' }; for (const author of [user.name, user.loginId, user.email]) { assert.equal(page.isPostOwner({ author }, user), false); } assert.equal(page.isPostOwner({ requesterId: 'fixture-owner' }, null), false); }); test('the signed primary identity takes precedence over stale alternate browser IDs', () => { const user = { requesterId: 'current-owner', ssoSubject: 'old-owner', userUuid: 'old-owner' }; assert.equal(page.isPostOwner({ requesterId: 'old-owner' }, user), false); assert.equal(page.isPostOwner({ requesterId: 'current-owner' }, user), true); }); test('server requester and user UUID fields remain the author identity when normalizing a session', () => { const user = page.normalizeAuthUser({ requesterId: 'current-owner', userUuid: 'current-owner', email: 'fixture@example.test' }, {}); assert.equal(user.requesterId, 'current-owner'); assert.equal(user.ssoSubject, 'current-owner'); assert.equal(user.userUuid, 'current-owner'); });