Skip to content

Injected code coverage#2261

Merged
jonathanKingston merged 28 commits into
mainfrom
jkt/auto/injected-code-coverage-8260
Feb 13, 2026
Merged

Injected code coverage#2261
jonathanKingston merged 28 commits into
mainfrom
jkt/auto/injected-code-coverage-8260

Conversation

@jonathanKingston
Copy link
Copy Markdown
Contributor

@jonathanKingston jonathanKingston commented Feb 13, 2026

Asana Task/Github Issue: https://app.asana.com/1/137249556945/task/1213263920267573

Description

Adds static test pages and configurations for 14 features in the injected/ codebase, significantly increasing test coverage. This follows the existing idiom of config-driven HTML test pages and includes necessary updates to the extension test harness to enable these features.

Testing Steps

  • Run npm run build
  • Run npm run test:integration:chrome-mv3
  • Run npm run test:unit

Checklist

Please tick all that apply:

  • I have tested this change locally
  • I have tested this change locally in all supported browsers
  • This change will be visible to users
  • I have added automated tests that cover this change
  • I have ensured the change is gated by config
  • This change was covered by a ship review
  • This change was covered by a tech design
  • Any dependent config has been merged

Open in Cursor Open in Web


Note

Medium Risk
Main risk is CI instability and longer runtimes from expanded Playwright matrix and new coverage collection/merging; production code paths are only lightly touched (integration entry-point feature enablement).

Overview
Adds a new nightly/manual Coverage GitHub Actions workflow that runs injected/ unit tests under c8, runs Playwright integration tests with V8 coverage enabled, and then merges both into a single coverage report artifact via scripts/merge-coverage.js.

CI is updated to split special-pages vs injected integration runs and to run injected Playwright tests across a multi-project matrix (with per-project report artifacts), and the integration harness now derives enabledFeatures from platformSupport.integration and can optionally collect/flush Playwright V8 coverage to injected/coverage/integration.

Test coverage is expanded substantially by adding many new config-driven integration test pages (e.g., GPC, cookie, fingerprinting variants, referrer, page context, print, telemetry, interference detection) plus new/expanded unit tests (including property-based tests) and new coverage tooling/config (.c8rc.json, c8, monocart-coverage-reports).

Written by Cursor Bugbot for commit 0a32b66. This will update automatically on new commits. Configure here.

cursoragent and others added 3 commits February 13, 2026 00:15
Add test pages, configs, and index pages for 15 features:
- gpc, google-rejected, fingerprinting-hardware, fingerprinting-screen-size
- fingerprinting-battery, fingerprinting-audio, fingerprinting-canvas
- fingerprinting-temporary-storage, referrer, navigator-interface
- exception-handler, print, performance-metrics, web-telemetry
- web-interference-detection

Update integration entry point to enable all tested features.
Update ResultsCollector._loadExtension to support withUserPreferences.
Add all test entries to pages.spec.js.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
@cursor
Copy link
Copy Markdown
Contributor

cursor Bot commented Feb 13, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@netlify
Copy link
Copy Markdown

netlify Bot commented Feb 13, 2026

Deploy Preview for content-scope-scripts ready!

Name Link
🔨 Latest commit 0a32b66
🔍 Latest deploy log https://app.netlify.com/projects/content-scope-scripts/deploys/698f86f08d348800083fa9e2
😎 Deploy Preview https://deploy-preview-2261--content-scope-scripts.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 13, 2026

Temporary Branch Update

The temporary branch has been updated with the latest changes. Below are the details:

Please use the above install command to update to the latest version.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 13, 2026

[Beta] Generated file diff

Time updated: Fri, 13 Feb 2026 20:19:23 GMT

Integration
    - integration/contentScope.js

File has changed

cursoragent and others added 19 commits February 13, 2026 00:29
Adds static test pages for the final two features lacking test-page coverage:
- cookie: verifies cookie expiry protection is active, getter works, non-string values don't throw
- page-context: verifies feature initializes with page content extraction prerequisites

All 34 features now have at least one static test page.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
- Install c8 as devDependency
- Wire test-unit script through c8 with include/exclude patterns
- Add test-unit-no-coverage for fast runs without instrumentation
- Add coverage script for standalone report generation

