import test from "node:test"; import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; async function readSource(path: string) { return readFile(new URL(path, import.meta.url), "utf8"); } test("independent Boss admin web app declares Vue Ant Design Vue runtime", async () => { const source = await readSource("../apps/boss-admin-web/package.json"); const pkg = JSON.parse(source); assert.equal(pkg.name, "@boss/admin-web"); assert.equal(pkg.private, true); assert.match(pkg.scripts.dev, /vite/); assert.match(pkg.scripts.build, /vite build/); assert.ok(pkg.dependencies.vue); assert.ok(pkg.dependencies["ant-design-vue"]); assert.ok(pkg.devDependencies.vite); assert.ok(pkg.devDependencies["@vitejs/plugin-vue"]); }); test("independent Boss admin web app uses the backoffice BFF with cookie session", async () => { const apiSource = await readSource("../apps/boss-admin-web/src/api/bossAdmin.ts"); assert.match(apiSource, /\/api\/v1\/admin\/backoffice/); assert.match(apiSource, /\/api\/v1\/admin\/access/); assert.match(apiSource, /\/api\/v1\/admin\/risks\/actions/); assert.match(apiSource, /\/api\/v1\/admin\/skills\/requests/); assert.match(apiSource, /\/api\/v1\/admin\/backups/); assert.match(apiSource, /\/api\/v1\/devices\/\$\{encodeURIComponent\(deviceId\)\}\/codex-remote-control/); assert.match(apiSource, /credentials:\s*["']include["']/); assert.match(apiSource, /menuTree/); assert.match(apiSource, /tenants/); assert.match(apiSource, /resourceGroups/); for (const fn of ["postAdminAccess", "postRiskAction", "postSkillLifecycleRequest", "postDeviceCodexRemoteControl", "fetchAdminBackups", "createAdminBackup", "restoreAdminBackup"]) { assert.match(apiSource, new RegExp(`function\\s+${fn}|const\\s+${fn}`)); } for (const action of ["create_snapshot", "restore_snapshot"]) { assert.match(apiSource, new RegExp(action)); } }); test("independent Boss admin web app includes enterprise management sections", async () => { const appSource = await readSource("../apps/boss-admin-web/src/App.vue"); for (const label of [ "Boss 平台总后台", "企业管理后台", "平台总览", "企业开通", "客户与套餐", "全局设备", "客户成功", "全局风险", "服务连接状态", "最近开通企业", "开通预览", "交付检查", "客户健康列表", "风险聚合", "客户成功跟进记录", "企业总览", "组织与成员", "设备与项目", "Agent 与流程", "Skill 中心", "风险与审计", "备份与回退", "经营目标", "部门进展", "主 Agent 摘要", "组织结构", "权限详情", "使用审计", "业务级回退", ]) { assert.match(appSource, new RegExp(label)); } assert.match(appSource, /adminSurface/); assert.match(appSource, /setSurface/); assert.match(appSource, /menuTree/); assert.match(appSource, /platform-overview/); assert.match(appSource, /enterprise-overview/); assert.match(appSource, /tenants/); }); test("independent Boss admin web app exposes management actions instead of read only tables", async () => { const appSource = await readSource("../apps/boss-admin-web/src/App.vue"); for (const label of [ "新建租户", "启用租户", "停用租户", "新建账号", "重置密码", "离职回收", "分配资源", "套用权限模板", "撤销授权", "指派负责人", "设置 SLA", "确认风险", "关闭风险", "创建工单", "创建 Skill 请求", "启动远控", "停止远控", "创建状态快照", "恢复到此快照", "快照清单", ]) { assert.match(appSource, new RegExp(label)); } for (const action of [ "upsert_company", "set_company_status", "upsert_account", "reset_account_password", "reclaim_account", "apply_template", "grant_device", "grant_project", "grant_skill", "revoke_grant", ]) { assert.match(appSource, new RegExp(action)); } assert.match(appSource, /backupSnapshots/); assert.match(appSource, /loadBackupSnapshots/); assert.match(appSource, /createAdminBackup/); assert.match(appSource, /restoreAdminBackup/); assert.match(appSource, /handleCodexRemoteControl/); }); test("independent Boss admin web app exposes skill management dispatch workspace", async () => { const [appSource, apiSource] = await Promise.all([ readSource("../apps/boss-admin-web/src/App.vue"), readSource("../apps/boss-admin-web/src/api/bossAdmin.ts"), ]); assert.match(apiSource, /fetchSkillLifecycleRequests/); assert.match(apiSource, /\/api\/v1\/admin\/skills\/requests/); assert.match(apiSource, /method:\s*["']GET["']/); for (const label of [ "Skill 管理分发", "快捷下发", "Skill 请求队列", "待执行", "执行中", "最近请求", "安装远端 Skill", "更新下发", "回滚", "版本锁定", ]) { assert.match(appSource, new RegExp(label)); } assert.match(appSource, /skillLifecycleRequests/); assert.match(appSource, /loadSkillLifecycleRequests/); assert.match(appSource, /quickSkillRequest/); }); test("independent Boss admin web app keeps backup tables inside their cards", async () => { const [appSource, cssSource] = await Promise.all([ readSource("../apps/boss-admin-web/src/App.vue"), readSource("../apps/boss-admin-web/src/styles.css"), ]); assert.match(appSource, /boss-admin-wide-card/); assert.match(cssSource, /\.ant-card\s*\{/); assert.match(cssSource, /\.boss-admin-wide-card/); assert.match(cssSource, /grid-column:\s*1\s*\/\s*-1/); assert.match(cssSource, /min-width:\s*0/); assert.match(cssSource, /\.ant-table-wrapper\s*\{/); assert.match(cssSource, /overflow-x:\s*auto/); assert.match(cssSource, /word-break:\s*break-word/); assert.match(cssSource, /white-space:\s*normal/); }); test("root Next project isolates the independent Vue admin workspace", async () => { const [tsconfigSource, eslintSource, rootPkgSource] = await Promise.all([ readSource("../tsconfig.json"), readSource("../eslint.config.mjs"), readSource("../package.json"), ]); const tsconfig = JSON.parse(tsconfigSource); const rootPkg = JSON.parse(rootPkgSource); assert.ok(tsconfig.exclude.includes("apps/boss-admin-web/**")); assert.match(eslintSource, /apps\/boss-admin-web\/\*\*/); assert.match(eslintSource, /public\/admin-web\/\*\*/); assert.match(rootPkg.scripts["admin:web:dev"], /apps\/boss-admin-web/); assert.match(rootPkg.scripts["admin:web:build"], /apps\/boss-admin-web/); });