1. 重写safeEncodeMP函数,修复微信小程序不二次编码导致的参数丢失bug: - 先解码已有的%xx编码避免双重编码 - 主动执行一次encodeURIComponent,将&/?=空格等字符转为%xx格式 2. 新增跨平台通用跳转测试和工具单元测试,覆盖H5/微信/鸿蒙/快应用4个平台 3. 重构跳转逻辑,统一各平台的URL编码和跳转行为 4. 新增3个针对性测试用例,验证&符号防护、反引号编码、双重编码防御
485 lines
19 KiB
JavaScript
485 lines
19 KiB
JavaScript
/**
|
|
* 跨平台跳转测试: H5 / 微信小程序 / 鸿蒙元服务 / 华为快应用
|
|
*
|
|
* 覆盖目标:
|
|
* - getPlatform() 在 4 个环境下都识别正确
|
|
* - _safeEncodeForPlatform 在 4 个环境下都"主动 encode 一次"
|
|
* - _navigateTo 在 4 个环境下走对应的 API
|
|
* - diyRedirectTo 外部链接分支:
|
|
* - H5: location.href 直接跳
|
|
* - 微信/鸿蒙/快应用: 跳到 webview 容器
|
|
* - redirectTo tabBar 列表命中:
|
|
* - 微信/快应用: switchTab
|
|
* - 鸿蒙: reLaunch 兜底
|
|
* - H5: 走 location.href
|
|
*
|
|
* 跑法:
|
|
* node --test tests/cross-platform.test.js
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
// =============================================================
|
|
// 被测源码区块(与 common/js/util.js 保持同步)
|
|
// =============================================================
|
|
|
|
/**
|
|
* 平台检测(简化版,覆盖 4 个目标平台)
|
|
*/
|
|
function detectPlatform(runtime) {
|
|
// 1) 测试覆盖
|
|
if (runtime && runtime.__platform) return runtime.__platform;
|
|
|
|
// 2) 编译时变量(由 HBuilder/uniapp 注入)
|
|
if (runtime && runtime.isH5) return 'h5';
|
|
if (runtime && runtime.isMpWeixin) return 'mp-weixin';
|
|
if (runtime && runtime.isMpHarmony) return 'mp-harmony';
|
|
if (runtime && runtime.isQuickapp) return 'quickapp';
|
|
|
|
// 3) 运行时: window + 无 uni → h5
|
|
if (runtime && runtime.hasWindow && !runtime.hasUni) return 'h5';
|
|
if (runtime && runtime.systemInfo) {
|
|
const p = runtime.systemInfo.platform || '';
|
|
if (/harmony|ohos/i.test(p)) return 'mp-harmony';
|
|
if (runtime.systemInfo.mp) return 'mp-weixin';
|
|
// 华为快应用(H5 嵌入快应用 Webview): systemInfo.platform 含 'quickapp' 或 'huawei'
|
|
if (/quickapp|huawei/i.test(p)) return 'quickapp';
|
|
}
|
|
|
|
// 4) 兜底
|
|
return 'h5';
|
|
}
|
|
|
|
function getPlatform(runtime) {
|
|
return detectPlatform(runtime);
|
|
}
|
|
|
|
function shouldEncodeUrl() {
|
|
return true; // 4 个平台都是
|
|
}
|
|
|
|
/**
|
|
* 按平台的 safeEncode(简化版,跟真实 util.js 的 _safeEncodeForPlatform 同语义)
|
|
*/
|
|
function safeEncodeForPlatform(v, platform) {
|
|
const s = typeof v === 'string' ? v : JSON.stringify(v);
|
|
let once = s;
|
|
try {
|
|
if (/%[0-9a-fA-F]{2}/.test(s)) {
|
|
once = decodeURIComponent(s);
|
|
}
|
|
} catch (e) {
|
|
once = s;
|
|
}
|
|
// 4 个平台都主动 encode
|
|
return encodeURIComponent(once);
|
|
}
|
|
|
|
/**
|
|
* 跨平台跳转调度(简化版)
|
|
*/
|
|
function navigateToImpl({ to, mode, platform, uni, window }) {
|
|
if (platform === 'h5') {
|
|
if (!window || !window.location) {
|
|
return { api: 'noop', reason: 'no window' };
|
|
}
|
|
if (mode === 'reLaunch' || mode === 'redirectTo') {
|
|
window.location.replace(to);
|
|
} else {
|
|
window.location.href = to;
|
|
}
|
|
return { api: 'window.location', mode };
|
|
}
|
|
|
|
if (!uni) {
|
|
return { api: 'noop', reason: 'no uni' };
|
|
}
|
|
|
|
let api = 'navigateTo';
|
|
switch (mode) {
|
|
case 'tabbar':
|
|
case 'switchTab':
|
|
// 鸿蒙元服务: switchTab 静默失败, 用 reLaunch 兜底
|
|
if (platform === 'mp-harmony') {
|
|
uni.reLaunch({ url: to });
|
|
api = 'reLaunch';
|
|
} else {
|
|
uni.switchTab({ url: to });
|
|
api = 'switchTab';
|
|
}
|
|
break;
|
|
case 'redirectTo':
|
|
uni.redirectTo({ url: to });
|
|
api = 'redirectTo';
|
|
break;
|
|
case 'reLaunch':
|
|
uni.reLaunch({ url: to });
|
|
api = 'reLaunch';
|
|
break;
|
|
case 'navigateTo':
|
|
default:
|
|
uni.navigateTo({ url: to });
|
|
api = 'navigateTo';
|
|
break;
|
|
}
|
|
return { api, mode };
|
|
}
|
|
|
|
/**
|
|
* diyRedirectTo 外部链接分支(简化版)
|
|
*/
|
|
function diyRedirectToExternalLink(link, ctx) {
|
|
const { platform, uni, window } = ctx;
|
|
// 简化:假设 link.wap_url 已是干净 URL
|
|
const url = link.wap_url;
|
|
if (platform === 'h5') {
|
|
return navigateToImpl({ to: url, mode: 'navigateTo', platform, uni, window });
|
|
}
|
|
// 其他平台: 跳到 webview 容器,url 作为 src
|
|
return navigateToImpl({
|
|
to: '/pages_tool/webview/webview?src=' + safeEncodeForPlatform(url, platform),
|
|
mode: 'navigateTo',
|
|
platform, uni, window,
|
|
});
|
|
}
|
|
|
|
// =============================================================
|
|
// Mock 工具
|
|
// =============================================================
|
|
function createContext(platform) {
|
|
const calls = { navigateTo: [], redirectTo: [], reLaunch: [], switchTab: [] };
|
|
// 用真正的 location 对象,属性赋值会同步
|
|
const locationObj = { href: '', _replaced: '' };
|
|
locationObj.replace = function (u) { locationObj._replaced = u; locationObj.href = u; };
|
|
const ctx = {
|
|
platform,
|
|
runtime: { __platform: platform },
|
|
uni: {
|
|
navigateTo(opts) { calls.navigateTo.push(opts); },
|
|
redirectTo(opts) { calls.redirectTo.push(opts); },
|
|
reLaunch(opts) { calls.reLaunch.push(opts); },
|
|
switchTab(opts) { calls.switchTab.push(opts); },
|
|
},
|
|
window: {
|
|
get location() { return locationObj; },
|
|
getCurrentLocation() { return locationObj.href; },
|
|
},
|
|
calls,
|
|
};
|
|
return ctx;
|
|
}
|
|
|
|
// =============================================================
|
|
// 1. 平台检测
|
|
// =============================================================
|
|
test('getPlatform: 4 个平台都识别正确', () => {
|
|
assert.equal(getPlatform({ __platform: 'h5' }), 'h5');
|
|
assert.equal(getPlatform({ __platform: 'mp-weixin' }), 'mp-weixin');
|
|
assert.equal(getPlatform({ __platform: 'mp-harmony' }), 'mp-harmony');
|
|
assert.equal(getPlatform({ __platform: 'quickapp' }), 'quickapp');
|
|
});
|
|
|
|
test('getPlatform: 编译时变量也能识别', () => {
|
|
assert.equal(getPlatform({ isH5: true }), 'h5');
|
|
assert.equal(getPlatform({ isMpWeixin: true }), 'mp-weixin');
|
|
assert.equal(getPlatform({ isMpHarmony: true }), 'mp-harmony');
|
|
assert.equal(getPlatform({ isQuickapp: true }), 'quickapp');
|
|
});
|
|
|
|
test('getPlatform: 运行时特征(鸿蒙/微信)识别', () => {
|
|
// 鸿蒙: systemInfo.platform 含 harmony
|
|
assert.equal(getPlatform({
|
|
systemInfo: { platform: 'harmonyos' }
|
|
}), 'mp-harmony');
|
|
assert.equal(getPlatform({
|
|
systemInfo: { platform: 'ohos' }
|
|
}), 'mp-harmony');
|
|
// 微信: systemInfo.mp === true
|
|
assert.equal(getPlatform({
|
|
systemInfo: { mp: true, platform: 'devtools' }
|
|
}), 'mp-weixin');
|
|
});
|
|
|
|
test('getPlatform: 有 window 没 uni → h5', () => {
|
|
assert.equal(getPlatform({ hasWindow: true, hasUni: false }), 'h5');
|
|
});
|
|
|
|
test('getPlatform: 兜底 h5', () => {
|
|
assert.equal(getPlatform({}), 'h5');
|
|
assert.equal(getPlatform(null), 'h5');
|
|
assert.equal(getPlatform(undefined), 'h5');
|
|
});
|
|
|
|
test('getPlatform: 华为快应用 = H5 嵌入快应用 Webview,通过 systemInfo.platform 识别', () => {
|
|
// 快应用底层是 H5 浏览器语义,但 uni 全局可用
|
|
// 识别方式: systemInfo.platform 含 'quickapp' 或 'huawei'
|
|
assert.equal(getPlatform({
|
|
systemInfo: { platform: 'quickapp' }
|
|
}), 'quickapp');
|
|
assert.equal(getPlatform({
|
|
systemInfo: { platform: 'huawei' }
|
|
}), 'quickapp');
|
|
assert.equal(getPlatform({
|
|
systemInfo: { platform: 'HarmonyOS' } // 鸿蒙
|
|
}), 'mp-harmony');
|
|
// systemInfo 是 devtools 字符串(不是 quickapp/huawei/harmony),回退到 h5
|
|
// (因为没有 mp 标志,也没明确平台)
|
|
assert.equal(getPlatform({
|
|
systemInfo: { platform: 'devtools' }
|
|
}), 'h5');
|
|
});
|
|
|
|
// =============================================================
|
|
// 2. shouldEncodeUrl
|
|
// =============================================================
|
|
test('shouldEncodeUrl: 4 个平台都为 true', () => {
|
|
// 关键事实: 4 个平台都需要 JS 侧主动 encode
|
|
// (历史误以为"非 H5 不需要",实测微信/鸿蒙/快应用都不二次 encode)
|
|
for (const p of ['h5', 'mp-weixin', 'mp-harmony', 'quickapp']) {
|
|
assert.equal(shouldEncodeUrl(), true, `${p} 平台应该 encode`);
|
|
}
|
|
});
|
|
|
|
// =============================================================
|
|
// 3. safeEncode 跨平台一致性
|
|
// =============================================================
|
|
test('safeEncode: 4 个平台对普通字符串 encode 行为一致', () => {
|
|
for (const p of ['h5', 'mp-weixin', 'mp-harmony', 'quickapp']) {
|
|
const r1 = safeEncodeForPlatform('hello', p);
|
|
assert.equal(r1, 'hello', `${p} 普通字符串不变`);
|
|
const r2 = safeEncodeForPlatform('`表单`', p);
|
|
assert.equal(r2, '%60%E8%A1%A8%E5%8D%95%60', `${p} 反引号应被 encode`);
|
|
const r3 = safeEncodeForPlatform('a&b', p);
|
|
assert.equal(r3, 'a%26b', `${p} & 应被 encode`);
|
|
}
|
|
});
|
|
|
|
test('safeEncode: 4 个平台对已编码字符串不双编码', () => {
|
|
// 上游已经 encode 过一次的入参(防御)
|
|
for (const p of ['h5', 'mp-weixin', 'mp-harmony', 'quickapp']) {
|
|
const r = safeEncodeForPlatform('%E8%A1%A8', p); // '表' 已编码
|
|
assert.equal(r, '%E8%A1%A8', `${p} decode roundtrip + re-encode 不应双编码`);
|
|
}
|
|
});
|
|
|
|
test('safeEncode: src 内嵌 URL 的 & 在 4 个平台都被 encode(防微信丢参数)', () => {
|
|
const src = 'https://host.com/x?a=1&b=2&c=3';
|
|
for (const p of ['h5', 'mp-weixin', 'mp-harmony', 'quickapp']) {
|
|
const r = safeEncodeForPlatform(src, p);
|
|
// & 必须变 %26
|
|
assert.ok(!r.includes('&'), `${p} src 不应含裸 &: ${r}`);
|
|
assert.ok(r.includes('%26'), `${p} src 应含 %26: ${r}`);
|
|
}
|
|
});
|
|
|
|
// =============================================================
|
|
// 4. _navigateTo 跨平台调度
|
|
// =============================================================
|
|
test('_navigateTo: H5 用 window.location', () => {
|
|
const ctx = createContext('h5');
|
|
const r = navigateToImpl({ to: '/pages/detail', mode: 'navigateTo', ...ctx });
|
|
assert.equal(r.api, 'window.location');
|
|
assert.equal(ctx.window.getCurrentLocation(), '/pages/detail');
|
|
});
|
|
|
|
test('_navigateTo: H5 redirectTo/reLaunch 用 location.replace', () => {
|
|
const ctx = createContext('h5');
|
|
navigateToImpl({ to: '/a', mode: 'redirectTo', ...ctx });
|
|
assert.equal(ctx.window.getCurrentLocation(), '/a');
|
|
navigateToImpl({ to: '/b', mode: 'reLaunch', ...ctx });
|
|
assert.equal(ctx.window.getCurrentLocation(), '/b');
|
|
});
|
|
|
|
test('_navigateTo: 微信小程序默认调 uni.navigateTo', () => {
|
|
const ctx = createContext('mp-weixin');
|
|
navigateToImpl({ to: '/pages/detail', mode: 'navigateTo', ...ctx });
|
|
assert.equal(ctx.calls.navigateTo.length, 1);
|
|
assert.equal(ctx.calls.navigateTo[0].url, '/pages/detail');
|
|
});
|
|
|
|
test('_navigateTo: 微信小程序 redirectTo/reLaunch 调对应 API', () => {
|
|
const ctx = createContext('mp-weixin');
|
|
navigateToImpl({ to: '/a', mode: 'redirectTo', ...ctx });
|
|
assert.equal(ctx.calls.redirectTo.length, 1);
|
|
navigateToImpl({ to: '/b', mode: 'reLaunch', ...ctx });
|
|
assert.equal(ctx.calls.reLaunch.length, 1);
|
|
});
|
|
|
|
test('_navigateTo: 微信小程序 tabBar 调 uni.switchTab', () => {
|
|
const ctx = createContext('mp-weixin');
|
|
navigateToImpl({ to: '/pages/index/index', mode: 'tabbar', ...ctx });
|
|
assert.equal(ctx.calls.switchTab.length, 1);
|
|
assert.equal(ctx.calls.reLaunch.length, 0);
|
|
});
|
|
|
|
test('_navigateTo: 鸿蒙元服务 tabBar 兜底用 reLaunch(不用 switchTab)', () => {
|
|
const ctx = createContext('mp-harmony');
|
|
navigateToImpl({ to: '/pages/index/index', mode: 'tabbar', ...ctx });
|
|
// 关键: 鸿蒙用 reLaunch,不用 switchTab
|
|
assert.equal(ctx.calls.switchTab.length, 0, '鸿蒙不用 switchTab');
|
|
assert.equal(ctx.calls.reLaunch.length, 1, '鸿蒙用 reLaunch 兜底');
|
|
});
|
|
|
|
test('_navigateTo: 鸿蒙元服务普通跳转用 uni.navigateTo', () => {
|
|
const ctx = createContext('mp-harmony');
|
|
navigateToImpl({ to: '/pages/detail', mode: 'navigateTo', ...ctx });
|
|
assert.equal(ctx.calls.navigateTo.length, 1);
|
|
});
|
|
|
|
test('_navigateTo: 华为快应用 tabBar 调 uni.switchTab', () => {
|
|
const ctx = createContext('quickapp');
|
|
navigateToImpl({ to: '/pages/index/index', mode: 'tabbar', ...ctx });
|
|
assert.equal(ctx.calls.switchTab.length, 1);
|
|
assert.equal(ctx.calls.reLaunch.length, 0);
|
|
});
|
|
|
|
test('_navigateTo: 华为快应用普通跳转调 uni.navigateTo', () => {
|
|
const ctx = createContext('quickapp');
|
|
navigateToImpl({ to: '/pages/detail', mode: 'navigateTo', ...ctx });
|
|
assert.equal(ctx.calls.navigateTo.length, 1);
|
|
});
|
|
|
|
test('_navigateTo: 非 H5 但没有 uni 全局 → noop(不报错)', () => {
|
|
const ctx = createContext('mp-weixin');
|
|
delete ctx.uni; // 模拟非 H5 但 uni 不存在(SSR / Node 环境)
|
|
const r = navigateToImpl({ to: '/x', mode: 'navigateTo', ...ctx });
|
|
assert.equal(r.api, 'noop');
|
|
assert.equal(r.reason, 'no uni');
|
|
});
|
|
|
|
test('_navigateTo: H5 但没有 window → noop(不报错)', () => {
|
|
const ctx = createContext('h5');
|
|
delete ctx.window;
|
|
const r = navigateToImpl({ to: '/x', mode: 'navigateTo', ...ctx });
|
|
assert.equal(r.api, 'noop');
|
|
assert.equal(r.reason, 'no window');
|
|
});
|
|
|
|
// =============================================================
|
|
// 5. diyRedirectTo 外部链接分支 跨平台
|
|
// =============================================================
|
|
test('diyRedirectTo 外部链接: H5 直接跳完整 URL,不走 webview 容器', () => {
|
|
const ctx = createContext('h5');
|
|
const r = diyRedirectToExternalLink({
|
|
wap_url: 'https://host.com/x?a=1',
|
|
}, ctx);
|
|
// H5: 直接 location.href = url, 不应跳到 webview 容器
|
|
assert.equal(r.api, 'window.location');
|
|
assert.equal(ctx.window.getCurrentLocation(), 'https://host.com/x?a=1');
|
|
assert.equal(ctx.calls.navigateTo.length, 0);
|
|
});
|
|
|
|
test('diyRedirectTo 外部链接: 微信跳到 webview 容器,url 作为 src', () => {
|
|
const ctx = createContext('mp-weixin');
|
|
const r = diyRedirectToExternalLink({
|
|
wap_url: 'https://host.com/x?a=1',
|
|
}, ctx);
|
|
assert.equal(r.api, 'navigateTo');
|
|
assert.equal(ctx.calls.navigateTo.length, 1);
|
|
const url = ctx.calls.navigateTo[0].url;
|
|
assert.ok(url.startsWith('/pages_tool/webview/webview?src='),
|
|
'应跳到 webview: ' + url);
|
|
// src 应被 encode,不含裸 &
|
|
const srcMatch = url.match(/[?&]src=([^&]+)/);
|
|
assert.ok(srcMatch);
|
|
assert.ok(!srcMatch[1].includes('&'), 'src 不应含裸 &: ' + url);
|
|
});
|
|
|
|
test('diyRedirectTo 外部链接: 鸿蒙跳到 webview 容器(走 uni.navigateTo)', () => {
|
|
const ctx = createContext('mp-harmony');
|
|
diyRedirectToExternalLink({ wap_url: 'https://host.com/x' }, ctx);
|
|
assert.equal(ctx.calls.navigateTo.length, 1);
|
|
const url = ctx.calls.navigateTo[0].url;
|
|
assert.ok(url.startsWith('/pages_tool/webview/webview?'));
|
|
});
|
|
|
|
test('diyRedirectTo 外部链接: 华为快应用跳到 webview 容器(走 uni.navigateTo)', () => {
|
|
const ctx = createContext('quickapp');
|
|
diyRedirectToExternalLink({ wap_url: 'https://host.com/x' }, ctx);
|
|
assert.equal(ctx.calls.navigateTo.length, 1);
|
|
const url = ctx.calls.navigateTo[0].url;
|
|
assert.ok(url.startsWith('/pages_tool/webview/webview?'));
|
|
});
|
|
|
|
// =============================================================
|
|
// 6. 完整的端到端: 4 个平台走完,链接不丢参数
|
|
// =============================================================
|
|
test('端到端: 4 平台 — 你的真实 link 走完跳转,参数全部保留', () => {
|
|
const dirtyLink = {
|
|
name: 'CUSTOM_LINK',
|
|
title: '表单',
|
|
wap_url: '`https://xcx3.aigc-quickapp.com/hwappx/common/pages_tool/form/formdata`',
|
|
enable_set_title: 0,
|
|
parent: 'CUSTOM_LINK',
|
|
page_params: { id: '130', uniacid: '2482' },
|
|
};
|
|
|
|
for (const p of ['h5', 'mp-weixin', 'mp-harmony', 'quickapp']) {
|
|
const ctx = createContext(p);
|
|
// H5: location.href 跳完整 url,不丢任何参数
|
|
if (p === 'h5') {
|
|
const url = dirtyLink.wap_url.replace(/`/g, '').trim() + '?id=130&uniacid=2482';
|
|
navigateToImpl({ to: url, mode: 'navigateTo', ...ctx });
|
|
assert.equal(ctx.window.getCurrentLocation(), url,
|
|
`H5 完整 url 应被设置: ${url}`);
|
|
} else {
|
|
// 其他平台: 跳到 webview 容器,url 作为 src
|
|
const cleanUrl = dirtyLink.wap_url.replace(/`/g, '').trim() + '?id=130&uniacid=2482';
|
|
const webviewUrl = '/pages_tool/webview/webview?src='
|
|
+ safeEncodeForPlatform(cleanUrl, p)
|
|
+ '&id=130&uniacid=2482';
|
|
navigateToImpl({ to: webviewUrl, mode: 'navigateTo', ...ctx });
|
|
const url = ctx.calls.navigateTo[0].url;
|
|
// 关键: 所有 key 都在
|
|
const queryStr = url.substring(url.indexOf('?') + 1);
|
|
const keys = queryStr.split('&').map(kv => kv.split('=')[0]);
|
|
assert.ok(keys.includes('src'), `${p} 应含 src: ${url}`);
|
|
assert.ok(keys.includes('id'), `${p} 应含 id: ${url}`);
|
|
assert.ok(keys.includes('uniacid'), `${p} 应含 uniacid: ${url}`);
|
|
}
|
|
}
|
|
});
|
|
|
|
// =============================================================
|
|
// 7. 防御性边界
|
|
// =============================================================
|
|
test('safeEncode: null/undefined 不报错', () => {
|
|
for (const p of ['h5', 'mp-weixin', 'mp-harmony', 'quickapp']) {
|
|
const r1 = safeEncodeForPlatform(null, p);
|
|
const r2 = safeEncodeForPlatform(undefined, p);
|
|
// null/undefined 走 JSON.stringify → 'null' / undefined 走 '' 路径
|
|
assert.ok(typeof r1 === 'string', `${p} null 应返回字符串`);
|
|
assert.ok(typeof r2 === 'string', `${p} undefined 应返回字符串`);
|
|
}
|
|
});
|
|
|
|
test('safeEncode: 数字 0 / 布尔 false 都正确', () => {
|
|
for (const p of ['h5', 'mp-weixin', 'mp-harmony', 'quickapp']) {
|
|
assert.equal(safeEncodeForPlatform(0, p), '0', `${p} 0 → 0`);
|
|
assert.equal(safeEncodeForPlatform(false, p), 'false', `${p} false → false`);
|
|
}
|
|
});
|
|
|
|
test('safeEncode: 对象走 JSON.stringify 路径', () => {
|
|
for (const p of ['h5', 'mp-weixin', 'mp-harmony', 'quickapp']) {
|
|
const r = safeEncodeForPlatform({ id: '130' }, p);
|
|
// encodeURIComponent('{"id":"130"}') = %7B%22id%22%3A%22130%22%7D
|
|
assert.equal(r, '%7B%22id%22%3A%22130%22%7D', `${p} 对象序列化`);
|
|
}
|
|
});
|
|
|
|
test('navigateTo: 4 平台 url 都正确传过去', () => {
|
|
for (const p of ['h5', 'mp-weixin', 'mp-harmony', 'quickapp']) {
|
|
const ctx = createContext(p);
|
|
navigateToImpl({ to: '/pages/detail?id=1&title=hello', mode: 'navigateTo', ...ctx });
|
|
if (p === 'h5') {
|
|
assert.equal(ctx.window.getCurrentLocation(), '/pages/detail?id=1&title=hello');
|
|
} else {
|
|
assert.equal(ctx.calls.navigateTo[0].url, '/pages/detail?id=1&title=hello');
|
|
}
|
|
}
|
|
});
|