59 lines
3.4 KiB
JavaScript
59 lines
3.4 KiB
JavaScript
const fs = require('node:fs');
|
|
const vm = require('node:vm');
|
|
const assert = require('node:assert/strict');
|
|
const html = fs.readFileSync(__dirname + '/index.html', 'utf8');
|
|
const script = html.match(/<script>([\s\S]*?)<\/script>/)[1];
|
|
const elements = new Map();
|
|
function element(id) {
|
|
if (!elements.has(id)) elements.set(id, { value: id === 'pageSize' ? '50' : '', innerHTML: '', textContent: '', classList: { toggle() { return true; } }, setAttribute() {}, showModal() {}, close() {} });
|
|
return elements.get(id);
|
|
}
|
|
const context = vm.createContext({ document: { getElementById: element, querySelectorAll: () => [] }, console: { assert: assert.ok }, setTimeout: () => 1, clearTimeout() {}, FormData, assert });
|
|
vm.runInContext(script, context);
|
|
vm.runInContext(`
|
|
assert.equal(visibleRows().length, 50);
|
|
page=2; assert.equal(visibleRows().length, 22);
|
|
query='乐乐'; assert.equal(filtered().length, 3);
|
|
query=''; group='服饰鞋包'; assert.equal(filtered().length, 24);
|
|
group=''; tab='已过期'; assert.ok(filtered().every(r=>r.status==='已过期'));
|
|
for (const key of Object.keys(configs)) {
|
|
switchPage(key);
|
|
assert.ok($('tbody').innerHTML.includes('data-edit'));
|
|
openEditor(data[key][0].id);
|
|
assert.ok($('editorFields').innerHTML.includes('name="name"'));
|
|
hiddenColumns.add('group'); renderTable();
|
|
assert.ok(!$('thead').innerHTML.includes('所属分组'));
|
|
}
|
|
switchPage('stores');
|
|
assert.equal(configs.stores.columns.length, 11);
|
|
assert.equal(configs.users.columns.length, 13);
|
|
assert.ok($('tbody').innerHTML.includes('data-store-action'));
|
|
selected.add(data.stores[3].id); $('login').onclick();
|
|
assert.equal(data.stores[3].login, '登录成功');
|
|
$('batch').onclick();
|
|
assert.equal(data.stores[3].status, '正常');
|
|
assert.equal(selected.size, 0);
|
|
query='no-matching-record'; renderTable();
|
|
assert.ok($('tbody').innerHTML.includes('没有匹配的记录'));
|
|
assert.equal($('next').disabled, true);
|
|
assert.equal(escapeHtml('<img onerror="bad">'), '<img onerror="bad">');
|
|
`, context);
|
|
console.log('PASS: script syntax, five page renders, pagination, filters, editors, columns, batch action, empty state and HTML escaping.');
|
|
|
|
// Verify contextual navigation against the actual HTML attributes.
|
|
const markup = html.split("<script>")[0];
|
|
const ids = [...markup.matchAll(/\bid="([^"]+)"/g)].map(m => m[1]);
|
|
assert.equal(ids.length, new Set(ids).size);
|
|
const modules = [...markup.matchAll(/data-module="([^"]+)" data-start="([^"]+)"/g)].map(m => ({ dataset: { module: m[1], start: m[2] }, classList: { toggle() {} }, setAttribute(name, value) { this[name] = value; } }));
|
|
const pages = [...markup.matchAll(/data-area="([^"]+)" data-page="([^"]+)"/g)].map(m => ({ dataset: { area: m[1], page: m[2] }, classList: { toggle() {} }, setAttribute() {} }));
|
|
context.document.querySelectorAll = selector => selector === "[data-module]" ? modules : pages;
|
|
assert.equal(modules.length, 3); assert.equal(pages.length, 5);
|
|
for (const page of pages) {
|
|
vm.runInContext("switchPage(" + JSON.stringify(page.dataset.page) + ")", context);
|
|
assert.equal(page.hidden, false);
|
|
assert.ok(pages.every(p => p.hidden === (p.dataset.area !== page.dataset.area)));
|
|
assert.equal(modules.filter(m => m["aria-pressed"]).length, 1);
|
|
assert.equal(modules.find(m => m["aria-pressed"]).dataset.module, page.dataset.area);
|
|
}
|
|
console.log("PASS: three icon modules, five contextual pages, active and hidden navigation states.");
|