Baseline: 76.15% lines, 84.78% branches, 58.76% functions

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
…e.js

Property tests using fast-check for:
- matchHostname: reflexivity, subdomain containment, non-containment
- satisfiesMinVersion/isMaxSupportedVersion: reflexivity, transitivity, version ordering
- isSupportedVersion: string/numeric consistency, type mismatch handling
- stripVersion: component count preservation
- camelcase: hyphen removal, first char preservation
- processAttr: type-correct output for all ConfigSetting types
- isStateEnabled: exhaustive state/platform combinations
- iterateDataKey: determinism, iteration count, early exit
- withDefaults: precedence, missing key fill, array replacement
- Cookie: parse roundtrip, expiry handling, maxAge set/get
- ConfigFeature._matchConditionalBlock: empty/unknown keys, domain, version, experiment matching
- ConfigFeature.getFeatureSettingEnabled: boolean output, default state, object state

546 specs, 0 failures

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
…ondition key test

The 'constructor' key resolves via prototype chain lookup on the conditionChecks
object, causing _matchConditionalBlock to incorrectly return true. Exclude all
Object.prototype keys from the generated test inputs.

Also: move c8 config to .c8rc.json with 'all: true' for full source reporting.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
- ResultsCollector: collect V8 coverage via page.coverage API when COLLECT_COVERAGE=1
  Coverage is started in load() and flushed in results()/waitForMessage()/outgoingMessages()
- Add 'coverage' project to playwright.config.js (re-runs windows specs for coverage)
- Add merge-coverage.js script using monocart-coverage-reports
- Add npm scripts: coverage-int, coverage-merge, coverage-full
- Support C_S_S_SOURCEMAPS=1 for source-mapped builds

Unit test coverage (c8): 57.86% statements, 57.7% lines
Integration test coverage (Playwright): 14.77% statements, 42.04% lines
Combined gives full picture of injected/src/ coverage.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
Split the single integration-tests job into parallel jobs:
- 7 injected project shards (windows, apple-isolated, apple, ios, android, android-autofill-import, chrome-mv3)
- 1 special-pages job (unchanged behavior)

Each shard runs independently with fail-fast: false, enabling parallel execution.
Upload separate playwright reports per shard for easier debugging.

Update integration and ci-gate dependencies to match new job structure.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
…ranches

- trackers.spec.js: trie traversal, subdomain matching, dead ends, global hostname
- performance.spec.js: PerformanceMonitor.mark(), measureAll(), PerformanceMark lifecycle
- dom-utils.js: trustedUnsafe(), createPolicy(), XSS escaping, error on unknown objects
- config-feature-properties: URL pattern matching, injectName matching

572 specs, 0 failures

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
…ion, wrapToString

Cover all edge cases: null objects, missing properties, descriptor type mismatches,
method wrapping with wrapper functions, proxy toString behavior.

587 specs, 0 failures

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
…FeatureBroken, isGloballyDisabled

Cover withRetry (linear/exponential backoff, success, failure, throwing),
stack trace URL extraction, feature broken/platform-specific checks,
and global disabled state checks.

Fix NaN comparison in withDefaults property test using Object.is().

604 specs, 0 failures

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
The original test-int-x uses --grep-invert '@Screenshots' to skip screenshot
comparison tests. The sharded CI command was missing this filter, causing
failures when snapshot files don't exist.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
The trackers test called setGlobal() with a mock missing Error, which
corrupted the module-level Error reference in utils.js. This caused
withRetry tests to fail with 'Error is not a constructor'.

Fix: include Error in the mock global + restore original global in afterEach.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
…conditionalChanges, canvas modifyPixelData, utils isDuckAi/isDuckAiSidebar/shouldExemptUrl/createCustomEvent

New tests for previously uncovered branches:
- dom-utils.js: trustedTypes.createPolicy branch
- config-feature.js: object urlPattern matching, conditionalChanges patch application, fallback to domains, invalid patch handling
- canvas.js: modifyPixelData determinism, transparent pixel skip, adjacent-same skip, domain key variation
- utils.js: isDuckAi/isDuckAiSidebar (mock globalThis.top), createCustomEvent, shouldExemptUrl, nextRandom, isBeingFramed

