// Pure UTS and page behavior checks; no real account, network or database. const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const vm = require('node:vm'); const ts = require(process.env.AIRZ_TYPESCRIPT_PATH || 'D:/Develop/HBuilderX/plugins/uniapp-uts-v1/node_modules/@dcloudio/uni-uts-v1/lib/typescript/lib/typescript.js'); const root = path.resolve(__dirname, '..'); class JsonObject { constructor(value = {}) { Object.assign(this, value); } getString(key) { return typeof this[key] === 'string' ? this[key] : null; } getNumber(key) { return typeof this[key] === 'number' ? this[key] : null; } getBoolean(key) { return typeof this[key] === 'boolean' ? this[key] : null; } } const json = value => Array.isArray(value) ? value.map(json) : value && typeof value === 'object' ? new JsonObject(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, json(item)]))) : value; const plain = value => JSON.parse(JSON.stringify(value)); const policy = { dailyLimit: 1, makeUpAllowed: false, consecutiveBonusEnabled: false, profileRewardEnabled: false, invitationRewardEnabled: false, expiryPolicy: 'none', levelPolicy: 'unchanged', benefitsPolicy: 'none' }; const published = { status: 'published', ruleVersion: 'points-checkin-20261019-v1', checkInReward: 10, timezone: 'Asia/Shanghai', publishedRules: policy }; const draft = { status: 'draft', ruleVersion: null, checkInReward: null, timezone: 'Asia/Shanghai', publishedRules: null }; let ruleReply = published; let signed = false; let loseResponse = false; let ledgerWrites = 0; let calls = []; let session = json({ userId: '1', token: 'synthetic-points-token' }); class ApiRequestError extends Error { constructor(message, status, errorCode) { super(message); this.status = status; this.errorCode = errorCode; } } const summary = () => ({ balance: signed ? 30 : 20, serverDate: '2026-10-19', timezone: 'Asia/Shanghai', signedToday: signed, checkInEnabled: ruleReply.status === 'published', ruleVersion: ruleReply.ruleVersion, checkInReward: ruleReply.checkInReward, balanceState: 'normal' }); const api = { ApiRequestError, getSession: () => session, requestJson: async (url, method, body) => { calls.push({ url, method, body: plain(body) }); if (url === '/points/rules') return json(ruleReply); if (url === '/points') return json(summary()); if (url === '/points/tasks') return json({ serverDate: '2026-10-19', timezone: 'Asia/Shanghai', items: [ { task: 'checkin', status: ruleReply.ruleVersion == null ? 'unavailable' : signed ? 'completed' : ruleReply.status === 'published' ? 'available' : 'unavailable', reward: ruleReply.checkInReward, ruleVersion: ruleReply.ruleVersion }, ...['profile', 'invitation'].map(task => ({ task, status: 'unavailable', reward: null, ruleVersion: null })) ] }); if (url === '/points/ledger') return json({ items: [], snapshotId: '0', nextBeforeId: null }); if (url === '/points/check-in') { const replayed = signed; if (!signed) { signed = true; ledgerWrites++; } if (loseResponse) { loseResponse = false; throw new Error('Synthetic response lost'); } return json({ ledgerId: '91', delta: 10, balanceAfter: 30, signedDate: body.expectedDate, ruleVersion: body.expectedRuleVersion, replayed }); } throw new Error('Unexpected points request: ' + url); } }; function transpile(source) { const result = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, reportDiagnostics: true }); assert.equal(result.diagnostics.filter(item => item.category === ts.DiagnosticCategory.Error).length, 0); return result.outputText; } const service = {}; vm.runInNewContext(transpile(fs.readFileSync(path.join(root, 'services/points.uts'), 'utf8')), { exports: service, UTSJSONObject: JsonObject, Date, Math, Number, Error, require: name => { assert.equal(name, '@/services/api.uts'); return api; } }); function page() { let shown; let share; const storage = new Map(); const modals = [], toasts = []; const source = fs.readFileSync(path.join(root, 'packages/account/points/points.uvue'), 'utf8').match(/