JS coverage medium: core/helpers + dynamic-fragments + device-signals/frontend partial (#170) - #171
Merged
Merged
Conversation
The original Sprint E plan was "extract pure helpers into new files
then test", on the assumption that both ffc-core.js and
ffc-frontend-helpers.js wrapped useful helpers inside IIFEs with no
public surface. Re-reading the code showed that they ALREADY publish:
- `window.FFC.*` from ffc-core.js (getString, getAjaxUrl, getNonce,
isModuleLoaded, log, ajax, toggleFields, ...).
- `window.FFC.Frontend.{Validation, Masks, UI, RateLimit}` from
ffc-frontend-helpers.js.
So this is a "test in place" pass instead of a refactor. 28 new tests:
- FFC.getString (3): localized hit, missing key falls back, missing
strings object falls back.
- FFC.getAjaxUrl / getNonce (2): both return the localized values.
- FFC.isModuleLoaded (2): true for registered (Frontend), false for
nonexistent.
- FFC.Frontend.Validation.validateCPF (6): valid formatted/unformatted,
too-short rejected, all-same-digit rejected (e.g. 111...), invalid
first check digit, invalid second check digit.
- FFC.Frontend.Validation.validateRF (5): valid 7 digits, formatting
stripped, too short, too long, letters reduce digit count.
- FFC.Frontend.Validation.validateEmail (5): valid forms, missing @,
missing local part, missing TLD, whitespace.
- FFC.Frontend.UI.showFormError (2): notice injected, replaces
previous (no stacking).
- FFC.Frontend.UI.showFormSuccess (1): replaces form HTML.
- FFC.Frontend.Masks (2): applyCpfRf masks 11 digits to
XXX.XXX.XXX-XX; applyAuthCode inserts midpoint dash.
Coverage delta:
- ffc-core.js: 0% → 59.13% lines.
- ffc-frontend-helpers.js: 0% → 63.47% lines.
- Overall: 16.86% → 22.21%.
Floor ratchet deferred to Sprint H so the bump captures E+F+G
combined.
https://claude.ai/code/session_01HiExaniSqvNBLpVTszCLNx
11 tests for the page-cache freshness IIFE in
assets/js/ffc-dynamic-fragments.js. The script has no public API —
it runs on parse, detects whether the page needs refreshed fragments,
fires an XHR to `ffc_get_dynamic_fragments`, and patches captchas /
nonces / user fields / geofence configs from the response.
Testing strategy: install a `MockXHR` over `window.XMLHttpRequest`
before loading the script so the test can inspect the request and
deliver canned responses on demand. The mock captures `method`, `url`,
and `payload`, plus a `deliver(response, status)` helper that fires
`onload` with the test-supplied data.
What's covered:
- 5 early-return paths: no FFC elements on page → no XHR; no
ajaxUrl source → no XHR; captcha row + ajaxUrl → XHR fired;
ffc_ajax fallback when ffcDynamic missing; form IDs collected
into the payload.
- 6 applyFragments paths: per-form captcha update (label/hash/blank
answer), default captcha update, geofence config refresh +
FFCGeofence.recheck() trigger, response.success=false ignored,
HTTP 500 ignored, malformed JSON swallowed without throwing.
Coverage:
- ffc-dynamic-fragments.js: 0% → 72.64% lines.
- Overall: 22.21% → 23.59%.
https://claude.ai/code/session_01HiExaniSqvNBLpVTszCLNx
…G of #170) 6 tests for the cheap parts of two heavy files. The deep paths (the crypto-based fingerprint pipeline, AJAX-bound form submission flow) require expensive mocking of SubtleCrypto + thumbmarkjs + jQuery AJAX, which is bigger than the rest of the sprint combined. This commit ships what's cheap and explicitly defers the rest. - ffc-device-signals (3 tests): bails silently when window.crypto.subtle is unavailable; bails silently when ThumbmarkJS is unavailable; calls ThumbmarkJS.setOption('logging', false) when both deps are present (proves the telemetry-off enforcement that the PHP unit test in DeviceSignalsLoggingOffTest.php greps for). - ffc-frontend (3 tests): republishes `window.ffcUtils` as the Frontend.Masks namespace after load; loads without throwing on a page with no forms; loads without throwing on a page with one .ffc-submission-form. `window.crypto` is non-writable in jsdom — tests swap it via `Object.defineProperty(window, 'crypto', { value, configurable: true })` and restore the original in `beforeEach`. Coverage: - ffc-device-signals.js: 0% → 38.27% lines (the early-return guards + the setOption call cover ~1/3 of the IIFE; the fingerprint/sha256/submit-time injection paths stay uncovered). - ffc-frontend.js: 0% → 27% lines (script-init code paths + the no-form / one-form load paths). - Overall: 23.59% → 25.78%. Deferred to a future sprint: - device-signals full fingerprint pipeline (mapComponents, collectSignals, sha256Hex on the 14 documented signal types). - frontend.js form-submit AJAX flow + magic-link verification + PDF generation handoff. These warrant a focused PR with dedicated mocking infrastructure (SubtleCrypto polyfill, thumbmarkjs response fixtures, jQuery AJAX intercept layer) — bigger lift than the rest of #170 combined. https://claude.ai/code/session_01HiExaniSqvNBLpVTszCLNx
#170) Sprints E+F+G of #170 added ~45 new tests covering: - FFC core + Frontend.{Validation, Masks, UI} helpers (Sprint E) - dynamic-fragments cache-refresh IIFE (Sprint F) - device-signals + frontend.js load-side paths (Sprint G) Overall line coverage went from 16.86% to 25.78%. The floor moves from 15 → 24, preserving the ~1.8% buffer the previous ratchets used. https://claude.ai/code/session_01HiExaniSqvNBLpVTszCLNx
rpgmem
marked this pull request as ready for review
May 12, 2026 14:50
5 tasks
rpgmem
pushed a commit
that referenced
this pull request
May 13, 2026
Bumps:
- ffcertificate.php plugin header `Version` → 6.5.3
- FFC_VERSION constant → 6.5.3
- readme.txt Stable tag → 6.5.3
CHANGELOG: collapses the Unreleased block into a 6.5.3 (2026-05-13)
section and adds the items merged since 6.5.2 that the prior diff was
missing:
Changed:
- thumbmarkjs 1.8.1 → 1.9.0 (this PR)
- jQuery UI theme 1.14.1 → 1.14.2 (this PR)
- Recruitment CSV import: CPF/RF normalisation at parse time
(#172, shipped via #182).
Fixed:
- Form-editor groups 7/8 toggle-off persistence (already on
Unreleased; kept).
- Form-editor public CSV CPF "No" reverting to "Audit" (already on
Unreleased; kept).
- Reregistration form: $.trim() TypeError under jQuery 4 (#185).
- Reregistration form: [name^="fields["] selector rejected under
jQuery 4, getFields() returned {} (#185).
Internal:
- JS coverage uplift 7.37% → 72.84% across multiple sprints
(#162 / #164 / #166 / #168-#171 / #174-#180 / #183-#186),
floor ratcheted 3 → 70.
- Coverage job timeout 15 → 20 min (#181).
- The 9 pre-existing ESLint no-unused-vars warnings cleared (#188).
- CLAUDE.md added documenting auto-merge convention + CI gates +
test-infrastructure notes (#187).
rpgmem
added a commit
that referenced
this pull request
May 13, 2026
…1 → 1.14.2 (#189) * chore(deps): bump thumbmarkjs 1.8.1 → 1.9.0 and jQuery UI theme 1.14.1 → 1.14.2 Two upstream patch bumps that keep the API/CSS surface this plugin relies on: thumbmarkjs 1.8.1 → 1.9.0: - New vendored bundle: `libs/js/thumbmark-1.9.0.umd.js` (33 KB). - Old bundle removed. - `FFC_THUMBMARK_VERSION` bumped; `Frontend::enqueue_*` resolves the filename from the constant so the enqueue call updates automatically. - Surface used by `assets/js/ffc-device-signals.js` (`window.ThumbmarkJS.setOption('logging', false)`, `stableStringify`, `getFingerprintData()`) verified present in the new bundle and exercised by the existing JS suites (device-signals-deep.test.js / device-signals-and-frontend.test.js) — both still pass. - `DeviceSignalsLoggingOffTest::test_vendored_thumbmarkjs_present_at_pinned_path` path + redownload-URL hint updated to track the new bundle. jQuery UI theme 1.14.1 → 1.14.2: - `libs/css/jquery-ui-smoothness.css` replaced with the 1.14.2 release. - The CSS payload is byte-identical between the two upstream releases; the diff is just the file-header comment moving to `v1.14.2 - 2026-01-28`. Visible change for users is the cache-bust version string `wp_enqueue_style` emits. - `FFC_JQUERY_UI_VERSION` bumped to `'1.14.2'`. Tests: 3893 PHP + 487 JS still green. * release: 6.5.2 → 6.5.3, consolidate CHANGELOG for the maintenance cut Bumps: - ffcertificate.php plugin header `Version` → 6.5.3 - FFC_VERSION constant → 6.5.3 - readme.txt Stable tag → 6.5.3 CHANGELOG: collapses the Unreleased block into a 6.5.3 (2026-05-13) section and adds the items merged since 6.5.2 that the prior diff was missing: Changed: - thumbmarkjs 1.8.1 → 1.9.0 (this PR) - jQuery UI theme 1.14.1 → 1.14.2 (this PR) - Recruitment CSV import: CPF/RF normalisation at parse time (#172, shipped via #182). Fixed: - Form-editor groups 7/8 toggle-off persistence (already on Unreleased; kept). - Form-editor public CSV CPF "No" reverting to "Audit" (already on Unreleased; kept). - Reregistration form: $.trim() TypeError under jQuery 4 (#185). - Reregistration form: [name^="fields["] selector rejected under jQuery 4, getFields() returned {} (#185). Internal: - JS coverage uplift 7.37% → 72.84% across multiple sprints (#162 / #164 / #166 / #168-#171 / #174-#180 / #183-#186), floor ratcheted 3 → 70. - Coverage job timeout 15 → 20 min (#181). - The 9 pre-existing ESLint no-unused-vars warnings cleared (#188). - CLAUDE.md added documenting auto-merge convention + CI gates + test-infrastructure notes (#187). --------- Co-authored-by: Claude <noreply@anthropic.com>
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 #170.
Summary
Four sprints (E + F + G + H) from #170. Each commit is independently revertable.
e7fbdd3window.FFC.*(core) andwindow.FFC.Frontend.{Validation, Masks, UI}(frontend-helpers). No extraction needed — those files already publish their helpers on the FFC namespace, so the originally-planned refactor wasn't necessary.ca7b293ffc-dynamic-fragments.js(cache-refresh IIFE). CustomMockXHRoverwindow.XMLHttpRequestto driveapplyFragmentspaths.f1e89ecdevice-signals+frontend.js. The deep paths (SubtleCrypto + thumbmarkjs fingerprint pipeline, AJAX form submit) explicitly deferred — they need a dedicated PR with heavier mocking infra.0ef0ec7JS_COVERAGE_FLOOR_LINESratchets 15 → 24.Coverage delta
ffc-core.jsffc-frontend-helpers.jsffc-dynamic-fragments.jsffc-device-signals.jsffc-frontend.jsJS_COVERAGE_FLOOR_LINESNotes
Sprint E plan revised mid-implementation: the original issue body proposed "extract pure helpers, then test". After reading
ffc-core.js/ffc-frontend-helpers.js, I found both already publish their helpers onwindow.FFC. Extraction would have been pure churn. Tests go straight against the existing public surface; the commit message documents this.Sprint G partial: device-signals and frontend.js both have heavy dependency surfaces (SubtleCrypto, thumbmarkjs, jQuery AJAX, jsdom-incompatible APIs). This commit ships the cheap parts (early-returns, telemetry-off enforcement, load-side namespace registration). The crypto + AJAX paths are deferred to a focused future sprint that builds the necessary mocking layer. Coverage moved from 0 to 38% / 27% respectively without that infrastructure — a real but partial win.
window.cryptois non-writable in jsdom: tests that need to mutate it useObject.defineProperty(window, 'crypto', { value, configurable: true })and restore the original inbeforeEach.XHR mocking pattern:
tests/js/dynamic-fragments.test.jsintroduces aMockXHRclass that capturesmethod/url/payloadand exposesdeliver(response, status)to triggeronload. Reusable for any future IIFE script that uses raw XHR.Test plan
npm run test:js— 172 / 172 OK (was 127).npm run test:js:coverage— line coverage 25.78%, gate (floor 24) passes.npm run lint:js— clean (9 pre-existing unused-vars warnings unchanged).vendor/bin/phpunit— runs unchanged (no PHP touched).What's deferred
ffc-csv-download.js(668 LOC, File API).ffc-reregistration-frontend.js(507 LOC).ffc-admin.js, field-builder, submission-edit, etc.).https://claude.ai/code/session_01HiExaniSqvNBLpVTszCLNx
Generated by Claude Code