Files
lucky_shop/tests/mp-share-default.test.js
ZF sun cb5878ad29 test: add unit test for mp-share-default module
complete all test cases for the disabled pages share logic, including blacklist check, route judgment, share api behavior and network call control
2026-07-15 09:02:54 +08:00

254 lines
8.4 KiB
JavaScript

/**
* mp-share-default.js 单元测试
*
* 测试重点:
* - _DISABLED_PAGES 黑名单机制
* - _isCurrentPageDisabled 正确判断 route
* - 命中禁用列表时,mixin 的 onShareAppMessage / onShareTimeline 返回 undefined
* - 命中禁用列表时,mixin 的 onLoad / onShow 不再调网络
* - 命中禁用列表时,会调 wx.hideShareMenu
*
* 跟 util.test.js 同样的策略:
* 因为源模块里 import 了 ./http.js,直接 require 会失败,所以把"被测逻辑"
* 复制一份到本测试文件(顶部"被测源码区块"),与原文件保持同步。
* _hideShareMenu / _isCurrentPageDisabled / mixin 主体 都拿到这里跑。
*
* 运行:
* node --test tests/mp-share-default.test.js
*/
'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
// =============================================================
// 被测源码区块(与 common/js/mp-share-default.js 保持同步)
// =============================================================
function _safeGetCurrentPage() {
try {
const pages = typeof getCurrentPages === 'function' ? getCurrentPages() : [];
return pages.length > 0 ? pages[pages.length - 1] : null;
} catch (e) {
return null;
}
}
const _DISABLED_PAGES = new Set([
'pages_tool/webview/webview', // webview 容器,转发无意义
]);
function _isCurrentPageDisabled() {
const page = _safeGetCurrentPage();
if (!page) return false;
const route = (page.route || (page.$page && page.$page.path) || '').replace(/^\//, '');
return _DISABLED_PAGES.has(route);
}
// 模拟 wx 收集器(测试用)
let _wxCalls = [];
function resetWx() { _wxCalls = []; }
function _hideShareMenu() {
try {
if (typeof globalThis.__wx !== 'undefined' && typeof globalThis.__wx.hideShareMenu === 'function') {
globalThis.__wx.hideShareMenu({ menus: ['shareAppMessage', 'shareTimeline'] });
}
} catch (e) {
try {
if (typeof globalThis.__wx !== 'undefined' && typeof globalThis.__wx.hideShareMenu === 'function') {
globalThis.__wx.hideShareMenu();
}
} catch (e2) { /* ignore */ }
}
}
// mixin 主体(简化版,只测 _isCurrentPageDisabled / _hideShareMenu 触发逻辑)
function createMixinHandlers() {
return {
onLoad(opts) {
this.__opts = opts;
if (_isCurrentPageDisabled()) {
_hideShareMenu();
return;
}
this.__networkCalled = true;
},
onShow() {
if (this.__mpShareCache) return;
if (_isCurrentPageDisabled()) return;
this.__networkCalled = true;
},
onShareAppMessage() {
if (_isCurrentPageDisabled()) return undefined;
return { title: 'shared', path: '/x' };
},
onShareTimeline() {
if (_isCurrentPageDisabled()) return undefined;
return { title: 'shared', query: 'a=1' };
}
};
}
// =============================================================
// 工具:把全局 getCurrentPages / wx mock 起来
// =============================================================
function setCurrentRoute(route) {
globalThis.getCurrentPages = function () {
return route === null ? [] : [{ route }];
};
}
function setWxMock(mockImpl) {
resetWx();
globalThis.__wx = {
hideShareMenu(opts) {
_wxCalls.push({ method: 'hideShareMenu', opts });
if (mockImpl && mockImpl.throwWithMenus) throw new Error('not supported');
}
};
}
function clearGlobals() {
delete globalThis.getCurrentPages;
delete globalThis.__wx;
resetWx();
}
// =============================================================
// _DISABLED_PAGES 内容
// =============================================================
test('黑名单包含 webview 页面', () => {
assert.ok(_DISABLED_PAGES.has('pages_tool/webview/webview'));
});
test('黑名单不包含普通商品详情页', () => {
assert.ok(!_DISABLED_PAGES.has('pages_goods/detail'));
assert.ok(!_DISABLED_PAGES.has('pages/index/index'));
});
// =============================================================
// _isCurrentPageDisabled 行为
// =============================================================
test('_isCurrentPageDisabled: 当前页是 webview 时返回 true', () => {
setCurrentRoute('pages_tool/webview/webview');
assert.equal(_isCurrentPageDisabled(), true);
});
test('_isCurrentPageDisabled: 当前页是其他页时返回 false', () => {
setCurrentRoute('pages_goods/detail');
assert.equal(_isCurrentPageDisabled(), false);
});
test('_isCurrentPageDisabled: 当前页带前导 / 时也认得', () => {
// mp-weixin 的 page.route 不带 /,但容错一下
setCurrentRoute('/pages_tool/webview/webview');
assert.equal(_isCurrentPageDisabled(), true);
});
test('_isCurrentPageDisabled: getCurrentPages 返回空时不报错', () => {
setCurrentRoute(null);
assert.equal(_isCurrentPageDisabled(), false);
});
test('_isCurrentPageDisabled: getCurrentPages 不存在时不报错', () => {
delete globalThis.getCurrentPages;
assert.equal(_isCurrentPageDisabled(), false);
});
// =============================================================
// mixin 主体:命中禁用列表时的行为
// =============================================================
test('mixin: 命中禁用列表时 onLoad 调 wx.hideShareMenu', () => {
clearGlobals();
setCurrentRoute('pages_tool/webview/webview');
setWxMock();
const m = createMixinHandlers();
m.onLoad.call({});
assert.equal(_wxCalls.length, 1, '应该调了一次 hideShareMenu');
assert.equal(_wxCalls[0].method, 'hideShareMenu');
assert.deepEqual(_wxCalls[0].opts, { menus: ['shareAppMessage', 'shareTimeline'] });
});
test('mixin: 命中禁用列表时 onLoad 不调网络', () => {
clearGlobals();
setCurrentRoute('pages_tool/webview/webview');
setWxMock();
const ctx = {};
createMixinHandlers().onLoad.call(ctx);
assert.equal(ctx.__networkCalled, undefined, '不应触发网络拉取');
});
test('mixin: 非命中页面 onLoad 调网络(且不调 hideShareMenu)', () => {
clearGlobals();
setCurrentRoute('pages_goods/detail');
setWxMock();
const ctx = {};
createMixinHandlers().onLoad.call(ctx);
assert.equal(ctx.__networkCalled, true, '应触发网络拉取');
assert.equal(_wxCalls.length, 0, '不应调 hideShareMenu');
});
test('mixin: 命中禁用列表时 onShow 不调网络', () => {
clearGlobals();
setCurrentRoute('pages_tool/webview/webview');
setWxMock();
const ctx = { __mpShareCache: null };
createMixinHandlers().onShow.call(ctx);
assert.equal(ctx.__networkCalled, undefined);
});
test('mixin: 命中禁用列表时 onShareAppMessage 返回 undefined', () => {
setCurrentRoute('pages_tool/webview/webview');
const m = createMixinHandlers();
const r = m.onShareAppMessage.call({});
assert.equal(r, undefined);
});
test('mixin: 命中禁用列表时 onShareTimeline 返回 undefined', () => {
setCurrentRoute('pages_tool/webview/webview');
const m = createMixinHandlers();
const r = m.onShareTimeline.call({});
assert.equal(r, undefined);
});
test('mixin: 非命中页面 onShareAppMessage 返回正常分享对象', () => {
setCurrentRoute('pages_goods/detail');
const m = createMixinHandlers();
const r = m.onShareAppMessage.call({});
assert.deepEqual(r, { title: 'shared', path: '/x' });
});
// =============================================================
// wx.hideShareMenu 失败时的降级
// =============================================================
test('_hideShareMenu: wx.hideShareMenu 不存在时静默', () => {
clearGlobals();
// 不设置 globalThis.__wx
assert.doesNotThrow(() => _hideShareMenu());
});
test('_hideShareMenu: menus 参数不支持时降级到无参', () => {
clearGlobals();
let secondCall = null;
globalThis.__wx = {
hideShareMenu(opts) {
if (opts && opts.menus) {
throw new Error('not supported');
}
secondCall = opts;
}
};
_hideShareMenu();
assert.equal(secondCall, undefined, '应降级到无参调用');
});
// =============================================================
// 清理
// =============================================================
test.afterEach(() => {
clearGlobals();
});