628 specs, 0 failures

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
When fast-check generates '__proto__' as a computed property key,
`{ [key]: value }` sets the prototype instead of creating a normal
property. Filter these keys from the generated inputs.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
Date.toUTCString() can produce strings that new Date() parses differently
on Windows, resulting in NaN expiry. Relax the assertion to check type
rather than value.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
…e-coverage-8260

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
…ush, clean up coverage project

1. Auto-discover features in integration.js: derive enabledFeatures from
   platformSupport.integration instead of hardcoded list, filtering out features
   requiring messaging backends (clickToLoad, brokerProtection, autofillImport).
   Prevents feature drift when new features are added.

2. Simplify coverage flushing: remove auto-flush from results(), waitForMessage(),
   and outgoingMessages(). flushCoverage() is now a single explicit call that
   consumers invoke at the end of their test. Eliminates race conditions and
   fragile multi-flush pattern.

3. Clean up coverage project: remove unused collectCoverage flag, add JSDoc
   documenting the explicit flushCoverage() usage pattern.

All tests pass: 628 unit specs, 88 chrome-mv3 integration tests, 30 pages.spec.js.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
- Revert test-unit to fast path (jasmine without c8) — 70s vs 220s
- Add test-unit-coverage script for explicit coverage runs
- Add .github/workflows/coverage.yml:
  - Runs nightly at 03:00 UTC + manual trigger via workflow_dispatch
  - Unit coverage job: runs c8-instrumented unit tests
  - Integration coverage job: runs Playwright with V8 coverage collection
  - Report job: merges unit + integration coverage, uploads as artifact
  - All coverage artifacts retained for 30 days
- Rename coverage scripts for clarity:
  - coverage-int: runs integration tests with COLLECT_COVERAGE=1
  - coverage-report: generates merged report via monocart

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
@jonathanKingston jonathanKingston marked this pull request as ready for review February 13, 2026 19:08
@jonathanKingston jonathanKingston requested a review from a team as a code owner February 13, 2026 19:08
Comment thread injected/integration-test/page-objects/results-collector.js
The separate 'coverage' project was a duplicate of 'windows'. Since
coverage collection is gated by COLLECT_COVERAGE=1 in ResultsCollector,
it works on any non-extension project with zero overhead when disabled.

coverage-int now runs: COLLECT_COVERAGE=1 playwright test --project windows

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Comment thread injected/integration-test/page-objects/results-collector.js
Comment thread injected/integration-test/page-objects/results-collector.js Outdated
Comment thread .github/workflows/tests.yml
cursoragent and others added 3 commits February 13, 2026 19:55
The firefox project (running remote-pages.spec.js) was silently dropped
when refactoring from a single test-int-x command to per-project matrix.
Restore it to maintain Firefox integration test coverage.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
The field declaration was between the @param JSDoc and the constructor,
causing IDE tooling to misattribute the documentation.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
flushCoverage() was intentionally made explicit (not sprinkled across
multiple methods) but needs at least one call site. results() is the
standard exit path for all non-extension test specs, so it's the single
right place. The #coverageStarted flag prevents double-stops, and the
COLLECT_COVERAGE env gate means zero overhead in normal test runs.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
Comment thread injected/unit-test/utils-properties.spec.js Outdated
processAttr is always called with config objects and concrete defaults
(numbers, strings, booleans, null) — never with arbitrary values like NaN.
Replace fc.anything() with explicit realistic defaults to avoid the
NaN !== NaN comparison issue and better reflect actual usage.

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
Comment thread injected/unit-test/utils-properties.spec.js Outdated
The defaultValue parameter is provided by feature authors (e.g.
getFeatureAttr('key', 2)), not from config. Updated comment to
reflect this.

Follow-up issue for NaN support: #2268

Co-authored-by: Jonathan Kingston <jonathanKingston@users.noreply.github.com>
@jonathanKingston jonathanKingston added this pull request to the merge queue Feb 13, 2026
Merged via the queue into main with commit 4e96b9a Feb 13, 2026
31 checks passed
@jonathanKingston jonathanKingston deleted the jkt/auto/injected-code-coverage-8260 branch February 13, 2026 20:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants