feat: update agreements and refine miniapp layouts and integrations
This commit is contained in:
1 parent
38fc4187ea
commit
7871114c50
26 files changed
+2018
-120
No files matched your search
@@ -0,0 +1,77 @@
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert/strict')
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
const vm = require('node:vm')
|
||||
const ts = require('typescript')
|
||||
function harness({ demo = false, bound = true, mode = 'view', iconUrl = 'https://example.invalid/backend-icon.png' } = {}) {
|
||||
const states = [], calls = []; let index = 0, closed = 0
|
||||
const exports = {}
|
||||
const deity = { id: 'wealth', name: '财神', icon: 'local-prototype.png' }
|
||||
vm.runInNewContext(ts.transpileModule(fs.readFileSync(path.join(__dirname, '../src/components/DeityBinding.tsx'), 'utf8'), {
|
||||
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2019, jsx: ts.JsxEmit.ReactJSX }
|
||||
}).outputText, { exports, require: id => {
|
||||
if (id === 'react/jsx-runtime') return require(id)
|
||||
if (id === 'react') return { useRef: value => ({ current: value }), useState: initial => {
|
||||
const current = index++; if (!(current in states)) states[current] = initial
|
||||
return [states[current], value => { states[current] = value }]
|
||||
} }
|
||||
if (id === '@tarojs/components') return { View: 'View', Image: 'Image', Text: 'Text', Button: 'Button' }
|
||||
if (id === '@tarojs/taro') return { default: { showToast: () => {} } }
|
||||
if (id.endsWith('/tiangong')) return { getDeity: () => deity, isTiangongDemo: () => demo,
|
||||
tiangongMock: { invite: () => calls.push('invite'), unbind: () => calls.push('unbind') } }
|
||||
if (id.endsWith('/request')) return { resolveAssetUrl: value => value || '' }
|
||||
if (id.endsWith('/useTiangongSnapshot')) return { useTiangongSnapshot: () => ({ deities: {
|
||||
wealth: { unlocked: bound, days: 23, holdingId: 726, iconUrl, remainingUnbinds: 2 }
|
||||
} }) }
|
||||
return {}
|
||||
} })
|
||||
return { calls, closed: () => closed, render: () => { index = 0; return exports.DeityCardDialog({ deityId: 'wealth', mode, onClose: () => { closed++ } }) } }
|
||||
}
|
||||
function nodes(tree) {
|
||||
if (!tree || typeof tree !== 'object') return []
|
||||
const children = tree.props?.children
|
||||
return [tree, ...(Array.isArray(children) ? children : [children]).flatMap(nodes)]
|
||||
}
|
||||
function text(tree) {
|
||||
const walk = node => typeof node === 'string' || typeof node === 'number' ? String(node) : node && typeof node === 'object' ? (Array.isArray(node.props?.children) ? node.props.children : [node.props?.children]).map(walk).join('') : ''
|
||||
return walk(tree)
|
||||
}
|
||||
const find = (tree, className) => nodes(tree).find(node => node.props.className === className)
|
||||
test('正式与Demo共用金色挂饰卡片、固定图片框与关闭入口', () => {
|
||||
for (const demo of [false, true]) {
|
||||
const h = harness({ demo }), tree = h.render()
|
||||
for (const name of ['binding-dialog-stack', 'binding-gold-card', 'binding-card-hook', 'binding-art-frame', 'binding-guarded']) assert.ok(find(tree, name))
|
||||
assert.equal(find(tree, 'binding-card-art').props.mode, 'aspectFit')
|
||||
assert.equal(find(tree, 'binding-card-art').props.src, demo ? 'local-prototype.png' : 'https://example.invalid/backend-icon.png')
|
||||
assert.equal(find(tree, 'binding-days').props.children, 23)
|
||||
find(tree, 'binding-card-close').props.onClick(); assert.equal(h.closed(), 1)
|
||||
}
|
||||
})
|
||||
test('正式卡片只显示真实持有记录,无演示ID、模拟绑定解绑或示例额度', () => {
|
||||
for (const mode of ['view', 'bind']) {
|
||||
const h = harness({ mode }), tree = h.render()
|
||||
assert.match(text(tree), /持有记录:726/)
|
||||
assert.doesNotMatch(text(tree), /DEMO|Mock|模拟|解绑|确认绑定|唯一 ID/)
|
||||
assert.equal(find(tree, 'binding-more'), undefined)
|
||||
assert.equal(find(tree, 'binding-primary binding-card-confirm'), undefined)
|
||||
assert.deepEqual(h.calls, [])
|
||||
}
|
||||
})
|
||||
test('正式未持有不伪造守护;缺图和加载失败保留金色布局而不替换成本地神像', () => {
|
||||
const missing = harness({ bound: false, iconUrl: '' }).render()
|
||||
assert.ok(find(missing, 'binding-gold-card')); assert.equal(find(missing, 'binding-guarded'), undefined)
|
||||
assert.match(text(missing), /图片暂未配置|请通过 NFC 绑定神仙/)
|
||||
assert.equal(find(missing, 'binding-card-art'), undefined)
|
||||
const h = harness(); find(h.render(), 'binding-card-art').props.onError()
|
||||
assert.match(text(h.render()), /图片加载失败/)
|
||||
assert.equal(find(h.render(), 'binding-card-art'), undefined)
|
||||
})
|
||||
test('Demo保留原有模拟解绑分支,正式模式不会复用它', () => {
|
||||
const h = harness({ demo: true })
|
||||
find(h.render(), 'binding-more').props.onClick()
|
||||
find(h.render(), 'binding-unbind-menu').props.onClick()
|
||||
const confirm = nodes(h.render()).find(node => node.props.className?.startsWith('binding-primary ') && text(node) === '确定解绑')
|
||||
assert.ok(confirm); confirm.props.onClick()
|
||||
assert.deepEqual(h.calls, ['unbind']); assert.equal(h.closed(), 1)
|
||||
})
|
||||
Reference in new issue
Block a user