104 lines
3.2 KiB
TypeScript
104 lines
3.2 KiB
TypeScript
import assert from 'node:assert/strict'
|
|
import { readFileSync } from 'node:fs'
|
|
import test from 'node:test'
|
|
import { parse } from '@vue/compiler-sfc'
|
|
import { computed, ref } from 'vue'
|
|
import ts from 'typescript'
|
|
|
|
function component(path: string) {
|
|
return parse(readFileSync(new URL(`../src/views/m/${path}.vue`, import.meta.url), 'utf8'))
|
|
.descriptor
|
|
}
|
|
function evaluate(path: string, name: string, bindings: Record<string, any>) {
|
|
const ast = ts.createSourceFile(
|
|
'page.ts',
|
|
component(path).scriptSetup!.content,
|
|
ts.ScriptTarget.Latest,
|
|
true
|
|
)
|
|
const statement = ast.statements.find((node) =>
|
|
ts.isVariableStatement(node)
|
|
? node.declarationList.declarations.some((d) => d.name.getText(ast) === name)
|
|
: ts.isFunctionDeclaration(node) && node.name?.text === name
|
|
)!
|
|
assert.ok(statement)
|
|
return new Function(
|
|
...Object.keys(bindings),
|
|
ts.transpile(statement.getText(ast)) + `; return ${name}`
|
|
)(...Object.values(bindings))
|
|
}
|
|
|
|
test('main record list/detail templates have no delete buttons or delete event bindings', () => {
|
|
for (const path of [
|
|
'crm/customer/index',
|
|
'crm/customer/detail',
|
|
'crm/product/index',
|
|
'crm/product/detail',
|
|
'crm/quote/MpQuoteList',
|
|
'crm/quote/detail',
|
|
'crm/quote/index',
|
|
'crm/quote/approval',
|
|
'crm/contract/MpContractList',
|
|
'crm/contract/detail',
|
|
'crm/contract/index',
|
|
'crm/contract/approval',
|
|
'pl/plan/index',
|
|
'pl/plan/detail',
|
|
'pl/plan-cert/index',
|
|
'pl/plan-cert/PlanCard',
|
|
'pl/plan-cert/detail',
|
|
'pl/plan-cert/CertDetail'
|
|
]) {
|
|
const template = component(path).template!.content
|
|
assert.doesNotMatch(template, /删除|@click="(?:onDelete|deleteCard|remove)\b/, path)
|
|
}
|
|
})
|
|
|
|
test('quote and contract management/approval actions never offer main record deletion across statuses', () => {
|
|
for (const domain of ['quote', 'contract']) {
|
|
for (const approve of [false, true]) {
|
|
for (const status of [
|
|
'draft',
|
|
'submitted',
|
|
'approving',
|
|
'accepted',
|
|
'rejected',
|
|
'approved',
|
|
'executing',
|
|
'completed',
|
|
'invalid'
|
|
]) {
|
|
const actions = evaluate(`crm/${domain}/detail`, 'fabActions', {
|
|
computed,
|
|
quote: ref({ status }),
|
|
contract: ref({ status }),
|
|
props: { embedded: false },
|
|
isApproveEntry: ref(approve),
|
|
pendingApproval: ref({ id: 'approval' }),
|
|
canApproveNow: ref(true),
|
|
canInvalid: ref(true),
|
|
canDelete: ref(true),
|
|
CREATOR_DELETE_TIP: '',
|
|
isQuoteEditableStatus: () => true,
|
|
isContractEditableStatus: () => true
|
|
}).value
|
|
assert.ok(actions.length > 0)
|
|
assert.ok(
|
|
actions.every((action: any) => action.key !== 'delete' && action.label !== '删除')
|
|
)
|
|
const cardActions = evaluate(
|
|
`crm/${domain}/Mp${domain === 'quote' ? 'Quote' : 'Contract'}List`,
|
|
'cardActions',
|
|
{
|
|
props: { mode: approve ? 'approve' : 'manage' },
|
|
view: ref('submitted')
|
|
}
|
|
)({ status, canApprove: true })
|
|
assert.ok(
|
|
cardActions.every((action: any) => action.key !== 'delete' && action.label !== '删除')
|
|
)
|
|
}
|
|
}
|
|
}
|
|
})
|