Skip to content

qa: add 10 E2E tests covering JS-disabled, adblock bypass, plugin health#222

Merged
parhumm merged 4 commits intodevelopmentfrom
qa/cover-test-gaps
Mar 15, 2026
Merged

qa: add 10 E2E tests covering JS-disabled, adblock bypass, plugin health#222
parhumm merged 4 commits intodevelopmentfrom
qa/cover-test-gaps

Conversation

@parhumm
Copy link
Copy Markdown
Contributor

@parhumm parhumm commented Mar 15, 2026

Summary

Adds 10 new Playwright E2E tests across 3 spec files to close the test gaps identified in the PR #170 consolidated QA summary. Also updates Playwright config with performance/diagnostic improvements.

New Spec Files

Spec Tests What it covers
server-side-tracking-js-disabled.spec.ts 3 Validates server-side PHP tracking (javascript_mode=off, the default mode) works when the browser has JavaScript disabled. Also confirms client-only mode produces no tracking when JS is off.
adblock-bypass-fallback.spec.ts 3 End-to-end validation of the adblock_bypass transport method. Confirms hits are recorded through the obfuscated /request/{hash}/ URL, that blocking REST+AJAX forces fallback, and that blocking all transports causes graceful failure (no JS crash, no DB row).
plugin-health-checks.spec.ts 4 Automates manual QA checklist items: plugin deactivate/reactivate cycle, PHP error log cleanliness, all 6 admin pages render HTTP 200, GDPR consent banner visibility.

Infrastructure Changes

  • 2 new mu-plugins: rewrite-flush-mu-plugin.php and plugin-lifecycle-mu-plugin.php. Both guarded by SLIMSTAT_E2E_TESTING constant.
  • setup.ts: Added installRewriteFlush/installPluginLifecycle helpers (same pattern as installHeaderInjector).
  • run-all.sh: Added Batch H with the 3 new spec files.
  • playwright.config.ts: trace on-first-retry, screenshot only-on-failure, video retain-on-failure, maxFailures CI-only.

Test Results (10/10 PASS)

  • server-side tracking records hit when browser JS is disabled (7.5s)
  • client-only mode does NOT track when browser JS is disabled (15.3s)
  • server-side tracking records hit with JS enabled - control (43.7s)
  • adblock_bypass transport records a pageview in the database (35.3s)
  • blocking REST and AJAX forces fallback to adblock bypass (41.0s)
  • blocking all transports causes no JS crash and no DB row (44.9s)
  • plugin deactivation and reactivation completes without errors (12.0s)
  • no PHP fatal errors or warnings from SlimStat after page visits (53.7s)
  • all SlimStat admin pages render with HTTP 200 (30.9s)
  • GDPR consent banner is visible when enabled (48.5s)

Why You Can Trust These Results

  1. Correlation ID isolation: Every test uses a unique Date.now() marker. DB assertions query only by that marker.
  2. Hermetic state: snapshotSlimstatOptions/restoreSlimstatOptions in beforeEach/afterEach ensures clean state.
  3. API-first setup: Settings mutations use setSlimstatOption (AJAX), not UI navigation.
  4. Real browser contexts: JS-disabled tests use browser.newContext({ javaScriptEnabled: false }). Adblock tests use page.route() to block endpoints. No mocking.
  5. wp-config constant injection: New mu-plugins use dedicated install/uninstall helpers (same pattern as installHeaderInjector).
  6. Independent verification: Tests ran twice. First run caught 3 issues, all fixed and verified in second run.

Test plan

  • Run 3 new spec files individually - 10/10 pass
  • Run via Batch H in run-all.sh order
  • Full suite regression via bash tests/e2e/run-all.sh

Summary by CodeRabbit

  • Tests
    • Added end-to-end coverage for ad‑blocker bypass fallback, server‑side tracking with JavaScript disabled, and plugin health checks (including lifecycle and GDPR banner validation).
    • Improved test runner behavior: retries, tracing and video retention, and CI failure handling.
  • Chores
    • Added test helpers to manage plugin lifecycle and to flush rewrite rules for E2E testing.

