feat: 完善淘宝小程序拍照、报告与登录流程
接入本地实时识别和自动三连拍,调整报告裁切、商品跳转、分享标题及居中页眉;完善游客会话、后台渠道隔离、部署脚本与回归测试。
This commit is contained in:
@@ -23,6 +23,59 @@ function page(file, deps = {}, extra = {}) {
|
||||
return { instance, timers, context };
|
||||
}
|
||||
const flush = () => new Promise(resolve => setImmediate(resolve));
|
||||
test('cold launch resets session without loading or creating a native audio context', () => {
|
||||
let app, resets = 0, restores = 0;
|
||||
vm.runInNewContext(fs.readFileSync(path.join(base, 'app.js'), 'utf8'), {
|
||||
App(value) { app = value; },
|
||||
require(name) {
|
||||
assert.equal(name, './utils/api.js', 'startup must not load the voice module');
|
||||
return { resetForLaunch() { resets++; }, hasSession: () => false, restore() { restores++; } };
|
||||
}
|
||||
});
|
||||
app.onLaunch(); app.onShow();
|
||||
assert.equal(resets, 1); assert.equal(restores, 0);
|
||||
});
|
||||
|
||||
test('global app share uses the login header title and a public entry without report or session parameters', () => {
|
||||
let app;
|
||||
vm.runInNewContext(fs.readFileSync(path.join(base, 'app.js'), 'utf8'), {
|
||||
App(value) { app = value; }, require(name) { return require(path.resolve(base, name)); }
|
||||
});
|
||||
const shared = app.onShareAppMessage();
|
||||
const title = require('../utils/page-header').layout().title;
|
||||
assert.equal(shared.title, title);
|
||||
assert.equal(shared.desc, title);
|
||||
assert.equal(shared.path, 'pages/login/login');
|
||||
assert.deepEqual(Object.keys(shared).sort(), ['desc', 'path', 'title']);
|
||||
});
|
||||
|
||||
test('every registered business page explicitly shares the apostrophe title and public login entry', () => {
|
||||
const routes = JSON.parse(fs.readFileSync(path.join(base, 'app.json'), 'utf8')).pages;
|
||||
const title = require('../utils/page-header').layout().title;
|
||||
for (const route of routes) {
|
||||
const p = page(route + '.js', { '../../utils/api': { assetUrl: value => value } }).instance;
|
||||
p.data.profile = { name: 'private-profile' }; p.data.payload = { report: 'private-report' };
|
||||
const result = p.onShareAppMessage({ from: 'menu' });
|
||||
assert.equal(result.title, title, route); assert.equal(result.desc, title, route);
|
||||
assert.equal(result.path, 'pages/login/login', route);
|
||||
assert.deepEqual(Object.keys(result).sort(), ['desc', 'path', 'title']);
|
||||
result.title = 'changed'; assert.equal(p.onShareAppMessage().title, title, 'each share returns a fresh object');
|
||||
}
|
||||
});
|
||||
|
||||
test('login first-screen images are packaged original H5 assets with no remote URL dependency', () => {
|
||||
const p = page('pages/login/login.js', { '../../utils/api': {} }).instance;
|
||||
let total = 0;
|
||||
for (const key of ['bgUrl', 'brandUrl', 'guestIconUrl']) {
|
||||
assert.match(p.data[key], /^\.\.\/\.\.\/assets\/startup\//);
|
||||
const local = path.resolve(base, 'pages/login', p.data[key]);
|
||||
const original = path.join(base, '../h5/assets/img/ui-20261009', path.basename(local));
|
||||
const bytes = fs.readFileSync(local); total += bytes.length;
|
||||
assert.deepEqual(bytes, fs.readFileSync(original), 'visual assets remain byte-for-byte identical');
|
||||
}
|
||||
assert(total < 140 * 1024);
|
||||
});
|
||||
|
||||
test('offline camera debug skips identity/profile, never uploads or plays remote voice, and clears previews on exit', async () => {
|
||||
let backendCalls = 0, voiceCalls = 0, exited = 0, authReads = 0;
|
||||
const voice = { play() { voiceCalls++; }, stop() {}, VOICE: { step: [] } };
|
||||
@@ -133,6 +186,35 @@ test('province changes reset cities, canceled choices do not leak into reopening
|
||||
p.setData({ birth: '1996-01', age: 30, birthText: '1996年1月', genderText: '女' });
|
||||
p.onStartCamera(); assert.equal(saved.key, 'juzi.taobao.profile.account-a'); assert.equal(app.globalData.profile.real_age, 30);
|
||||
});
|
||||
test('gender wheel saves only on confirmation and canceled drafts never replace the committed value', () => {
|
||||
const api = { assetUrl: v => v, user: () => ({ id: 'guest-a', kind: 'taobao_guest' }) };
|
||||
const p = page('pages/profile/profile.js', { '../../utils/api.js': api }).instance;
|
||||
p.onLoad();
|
||||
p.onOpenGender();
|
||||
assert.equal(p.data.pickerTitle, '性别'); assert.equal(p.data.picker, 'gender');
|
||||
assert.deepEqual(Array.from(p.data.pickerValue), [0]);
|
||||
p.onPickerClose(); assert.equal(p.data.genderText, '', 'cancel does not implicitly choose the first option');
|
||||
p.onOpenGender(); p.onPickerChange({ detail: { value: [1] } });
|
||||
assert.equal(p.data.genderText, '', 'scrolling changes only the draft');
|
||||
p.onPickerConfirm(); assert.equal(p.data.genderText, '男'); assert.equal(p.data.picker, '');
|
||||
p.onOpenGender(); assert.deepEqual(Array.from(p.data.pickerValue), [1]);
|
||||
p.onPickerChange({ detail: { value: [0] } }); p.onPickerClose();
|
||||
assert.equal(p.data.genderText, '男');
|
||||
p.onOpenGender(); assert.deepEqual(Array.from(p.data.pickerValue), [1]);
|
||||
p.onPickerChange({ detail: { value: [0] } }); p.onPickerConfirm();
|
||||
assert.equal(p.data.genderText, '女');
|
||||
});
|
||||
|
||||
test('restored gender initializes the wheel and confirmation leaves birth and region intact', () => {
|
||||
const api = { assetUrl: v => v, user: () => ({ id: 'account-a' }) };
|
||||
const p = page('pages/profile/profile.js', { '../../utils/api.js': api }, {
|
||||
my: { getStorageSync: () => ({ data: { birth: '1996-01', genderText: '男', regionText: '北京' } }) }
|
||||
}).instance;
|
||||
p.onLoad(); p.onOpenGender(); assert.deepEqual(Array.from(p.data.pickerValue), [1]);
|
||||
p.onPickerChange({ detail: { value: [0] } }); p.onPickerConfirm();
|
||||
assert.equal(p.data.genderText, '女'); assert.equal(p.data.birth, '1996-01'); assert.equal(p.data.regionText, '北京');
|
||||
});
|
||||
|
||||
test('native AXML event handlers resolve and all routes have JS/AXML/ACSS/JSON files', () => {
|
||||
const pages = require('../app.json').pages;
|
||||
for (const route of pages) {
|
||||
|
||||
Reference in New Issue
Block a user