mp-pl-plan-cert-entry.test.mjs 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import assert from 'node:assert/strict'
  2. import test from 'node:test'
  3. import { readFile } from 'node:fs/promises'
  4. import ts from 'typescript'
  5. const root = new URL('../../', import.meta.url)
  6. const read = (path) => readFile(new URL(path, root), 'utf8')
  7. test('危化品证上传位于运输管理并复用现有 WebView 壳', async () => {
  8. const source = await read('miniprogram/config/workbench-menus.js')
  9. const { WORKBENCH_MODULES } = await import(`data:text/javascript,${encodeURIComponent(source)}`)
  10. const transport = WORKBENCH_MODULES.find((m) => m.key === 'pl')
  11. const entry = transport.menus.find((m) => m.code === 'pl-plan-cert-webview')
  12. assert.ok(entry, '运输管理缺少危化品证上传入口')
  13. assert.equal(entry.name, '危化品证上传')
  14. assert.equal(entry.perms, 'mini:pl:plan-cert:list')
  15. assert.equal(entry.enabled, true)
  16. const api = await read('miniprogram/config/api.js')
  17. const ast = ts.createSourceFile('api.js', api, ts.ScriptTarget.Latest, true)
  18. let expression
  19. function visit(node) {
  20. if (ts.isPropertyAssignment(node) && node.name.getText(ast) === "'pl-plan-cert-webview'")
  21. expression = node.initializer.getText(ast)
  22. ts.forEachChild(node, visit)
  23. }
  24. visit(ast)
  25. assert.ok(expression, '缺少工作台路由映射')
  26. const path = new Function('PAGE_PATHS', `return ${expression}`)({
  27. mpWebview: '/pages/common/mp-webview'
  28. })
  29. assert.equal(path, '/pages/common/mp-webview?path=%2Fm%2Fpl%2Fplan-cert')
  30. })
  31. test('H5 列表与详情均使用独立移动路由并隐藏桌面工作标签', async () => {
  32. const source = await read('web-admin/src/router/routes/staticRoutes.ts')
  33. const ast = ts.createSourceFile('routes.ts', source, ts.ScriptTarget.Latest, true)
  34. const routes = new Map()
  35. function visit(node) {
  36. if (ts.isObjectLiteralExpression(node)) {
  37. const pathProp = node.properties.find(
  38. (prop) => ts.isPropertyAssignment(prop) && prop.name.getText(ast) === 'path'
  39. )
  40. if (pathProp && ts.isPropertyAssignment(pathProp) && ts.isStringLiteral(pathProp.initializer))
  41. routes.set(pathProp.initializer.text, node)
  42. }
  43. ts.forEachChild(node, visit)
  44. }
  45. visit(ast)
  46. const listRoute = routes.get('/m/pl/plan-cert')
  47. const detailRoute = routes.get('/m/pl/plan-cert/:id')
  48. assert.ok(listRoute, '缺少 /m/pl/plan-cert 路由')
  49. assert.match(listRoute.getText(ast), /views\/m\/pl\/plan-cert\/index\.vue/)
  50. assert.ok(detailRoute, '缺少 /m/pl/plan-cert/:id 独立详情路由')
  51. assert.match(detailRoute.getText(ast), /views\/m\/pl\/plan-cert\/detail\.vue/)
  52. for (const route of [listRoute, detailRoute]) {
  53. assert.match(route.getText(ast), /isMpWebview:\s*true/)
  54. assert.match(route.getText(ast), /isHideTab:\s*true/)
  55. }
  56. })
  57. test('菜单 SQL 仅补移动入口与已有授权角色的完整祖先链', async () => {
  58. const sql = await read('docs/sql/migrations/2026-10-17-mini-pl-plan-cert-webview-menus.sql')
  59. assert.match(sql, /START TRANSACTION/i)
  60. assert.match(sql, /COMMIT/i)
  61. assert.match(sql, /mini:pl:plan-cert:list/)
  62. assert.match(sql, /MINI_PL_ROOT/)
  63. assert.match(sql, /parent_id\s*=\s*'1'/)
  64. assert.match(sql, /EXISTS\s*\([\s\S]*m\.perms\s*=\s*'pl:plan-cert:list'[\s\S]*\)/)
  65. assert.match(sql, /r\.tenant_no\s*=\s*'shanxia2.0'/)
  66. assert.match(sql, /ON DUPLICATE KEY UPDATE/i)
  67. assert.doesNotMatch(sql, /\b(?:DELETE|DROP|ALTER|TRUNCATE)\s/i)
  68. assert.doesNotMatch(sql, /pl:plan-cert:(?:upload|ready)/)
  69. })