dy-dashboard/tests/test_product_pagination.js
2026-10-28 11:14:17 +08:00

59 lines
2.9 KiB
JavaScript

// Run with: node tests/test_product_pagination.js
const assert = require('node:assert/strict');
const fs = require('node:fs');
const vm = require('node:vm');
const source = fs.readFileSync(process.argv[2] || 'static/js/app.js', 'utf8');
const requests = [];
const nodes = {};
for (const id of ['prodCodeName', 'prodSupplier', 'prodBrandFilter', 'prodTypeFilter',
'prodTbody', 'prodCount', 'prodPagination']) {
nodes[id] = {value: '', innerHTML: '', textContent: ''};
}
nodes.prodSupplier.value = '瑞沣';
const renderedPages = [];
const context = {
window: {}, document: {getElementById: id => nodes[id]},
PROD_COLUMNS: [], escHtml: String, inlineJsString: JSON.stringify,
renderPaginationWithSize: (el, page, total, size) => renderedPages.push({page, total, size}),
fetch: url => new Promise(resolve => requests.push({url, resolve})),
};
vm.createContext(context);
vm.runInContext(source.slice(source.indexOf('let prodCurrentPage ='),
source.indexOf('function loadProductsPage(')), context);
vm.runInContext(source.slice(source.indexOf('function loadProducts(page)'),
source.indexOf('window.searchProducts =')), context);
vm.runInContext(source.slice(source.indexOf('function loadRecycleProducts(page)'),
source.indexOf('\nwindow.', source.indexOf('function loadRecycleProducts(page)'))), context);
const tick = () => new Promise(resolve => setImmediate(resolve));
function finish(index) {
requests[index].resolve({json: () => Promise.resolve({code: 0, data: {rows: [], total: 194}})});
}
async function run() {
for (const page of [1, 2, 3, 4]) context.loadProducts(page);
for (let i = 0; i < 4; i++) {
const url = new URL(requests[i].url, 'http://localhost');
assert.equal(url.searchParams.get('supplier'), '瑞沣');
assert.equal(url.searchParams.get('page'), String(i + 1));
}
finish(3); await tick();
for (const i of [2, 1, 0]) { finish(i); await tick(); }
assert.deepEqual(renderedPages.map(x => x.page), [4], 'Older responses must not change the last requested page');
// A pending normal-list response cannot overwrite the recycle tab.
context.loadProducts(2);
vm.runInContext("prodActiveTab = '回收站'", context);
context.loadProducts(1);
finish(5); await tick();
finish(4); await tick();
assert.deepEqual(renderedPages.map(x => x.page), [4, 1]);
// A pending response must not render into a newly mounted products page.
context.loadProducts(1);
nodes.prodTbody = {innerHTML: 'new page'};
finish(6); await tick();
assert.equal(nodes.prodTbody.innerHTML, 'new page');
assert.equal(renderedPages.length, 2);
console.log('Product pagination: reverse response order, supplier filter, tab switch and page remount passed');
}
run().catch(error => { console.error(error); process.exitCode = 1; });