111 lines
4.7 KiB
JavaScript
111 lines
4.7 KiB
JavaScript
/* Run with node: actual page functions in a minimal browser context. */
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const vm = require('node:vm');
|
|
const source = fs.readFileSync(path.join(__dirname, '../static/js/app.js'), 'utf8');
|
|
|
|
function functionSource(start, end) {
|
|
const offset = source.indexOf(start);
|
|
assert.ok(offset >= 0, start);
|
|
const finish = source.indexOf(end, offset);
|
|
assert.ok(finish > offset, end);
|
|
return source.slice(offset, finish);
|
|
}
|
|
|
|
function context() {
|
|
const calls = [];
|
|
const overlays = [];
|
|
const mainContent = {
|
|
querySelectorAll: () => [],
|
|
appendChild: element => { element.isConnected = true; }
|
|
};
|
|
const elements = { mainContent };
|
|
const environment = {
|
|
window: { _pageCache: {}, _pageDataCache: {}, _pageReloaders: {} },
|
|
document: {
|
|
getElementById: id => elements[id] || null,
|
|
querySelectorAll: () => [],
|
|
querySelector: () => null,
|
|
createElement: () => ({ style: {}, innerHTML: '' }),
|
|
body: { appendChild: element => overlays.push(element) }
|
|
},
|
|
domesticOrderPage: 3,
|
|
overseasOrderPage: 2,
|
|
packagingOrderPage: 4,
|
|
domesticLoadOrders: page => calls.push(['domestic', page]),
|
|
overseasLoadOrders: page => calls.push(['overseas', page]),
|
|
packagingLoadOrders: page => calls.push(['packaging', page]),
|
|
loadBackupList: reset => calls.push(['backup', reset]),
|
|
invalidateOrderColumnCache: type => calls.push(['invalidate', type]),
|
|
requestAnimationFrame: callback => callback(),
|
|
setTimeout: callback => callback(),
|
|
};
|
|
vm.createContext(environment);
|
|
vm.runInContext(functionSource('function _refreshLinkedOrderLists()', '// 防重复提交锁'), environment);
|
|
vm.runInContext(functionSource('function loadPage(page)', '// ============ SPA 导航系统'), environment);
|
|
return { environment, calls, overlays, elements };
|
|
}
|
|
|
|
// Returning to a previously visited domestic order page queries current records,
|
|
// even when the order was confirmed in another user's browser.
|
|
{
|
|
const { environment: env, calls } = context();
|
|
const cached = { style: {}, isConnected: false, querySelectorAll: () => [] };
|
|
env.window._pageCache.orders_domestic = cached;
|
|
env.loadPage('orders_domestic');
|
|
assert.equal(cached.isConnected, true);
|
|
assert.deepEqual(calls, [['invalidate', 'domestic'], ['domestic', 3]]);
|
|
}
|
|
|
|
// Confirming an order while its destination pages are detached removes their
|
|
// old containers/data, while unrelated pages remain intact.
|
|
{
|
|
const { environment: env, calls } = context();
|
|
const pages = ['orders_domestic', 'orders_overseas', 'orders_packaging', 'purchase_ready'];
|
|
pages.forEach(page => {
|
|
env.window._pageCache[page] = { isConnected: false };
|
|
env.window._pageDataCache[page] = { old: true };
|
|
});
|
|
const unrelated = { isConnected: false };
|
|
env.window._pageCache.planning = unrelated;
|
|
env._refreshLinkedOrderLists();
|
|
pages.forEach(page => {
|
|
assert.equal(env.window._pageCache[page], undefined);
|
|
assert.equal(env.window._pageDataCache[page], undefined);
|
|
});
|
|
assert.equal(env.window._pageCache.planning, unrelated);
|
|
assert.deepEqual(calls, ['domestic', 'overseas', 'packaging', 'backup'].map(type => ['invalidate', type]));
|
|
}
|
|
|
|
// A currently mounted list stays mounted and refreshes with its current page.
|
|
{
|
|
const { environment: env, elements, calls } = context();
|
|
const current = { isConnected: true };
|
|
env.window._pageCache.orders_domestic = current;
|
|
elements.domesticOrdersTbody = {};
|
|
env._refreshLinkedOrderLists();
|
|
assert.equal(env.window._pageCache.orders_domestic, current);
|
|
assert.deepEqual(calls.at(-1), ['domestic', 3]);
|
|
}
|
|
|
|
// Finished-product navigation follows the server's route and the backup link
|
|
// actually opens the backup menu rather than returning to pending orders.
|
|
for (const [route, url] of [['orders_domestic', '/orders/domestic'], ['orders_overseas', '/orders/overseas']]) {
|
|
const { environment: env, overlays } = context();
|
|
env.showConfirmRedirect(true, false, route);
|
|
const html = overlays[0].innerHTML;
|
|
assert.ok(html.includes(`href="${url}"`));
|
|
assert.ok(html.includes('href="/purchase/ready"'));
|
|
assert.ok(!html.includes('href="/purchase"'));
|
|
}
|
|
|
|
{
|
|
const { environment: env, overlays } = context();
|
|
env.showConfirmRedirect(false, true, null);
|
|
assert.ok(overlays[0].innerHTML.includes('href="/orders/packaging"'));
|
|
assert.ok(!overlays[0].innerHTML.includes('href="/orders/domestic"'));
|
|
}
|
|
|
|
console.log('Order navigation regression tests passed (6 scenarios).');
|