Some checks failed
Deploy Production / Build, push, deploy, verify (push) Has been cancelled
- 移除已迁移业务 AppData 运行时 fallback,改走领域 API 和关系表快读 - 补齐需求产品负责人、版本计划任务 JSON 和成员 username 回填迁移 - 统一治理字典入口,并补充 AI provider、数据源契约和领域服务测试 Co-Authored-By: Codex GPT-5 <codex@openai.com>
67 lines
3.4 KiB
TypeScript
67 lines
3.4 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import test from 'node:test';
|
|
|
|
function source(path: string) {
|
|
return readFileSync(join(process.cwd(), path), 'utf8');
|
|
}
|
|
|
|
const migratedBusinessStores = [
|
|
['stores/useProductStore.ts', 'products-overview'],
|
|
['stores/useRequirementStore.ts', 'requirements'],
|
|
['stores/useVersionPlanStore.ts', 'version-plans'],
|
|
['stores/useDevTaskStore.ts', 'dev-tasks'],
|
|
['stores/useTestCaseStore.ts', 'test-cases'],
|
|
['stores/useBugStore.ts', 'bugs'],
|
|
['stores/useTaskCategoryStore.ts', 'task-categories'],
|
|
['stores/useTaskWorklogStore.ts', 'task-worklogs'],
|
|
['stores/useWorkActivityStore.ts', 'work-activities'],
|
|
] as const;
|
|
|
|
test('migrated business stores do not read or write AppData documents at runtime', () => {
|
|
for (const [file, key] of migratedBusinessStores) {
|
|
const text = source(file);
|
|
|
|
assert.doesNotMatch(text, new RegExp(`loadServerData<[^>]*>\\('${key}'`), `${file} must not read ${key}`);
|
|
assert.doesNotMatch(text, new RegExp(`loadServerData\\([^)]*'${key}'`), `${file} must not read ${key}`);
|
|
assert.doesNotMatch(text, new RegExp(`saveServerData\\('${key}'`), `${file} must not write ${key}`);
|
|
assert.doesNotMatch(text, /\.catch\(loadStored\)/, `${file} must not fall back to legacy AppData reads`);
|
|
}
|
|
});
|
|
|
|
test('only explicit legacy config stores keep AppData access', () => {
|
|
assert.match(source('stores/useMemberStore.ts'), /saveServerData\('members'/);
|
|
assert.match(source('stores/useMemberStore.ts'), /loadServerData<[^>]+>\('members'/);
|
|
assert.match(source('stores/useOvertimeStore.ts'), /loadServerData<[^>]+>\('overtime'/);
|
|
});
|
|
|
|
test('read-only Xiaobao AppData archive keys are not used by runtime stores', () => {
|
|
for (const file of ['stores/useXiaobaoRiskStore.ts', 'stores/useXiaobaoWarningReadStore.ts']) {
|
|
const text = source(file);
|
|
|
|
assert.doesNotMatch(text, /loadServerData<[^>]+>\('xiaobao-risk-snapshots'/, `${file} must not read Xiaobao snapshots AppData`);
|
|
assert.doesNotMatch(text, /loadServerData<[^>]+>\('xiaobao-risk-insights'/, `${file} must not read Xiaobao insights AppData`);
|
|
assert.doesNotMatch(text, /loadServerData<[^>]+>\('xiaobao-warning-views'/, `${file} must not read Xiaobao warning read-state AppData`);
|
|
assert.doesNotMatch(text, /saveServerData\('xiaobao-risk-snapshots'/, `${file} must not write Xiaobao snapshots AppData`);
|
|
assert.doesNotMatch(text, /saveServerData\('xiaobao-risk-insights'/, `${file} must not write Xiaobao insights AppData`);
|
|
assert.doesNotMatch(text, /saveServerData\('xiaobao-warning-views'/, `${file} must not write Xiaobao warning read-state AppData`);
|
|
}
|
|
});
|
|
|
|
test('auth reads member identities from the member domain API instead of members AppData', () => {
|
|
const text = source('stores/useAuthStore.ts');
|
|
|
|
assert.match(text, /listMembersDomain/);
|
|
assert.doesNotMatch(text, /loadServerData<[^>]+>\('members'/);
|
|
assert.doesNotMatch(text, /from '@\/lib\/server-data'/);
|
|
});
|
|
|
|
test('member store keeps members AppData as config only, not member identity fallback', () => {
|
|
const text = source('stores/useMemberStore.ts');
|
|
|
|
assert.doesNotMatch(text, /cached\.members/);
|
|
assert.doesNotMatch(text, /members: get\(\)\.members,/);
|
|
assert.match(text, /saveServerData\('members', \{ departments: state\.departments, members: \[\], roles: state\.roles, passwordRule: state\.passwordRule \}\)/);
|
|
});
|