parhumm added 2 commits March 15, 2026 12:25
…nd plugin health

- Gap 1: server-side-tracking-js-disabled.spec.ts (3 tests) — validates
  server-side PHP tracking works when browser JS is disabled
- Gap 2: adblock-bypass-fallback.spec.ts (3 tests) — validates adblock
  bypass transport records hits and graceful failure when all blocked
- Gap 3: plugin-health-checks.spec.ts (4 tests) — automates manual QA
  checklist: deactivate/reactivate, PHP error log, admin pages, GDPR banner
- Infrastructure: 2 new mu-plugins, setup.ts helpers, Batch H in run-all.sh
- Config: trace on-first-retry, screenshot on-failure, maxFailures=10
Prevents maxFailures=10 from stopping the suite early when pre-existing
flaky tests (cloudflare-ip, consent-banner) fail on local dev environment.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 15, 2026

Warning

Rate limit exceeded

@parhumm has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 20 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b8562981-e026-416b-bb0d-9532da9efe33

📥 Commits

Reviewing files that changed from the base of the PR and between 0332a96 and 69e9617.

📒 Files selected for processing (1)
  • tests/e2e/adblock-bypass-fallback.spec.ts
📝 Walkthrough

Walkthrough

Adds multiple end-to-end Playwright test suites, two MU-plugin helpers exposing AJAX endpoints for test control, supporting test setup utilities, and Playwright/runtime config tweaks for retries, tracing, and CI behavior.

Changes

Cohort / File(s) Summary
Ad-blocker Bypass Tests
tests/e2e/adblock-bypass-fallback.spec.ts
New Playwright E2E tests verifying transport fallback (REST → admin-ajax → adblock-bypass), request capture, route blocking scenarios, and DB row assertions.
Server-side Tracking Tests
tests/e2e/server-side-tracking-js-disabled.spec.ts
New Playwright E2E tests validating server-side tracking when browser JS is disabled, plus control and client-only scenarios.
Plugin Health & Lifecycle Tests
tests/e2e/plugin-health-checks.spec.ts
New suite for plugin deactivate/reactivate flows via AJAX, PHP error-log checks, admin page HTTP 200 validations, and GDPR banner visibility checks.
MU-Plugin Helpers (PHP)
tests/e2e/helpers/plugin-lifecycle-mu-plugin.php, tests/e2e/helpers/rewrite-flush-mu-plugin.php
New MU-plugins exposing AJAX endpoints: e2e_activate_plugin / e2e_deactivate_plugin and e2e_flush_rewrite_rules; guarded by SLIMSTAT_E2E_TESTING and permission checks.
Test Setup Utilities
tests/e2e/helpers/setup.ts
Adds install/uninstall helpers and manifests for the two MU-plugins; note: duplicated helper definitions present for each MU-plugin.
Playwright Config & Runner
tests/e2e/playwright.config.ts, tests/e2e/run-all.sh
CI/local retry and tracing policy updates, retain-on-failure video, maxFailures for CI; new test batch H added to run-all.sh including the new suites.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related issues

Possibly related PRs

Poem

"I'm a rabbit in the test-run light,
Hopping through rewrites late at night.
Plugins toggle, traces keep,
Ad-blockers chase — but hits still creep.
Cheers — the green tests pass in sight!" 🐰✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding 10 E2E tests covering three key areas (JS-disabled tracking, adblock bypass, plugin health checks), which aligns with the substantial test additions across three spec files and infrastructure changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch qa/cover-test-gaps
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
tests/e2e/helpers/plugin-lifecycle-mu-plugin.php (1)

1-47: Consider using tabs for indentation.

