JS coverage easy wins: geofence completo + panels restantes + scripts isolados (#168) - #169
Merged
Conversation
…A of #168) Adds 37 tests for `window.FFCGeofence` methods left at 0% after #160's initial pass that covered only `validateDateTime` + `pickHideMode`. Coverage of `ffc-geofence-frontend.js` jumps: - Lines: 39.26% → 56.94% - Functions: 25.92% → 81.48% - Branches: 73.33% → 82.22% What's covered now: - `getString` — i18n lookup with three fallback layers (key missing, strings object missing, config missing entirely). - `formatDate` / `formatTime` — zero-padding edge cases for single- digit month/day/hour/minute. - `escapeHtml` — proves HTML entity encoding on the dangerous chars (script tag injection attempt → encoded). - `calculateDistance` / `deg2rad` — Haversine math: identity case, real-world São Paulo→Rio (~360 km), symmetry, and angle conversion for 0°/180°/-90°. - `isSafari` — UA matching across iPhone, desktop Safari, iPad-as- desktop (`maxTouchPoints > 1` + Macintosh UA), Chrome, Firefox. - `getLocationCache` / `setLocationCache` — round-trip, missing key returns null, expired TTL clears the entry, malformed JSON yields null defensively. - `handleBlocked` — three branches (`hide`, `message`, default) plus XSS-prevention assertion (escapes raw HTML before injecting). - `showAdminBypassMessages` — generic vs datetime-only vs both-flags paths. - `showForm` / `resetForm` — class toggling + cleanup of injected blocked messages. - `showLoadingMessage` / `updateLoadingMessage` / `hideLoadingMessage` — spinner appended, text rewritten without losing spinner, full removal on hide. - `applyGpsFallback` — allow vs block branches (shows form vs handleBlocked). Test infrastructure unchanged — uses the same `loadScript` + real jQuery setup from #163. Each test starts with a fresh `#ffc-form-1` fixture and clears `localStorage`. Per-file `ffc-geofence-frontend.js` coverage report (`% Lines`): 39.26 → 56.94 (Δ +17.7 points). Overall JS coverage: 8.67% → 9.93%. Floor in `lint.yml` ratchets after sprints B and C land in this PR. https://claude.ai/code/session_01HiExaniSqvNBLpVTszCLNx
23 new tests for the 3 dashboard panels left at 0% after #163 S4. - dashboard-reregistrations.test.js (6 tests) — empty state, Active/ Completed section split, past-row class, edit-button visibility (gated by `can_submit`), download-ficha link (gated by `can_download` AND `magic_link`), auth_code as <code> vs dash. - dashboard-profile.test.js (9 tests) — read view rendering: profile container, logout link visibility (gated by `ffcDashboard.logoutUrl`), phone/department/organization labels + values, notes block (gated by non-empty `notes`), audience-group chips and the "Leave all groups" button (gated by group count), Edit Profile / Change Password buttons, audience-join section placeholder, panel state storage. - dashboard-audience-join.test.js (8 tests) — `$.ajax` is mocked so we drive the load() → render path deterministically: empty parents array empties section, heading + description render, Join button (non-member) vs Leave button (member), disabled-Join when joined_count >= max_groups, nested parent accordion, error branch empties the section, no-op when section is missing. Per-file coverage: - ffc-user-dashboard-reregistrations.js: 0% → 74.66% lines. - ffc-user-dashboard-profile.js: 0% → 40.21% lines. - ffc-user-dashboard-audience-join.js: 0% → 56.25% lines. Profile is below the 60-80% target because its render builds 6+ sections (read view, password form, preferences toggles, notifications settings, LGPD export buttons); this commit covers the read view and core actions only. The form-submission / password-change / preferences- save handlers each open their own panels of behaviour that warrant dedicated test files when those flows surface bugs. Overall JS coverage: 9.93% → 13.27%. Floor ratchet deferred to Sprint D's commit so all of A+B+C contribute to a single bump. https://claude.ai/code/session_01HiExaniSqvNBLpVTszCLNx
25 new tests across 3 files for the small IIFE-only scripts in
`assets/js/` that had no test coverage.
- tiny-scripts.test.js (11 tests) — combined file for the truly
tiny scripts:
• ffc-dark-mode.js (4 tests): off/undefined no-ops, mode=on
adds class, mode=auto follows matchMedia + responds to
change events.
• ffc-user-capabilities.js (4 tests): Grant all / Revoke all
/ Grant certificates only / Grant appointments only — each
verifies that only the targeted name prefix is toggled.
• ffc-smtp-settings.js (3 tests): smtp_mode=custom reveals
#smtp-options, disable_all_emails disables every SMTP
input, default page-load leaves inputs enabled.
- webview-warning.test.js (8 tests) — UA detection, banner
rendering, dismiss flow. Covers plain desktop UA, Android
WebView, Instagram in-app, Facebook in-app (FBAN marker),
pre-dismissed session, the dismiss button → banner removal +
sessionStorage flag, anchor placement above .ffc-form-wrapper,
no-anchor no-op.
- already-submitted-notice.test.js (6 tests) — localStorage form-
ID list driving the notice. Covers not-in-list no-render,
in-list render, session-dismissed no-render, dismiss → flag
+ removal, missing form no-op, malformed JSON resilience.
Test infrastructure additions:
- `await new Promise((r) => setTimeout(r, 0))` after `loadScript`
for scripts that wire handlers inside `$(document).ready(cb)` —
jQuery 4 defers the callback to a microtask even when the
document is already complete in the jsdom environment.
- UA override via `Object.defineProperty(navigator, 'userAgent',
{ configurable: true })` is restored in `beforeEach`.
Coverage delta on the affected files (`% Lines`):
- ffc-dark-mode.js: 0 → ~90.
- ffc-user-capabilities.js: 0 → ~90.
- ffc-smtp-settings.js: 0 → ~85.
- ffc-webview-warning.js: 0 → ~60.
- ffc-already-submitted-notice.js: 0 → ~65.
Overall JS coverage: 13.27% → 16.86%.
Floor ratchet ships in the next commit so the bump reflects the
combined gain of A + B + C.
https://claude.ai/code/session_01HiExaniSqvNBLpVTszCLNx
…#168) Sprints A+B+C of #168 added 60+ new tests covering: - geofence-frontend pure helpers + DOM methods (Sprint A) - 3 remaining dashboard panels (Sprint B) - 5 small isolated scripts (Sprint C) Overall line coverage went from 8.67% to 16.86% (a ~94% relative increase). The floor moves from 7 → 15, preserving the ~1.8% buffer the previous ratchets used. The buffer pattern still applies: PRs that touch tested code without adding coverage may drop the number slightly without firing the gate; PRs that genuinely improve coverage should bump the floor in the same commit (see the running comment in `lint.yml`). https://claude.ai/code/session_01HiExaniSqvNBLpVTszCLNx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #168.
Summary
Four sprints implementing the easy-testability JS coverage uplift from #168. Each commit is independently revertable.
fb153bdffc-geofence-frontend.js— pure helpers, DOM methods, browser detection, location cache, blocked-message rendering, GPS fallback.07e5af9$.ajax).b107c81f10baaaJS_COVERAGE_FLOOR_LINESratchets 7 → 15 to lock in the bigger baseline without firing on minor flux.Coverage delta
ffc-geofence-frontend.jsffc-user-dashboard-reregistrations.jsffc-user-dashboard-profile.jsffc-user-dashboard-audience-join.jsffc-dark-mode.jsffc-user-capabilities.jsffc-smtp-settings.jsffc-webview-warning.jsffc-already-submitted-notice.jsJS_COVERAGE_FLOOR_LINESNotes
$(document).ready(cb)deferral — jQuery 4 defers ready callbacks to a microtask even whendocument.readyState === 'complete'. Tests for scripts using that pattern await one tick viaawait new Promise((r) => setTimeout(r, 0))afterloadScript.Object.defineProperty(navigator, 'userAgent', { configurable: true })works in jsdom; tests restore the original UA inbeforeEachto avoid cross-test bleed.Test plan
npm run test:js— 127 / 127 OK (was 42).npm run test:js:coverage— line coverage 16.86%, gate (floor 15) passes.npm run lint:js— clean (9 pre-existing unused-vars warnings unchanged).vendor/bin/phpunit— runs unchanged (no PHP touched).What's deferred to future PRs
ffc-frontend.js(500 LOC, hub),ffc-frontend-helpers.js(656 LOC),ffc-core.js(300 LOC) — extract-pure-helpers-then-test, larger sprint of its own.ffc-csv-download.js,ffc-reregistration-frontend.js— large critical-path files.ffc-admin.js+ admin pages — separate sprint.ffc-audience.js(1470 LOC) — skipped per [Skipped] Sprint J — split ffc-audience.js (won't do, see body) #167.https://claude.ai/code/session_01HiExaniSqvNBLpVTszCLNx
Generated by Claude Code