Files
one-pipe-system/scripts/tests/carrierRealnameControl.test.mjs
luo 22e796ba23
All checks were successful
构建并部署前端到测试环境 / deploy (push) Successful in 55s
fix:some
2026-10-20 17:35:12 +08:00

378 lines
13 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import ts from 'typescript'
import * as vue from 'vue'
import { compileScript, parse } from '@vue/compiler-sfc'
function evaluate(source, imports = {}, globals = {}) {
const compiled = ts.transpileModule(source, {
compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.CommonJS }
}).outputText
const module = { exports: {} }
new Function('require', 'module', 'exports', ...Object.keys(globals), compiled)(
(name) => {
assert.ok(imports[name], `Unexpected dependency: ${name}`)
return imports[name]
},
module,
module.exports,
...Object.values(globals)
)
return module.exports
}
const read = (path) => readFileSync(path, 'utf8')
const carrierTypes = evaluate(read('src/types/api/carrier.ts'))
const carrierConfig = evaluate(read('src/config/constants/carrierTypes.ts'), {
'@/types/api': carrierTypes
})
const checkedColumns = evaluate(read('src/composables/useCheckedColumns.ts'), { vue })
const components = Object.fromEntries(
['index', 'detail'].map((name) => {
const { descriptor } = parse(read(`src/views/system/carrier-management/${name}.vue`))
return [
name,
{ descriptor, script: compileScript(descriptor, { id: `carrier-${name}` }).content }
]
})
)
test('carrier form grid top-aligns items so helper text cannot offset adjacent controls', () => {
const style = components.index.descriptor.styles.map((block) => block.content).join('\n')
assert.match(style, /\.carrier-form-grid\s*\{[^}]*align-items:\s*start\s*;/)
})
const carrier = (enabled) => ({
id: 7,
carrier_code: 'carrier-test',
carrier_name: '测试运营商',
carrier_type: 'CMCC',
realname_control_enabled: enabled,
status: 1,
created_at: '',
updated_at: ''
})
function harness(userType, responseCarrier = carrier(1)) {
const writes = []
const confirmations = []
const user = vue.reactive({ info: { user_type: userType }, permissions: [], buttons: [] })
const permission = evaluate(read('src/composables/usePermission.ts'), {
vue,
'@/store/modules/user': { useUserStore: () => user }
})
const service = {
getCarriers: async () => ({ code: 0, data: { items: [responseCarrier], total: 1 } }),
getCarrierDetail: async () => ({ code: 0, data: responseCarrier }),
createCarrier: async (data) => writes.push({ method: 'create', data: { ...data } }),
updateCarrier: async (id, data) => writes.push({ method: 'update', id, data: { ...data } })
}
const runtimeVue = { ...vue, onMounted: () => {} }
const imports = {
vue: runtimeVue,
'vue-router': { useRouter: () => ({ push() {} }), useRoute: () => ({ params: { id: '7' } }) },
'@vueuse/core': { useWindowSize: () => ({ width: vue.ref(1200) }) },
'@/api/modules': { CarrierService: service },
'element-plus': {
ElMessage: { success() {}, warning() {} },
ElMessageBox: {
confirm: async (...args) => {
confirmations.push(args)
return 'confirm'
}
},
ElTag: {},
ElSwitch: {},
ElButton: {}
},
'@/composables/useCheckedColumns': checkedColumns,
'@/composables/useAuth': { useAuth: () => ({ hasAuth: () => true }) },
'@/composables/usePermission': permission,
'@/router/routesAlias': {
RoutesAlias: { CarrierDetail: '/carrier', CarrierManagement: '/carrier' }
},
'@/utils/codeGenerator': { generateCarrierCode: () => 'carrier-test' },
'@/utils/business/format': { formatDateTime: (value) => value },
'@/config/constants': {
...carrierConfig,
CommonStatus: { ENABLED: 1, DISABLED: 0 },
getStatusText: (value) => String(value)
}
}
const setup = (name) =>
evaluate(components[name].script, imports, runtimeVue).default.setup({}, { expose() {} })
return {
list: setup('index'),
detail: setup('detail'),
writes,
confirmations,
messageBox: imports['element-plus'].ElMessageBox,
service
}
}
const validForm = {
validate: async (callback) => callback(true),
resetFields() {},
clearValidate() {}
}
for (const userType of [1, 2, '1', '2', 3, 4, 0, undefined]) {
const allowed = [1, 2].includes(Number(userType))
test(`user_type=${userType}: list visibility, detail visibility and create/update field access`, async () => {
const { list, detail, writes } = harness(userType)
assert.equal(list.canConfigureRealnameControl.value, allowed)
assert.equal(detail.canConfigureRealnameControl.value, allowed)
assert.equal(
list.columnOptions.some((column) => column.prop === 'realname_control_enabled'),
allowed
)
assert.equal(
list.columns.value.some((column) => column.prop === 'realname_control_enabled'),
allowed
)
assert.equal(
list.columnChecks.value.some((column) => column.prop === 'realname_control_enabled'),
allowed
)
await list.getTableData()
await detail.loadCarrier()
assert.equal(list.carrierList.value[0].realname_control_enabled, 1)
assert.equal(detail.carrier.value.realname_control_enabled, 1)
list.showDialog('add')
assert.equal(list.form.realname_control_enabled, 0)
list.form.realname_control_enabled = 1
await list.handleSubmit(validForm)
list.showDialog('edit', carrier(1))
assert.equal(list.form.realname_control_enabled, 1)
list.form.realname_control_enabled = 0
await list.handleSubmit(validForm)
assert.equal(writes.length, 2)
assert.equal(writes[0].method, 'create')
assert.equal(writes[1].method, 'update')
assert.equal(writes[1].id, 7)
for (const [index, write] of writes.entries()) {
assert.equal(Object.hasOwn(write.data, 'realname_control_enabled'), allowed)
if (allowed) assert.equal(write.data.realname_control_enabled, index === 0 ? 1 : 0)
}
})
}
test('labels preserve numeric zero and handle missing fields without inventing a state', () => {
const { getCarrierRealnameControlLabel: label } = carrierConfig
assert.equal(label(0), '不管控')
assert.equal(label(1), '管控')
assert.equal(label(undefined), '-')
assert.equal(label(null), '-')
const { list } = harness(1)
const column = list.columns.value.find((item) => item.prop === 'realname_control_enabled')
assert.equal(column.formatter(carrier(0)), '不管控')
assert.equal(column.formatter(carrier(1)), '管控')
assert.equal(column.formatter(carrier(undefined)), '-')
})
test('editing then creating resets control state; default creation sends numeric zero', async () => {
const { list, writes } = harness(2)
list.showDialog('edit', carrier(1))
list.showDialog('add')
assert.equal(list.form.realname_control_enabled, 0)
await list.handleSubmit(validForm)
assert.equal(writes[0].data.realname_control_enabled, 0)
list.showDialog('edit', carrier(0))
assert.equal(list.form.realname_control_enabled, 0)
list.showDialog('edit', carrier(undefined))
assert.equal(list.form.realname_control_enabled, 0)
})
for (const userType of [1, 2]) {
test(`user_type=${userType}: enabling control requires confirmation before PUT and sends true`, async () => {
const { list, writes, confirmations, messageBox } = harness(userType)
list.showDialog('edit', carrier(0))
list.form.realname_control_enabled = 1
let confirm
messageBox.confirm = (...args) => {
confirmations.push(args)
return new Promise((resolve) => {
confirm = resolve
})
}
const pending = list.handleSubmit(validForm)
assert.equal(confirmations.length, 1)
assert.match(confirmations[0][0], /未实名的开机卡会在下一次评估时被停机/)
assert.deepEqual(writes, [])
assert.equal(list.submitLoading.value, true)
await list.handleSubmit(validForm)
assert.equal(confirmations.length, 1)
confirm('confirm')
await pending
assert.equal(writes.length, 1)
assert.equal(writes[0].method, 'update')
assert.equal(writes[0].data.realname_control_enabled, 1)
assert.equal(writes[0].data.realname_control_confirm, true)
assert.equal(list.submitLoading.value, false)
})
}
for (const reason of ['cancel', 'close']) {
test(`${reason} of realname confirmation does not submit; retry requires a fresh confirmation`, async () => {
const { list, writes, messageBox } = harness(1)
list.showDialog('edit', carrier(0))
list.form.realname_control_enabled = 1
let prompts = 0
messageBox.confirm = async () => {
prompts += 1
throw reason
}
await list.handleSubmit(validForm)
assert.deepEqual(writes, [])
assert.equal(list.dialogVisible.value, true)
assert.equal(list.submitLoading.value, false)
assert.equal(list.form.realname_control_enabled, 1)
messageBox.confirm = async () => {
prompts += 1
return 'confirm'
}
await list.handleSubmit(validForm)
assert.equal(prompts, 2)
assert.equal(writes[0].data.realname_control_confirm, true)
})
}
test('unchanged, disabled, new, and unauthorized carriers never send confirmation automatically', async () => {
for (const [userType, mode, original, selected] of [
[1, 'edit', 1, 1],
[1, 'edit', 0, 0],
[2, 'edit', 1, 0],
[1, 'add', 0, 1],
[3, 'edit', 0, 1],
[4, 'edit', 0, 1]
]) {
const { list, writes, confirmations } = harness(userType)
list.showDialog(mode, carrier(original))
list.form.realname_control_enabled = selected
await list.handleSubmit(validForm)
assert.equal(confirmations.length, 0)
assert.equal(writes.length, 1)
assert.equal(Object.hasOwn(writes[0].data, 'realname_control_confirm'), false)
}
})
test('opening another carrier resets the original control state after a cancelled enabling', async () => {
const { list, writes, messageBox } = harness(2)
list.showDialog('edit', carrier(0))
list.form.realname_control_enabled = 1
messageBox.confirm = async () => {
throw 'cancel'
}
await list.handleSubmit(validForm)
list.showDialog('edit', { ...carrier(1), id: 8 })
await list.handleSubmit(validForm)
assert.equal(writes[0].id, 8)
assert.equal(Object.hasOwn(writes[0].data, 'realname_control_confirm'), false)
})
test('a failed PUT requires a fresh confirmation on retry', async (t) => {
const { list, writes, confirmations, service } = harness(2)
t.mock.method(console, 'error', () => {})
list.showDialog('edit', carrier(0))
list.form.realname_control_enabled = 1
const updateCarrier = service.updateCarrier
service.updateCarrier = async () => {
throw new Error('PUT failed')
}
await list.handleSubmit(validForm)
assert.equal(confirmations.length, 1)
assert.deepEqual(writes, [])
assert.equal(list.dialogVisible.value, true)
assert.equal(list.submitLoading.value, false)
service.updateCarrier = updateCarrier
await list.handleSubmit(validForm)
assert.equal(confirmations.length, 2)
assert.equal(writes[0].data.realname_control_confirm, true)
})
function findElement(node, predicate) {
if (node.type === 1 && predicate(node)) return node
for (const child of node.children || []) {
const match = findElement(child, predicate)
if (match) return match
}
}
test('form and detail guard the field, and the switch uses numeric 1/0', () => {
for (const [name, tag] of [
['index', 'ElFormItem'],
['detail', 'ElDescriptionsItem']
]) {
const field = findElement(
components[name].descriptor.template.ast,
(node) =>
node.tag === tag &&
node.props.some((prop) => prop.name === 'label' && prop.value?.content === '通道实名管控')
)
assert.ok(field)
assert.equal(
field.props.find((prop) => prop.type === 7 && prop.name === 'if')?.exp?.content,
'canConfigureRealnameControl'
)
if (name === 'index') {
const toggle = findElement(field, (node) => node.tag === 'ElSwitch')
for (const [arg, value] of [
['active-value', '1'],
['inactive-value', '0']
]) {
assert.equal(
toggle.props.find((prop) => prop.type === 7 && prop.arg?.content === arg)?.exp?.content,
value
)
}
}
}
})
test('carrier endpoints preserve the field in list/detail responses and create/update requests', async () => {
const calls = []
class BaseService {
static getPage(url) {
calls.push({ method: 'GET', url })
return Promise.resolve({ code: 0, data: { items: [carrier(1)] } })
}
static getOne(url) {
calls.push({ method: 'GET', url })
return Promise.resolve({ code: 0, data: carrier(0) })
}
static create(url, data) {
calls.push({ method: 'POST', url, data })
return Promise.resolve({ code: 0, data })
}
static update(url, data) {
calls.push({ method: 'PUT', url, data })
return Promise.resolve({ code: 0, data })
}
}
const { CarrierService } = evaluate(read('src/api/modules/carrier.ts'), {
'../BaseService': { BaseService }
})
assert.equal((await CarrierService.getCarriers()).data.items[0].realname_control_enabled, 1)
assert.equal((await CarrierService.getCarrierDetail(7)).data.realname_control_enabled, 0)
await CarrierService.createCarrier({ ...carrier(1) })
await CarrierService.updateCarrier(7, {
realname_control_enabled: 1,
realname_control_confirm: true
})
assert.deepEqual(calls, [
{ method: 'GET', url: '/api/admin/carriers' },
{ method: 'GET', url: '/api/admin/carriers/7' },
{ method: 'POST', url: '/api/admin/carriers', data: carrier(1) },
{
method: 'PUT',
url: '/api/admin/carriers/7',
data: { realname_control_enabled: 1, realname_control_confirm: true }
}
])
})