108 lines
6.9 KiB
JavaScript
108 lines
6.9 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const vm = require('node:vm');
|
|
const ts = require('typescript');
|
|
function load(path, cc, dependencies) {
|
|
const context = { cc, exports: {}, require: id => dependencies(id), setTimeout, clearTimeout };
|
|
vm.runInNewContext(ts.transpileModule(fs.readFileSync(path, 'utf8'), { compilerOptions: {
|
|
experimentalDecorators: true, module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2017,
|
|
} }).outputText, context);
|
|
return context.exports.default;
|
|
}
|
|
test('test entry requires develop/trial and a distinct configured test origin', () => {
|
|
let version = '开发版';
|
|
const utils = { httpip: 'https://production.example/', testHttpip: 'https://test.example/' };
|
|
const cc = { fx: { GameTool: { getWechatGameVersion: () => version } } };
|
|
const api = load('assets/Script/seven_day_gift/SevenDayGiftBootstrapApi.ts', cc, () => ({ default: utils }));
|
|
for (const v of ['正式版', '未知版本', '网页版']) { version = v; assert.equal(api.getTestEnvironment().allowed, false); }
|
|
for (const v of ['开发版', '体验版']) { version = v; assert.equal(api.getTestEnvironment().allowed, true); }
|
|
utils.testHttpip = 'https://PRODUCTION.example/test/';
|
|
assert.equal(api.getTestEnvironment().allowed, false);
|
|
utils.testHttpip = '';
|
|
assert.equal(api.getTestEnvironment().allowed, false);
|
|
});
|
|
test('cache clearing preserves other users, activities and rounds and blocks stale snapshots', () => {
|
|
const store = new Map();
|
|
let uid = 'user1', url = 'https://test.example/';
|
|
const api = { getUid: () => uid, getTestEnvironment: () => ({ allowed: true, baseUrl: url }) };
|
|
const cc = { Component: class {}, _decorator: { ccclass: x => x }, fx: { StorageMessage: {
|
|
getStorage: key => store.get(key), setStorage: (key, value) => store.set(key, value), removeStorage: key => store.delete(key),
|
|
} } };
|
|
const Panel = load('assets/seven_day_gift/test/SevenDayTest.ts', cc, () => ({ default: api }));
|
|
const p = new Panel(); p.render = () => {};
|
|
p.snapshot = { activityId: 'activity1', startAt: 123 };
|
|
p.snapshotUid = uid; p.snapshotUrl = url;
|
|
const key = (user, activity, start, day) => user + ':' + JSON.stringify([activity, start, day]);
|
|
const own = key(uid, 'activity1', 123, 1), own2 = key(uid, 'activity1', 123, 2);
|
|
const other = [key('user2', 'activity1', 123, 1), key(uid, 'activity2', 123, 1), key(uid, 'activity1', 456, 1)];
|
|
const records = Object.fromEntries([own, own2, ...other].map(k => [k, true]));
|
|
store.set('seven_day_gift_processed_claims_v1', records);
|
|
p.isActivityOpen = () => true; p.clearCache(true); assert.equal(records[own], true);
|
|
p.isActivityOpen = () => false; uid = 'user2'; p.clearCache(true); assert.equal(records[own], true);
|
|
uid = 'user1'; url = 'https://changed.example/'; p.clearCache(true); assert.equal(records[own], true);
|
|
url = p.snapshotUrl; p.clearCache(true);
|
|
assert.equal(records[own], undefined); assert.equal(records[own2], undefined);
|
|
other.forEach(k => assert.equal(records[k], true));
|
|
const auto = 'seven_day_gift_auto_open_v1:user1:activity1';
|
|
store.set(auto, '123'); store.set('seven_day_gift_auto_open_v1:user2:activity1', '123');
|
|
p.clearCache(false); assert.equal(store.has(auto), false);
|
|
assert.equal(store.get('seven_day_gift_auto_open_v1:user2:activity1'), '123');
|
|
});
|
|
test('debug prefab references and required controls exist', () => {
|
|
const a = JSON.parse(fs.readFileSync('assets/seven_day_gift/test/SevenDayTest.prefab'));
|
|
function walk(x) { if (!x || typeof x !== 'object') return; if ('__id__' in x) assert.ok(a[x.__id__]); Object.values(x).forEach(walk); }
|
|
a.forEach(walk);
|
|
for (const name of ['entry', 'panel', 'close', 'query', 'clearClaim', 'clearAuto', 'recheck', 'viewport', 'content'])
|
|
assert.equal(a.filter(n => n.__type__ === 'cc.Node' && n._name === name).length, 1);
|
|
assert.equal(a.find(n => n._name === 'panel')._active, false);
|
|
for (const node of a.filter(n => n.__type__ === 'cc.Node')) {
|
|
for (const ref of node._components) {
|
|
assert.ok(ref && a[ref.__id__], 'no null component slots');
|
|
assert.ok(a[ref.__id__].__type__.startsWith('cc.'), 'UI prefab must not serialize custom script references');
|
|
}
|
|
}
|
|
});
|
|
|
|
test('test entry attaches the registered constructor without calling getComponent on the prefab', () => {
|
|
let added = 0, initialized = false, mounted = false;
|
|
class TestPanel {}
|
|
const panel = { initialize() { assert.equal(node.active, false); initialized = true; } };
|
|
const node = { active: true, getComponent: () => { throw new TypeError("Cannot read property 'constructor' of null"); },
|
|
addComponent(type) { assert.equal(type, TestPanel); added++; return panel; }, destroy() { assert.fail('unexpected destruction'); } };
|
|
const bundle = { load(path, type, done) { assert.equal(path, 'test/SevenDayTest'); done(null, {}); } };
|
|
const canvas = { getComponent: () => ({ loadHomeBundleWithDependencies(name, priority, done) { done(null, bundle); } }),
|
|
addChild(child) { assert.equal(child, node); assert.equal(initialized, true); mounted = true; } };
|
|
const api = { getTestEnvironment: () => ({ allowed: true }) };
|
|
const cc = { Component: class {}, Prefab: class {}, _decorator: { ccclass: x => x },
|
|
js: { getClassByName: name => { assert.equal(name, 'SevenDayTest'); return TestPanel; } },
|
|
find: () => canvas, isValid: () => true, instantiate: () => node };
|
|
const Host = load('assets/Script/seven_day_gift/SevenDayGiftHost.ts', cc, () => ({ default: api }));
|
|
const host = new Host(); host.node = {};
|
|
host.loadTestEntry();
|
|
assert.equal(added, 1);
|
|
assert.equal(mounted, true);
|
|
assert.equal(node.active, true);
|
|
});
|
|
|
|
test('entry touch opens panel and close touch hides it', () => {
|
|
const api = { getTestEnvironment: () => ({ allowed: true }) };
|
|
const controls = new Map();
|
|
function control(name) {
|
|
if (!controls.has(name)) controls.set(name, { active: false, handlers: {},
|
|
on(event, action) { this.handlers[event] = action; }, getChildByName: control,
|
|
getComponent: () => ({}), addComponent: () => ({ roundRect() {}, fill() {} }),
|
|
});
|
|
return controls.get(name);
|
|
}
|
|
const cc = { Component: class {}, Graphics: class {}, Label: class {}, color: () => ({}),
|
|
Node: { EventType: { TOUCH_END: 'touchend' } }, _decorator: { ccclass: x => x } };
|
|
const Panel = load('assets/seven_day_gift/test/SevenDayTest.ts', cc, () => ({ default: api }));
|
|
const p = new Panel(); p.node = control('root'); p.render = () => {};
|
|
p.onLoad();
|
|
control('entry').handlers.touchend({ stopPropagation() {} });
|
|
assert.equal(control('panel').active, true);
|
|
control('close').handlers.touchend({ stopPropagation() {} });
|
|
assert.equal(control('panel').active, false);
|
|
});
|