import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
const appSource = readFileSync(new URL("../src/App.vue", import.meta.url), "utf8");
const routerSource = readFileSync(new URL("../src/router/index.js", import.meta.url), "utf8");
const systemPermissionSource = readFileSync(new URL("../src/views/SystemPermissionView.vue", import.meta.url), "utf8");
const orgMindMapSource = readFileSync(new URL("../src/components/OrgMindMap.vue", import.meta.url), "utf8");
const orgPermissionTreeSource = readFileSync(new URL("../src/components/OrgPermissionTree.vue", import.meta.url), "utf8");
assert.match(appSource, /系统管理/, "App.vue should show the system-management parent menu");
assert.match(appSource, /系统权限管理/, "App.vue should show the system permission child menu");
assert.match(appSource, /系统拓展/, "App.vue should keep the system extension child menu");
assert.match(
appSource,
/permissionsAny:\s*\[[\s\S]*"MENU_SYSTEM_PERMISSION"[\s\S]*"MENU_SYSTEM_EXTENSION"[\s\S]*\]/,
"App.vue system menu should allow either system permission"
);
assert.match(
routerSource,
/import SystemPermissionView from "\.\.\/views\/SystemPermissionView\.vue";/,
"router should import SystemPermissionView"
);
assert.match(routerSource, /path:\s*"\/system-management"[\s\S]*redirect:/, "router should add /system-management redirect");
assert.match(routerSource, /path:\s*"\/system-permissions"/, "router should add /system-permissions route");
assert.match(
routerSource,
/name:\s*"system-permissions"[\s\S]*permission:\s*"MENU_SYSTEM_PERMISSION"/,
"system-permissions route should require MENU_SYSTEM_PERMISSION"
);
assert.match(systemPermissionSource, /系统权限管理/, "SystemPermissionView should show page title");
assert.match(systemPermissionSource, /组织架构/, "SystemPermissionView should expose organization structure tab");
assert.match(systemPermissionSource, /角色维护/, "SystemPermissionView should expose role-only maintenance tab");
assert.doesNotMatch(systemPermissionSource, /人员与角色维护/, "personnel and role maintenance should be renamed");
assert.doesNotMatch(systemPermissionSource, /maintenanceSubTab/, "role maintenance should not keep nested personnel tabs");
assert.doesNotMatch(systemPermissionSource, /system-permission-sub-tabs/, "role maintenance should not render nested sub tabs");
assert.doesNotMatch(
systemPermissionSource,
/v-if="maintenanceSubTab === 'users'"/,
"standalone system users table should be removed from maintenance page"
);
assert.doesNotMatch(
systemPermissionSource,
/v-if="maintenanceSubTab === 'roles'"/,
"roles should render directly in the role maintenance tab"
);
assert.match(
systemPermissionSource,
/import PaginationBar from "\.\.\/components\/PaginationBar\.vue";/,
"page should use global PaginationBar"
);
assert.match(
systemPermissionSource,
/import \{ usePagination \} from "\.\.\/utils\/pagination";/,
"page should use global pagination helper"
);
assert.match(systemPermissionSource, /paginatedRoles/, "roles table should use paginated rows");
assert.match(systemPermissionSource, /
/, "role maintenance should use global table styling");
assert.doesNotMatch(
systemPermissionSource,
/class="maintenance-grid"/,
"maintenance page should not use the old side-by-side card grid"
);
assert.doesNotMatch(
systemPermissionSource,
/[\s\S]*v-for="role in roles"/,
"roles should not render as old card list"
);
assert.doesNotMatch(
systemPermissionSource,
/[\s\S]*v-for="user in users"/,
"users should not render as old card list"
);
assert.match(systemPermissionSource, /permissionMainTab/, "SystemPermissionView should keep top-level tabs separate");
assert.match(
systemPermissionSource,
/v-if="permissionMainTab === 'org'"/,
"organization mind map should live in its own top-level tab"
);
assert.match(
systemPermissionSource,
/v-if="permissionMainTab === 'maintenance'"/,
"role maintenance should live in a separate top-level tab"
);
assert.match(systemPermissionSource, /orgViewMode/, "organization tab should keep organization view mode state");
assert.match(systemPermissionSource, /脑图模式/, "organization tab should expose mind-map mode switch");
assert.match(systemPermissionSource, /组织树模式/, "organization tab should expose organization-tree mode switch");
assert.match(
systemPermissionSource,
//,
"manager selector should not rely on native multi-select keyboard behavior"
);
assert.match(systemPermissionSource, /多位主管/, "manager drawer should explain multiple manager binding");
assert.match(systemPermissionSource, /contextMenu/, "page must expose a right-click context menu for mind-map nodes");
assert.match(systemPermissionSource, /@node-contextmenu/, "page must listen for node context menu events");
assert.match(systemPermissionSource, /重命名/, "context menu should support renaming organization nodes");
assert.match(systemPermissionSource, /新增分公司节点/, "company context menu should support adding branch nodes");
assert.match(systemPermissionSource, /新增部门节点/, "branch context menu should support adding department nodes");
assert.match(systemPermissionSource, /新增小组节点/, "department context menu should support adding group nodes");
assert.match(systemPermissionSource, /新增人员/, "department and group context menu should support adding employee leaves");
assert.match(systemPermissionSource, /添加该节点的主管/, "context menu should support manager binding");
assert.match(systemPermissionSource, /deleteResource/, "page must call backend delete endpoints for org actions");
assert.match(systemPermissionSource, /\/employees/, "page must call backend employee binding endpoints");
assert.match(systemPermissionSource, /员工节点默认收拢/, "page should document collapsed employee leaves");
assert.doesNotMatch(systemPermissionSource, /class="org-node-detail"/, "mind-map node operations must not stay in a persistent bottom bar");
assert.match(systemPermissionSource, /mindmap-toolbar/, "mind-map should expose a top-right toolbar");
assert.match(systemPermissionSource, /放大/, "mind-map toolbar should support zooming in");
assert.match(systemPermissionSource, /缩小/, "mind-map toolbar should support zooming out");
assert.match(systemPermissionSource, /刷新/, "mind-map toolbar should support refreshing data");
assert.match(systemPermissionSource, /一屏展示/, "mind-map toolbar should expose a separate one-screen fit button");
assert.match(systemPermissionSource, /mindMapScale/, "page should keep mind-map zoom state");
assert.match(systemPermissionSource, /refreshMindMap/, "page should refresh mind-map data from toolbar");
assert.match(systemPermissionSource, /fitMindMapToScreen/, "page should separate one-screen fitting from refreshing");
assert.match(systemPermissionSource, /mindMapFitRequestKey/, "page should request one-screen mind-map fitting");
assert.match(
systemPermissionSource,
/:fit-request-key="mindMapFitRequestKey"/,
"SystemPermissionView should pass fit request key to OrgMindMap"
);
assert.doesNotMatch(
systemPermissionSource,
/@zoom-scale=/,
"SystemPermissionView should not accept mouse-wheel zoom from OrgMindMap"
);
assert.match(
systemPermissionSource,
/@fit-scale="applyMindMapFitScale"/,
"SystemPermissionView should accept fit scale from OrgMindMap"
);
assert.match(
systemPermissionSource,
/function applyMindMapFitScale/,
"SystemPermissionView should apply one-screen fit scale"
);
assert.doesNotMatch(
systemPermissionSource,
/:key="mindMapRenderKey"/,
"mind-map refresh must not recreate OrgMindMap because that collapses expanded employees"
);
const refreshMindMapMatch = systemPermissionSource.match(/async function refreshMindMap\(\)\s*\{([\s\S]*?)\n\}/);
assert.ok(refreshMindMapMatch, "refreshMindMap function block must be parseable");
assert.doesNotMatch(
refreshMindMapMatch[1],
/mindMapFitRequestKey\.value \+= 1/,
"refresh must not request one-screen fit; one-screen fit is a separate user action"
);
assert.doesNotMatch(
refreshMindMapMatch[1],
/mindMapRenderKey\.value \+= 1/,
"refresh must not recreate mind-map component"
);
assert.match(
systemPermissionSource,
/function fitMindMapToScreen\(\)[\s\S]*mindMapFitRequestKey\.value \+= 1/,
"one-screen fit action should request a viewport fit explicitly"
);
assert.match(systemPermissionSource, /const updatePayload\s*=/, "org edit must build an update-only payload");
assert.match(systemPermissionSource, /const createPayload\s*=/, "org create must build a create payload");
const updatePayloadMatch = systemPermissionSource.match(/const updatePayload\s*=\s*\{([\s\S]*?)\n\s*\};/);
assert.ok(updatePayloadMatch, "org edit updatePayload block must be parseable");
assert.doesNotMatch(
updatePayloadMatch[1],
/parent_id|node_type|dept_code/,
"org edit updatePayload must exclude create-only fields"
);
assert.match(
systemPermissionSource,
/putResource\(`\/system-permissions\/org-nodes\/\$\{editingOrgNode\.value\.node_id\}`,\s*updatePayload\)/,
"org edit PUT must only send the update payload"
);
assert.match(
systemPermissionSource,
/postResource\("\/system-permissions\/org-nodes",\s*createPayload\)/,
"org create POST must send the create payload"
);
assert.match(
systemPermissionSource,
/@change="togglePermissionNode\(group, \$event\.target\.checked\)"/,
"parent permission checkbox must toggle descendants"
);
const persistablePermissionCodesMatch = systemPermissionSource.match(/function collectPersistablePermissionCodes\(node\)\s*\{([\s\S]*?)\n\}/);
assert.ok(persistablePermissionCodesMatch, "collectPersistablePermissionCodes function block must be parseable");
assert.match(
persistablePermissionCodesMatch[1],
/if \(children\.length\)[\s\S]*return children\.flatMap\(\(child\) => collectPersistablePermissionCodes\(child\)\)/,
"group-only parent permission codes must be skipped in favor of child menu permissions"
);
assert.match(
systemPermissionSource,
/for \(const code of collectPersistablePermissionCodes\(node\)\)/,
"permission toggling must persist only real menu permission codes"
);
assert.match(
systemPermissionSource,
/if \(!authorizingEmployee\.value\?\.employee_id\)[\s\S]*notifyError\("请选择有效人员"\)/,
"authorization submit must reject missing employee context"
);
assert.match(
systemPermissionSource,
/if \(!authorizingEmployeePhone\.value\)[\s\S]*notifyError\("该人员没有电话号码,不能作为账号"\)/,
"authorization submit must reject employees without a phone account"
);
assert.doesNotMatch(
systemPermissionSource,
/window\.alert\("新增系统使用人员抽屉将在实现任务中接入/,
"temporary user alert must be removed"
);
assert.doesNotMatch(
systemPermissionSource,
/window\.alert\("新增角色抽屉将在实现任务中接入/,
"temporary role alert must be removed"
);
assert.match(orgMindMapSource, /defineProps/, "OrgMindMap should use defineProps");
assert.match(orgMindMapSource, /orthogonal/i, "OrgMindMap should name orthogonal connector logic");
assert.match(orgMindMapSource, /collapsedEmployeeNodeIds/, "OrgMindMap should default employee leaves to collapsed");
assert.match(orgMindMapSource, /toggle-employee-leaves/, "OrgMindMap should emit employee leaf expand or collapse events");
assert.match(orgMindMapSource, /employee_count/, "OrgMindMap should display employee count on parent org cards");
assert.match(orgMindMapSource, /node-contextmenu/, "OrgMindMap should emit right-click context menu events");
assert.match(orgMindMapSource, /manager_names/, "OrgMindMap should display multiple manager names");
assert.match(orgMindMapSource, /zoomScale/, "OrgMindMap should accept a zoom scale prop");
assert.match(orgMindMapSource, /fitRequestKey/, "OrgMindMap should accept fit request key");
assert.match(orgMindMapSource, /fit-scale/, "OrgMindMap should emit fit scale");
assert.match(orgMindMapSource, /mindMapViewport/, "OrgMindMap should keep a viewport ref for canvas panning");
assert.match(orgMindMapSource, /isCanvasPanning/, "OrgMindMap should track canvas panning state");
assert.match(orgMindMapSource, /startCanvasPan/, "OrgMindMap should start canvas panning from empty canvas space");
assert.match(orgMindMapSource, /moveCanvasPan/, "OrgMindMap should move the viewport while panning");
assert.match(orgMindMapSource, /endCanvasPan/, "OrgMindMap should stop canvas panning");
assert.doesNotMatch(orgMindMapSource, /@wheel/, "OrgMindMap should not bind mouse-wheel zooming");
assert.doesNotMatch(orgMindMapSource, /function handleCanvasWheel/, "OrgMindMap should remove mouse-wheel zoom handling");
assert.doesNotMatch(orgMindMapSource, /WHEEL_ZOOM_STEP/, "OrgMindMap should not keep mouse-wheel zoom step configuration");
assert.doesNotMatch(orgMindMapSource, /emit\("zoom-scale"/, "OrgMindMap should not emit wheel zoom scale to parent");
assert.match(orgMindMapSource, /fitCanvasToViewport/, "OrgMindMap should fit canvas to visible viewport");
assert.match(
orgMindMapSource,
/window\.addEventListener\("mousemove", moveCanvasPan\)/,
"OrgMindMap should pan canvas through window mousemove listener"
);
assert.match(
orgMindMapSource,
/viewport\.scrollTop = canvasPan\.value\.scrollTop - deltaY/,
"OrgMindMap should support vertical canvas panning in addition to horizontal panning"
);
assert.match(
orgMindMapSource,
/window\.removeEventListener\("mousemove", moveCanvasPan\)/,
"OrgMindMap should clean up canvas pan listener"
);
assert.match(
orgMindMapSource,
/closest\?\.\("\.org-mind-map-node"\)/,
"canvas panning should not start from node cards"
);
assert.match(
orgMindMapSource,
/defineExpose/,
"OrgMindMap should expose fit helper for explicit refresh handling if needed"
);
assert.match(orgMindMapSource, /scaledCanvasStyle/, "OrgMindMap should size the canvas according to zoom scale");
assert.match(orgMindMapSource, /overscroll-behavior: contain;/, "OrgMindMap should keep drag interaction inside the canvas viewport");
assert.match(orgMindMapSource, /NODE_MIN_WIDTH/, "OrgMindMap should have a minimum node width");
assert.match(orgMindMapSource, /NODE_MAX_WIDTH/, "OrgMindMap should have a maximum node width");
assert.match(orgMindMapSource, /function estimateTextWidth/, "OrgMindMap should estimate text width before laying out cards");
assert.match(orgMindMapSource, /function computeNodeWidth/, "OrgMindMap should compute node width from text length");
assert.match(orgMindMapSource, /function fitTextToWidth/, "OrgMindMap should safely fit very long text into cards");
assert.match(orgMindMapSource, /:width="node\.width"/, "OrgMindMap node card width should use computed per-node width");
assert.match(
orgMindMapSource,
/parent\.x \+ parent\.width/,
"connector layout should use each node's computed width"
);
assert.match(orgMindMapSource, /function measureSubtree/, "mind map must measure subtree leaf spans before layout");
assert.match(orgMindMapSource, /function layoutTree/, "mind map must use deterministic tree layout");
assert.match(orgMindMapSource, /connectorSegments/, "mind map must deduplicate connector segments");
assert.match(orgMindMapSource, /COLUMN_GAP/, "mind map must reserve a column gutter for connector lines");
assert.match(orgMindMapSource, /NODE_MAX_WIDTH/, "mind map must know maximum node width for line avoidance");
assert.match(
orgMindMapSource,
/H \$\{connector\.midX\} V \$\{connector\.toY\} H \$\{connector\.toX\}/,
"OrgMindMap should render H/V/H orthogonal connector paths"
);
assert.doesNotMatch(orgMindMapSource, /draggable="true"/, "OrgMindMap should not mark cards draggable");
assert.doesNotMatch(
orgMindMapSource,
/@(drag|dragstart|dragend|pointermove|mousemove)\b/,
"OrgMindMap should not bind free-drag handlers"
);
assert.doesNotMatch(
orgMindMapSource,
/]*\sd="[^"]*[CQ]/i,
"OrgMindMap should not render curved SVG path commands"
);
assert.match(orgPermissionTreeSource, /组织树/, "OrgPermissionTree should render organization tree UI");
assert.match(orgPermissionTreeSource, /onContextmenu/, "OrgPermissionTree should support right-click org node actions");
assert.match(orgPermissionTreeSource, /授权/, "OrgPermissionTree should expose personnel authorization action");
assert.match(orgPermissionTreeSource, /移除/, "OrgPermissionTree should expose personnel removal action");
assert.match(orgPermissionTreeSource, /新增人员/, "OrgPermissionTree should expose add-person action for selected org node");
assert.match(orgPermissionTreeSource, /PaginationBar/, "OrgPermissionTree should use global pagination bar");
assert.match(orgPermissionTreeSource, /搜索人员姓名或手机号/, "OrgPermissionTree should support personnel search");
console.log("system permission management UI static assertions passed");