Same as the rewrite-flush MU-plugin, this file uses 4-space indentation rather than tabs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/helpers/plugin-lifecycle-mu-plugin.php` around lines 1 - 47, The
file uses 4-space indentation for the anonymous AJAX handlers (hooks
wp_ajax_e2e_deactivate_plugin and wp_ajax_e2e_activate_plugin); convert the
leading spaces to tabs throughout the file so indentation matches the project's
tab style (apply to the function blocks, array formatting in
wp_send_json_success calls, and any other indented lines in this MU-plugin).
tests/e2e/helpers/rewrite-flush-mu-plugin.php (1)

1-23: Consider using tabs for indentation.

The file uses 4-space indentation, but the coding guidelines specify tabs for PHP files. This is a minor consistency issue for a test helper.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/helpers/rewrite-flush-mu-plugin.php` around lines 1 - 23, The file
uses 4-space indentation instead of tabs; update the indentation to tabs
throughout this MU-plugin test helper (the add_action callback block registering
'wp_ajax_e2e_flush_rewrite_rules', including the anonymous function body that
calls flush_rewrite_rules( true ) and wp_send_json_success( [ 'flushed' => true
] )). Ensure all leading spaces are replaced with tabs to comply with the PHP
coding guidelines while keeping the same logic and function names unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/e2e/adblock-bypass-fallback.spec.ts`:
- Around line 88-94: The computed boolean hasAdblockRequest (derived from
postUrls) is unused; either assert it to verify the adblock bypass transport or
remove it and the related comment—update the test in
adblock-bypass-fallback.spec.ts by adding expect(hasAdblockRequest).toBe(true)
(or toBeTruthy()) after computing hasAdblockRequest to validate the tracker used
the adblock_bypass path, or delete the hasAdblockRequest variable and its
comment if any-transport acceptance is intended; refer to the hasAdblockRequest
variable, postUrls array, and existing expect(stat).not.toBeNull() when making
the change.

In `@tests/e2e/helpers/rewrite-flush-mu-plugin.php`:
- Around line 20-23: The AJAX handler hooked to
'wp_ajax_e2e_flush_rewrite_rules' mutates server state without verifying
permissions; update the anonymous function to first ensure SLIMSTAT_E2E_TESTING
is set, then validate a request nonce using wp_verify_nonce() (matching the
pattern in nonce-helper-mu-plugin.php), and check
current_user_can('manage_options') before calling flush_rewrite_rules(true); if
either check fails, return early with wp_send_json_error (or wp_die) and an
appropriate message; keep the final successful path using wp_send_json_success([
'flushed' => true ]) after the checks.

---

Nitpick comments:
In `@tests/e2e/helpers/plugin-lifecycle-mu-plugin.php`:
- Around line 1-47: The file uses 4-space indentation for the anonymous AJAX
handlers (hooks wp_ajax_e2e_deactivate_plugin and wp_ajax_e2e_activate_plugin);
convert the leading spaces to tabs throughout the file so indentation matches
the project's tab style (apply to the function blocks, array formatting in
wp_send_json_success calls, and any other indented lines in this MU-plugin).

In `@tests/e2e/helpers/rewrite-flush-mu-plugin.php`:
- Around line 1-23: The file uses 4-space indentation instead of tabs; update
the indentation to tabs throughout this MU-plugin test helper (the add_action
callback block registering 'wp_ajax_e2e_flush_rewrite_rules', including the
anonymous function body that calls flush_rewrite_rules( true ) and
wp_send_json_success( [ 'flushed' => true ] )). Ensure all leading spaces are
replaced with tabs to comply with the PHP coding guidelines while keeping the
same logic and function names unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ad1f1932-5eac-4db9-90e2-5c7172fc3a79

📥 Commits

Reviewing files that changed from the base of the PR and between a3d6ce8 and e20e6c2.

📒 Files selected for processing (8)
  • tests/e2e/adblock-bypass-fallback.spec.ts
  • tests/e2e/helpers/plugin-lifecycle-mu-plugin.php
  • tests/e2e/helpers/rewrite-flush-mu-plugin.php
  • tests/e2e/helpers/setup.ts
  • tests/e2e/playwright.config.ts
  • tests/e2e/plugin-health-checks.spec.ts
  • tests/e2e/run-all.sh
  • tests/e2e/server-side-tracking-js-disabled.spec.ts

Comment on lines +20 to +23
add_action( 'wp_ajax_e2e_flush_rewrite_rules', function () {
flush_rewrite_rules( true );
wp_send_json_success( [ 'flushed' => true ] );
} );
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add capability check for the AJAX handler.

The e2e_flush_rewrite_rules action modifies server state without verifying user capabilities. While the SLIMSTAT_E2E_TESTING guard provides some protection, adding a capability check aligns with WordPress security best practices and the pattern used in nonce-helper-mu-plugin.php.

🛡️ Proposed fix
 add_action( 'wp_ajax_e2e_flush_rewrite_rules', function () {
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( 'Insufficient permissions', 403 );
+    }
+
     flush_rewrite_rules( true );
     wp_send_json_success( [ 'flushed' => true ] );
 } );

As per coding guidelines: "Perform nonce check and capability check for every state-changing action using wp_verify_nonce() and current_user_can() with manage_options."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/helpers/rewrite-flush-mu-plugin.php` around lines 20 - 23, The AJAX
handler hooked to 'wp_ajax_e2e_flush_rewrite_rules' mutates server state without
verifying permissions; update the anonymous function to first ensure
SLIMSTAT_E2E_TESTING is set, then validate a request nonce using
wp_verify_nonce() (matching the pattern in nonce-helper-mu-plugin.php), and
check current_user_can('manage_options') before calling
flush_rewrite_rules(true); if either check fails, return early with
wp_send_json_error (or wp_die) and an appropriate message; keep the final
successful path using wp_send_json_success([ 'flushed' => true ]) after the
checks.

