74 lines
3.4 KiB
JavaScript
74 lines
3.4 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import test from 'node:test'
|
|
import { readFile } from 'node:fs/promises'
|
|
import ts from 'typescript'
|
|
|
|
const root = new URL('../../', import.meta.url)
|
|
const read = (path) => readFile(new URL(path, root), 'utf8')
|
|
|
|
test('危化品证上传位于运输管理并复用现有 WebView 壳', async () => {
|
|
const source = await read('miniprogram/config/workbench-menus.js')
|
|
const { WORKBENCH_MODULES } = await import(`data:text/javascript,${encodeURIComponent(source)}`)
|
|
const transport = WORKBENCH_MODULES.find((m) => m.key === 'pl')
|
|
const entry = transport.menus.find((m) => m.code === 'pl-plan-cert-webview')
|
|
assert.ok(entry, '运输管理缺少危化品证上传入口')
|
|
assert.equal(entry.name, '危化品证上传')
|
|
assert.equal(entry.perms, 'mini:pl:plan-cert:list')
|
|
assert.equal(entry.enabled, true)
|
|
const api = await read('miniprogram/config/api.js')
|
|
const ast = ts.createSourceFile('api.js', api, ts.ScriptTarget.Latest, true)
|
|
let expression
|
|
function visit(node) {
|
|
if (ts.isPropertyAssignment(node) && node.name.getText(ast) === "'pl-plan-cert-webview'")
|
|
expression = node.initializer.getText(ast)
|
|
ts.forEachChild(node, visit)
|
|
}
|
|
visit(ast)
|
|
assert.ok(expression, '缺少工作台路由映射')
|
|
const path = new Function('PAGE_PATHS', `return ${expression}`)({
|
|
mpWebview: '/pages/common/mp-webview'
|
|
})
|
|
assert.equal(path, '/pages/common/mp-webview?path=%2Fm%2Fpl%2Fplan-cert')
|
|
})
|
|
|
|
test('H5 列表与详情均使用独立移动路由并隐藏桌面工作标签', async () => {
|
|
const source = await read('web-admin/src/router/routes/staticRoutes.ts')
|
|
const ast = ts.createSourceFile('routes.ts', source, ts.ScriptTarget.Latest, true)
|
|
const routes = new Map()
|
|
function visit(node) {
|
|
if (ts.isObjectLiteralExpression(node)) {
|
|
const pathProp = node.properties.find(
|
|
(prop) => ts.isPropertyAssignment(prop) && prop.name.getText(ast) === 'path'
|
|
)
|
|
if (pathProp && ts.isPropertyAssignment(pathProp) && ts.isStringLiteral(pathProp.initializer))
|
|
routes.set(pathProp.initializer.text, node)
|
|
}
|
|
ts.forEachChild(node, visit)
|
|
}
|
|
visit(ast)
|
|
const listRoute = routes.get('/m/pl/plan-cert')
|
|
const detailRoute = routes.get('/m/pl/plan-cert/:id')
|
|
assert.ok(listRoute, '缺少 /m/pl/plan-cert 路由')
|
|
assert.match(listRoute.getText(ast), /views\/m\/pl\/plan-cert\/index\.vue/)
|
|
assert.ok(detailRoute, '缺少 /m/pl/plan-cert/:id 独立详情路由')
|
|
assert.match(detailRoute.getText(ast), /views\/m\/pl\/plan-cert\/detail\.vue/)
|
|
for (const route of [listRoute, detailRoute]) {
|
|
assert.match(route.getText(ast), /isMpWebview:\s*true/)
|
|
assert.match(route.getText(ast), /isHideTab:\s*true/)
|
|
}
|
|
})
|
|
|
|
test('菜单 SQL 仅补移动入口与已有授权角色的完整祖先链', async () => {
|
|
const sql = await read('docs/sql/migrations/2026-10-17-mini-pl-plan-cert-webview-menus.sql')
|
|
assert.match(sql, /START TRANSACTION/i)
|
|
assert.match(sql, /COMMIT/i)
|
|
assert.match(sql, /mini:pl:plan-cert:list/)
|
|
assert.match(sql, /MINI_PL_ROOT/)
|
|
assert.match(sql, /parent_id\s*=\s*'1'/)
|
|
assert.match(sql, /EXISTS\s*\([\s\S]*m\.perms\s*=\s*'pl:plan-cert:list'[\s\S]*\)/)
|
|
assert.match(sql, /r\.tenant_no\s*=\s*'shanxia2.0'/)
|
|
assert.match(sql, /ON DUPLICATE KEY UPDATE/i)
|
|
assert.doesNotMatch(sql, /\b(?:DELETE|DROP|ALTER|TRUNCATE)\s/i)
|
|
assert.doesNotMatch(sql, /pl:plan-cert:(?:upload|ready)/)
|
|
})
|