309 lines
11 KiB
JavaScript
309 lines
11 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import { test } from 'node:test';
|
|
import vm from 'node:vm';
|
|
import ts from 'typescript';
|
|
import * as config from '../miniprogram/papersPages/paperSheet/paperSheet.config.ts';
|
|
import { PAPER_SHEET_WORKSHEET_DEFINITIONS } from '../miniprogram/config/worksheets/papers.ts';
|
|
import * as debugPublish from '../miniprogram/utils/debugPublish.ts';
|
|
import { ApiRequestError } from '../miniprogram/services/api-transport.ts';
|
|
|
|
const route = 'papersPages/paperSheet/paperSheet';
|
|
const deferred = () => {
|
|
let resolve;
|
|
const promise = new Promise((done) => {
|
|
resolve = done;
|
|
});
|
|
return { promise, resolve };
|
|
};
|
|
|
|
/** 使用真实页面和公共分享/导出方法,仅隔离微信、网络、绘图与埋点。 */
|
|
function createPage({
|
|
getWorksheet,
|
|
favorite = async () => true,
|
|
check = async () => ({}),
|
|
} = {}) {
|
|
const toasts = [],
|
|
downloads = [],
|
|
favorites = [];
|
|
const wx = {
|
|
getAccountInfoSync: () => ({ miniProgram: { envVersion: 'release' } }),
|
|
setNavigationBarTitle() {},
|
|
showToast: (options) => toasts.push(options.title),
|
|
};
|
|
const load = (file, modules) => {
|
|
const exports = {};
|
|
const source = readFileSync(new URL(file, import.meta.url), 'utf8');
|
|
vm.runInNewContext(
|
|
ts.transpileModule(source, {
|
|
compilerOptions: {
|
|
module: ts.ModuleKind.CommonJS,
|
|
target: ts.ScriptTarget.ES2020,
|
|
},
|
|
}).outputText,
|
|
{
|
|
exports,
|
|
wx,
|
|
console,
|
|
Error,
|
|
require(id) {
|
|
assert.ok(id in modules, id);
|
|
return modules[id];
|
|
},
|
|
},
|
|
);
|
|
return exports;
|
|
};
|
|
const defaultShareConfig = {
|
|
title: '分享',
|
|
path: '/pages/index/index',
|
|
imageUrl: '',
|
|
};
|
|
const mixin = load('../miniprogram/base/pageMixin.ts', {
|
|
'../services/member-api': {},
|
|
'../services/api-request': {},
|
|
'../constants/colors': {},
|
|
'../core/draw/baseDraw': {},
|
|
'../utils/downloadPrint': {
|
|
downloadPrint: async (_canvas, options) => downloads.push(options),
|
|
},
|
|
'../utils/shareGuide': {
|
|
shouldUnlockWithAd: () => false,
|
|
shouldShowShareGuide: () => false,
|
|
},
|
|
'../utils/tracker': { default: new Proxy({}, { get: () => () => {} }) },
|
|
'../config/config': { defaultShareConfig },
|
|
'../utils/debugPublish': {
|
|
...debugPublish,
|
|
isDebugPublishEnabled: () =>
|
|
wx.getAccountInfoSync().miniProgram.envVersion === 'develop',
|
|
},
|
|
});
|
|
let options;
|
|
load('../miniprogram/papersPages/paperSheet/paperSheet.ts', {
|
|
'./draw/paperDrawService': {},
|
|
'./paperSheet.config': config,
|
|
'../../base/pageMixin': {
|
|
...mixin,
|
|
createPage(value, settings) {
|
|
options = mixin.applyPageMixin(value, settings);
|
|
},
|
|
},
|
|
'../../config/config': { defaultShareConfig },
|
|
'../../services/api-request': { ApiRequestError },
|
|
'../../services/content-api': {
|
|
getWorksheet:
|
|
getWorksheet ||
|
|
(async (id) => ({
|
|
id,
|
|
rendering: {
|
|
rendererKey: 'paper-sheet',
|
|
paperType: config.resolvePaperEntry({ id }).paperType,
|
|
},
|
|
})),
|
|
},
|
|
'../../utils/favorites': {
|
|
addFavorite: async (id) => {
|
|
favorites.push(['add', id]);
|
|
return favorite(id);
|
|
},
|
|
removeFavorite: async (id) => {
|
|
favorites.push(['remove', id]);
|
|
return favorite(id);
|
|
},
|
|
batchCheckFavorited: check,
|
|
},
|
|
});
|
|
const page = {
|
|
...options,
|
|
route,
|
|
data: structuredClone(options.data),
|
|
setData(value, callback) {
|
|
Object.assign(this.data, value);
|
|
callback?.();
|
|
},
|
|
drawService: { async draw() {} },
|
|
canvas: {},
|
|
};
|
|
return { page, toasts, downloads, favorites, wx };
|
|
}
|
|
|
|
test('十种独立条目复用绘制器,旧入口/type 分享兼容,独立 ID 不受额外 type 干扰', () => {
|
|
assert.equal(PAPER_SHEET_WORKSHEET_DEFINITIONS.length, 11);
|
|
for (const paper of config.PAPER_TYPE_OPTIONS) {
|
|
const id = config.getWorksheetIdForPaperType(paper.id);
|
|
const { entry, paperType } = config.resolvePaperEntry({
|
|
id,
|
|
type: 'unknown',
|
|
});
|
|
assert.equal(paperType, paper.id);
|
|
assert.equal(entry.rendererKey, 'paper-sheet');
|
|
assert.equal(
|
|
config.getPublishMetaByMode(id).path,
|
|
`/${route}?id=${id}`,
|
|
);
|
|
}
|
|
assert.equal(config.resolvePaperEntry({}).entry.id, 'paper-sheet');
|
|
assert.equal(
|
|
config.resolvePaperEntry({ id: 'paper-sheet', type: 'mi' }).paperType,
|
|
'mi',
|
|
);
|
|
assert.equal(
|
|
config.resolvePaperEntry({ id: 'paper-sheet', mode: 'vertical' })
|
|
.paperType,
|
|
'vertical',
|
|
);
|
|
assert.throws(() => config.resolvePaperEntry({ id: 'paper-unknown' }));
|
|
});
|
|
|
|
test('切换后页面身份、收藏、分享、发布和实际导出统计均属于当前条目', async () => {
|
|
const { page, downloads, favorites } = createPage();
|
|
await page.onLoad({ id: 'paper-mi' });
|
|
assert.equal(page.data.pageTitle, '米字格');
|
|
assert.equal(page.data.functionId, 'paper-mi');
|
|
assert.equal(page.data.selectedPaperType, 'mi');
|
|
assert.equal(page.onShareAppMessage().path, `/${route}?id=paper-mi`);
|
|
await page.onPreviewFavorite();
|
|
assert.deepEqual(favorites, [['add', 'paper-mi']]);
|
|
await page.exportToPrint();
|
|
assert.equal(downloads[0].worksheetId, 'paper-mi');
|
|
page.setData({
|
|
debugPublishVisible: true,
|
|
debugPublishMeta: page.getPublishMeta(),
|
|
});
|
|
await page.onSelectPaperType({
|
|
currentTarget: { dataset: { id: 'tian' } },
|
|
});
|
|
assert.equal(page.data.debugPublishVisible, false);
|
|
assert.equal(page.data.debugPublishMeta, null);
|
|
assert.equal(page.data.functionId, 'paper-tian');
|
|
assert.equal(page.data.isPreviewFavorite, false);
|
|
assert.equal(page.getPublishMeta().id, 'paper-tian');
|
|
assert.equal(page.onShareTimeline().query, 'id=paper-tian');
|
|
await page.onSelectPaperType({ currentTarget: { dataset: { id: 'mi' } } });
|
|
assert.equal(page.data.isPreviewFavorite, true);
|
|
await page.onPreviewFavorite();
|
|
assert.deepEqual(favorites[1], ['remove', 'paper-mi']);
|
|
await page.onLoad({ id: 'paper-sheet', type: 'vertical' });
|
|
assert.equal(
|
|
page.onShareAppMessage().path,
|
|
`/${route}?id=paper-sheet&mode=vertical`,
|
|
);
|
|
});
|
|
|
|
test('快速切换丢弃旧响应,加载期间禁止导出,未知条目/下架/配置错误不生成其他纸张', async () => {
|
|
const old = deferred();
|
|
const { page, downloads, toasts } = createPage({
|
|
getWorksheet: (id) =>
|
|
id === 'paper-mi'
|
|
? old.promise
|
|
: Promise.resolve({
|
|
rendering: {
|
|
rendererKey: 'paper-sheet',
|
|
paperType: 'tian',
|
|
},
|
|
}),
|
|
});
|
|
const first = page.onLoad({ id: 'paper-mi' });
|
|
await page.exportToPrint();
|
|
assert.equal(downloads.length, 0);
|
|
await page.onSelectPaperType({
|
|
currentTarget: { dataset: { id: 'tian' } },
|
|
});
|
|
old.resolve({ rendering: { rendererKey: 'paper-sheet', paperType: 'mi' } });
|
|
await first;
|
|
assert.equal(page.data.worksheetId, 'paper-tian');
|
|
await page.openEntry({ id: 'paper-unknown' });
|
|
assert.equal(page.data.hasContent, false);
|
|
assert.ok(toasts.length);
|
|
for (const getWorksheet of [
|
|
async () => {
|
|
throw new ApiRequestError('已下架', 404);
|
|
},
|
|
async () => ({
|
|
rendering: { rendererKey: 'paper-sheet', paperType: 'tian' },
|
|
}),
|
|
]) {
|
|
const blocked = createPage({ getWorksheet }).page;
|
|
await blocked.onLoad({ id: 'paper-mi' });
|
|
assert.equal(blocked.data.hasContent, false);
|
|
}
|
|
});
|
|
|
|
test('收藏失败不报成功,慢速查询不能覆盖新收藏,切换时收藏响应不写错条目', async () => {
|
|
const pending = deferred();
|
|
const { page, toasts } = createPage({ favorite: async () => false });
|
|
await page.onLoad({ id: 'paper-mi' });
|
|
await page.onPreviewFavorite();
|
|
assert.equal(page.data.isPreviewFavorite, false);
|
|
assert.ok(toasts.some((title) => title.includes('失败')));
|
|
const active = createPage({ check: () => pending.promise }).page;
|
|
await active.onLoad({ id: 'paper-mi' });
|
|
await active.onPreviewFavorite();
|
|
pending.resolve({ 'paper-mi': false });
|
|
await new Promise((resolve) => setImmediate(resolve));
|
|
assert.equal(active.data.isPreviewFavorite, true);
|
|
const write = deferred();
|
|
const switching = createPage({ favorite: () => write.promise }).page;
|
|
await switching.onLoad({ id: 'paper-mi' });
|
|
const saving = switching.onPreviewFavorite();
|
|
await switching.openEntry({ id: 'paper-tian' });
|
|
write.resolve(true);
|
|
await saving;
|
|
assert.equal(switching.data.isPreviewFavorite, false);
|
|
assert.equal(switching._favoritedMap['paper-mi'], true);
|
|
});
|
|
|
|
test('开发版离线预览十种已注册纸张,切换不请求公开详情,未知 ID 仍不可用', async () => {
|
|
let requests = 0;
|
|
const { page, wx, toasts } = createPage({
|
|
getWorksheet: async () => {
|
|
requests++;
|
|
throw new Error('开发预览不应请求公开详情');
|
|
},
|
|
});
|
|
wx.getAccountInfoSync = () => ({ miniProgram: { envVersion: 'develop' } });
|
|
await page.onLoad({ id: 'paper-sheet' });
|
|
for (const paper of config.PAPER_TYPE_OPTIONS) {
|
|
await page.onSelectPaperType({
|
|
currentTarget: { dataset: { id: paper.id } },
|
|
});
|
|
assert.equal(page.data.hasContent, true);
|
|
assert.equal(page.data.selectedPaperType, paper.id);
|
|
assert.equal(
|
|
page.getPublishMeta().id,
|
|
config.getWorksheetIdForPaperType(paper.id),
|
|
);
|
|
}
|
|
assert.equal(requests, 0);
|
|
assert.equal(toasts.length, 0);
|
|
await page.openEntry({ id: 'paper-unknown' });
|
|
assert.equal(page.data.hasContent, false);
|
|
assert.equal(requests, 0);
|
|
assert.equal(toasts.length, 1);
|
|
});
|
|
|
|
test('体验版与正式版均校验公开详情,404 和网络故障不能降级成本地预览', async () => {
|
|
for (const version of ['trial', 'release']) {
|
|
for (const failure of [
|
|
new ApiRequestError('未发布', 404),
|
|
new ApiRequestError('网络故障', 0),
|
|
]) {
|
|
let requests = 0;
|
|
const { page, wx } = createPage({
|
|
getWorksheet: async () => {
|
|
requests++;
|
|
throw failure;
|
|
},
|
|
});
|
|
wx.getAccountInfoSync = () => ({
|
|
miniProgram: { envVersion: version },
|
|
});
|
|
await page.onLoad({ id: 'paper-square' });
|
|
assert.equal(requests, 1);
|
|
assert.equal(page.data.hasContent, false);
|
|
assert.equal(page.data.isWorksheetReady, false);
|
|
}
|
|
}
|
|
});
|