Release 2.21.6: prevent duplicate list searches
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m33s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 41s

This commit is contained in:
lzstealth committed 2026-10-27 18:56:40 +00:00
1 parent 9e988c307e
commit 675483624b
7 files changed
+66 -10

No files matched your search

+36 -4
View File
@@ -159,6 +159,8 @@ function createNavigationHarness() {
const footer = { outerHTML: 'original footer' };
const attributes = {};
const inputEvents = {};
const timers = new Map();
let nextTimerId = 0;
const scroller = { scrollTop: 90 };
const input = {
value: '',
@@ -212,8 +214,12 @@ function createNavigationHarness() {
location: { href: 'http://localhost/slides?search=demo&sort=name', assign(url) { navigations.push(url); } },
history: { state: { preserved: true } },
addEventListener(name, handler) { events[name] = handler; },
clearTimeout() {},
setTimeout(handler) { events.timer = handler; return 1; }
clearTimeout(id) { timers.delete(id); },
setTimeout(handler) {
const id = ++nextTimerId;
timers.set(id, handler);
return id;
}
}
};
for (const method of ['pushState', 'replaceState']) {
@@ -248,7 +254,14 @@ function createNavigationHarness() {
requests[index].resolve({ ok, text: async () => text });
await new Promise(resolve => setImmediate(resolve));
}
return { sandbox, container, events, requests, navigations, history, body, footer, attributes, input, inputEvents, scroller, click, respond };
return {
sandbox, container, events, requests, navigations, history, body, footer, attributes, input, inputEvents, scroller, click, respond,
runTimers() {
const pending = Array.from(timers.values());
timers.clear();
pending.forEach(handler => handler());
}
};
}
test('pagination replaces only table results and pushes a URL preserving search and sort', async () => {
@@ -319,9 +332,28 @@ test('typing invalidates pending pagination and search still resets to page one'
await harness.respond(0, 'outdated');
assert.equal(harness.body.outerHTML, 'original rows');
assert.equal(harness.input.value, 'new query');
harness.events.timer();
harness.runTimers();
assert.equal(new URL(harness.requests[1].url).searchParams.get('page'), null);
await harness.respond(1, 'searched');
assert.equal(harness.body.outerHTML, 'searched rows');
assert.equal(harness.history[0].method, 'replaceState');
});
test('blur flushes a pending search once and does not repeat an active search', async () => {
const pendingHarness = createNavigationHarness();
pendingHarness.input.value = 'button race';
pendingHarness.inputEvents.input();
pendingHarness.inputEvents.change();
assert.equal(pendingHarness.requests.length, 1);
pendingHarness.runTimers();
assert.equal(pendingHarness.requests.length, 1);
const activeHarness = createNavigationHarness();
activeHarness.input.value = 'button race';
activeHarness.inputEvents.input();
activeHarness.runTimers();
assert.equal(activeHarness.requests.length, 1);
activeHarness.inputEvents.change();
assert.equal(activeHarness.requests.length, 1);
await activeHarness.respond(0, 'searched');
});