…ck, fix indentation

- Assert hasAdblockRequest instead of leaving it unused
- Add current_user_can('manage_options') check to rewrite-flush mu-plugin
- Convert both mu-plugins from spaces to tabs (project PHP style)
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
tests/e2e/adblock-bypass-fallback.spec.ts (1)

147-154: Consider anchoring the hash URL pattern.

The regex /\/[a-f0-9]{32}/ matches any 32-character hex sequence in the URL path. While this works for testing, a more precise pattern like /\/[a-f0-9]{32}(?:\/|$)/ would ensure it matches complete path segments (ending with / or end of path). This is a minor nitpick for test code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/e2e/adblock-bypass-fallback.spec.ts` around lines 147 - 154, The regex
used in anonPage.route to block the adblock bypass hash (/\/[a-f0-9]{32}/) is
too permissive; update the route matcher in the anonPage.route call to anchor
the segment so it only matches full 32-char hex path segments (e.g., change to a
pattern that requires a trailing slash or end-of-path such as
/\/[a-f0-9]{32}(?:\/|$)/) so the route.abort('blockedbyclient') only triggers
for complete hash path segments.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/e2e/adblock-bypass-fallback.spec.ts`:
- Around line 147-154: The regex used in anonPage.route to block the adblock
bypass hash (/\/[a-f0-9]{32}/) is too permissive; update the route matcher in
the anonPage.route call to anchor the segment so it only matches full 32-char
hex path segments (e.g., change to a pattern that requires a trailing slash or
end-of-path such as /\/[a-f0-9]{32}(?:\/|$)/) so the
route.abort('blockedbyclient') only triggers for complete hash path segments.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7063460a-101c-4a8e-b8bf-f024c8b847f5

📥 Commits

Reviewing files that changed from the base of the PR and between e20e6c2 and 0332a96.

📒 Files selected for processing (3)
  • tests/e2e/adblock-bypass-fallback.spec.ts
  • tests/e2e/helpers/plugin-lifecycle-mu-plugin.php
  • tests/e2e/helpers/rewrite-flush-mu-plugin.php

@parhumm parhumm merged commit 354ee40 into development Mar 15, 2026
1 check passed
@parhumm parhumm deleted the qa/cover-test-gaps branch March 15, 2026 12:43
@parhumm parhumm mentioned this pull request Mar 15, 2026
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.

1 participant