Files
device-voice-h5/tests/package-history.test.mjs
2026-10-14 11:18:29 +08:00

83 lines
3.3 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import vm from 'node:vm';
import { readFileSync } from 'node:fs';
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const vue = require('vue');
const source = readFileSync(new URL('../pages/asset-package-history/asset-package-history.vue', import.meta.url), 'utf8');
const plain = value => JSON.parse(JSON.stringify(value));
async function loadPage(responses) {
const requestedPages = [];
const context = vm.createContext({ console: { error() {} } });
const exports = {
vue: { ref: vue.ref, reactive: vue.reactive, onMounted() {} },
'@/api/index.js': { assetApi: { getPackageHistory: async (identifier, page, size) => {
assert.equal(identifier, 'A'); assert.equal(size, 10);
requestedPages.push(page);
return responses[page - 1] || { items: [] };
} } },
'@/store/index.js': { useUserStore: () => ({ state: { identifier: 'A' } }) }
};
const script = source.match(/<script setup>([\s\S]*?)<\/script>/)[1];
const page = new vm.SourceTextModule(script + '\nexport { loadPackageList, packageList, noMore, historyLoaded };', { context });
await page.link(specifier => {
const values = exports[specifier];
return new vm.SyntheticModule(Object.keys(values), function () {
for (const [key, value] of Object.entries(values)) this.setExport(key, value);
}, { context });
});
await page.evaluate();
return { page: page.namespace, requestedPages };
}
test('main package history hides status 4 and string 4, preserving other states and dates', async () => {
const { page } = await loadPage([{ items: [
{ status: 4 }, { status: '4' },
{ status: 0, package_name: '待生效', expires_at: '2026-10-14T12:00:00Z' },
{ status: 1 }, { status: 2 }, { status: 3 }
] }]);
await page.loadPackageList();
assert.deepEqual(plain(page.packageList).map(item => item.status), [0, 1, 2, 3]);
assert.equal(page.packageList[0].expires_at, '2026-10-14 12:00:00');
assert.equal(page.noMore.value, true);
});
test('filtering a full page must not make later records unreachable', async () => {
const { page, requestedPages } = await loadPage([
{ items: [...Array.from({ length: 9 }, () => ({ status: 4 })), { status: 1, id: 1 }] },
{ items: [{ status: 2, id: 2 }] }
]);
await page.loadPackageList();
assert.equal(page.noMore.value, false);
await page.loadPackageList(true);
assert.deepEqual(requestedPages, [1, 2]);
assert.deepEqual(plain(page.packageList).map(item => item.id), [1, 2]);
assert.equal(page.noMore.value, true);
});
test('fully invalidated first page is skipped automatically', async () => {
const { page, requestedPages } = await loadPage([
{ items: Array.from({ length: 10 }, () => ({ status: 4 })) },
{ items: [{ status: 1, id: 12 }] }
]);
await page.loadPackageList();
assert.deepEqual(requestedPages, [1, 2]);
assert.equal(page.packageList[0].id, 12);
assert.equal(page.noMore.value, true);
});
test('server total keeps pagination correct even when a filtered page is empty', async () => {
const { page, requestedPages } = await loadPage([
{ items: [{ status: '4' }], size: 10, total: 20 },
{ items: [{ status: 4 }], size: 10, total: 20 }
]);
await page.loadPackageList();
assert.deepEqual(requestedPages, [1, 2]);
assert.equal(page.packageList.length, 0);
assert.equal(page.noMore.value, true);
assert.equal(page.historyLoaded.value, true);
});