Files
shanxia2.0/web-admin/scripts/mobile-attachment-preview.test.ts
2026-10-22 16:24:46 +08:00

70 lines
3.0 KiB
TypeScript

import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import test from 'node:test'
import { computed, reactive } from 'vue'
import { parse } from '@vue/compiler-sfc'
import ts from 'typescript'
import { isMpWebviewPath } from '../src/utils/mp-webview'
const components = [
{ path: 'attachment-preview-dialog', mobileClass: 'attachment-preview-dialog--mobile' },
{ path: 'attachment-upload-field', mobileClass: 'attachment-upload-preview--mobile' }
]
for (const component of components) {
test(`${component.path}: teleported dialog mobile class follows /m routes, never desktop compact`, () => {
const file = new URL(`../src/components/business/${component.path}/index.vue`, import.meta.url)
const { descriptor } = parse(readFileSync(file, 'utf8'))
const ast = ts.createSourceFile(
'preview.ts',
descriptor.scriptSetup!.content,
ts.ScriptTarget.Latest,
true
)
const names = ['route', 'useTiles', 'isMpPreviewToolbar', 'mpBtnSize']
const source = ast.statements
.filter(
(node) =>
ts.isVariableStatement(node) &&
names.includes(node.declarationList.declarations[0].name.getText(ast))
)
.map((node) => node.getText(ast))
.join('\n')
const dialog = descriptor
.template!.ast!.children.flatMap((node: any) =>
node.tag === 'el-dialog' ? [node] : node.children || []
)
.find((node: any) => node.tag === 'el-dialog') as any
assert.ok(dialog, 'real preview el-dialog must exist')
assert.ok(dialog.props.some((prop: any) => prop.name === 'append-to-body'))
const classBinding = dialog.props.find(
(prop: any) => prop.name === 'bind' && prop.arg?.content === 'class'
)
assert.ok(classBinding, 'mobile styling must bind to the teleported dialog root')
const code = ts.transpile(source, { target: ts.ScriptTarget.ESNext })
for (const compact of [false, true]) {
const route = reactive({ path: '/crm/customer' })
const bindings = { computed, isMpWebviewPath, useRoute: () => route, props: { compact } }
const state = new Function(
...Object.keys(bindings),
`${code}\nreturn { isMpPreviewToolbar, mpBtnSize, useTiles: typeof useTiles === 'undefined' ? undefined : useTiles }`
)(...Object.values(bindings))
const readClass = () =>
new Function('isMpPreviewToolbar', 'useTiles', `return (${classBinding.exp.content})`)(
state.isMpPreviewToolbar.value,
state.useTiles?.value
)
assert.equal(Boolean(readClass()[component.mobileClass]), false)
assert.equal(
state.mpBtnSize.value,
component.path === 'attachment-upload-field' && compact ? 'small' : 'default'
)
route.path = '/m/crm/customer/form'
assert.equal(readClass()[component.mobileClass], true)
assert.equal(state.mpBtnSize.value, 'small')
route.path = '/crm/customer'
assert.equal(Boolean(readClass()[component.mobileClass]), false)
}
})
}