import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import test from 'node:test' import { parse, compileScript } from 'vue/compiler-sfc' import ts from 'typescript' import * as vue from 'vue' const source = readFileSync(new URL('./DataTable.vue', import.meta.url), 'utf8') function paginationHarness(t) { const descriptor = parse(source).descriptor const compiled = compileScript(descriptor, { id: 'data-table-pagination-test' }) const code = ts.transpileModule(compiled.content, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 } }).outputText const exports = {} const deps = { vue, '@lucide/vue': { ChevronLeft: {}, ChevronRight: {} }, './tableActions': {} } new Function('require', 'exports', code)(id => { assert.ok(id in deps, id); return deps[id] }, exports) const component = exports.default component.render = () => null const state = vue.reactive({ page: 5, total: 5542, loading: false, error: false }) const emitted = [] const renderer = vue.createRenderer({ createElement: tag => ({ tag }), createText: text => ({ text }), createComment: text => ({ text }), insert() {}, remove() {}, setElementText() {}, setText() {}, patchProp() {}, parentNode: () => null, nextSibling: () => null, }) const app = renderer.createApp({ render: () => vue.h(component, { data: [], columns: [], page: state.page, pageSize: 50, total: state.total, loading: state.loading, 'onUpdate:page': value => { emitted.push(value); state.page = value }, }, state.error ? { error: () => vue.h('div', 'Request failed') } : {}) }) app.mount({}) t.after(() => app.unmount()) return { state, emitted } } test('server-page loading must not reset the requested page when total temporarily clears', async t => { const { state, emitted } = paginationHarness(t) state.loading = true; state.total = 0 await vue.nextTick() assert.equal(state.page, 5) assert.deepEqual(emitted, []) state.total = 5542; state.loading = false await vue.nextTick() assert.equal(state.page, 5) assert.deepEqual(emitted, []) }) test('failed server page retains its page for explicit retry and emits no automatic fallback request', async t => { const { state, emitted } = paginationHarness(t) state.loading = true; state.total = 0 await vue.nextTick() state.error = true; state.loading = false await vue.nextTick() assert.equal(state.page, 5) assert.deepEqual(emitted, []) state.error = false; state.loading = true await vue.nextTick() state.total = 5542; state.loading = false await vue.nextTick() assert.equal(state.page, 5) assert.deepEqual(emitted, []) }) test('settled successful totals still clamp out-of-range and empty pages', async t => { const { state, emitted } = paginationHarness(t) state.total = 120 await vue.nextTick() assert.equal(state.page, 3) state.total = 0 await vue.nextTick() assert.equal(state.page, 1) assert.deepEqual(emitted, [3, 1]) }) test('keeps action-only table toolbars on the left', () => { assert.match(source, /'data-table__toolbar--actions-only': !\$slots\.toolbar/) assert.match(source, /v-if="\$slots\.toolbar" class="data-table__toolbar-heading"/) assert.match(source, /\.data-table__toolbar--actions-only \{ justify-content: flex-start; \}/) })