Files
dsh-worktable/01_content/client-factory-gate.test.mjs
T

73 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* client-factory-gate 失败测试:证明 TDZ / 错误 ID / 未知依赖 / 错误 inject 能被拦截。
* 用法:node client-factory-gate.test.mjs(不依赖 npm,纯 node;失败用例抛错即测试失败)
*/
import { gateClientFactory } from './client-factory-gate.mjs'
const WRAP = (body) => "window.__ModuleLoader__.load({ id: 'dsh-worktable', factory: (require) => { var module = { exports: {} }; var exports = module.exports; " + body + " return module.exports; } });"
const OK_BODY = "exports.apply = function apply() {}; exports.inject = ['slots','locale','sessions','conversation','workspaces'];"
let pass = 0
function expectFail(name, source, expectId, expectInject, pattern) {
try {
gateClientFactory(source, expectId, expectInject)
console.error('FAIL(should have been blocked): ' + name)
process.exit(1)
} catch (e) {
const msg = String(e && e.message ? e.message : e)
if (pattern && !pattern.test(msg)) {
console.error('FAIL(wrong reason): ' + name + ' => ' + msg)
process.exit(1)
}
console.log('ok blocked: ' + name + ' => ' + msg)
pass++
}
}
// 1. TDZ 顶层自引用(#491 同款 const Ge=Ge)
expectFail('TDZ self-reference', WRAP("const Ge = Ge;"), 'dsh-worktable', ['slots'], /factory threw|evaluation failed/)
// 2. 错误 ModuleLoader ID
expectFail('wrong ModuleLoader ID', "window.__ModuleLoader__.load({ id: 'wrong-plugin', factory: (require) => { return { apply() {}, inject: [] } } });", 'dsh-worktable', [], /ID mismatch/)
// 3. 未知外部依赖 require
expectFail('unknown external require', WRAP("require('totally-unknown-pkg'); exports.apply = function(){}; exports.inject = [];"), 'dsh-worktable', [], /unexpected external require/)
// 4. 导出结构错误:apply 非函数
expectFail('apply not a function', WRAP("exports.apply = null; exports.inject = [];"), 'dsh-worktable', [], /apply is not a function/)
// 5. inject 内容错误
expectFail('inject mismatch', WRAP("exports.apply = function(){}; exports.inject = ['slots'];"), 'dsh-worktable', ['slots','locale'], /inject mismatch/)
// 6. 白名单外 @deepseek-ai 包(曾是最常见的"引用已删除宿主模块白屏")
expectFail('disallowed @deepseek-ai require', WRAP("require('@deepseek-ai/dsh-client-runtime/client'); exports.apply = function(){}; exports.inject = [];"), 'dsh-worktable', [], /unexpected external require/)
// 7. 重复注册 ModuleLoader(load 调用超过一次)
expectFail('double ModuleLoader registration', "window.__ModuleLoader__.load({ id: 'dsh-worktable', factory: () => ({ apply() {}, inject: [] }) }); window.__ModuleLoader__.load({ id: 'dsh-worktable', factory: () => ({ apply() {}, inject: [] }) });", 'dsh-worktable', [], /more than once/)
// 8. 正向:合法最小 bundle 通过
try {
gateClientFactory(WRAP(OK_BODY), 'dsh-worktable', ['slots','locale','sessions','conversation','workspaces'])
console.log('ok passed: valid minimal bundle')
pass++
} catch (e) {
console.error('FAIL(should pass): valid minimal bundle => ' + (e && e.message ? e.message : e))
process.exit(1)
}
// 9. 死循环工厂(>10s 超时拦截;用 11s 忙等模拟)
expectFail('factory infinite loop timeout', WRAP("var t0 = Date.now(); while (Date.now() - t0 < 11000) {}; exports.apply = function(){}; exports.inject = [];"), 'dsh-worktable', [], /timed out|>10s/)
// 10. 正向:白名单内 require 被记录(react/jsx-runtime 允许)
try {
const r = gateClientFactory(WRAP("require('react/jsx-runtime'); exports.apply = function(){}; exports.inject = [];"), 'dsh-worktable', [])
if (!r.actualRequires.includes('react/jsx-runtime')) throw new Error('actualRequires not recorded')
console.log('ok passed: allowed require recorded')
pass++
} catch (e) {
console.error('FAIL(should pass): allowed require => ' + (e && e.message ? e.message : e))
process.exit(1)
}
console.log('all gate tests passed: ' + pass + '/10')