fix(packets): empty observer/type selections on Clear Filters - #132
Conversation
#121) test-issue-121-clear-filters-selection.js evaluates the real buildPacketsQuery(), updatePacketsUrl() and filter-bar section of public/packets.js (observer multi-select through the Clear handler) in one scope against a minimal fake DOM, and drives the menus and the Clear button. On master 6 of 8 cases fail: - select A, Clear, select B gives "obsA,obsB" (and "4,5" for types), because Clear leaves the closure Sets populated; - after Clear the "All Observers"/"All Types" rows are unchecked; - with only a type selected the Clear button stays hidden, because the type handler never calls updatePacketsUrl(). The two controls (Clear reloads exactly once; the other filters are reset) pass. Registered in test-all.sh and the deploy.yml unit step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019TcZHooUiiknVWbECVWzk8
The Clear handler reset filters.observer/type, localStorage and every
checkbox, but left the closure Sets selectedObservers and selectedTypes
populated, so the next pick added to the old selection ("obsA,obsB"),
and it unchecked the "All Observers"/"All Types" rows while no filter
was active. It now empties both Sets and rebuilds both menus and
triggers through buildObserverMenu()/buildTypeMenu() and
updateObsTrigger()/updateTypeTrigger(), which are in the same scope.
The type change handler now also calls updatePacketsUrl(), which is what
shows the Clear button; with only a type selected the button stayed
hidden. Type is not part of the URL, so the hash itself is unchanged.
test-clear-filters.js gave the handler body no binding for the new
identifiers and passed no `location` to updatePacketsUrl() (2 cases
already failed on master); both fixed, and the file is now registered
in test-all.sh and CI next to the #121 test.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019TcZHooUiiknVWbECVWzk8
Independent review of
|
| Criterion | Result |
|---|---|
| Empty both Sets and rebuild the menus from an empty state | Met [F]: code, and mutants M1 to M3 |
| "All Observers"/"All Types" checked, triggers and titles match | Met [F]: browser at 1440×900 and 1024×768, plus the unit test (master: both "All" unchecked, stale title) |
URL, localStorage and filters hold no stale values |
Met [F]: after Clear, ls* is null and the hash is #/packets; after B, only B/5 in the menu, localStorage and URL |
| Other filters unchanged | Met [F]: unit test "the other filters…", test-clear-filters.js 8/8, test-filter-ux-e2e.js 12/12 |
| Clear gives exactly one reload/render | Met [F]: exactly 1 /api/packets? request per Clear in the browser; mutant M6 (double loadPackets) is caught |
| Regression test: A, Clear, B; repeated Clears; SPA remount | Met [F], with the caveat in finding 1 |
Test-first and mutants
- [F] The test file is unchanged from commit A to the head. On master: 2 passed, 6 failed. On the head: 8 passed, 0 failed.
- [F]
test-clear-filters.js: master 6/2 (thelocation is not definedharness failure), head 8/0. - [F] Six mutants of
public/packets.js, all caught:
| Mutant | test-issue-121 | test-clear-filters |
|---|---|---|
M1 drop selectedObservers.clear() |
4 fail | 1 fail |
M2 drop selectedTypes.clear() |
3 fail | 1 fail |
M3 drop buildObserverMenu() in Clear |
1 fail | 1 fail |
M4 drop updateTypeTrigger() in Clear |
1 fail | 1 fail |
M5 drop updatePacketsUrl() in the type handler |
1 fail | green |
M6 double loadPackets() in Clear |
1 fail | green |
Suites run locally (master vs head)
- [F]
test-packet-filter.js92/0,test-packet-filter-ux.js19/0,test-packet-filter-time.js20/0,test-aging.js19/0. Identical on both. - [F]
test-frontend-helpers.js705/2 andtest-packets.js115/13. The failing test names are the same on master and the head, so the failures are pre-existing. This matches the PR text. - [F] Playwright against a local Go server on a freshened and migrated
test-fixtures/e2e-fixture.db, with CI's seed block:test-filter-ux-e2e.js: 12/0.- My own scenario at 1440×900 and 1024×768: only a type selected, so Clear is visible; observer A and type ADVERT; Clear; observer B and type GRP_TXT; remount. The head passes every Clear step. Master fails: Clear is hidden with only a type selected, "All" is unchecked after Clear, and after B
obsA,obsBand4,5are stored. No page errors. test-e2e-playwright.jsstops locally (fail-fast) after 6 tests on "Version info lives on Perf dashboard", identically on master and the head. I put this down to my local environment. CI's Playwright job is green.
- Go: no Go changes, so I did not run
go testlocally. CI's Go job is green [F].
Performance and security
- [F] Not a hot path. Clear rebuilds two small menus (O(observers + types)) once per click.
- [F] No new DOM sinks. The menu HTML is unchanged, and observer names still go through
escapeHtml. No Go, API or DB changes, so themode=roinvariant and themap[string]interface{}rule are not affected.
Not verified
- I did not run
scripts/check-xss-sinks.sh --diff origin/masteror eslint myself [T]. - Mobile widths below 768 px, real devices and staging were not tested. The PR's "Not verified" list says so, and that list is honest and complete.
- The rest of
test-e2e-playwright.jsafter the local fail-fast stop. I rely on CI's green Playwright job for it. - I did not check the region-listener leak on repeated mounts that the PR lists as out of scope [T].
The type handler called updatePacketsUrl() only to show the Clear button. That rebuilds the query from filter params alone, so #/packets/<hash>?obs=123&viewPath=1 lost its query. Split the button visibility into updateClearFiltersVisibility() (also used by updatePacketsUrl()) and call only that from the type handler. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AnDeApGxcZChs24fdMWepA
|
Review feedback addressed (commit
Generated by Claude Code |
Independent review of
|
| Mutant | test-issue-121 | test-clear-filters |
|---|---|---|
N1 updatePacketsUrl() back in the type handler |
2 fail | green |
| N2 no visibility refresh in the type handler | 3 fail | green |
N3 updatePacketsUrl() no longer refreshes visibility |
1 fail | 1 fail |
N4 visibility ignores filters.type |
3 fail | green |
M1 drop selectedObservers.clear() (re-run) |
4 fail | 1 fail |
M2 drop selectedTypes.clear() (re-run) |
3 fail | 1 fail |
Suites and browser
- [F]
test-issue-121-clear-filters-selection.js10/0,test-clear-filters.js8/0,test-packet-filter.js92/0,test-packet-filter-ux.js19/0,test-packet-filter-time.js20/0,test-aging.js19/0. - [F]
test-frontend-helpers.js705/2 andtest-packets.js115/13, the same pre-existing failures as on master. - [F] Browser (Playwright/Chromium, local Go server on the freshened and migrated fixture):
- The A → Clear → B scenario at 1440×900 and 1024×768 passes every Clear step: "All" checked, triggers and title reset, localStorage empty, hash
#/packets, exactly 1/api/packets?request per Clear, only B/5 after the new pick. No page errors. - Deep link
#/packets/<hash>?obs=123&viewPath=1, then pick type ADVERT: the hash is unchanged and Clear is visible.
- The A → Clear → B scenario at 1440×900 and 1024×768 passes every Clear step: "All" checked, triggers and title reset, localStorage empty, hash
Metadata
- [F] Fast-forward from
8b8b5bcd.merge-treeagainst the currentorigin/master(d264716c) has no conflicts. - [F] No workflow change in the delta. No closing keywords, no @mentions, no full upstream URLs in the updated body.
- [F] CI on
7f37e0b7is complete: Go Build & Test, Playwright E2E and Docker are SUCCESS; the rest are SKIPPED.
Not verified
scripts/check-xss-sinks.shand eslint on the delta [T]. The delta adds no DOM sinks [F].- Mobile widths below 768 px, real devices and staging.
Relates to #121
Summary
Clear Filters on the Packets page now actually empties the observer and packet-type selections. Before this change, the next pick after Clear added to the old selection: select observer A, Clear, select B gave
observer=obsA,obsB. The "All Observers" and "All Types" rows were also left unchecked after Clear.Upstream reference (read only):
Kpa-clawbot/CoreScope#2015.Plan and design
Autonomous run, so the plan is written here instead of waiting for approval (AGENTS.md rule 5).
a443333c). A new unit test runs the real code frompublic/packets.jsin a sandbox with a minimal fake DOM. It drives the menus and the Clear button as a user would. It is red on master.8b8b5bcd).selectedObservers.clear()andselectedTypes.clear(), then rebuilds both menus and trigger labels. The rebuild uses the existingbuildObserverMenu()/buildTypeMenu()andupdateObsTrigger()/updateTypeTrigger(). It replaces the hand-written loops that only unchecked checkboxes.7f37e0b7).8b8b5bcddid that refresh by callingupdatePacketsUrl(). That function rebuilds the query from filter params only, so#/packets/<hash>?obs=123&viewPath=1lostobsandviewPathwhen a type was picked. The Clear-button visibility is now its own function,updateClearFiltersVisibility(), whichupdatePacketsUrl()also uses. The type handler calls only that function, so the hash is left untouched (type is not a URL parameter).Fork compared with upstream. The core change matches upstream. Upstream's merge also resets an observer search box from its Kpa-clawbot#1884. This fork has no such box, so that part is not ported. The test is fork-specific: it covers repeated Clears, SPA remount, the one-reload guarantee and the other filters, which upstream's test does not.
Config and customizer (AGENTS.md rule 8). No new configurable values.
Acceptance criteria
filterskeep no stale observer/type valuestest-clear-filters.js8/8;test-filter-ux-e2e.js12/12loadPackets+1 andrenderTableRows+0 per Clear; browser: exactly one/api/packets?request per Clear.RegionFilter.setSelected()does not notify listeners, so there is no second reload.test-issue-121-clear-filters-selection.js?obs=and?viewPath=in the URL and shows Clear (review P2)test-issue-121-clear-filters-selection.js(?obs=123,?obs=123&viewPath=1); red on8b8b5bcd(8 passed, 2 failed)updatePacketsUrl(), and does call the visibility functionupdatePacketsUrl()back in the type handler gives 8 passed, 2 failed; visibility call removed gives 7 passed, 3 failedTests
node test-issue-121-clear-filters-selection.js'obsA,obsB' !== 'obsB','4,5' !== '5', All rows unchecked, Clear hidden with only a type selected. The two passing cases are the controls.node test-clear-filters.jslocation is not definedin its own harness.updateClearFiltersVisibility()together withupdatePacketsUrl(). Its checkbox case asserts that the Sets are emptied and the menus rebuilt.test-all.sh.Other suites, same results on this branch as on master
test-packet-filter.jstest-packet-filter-ux.jstest-packet-filter-time.jstest-aging.jstest-frontend-helpers.jstest-all.shonlytest-packets.jsThe failures in the last two are pre-existing: a diff of the failing test names between
origin/master85bfee49and this branch is empty.Static checks
scripts/check-xss-sinks.sh --diff origin/master: exit 0 (re-run after7f37e0b7).eslint@8 public/*.js: 0 errors. There are 88 warnings, all pre-existing no-unused-vars.Browser validation (Playwright with Chromium, local server on the migrated and freshened
test-fixtures/e2e-fixture.db; run on8b8b5bcd, not repeated after7f37e0b7)The scenario:
Results:
test-filter-ux-e2e.js(in CI): 12/12 on this branch and on master.The sandbox blocks the Leaflet CDN (unpkg.com), so every page logs
L is not defined. That comes from the environment and is the same on master.Performance. Not a hot path. Clear rebuilds two small menus once per click.
Not verified
7f37e0b7fix is covered by unit tests only, not re-driven in a browser.Observed but out of scope (follow-ups)
updatePacketsUrl()and so drops?obs=/?viewPath=from a detail deep link. This is on master too and is deliberately not changed here.init()also callsupdatePacketsUrl()on page load (after wiring the Clear handler), which rewrites the query the same way. Also on master; left for a separate issue.init()registersRegionFilter.onChange(...)on every mount, anddestroy()never removes it. After several SPA remounts, a region change therefore reloads packets more than once. Clear is not affected, becauseRegionFilter.setSelected()does not notify listeners.Overlap with my other open PRs
None: no other open PR of mine touches these files.
🤖 Generated with Claude Code
https://claude.ai/code/session_019TcZHooUiiknVWbECVWzk8
Generated by Claude Code