Files
UI/packages/core/table-core/scripts/smoke.mjs
T
2026-10-26 13:08:25 +08:00

176 lines
6.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
createTable,
filterPlugin,
paginationPlugin,
selectionPlugin,
sortPlugin,
} from '../dist/index.js';
const users = [
{ id: 1, name: 'Charlie', age: 35, city: 'Shenzhen' },
{ id: 2, name: 'Alice', age: 28, city: 'Beijing' },
{ id: 3, name: 'Bob', age: 31, city: 'Shanghai' },
{ id: 4, name: 'Dave', age: 22, city: 'Beijing' },
{ id: 5, name: 'Eve', age: 29, city: 'Shanghai' },
];
const table = createTable({
data: users,
columns: [
{ key: 'name', header: 'Name', sortable: true },
{ key: 'age', header: 'Age', sortable: true },
{ key: 'city', header: 'City' },
],
rowKey: 'id',
plugins: [filterPlugin(), sortPlugin(), paginationPlugin(), selectionPlugin()],
initialState: { pagination: { page: 1, pageSize: 2 } },
});
/*** 断言工具:失败即退出 ***/
const assert = (cond, msg) => {
if (!cond) {
console.error('FAIL:', msg);
process.exit(1);
}
console.log('ok -', msg);
};
table.dispatch({ type: 'toggleSort', key: 'name' }); // 按名称升序
assert(
JSON.stringify(table.getVisibleRows().rows.map((r) => r.name)) ===
JSON.stringify(['Alice', 'Bob']),
'sort by name asc + page 1 of size 2',
);
table.dispatch({ type: 'setFilter', key: 'city', value: 'shang' }); // 筛选上海
const filtered = table.getVisibleRows();
assert(
JSON.stringify(filtered.rows.map((r) => r.name)) ===
JSON.stringify(['Bob', 'Eve']) &&
filtered.total === 2,
'filter city~sh keeps Shanghai rows, total=2',
);
assert(table.getPageInfo().totalPages === 1, 'totalPages computed from filtered total');
table.dispatch({ type: 'clearFilters' }); // 清筛选回到全量
table.dispatch({ type: 'setPage', page: 2 });
assert(
JSON.stringify(table.getVisibleRows().rows.map((r) => r.name)) ===
JSON.stringify(['Charlie', 'Dave']),
'page 2 after clearing filter',
);
assert(table.getPageInfo().page === 2 && table.getPageInfo().totalPages === 3, 'page info total=3 pages');
table.dispatch({ type: 'toggleSelect', key: 3 }); // 勾选行 3
assert(JSON.stringify(table.getState().selection) === JSON.stringify([3]), 'toggleSelect adds rowKey');
table.selectAllVisible(); // 全选当前页(替换语义)
assert(
JSON.stringify(table.getState().selection) === JSON.stringify([1, 4]),
'selectAllVisible replaces selection with visible rowKeys',
);
table.dispatch({ type: 'setPage', page: 99 }); // 越界页码
const clamped = table.getVisibleRows();
assert(
table.getPageInfo().page === 3 && clamped.rows.length === 1,
'page clamped to totalPages',
);
const before = table.getVisibleRows(); // memo 基线
table.dispatch({ type: 'clearSelection' }); // 无关状态变更
assert(table.getVisibleRows() === before, 'derive stages memoized across unrelated state changes');
// —— 补充不变量 ——
const fresh = createTable({
data: users,
columns: [{ key: 'name', header: 'Name', sortable: true }],
rowKey: 'id',
plugins: [paginationPlugin()],
initialState: { pagination: { page: 2, pageSize: 2 } },
});
assert(
fresh.getPageInfo().page === 2 && fresh.getPageInfo().pageSize === 2,
'getPageInfo 无需先取可见行即返回 initialState 生效值',
);
assert(fresh.getPageInfo().totalPages === 3, 'getPageInfo 的 totalPages 由上游 total 推导');
const marks = createTable({
data: users,
columns: [{ key: 'name', header: 'Name' }, { key: 'city', header: 'City' }],
rowKey: 'id',
plugins: [filterPlugin(), paginationPlugin(), selectionPlugin()],
initialState: { pagination: { page: 1, pageSize: 2 } },
});
marks.selectAllVisible(); // 选中第 1 页的 id 1 / 2
marks.dispatch({ type: 'setFilter', key: 'city', value: 'Beijing' }); // 可见行整体换掉
assert(
JSON.stringify(marks.getState().selection) === JSON.stringify([1, 2]),
'selection 以 rowKey 记账,筛选换掉可见行后仍保留',
);
const toggle = createTable({
data: users,
columns: [{ key: 'age', header: 'Age', sortable: true }],
rowKey: 'id',
plugins: [sortPlugin()],
});
toggle.dispatch({ type: 'toggleSort', key: 'age' });
toggle.dispatch({ type: 'toggleSort', key: 'age' });
toggle.dispatch({ type: 'toggleSort', key: 'age' });
assert(toggle.getState().sorting.length === 0, '同一列连点三次回到无序(asc → desc → 取消)');
const multi = createTable({
data: users,
columns: [{ key: 'city', header: 'City' }, { key: 'age', header: 'Age', sortable: true }],
rowKey: 'id',
plugins: [sortPlugin({ multi: true })],
});
multi.dispatch({ type: 'toggleSort', key: 'city', multi: true });
multi.dispatch({ type: 'toggleSort', key: 'age', multi: true });
assert(multi.getState().sorting.length === 2, 'multi 排序保留两列规则');
assert(
JSON.stringify(multi.getVisibleRows().rows.map((r) => r.id)) === JSON.stringify([4, 2, 5, 3, 1]),
'多列排序按规则顺序生效(city 升序,同城内 age 升序:Beijing 4→2、Shanghai 5→3)',
);
const sizing = createTable({
data: users,
columns: [{ key: 'name', header: 'Name' }],
rowKey: 'id',
plugins: [paginationPlugin()],
initialState: { pagination: { page: 1, pageSize: 2 } },
});
sizing.dispatch({ type: 'setPage', page: 2 });
sizing.dispatch({ type: 'setPageSize', pageSize: 3 });
assert(sizing.getPageInfo().page === 1 && sizing.getPageInfo().pageSize === 3, '改页大小回到第 1 页');
sizing.dispatch({ type: 'toggleSort', key: 'name' });
sizing.dispatch({ type: 'reset' });
assert(
sizing.getState().sorting.length === 0 &&
sizing.getState().filters.length === 0 &&
sizing.getState().pagination.page === 1 &&
sizing.getState().pagination.pageSize === 20,
'reset 回到默认态(排序/筛选清空,分页回 1/20)',
);
// getAllRows:过筛选 + 排序但跳过分页,供导出用
const all = createTable({
data: users,
columns: [{ key: 'name', header: 'Name' }, { key: 'city', header: 'City' }],
rowKey: 'id',
plugins: [filterPlugin(), sortPlugin(), paginationPlugin()],
initialState: { pagination: { page: 1, pageSize: 2 } },
});
assert(all.getVisibleRows().rows.length === 2, 'getVisibleRows 受分页约束只给当页');
all.dispatch({ type: 'setFilter', key: 'city', value: 'Beijing' });
assert(all.getAllRows().rows.length === 2 && all.getVisibleRows().rows.length === 2, 'getAllRows 跳过分页但与筛选一致(Beijing 2 行)');
all.dispatch({ type: 'toggleSort', key: 'age' });
assert(
JSON.stringify(all.getAllRows().rows.map((r) => r.id)) === JSON.stringify([4, 2]),
'getAllRows 仍按排序规则排(age 升序 4→2)',
);
assert(all.getPageInfo().totalPages === 1, 'getAllRows 不影响分页快照(2 行 / 每页 2 = 1 页)');
console.log('SMOKE OK');