Skip to content

Closes #66: expose the requests HttpRequestTrait received - #67

Merged
remyperona merged 2 commits into
developfrom
enhancement/66-httprequesttrait-expose-the-requests
Oct 28, 2026
Merged

remyperona merged 2 commits into
developfrom
enhancement/66-httprequesttrait-expose-the-requests

Conversation

@remyperona

@remyperona remyperona commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

🤖 AI-generated — created by an automated pipeline. Review before acting on this.

Closes #66

Description

HttpRequestTrait now records every outbound request it receives, so tests can assert on the request itself (method, headers, body, call count) without adding their own pre_http_request spy filter.

What was done

  • HttpRequestTrait::http_callback() appends each request (url and parsed args) to a per-test log before any mock lookup, so mocked and blocked requests are both recorded.
  • New protected get_http_requests( $url = null ) returns the full log in order, or only the entries whose URL matches exactly.
  • reset_http() clears the log, so it is empty at the start of each test and after teardown.
  • The class docblock documents the accessor, the shape of args, and the limitation that only requests reaching the priority-10 filter are logged.
  • Tests added to Tests/Integration/testHttpRequestTrait.php (9 new methods) covering order, parsed args, exact-URL filtering, response lists, blocked requests, and reset on setup and teardown.

How to test

  1. Run the integration suite (npm run test:php:integration, or composer test-integration with a WP test suite installed). The Test_HttpRequestTrait tests must pass.
  2. Check each acceptance criterion from HttpRequestTrait: expose the requests it received so tests can assert on them #66:
    • get_http_requests() returns every request of the current test, in order, with url and args.
    • get_http_requests( $url ) returns only requests to that exact URL (no match on trailing slash, query string or case).
    • Unmocked (blocked) requests appear in the log, and the test still fails at teardown as before.
    • The log is empty at the start of each test.
  3. Run composer phpcs and composer phpstan; both should pass with no baseline change.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring / maintenance (no functional change)

Affected Features & Quality Assurance Scope

  • src/Integration/HttpRequestTrait.php: request logging, get_http_requests(), reset lifecycle, class docblock.
  • Tests/Integration/testHttpRequestTrait.php: new coverage for the log.
  • Existing composition tests (testHttpRequestTraitPropertyComposition.php, testHttpRequestTraitWithVirtualFilesystem.php) are unchanged and must stay green.
  • Consumers of HttpRequestTrait (any integration test class using it) gain a new protected method and a private property. No existing signature changes.

Technical description

The log is a private array property, $http_request_log, that http_callback() appends to as its first statement, so the existing lookup and blocking logic is untouched. The entry is [ 'url' => $url, 'args' => $args ], where $args is what WordPress passes to pre_http_request after default args are merged and http_request_args filters are applied. The property name avoids core's $blocked_http_requests (see #62).

get_http_requests() returns the array unchanged when no URL is given. When a URL is given, it filters with a strict comparison and wraps the result in array_values(), so get_http_requests( $url )[0] is valid. reset_http(), already called from setup_http() and tear_down_http(), empties the log, so the log only covers the window between setup and teardown.

New dependencies

None.

Risks

  • Compatibility: a consuming test class that already defines a method named get_http_requests or a property named $http_request_log would clash with the trait. Low likelihood; accepted per the issue.
  • Limitation, not a regression: a filter at a priority below 10 that short-circuits a request hides it from the log. Documented in the class docblock.
  • Performance: one array entry per outbound request during a test. Negligible for integration suites.
  • Security: none identified. Logged args (including headers and body) are held in memory only for the duration of the test.

What was tested

QA report: #67 (comment)

# Acceptance criterion Method Result
1 get_http_requests() returns every request, in order, with url and args Scratch consumer test in wp-env (POST with body/headers, query-string URL, repeated URL): 3 entries in call order, args parsed (method POST, body) ✅ PASS
2 get_http_requests( $url ) returns only requests to that exact URL Scratch test + PR tests: exact match only; trailing slash, query string, case and unknown URLs return []; keys re-indexed from 0 ✅ PASS
3 Blocked (unmocked) requests are logged Scratch test: unmocked request appears in the log and the test still fails at teardown with the existing "fixture does not mock" message ✅ PASS
4 Log is empty at the start of each test Mutation check: removing reset_http() from setup_http() makes testShouldStartWithEmptyLogOnSetup fail (the only failure of 40); restored, all green ✅ PASS
5 Covered in Tests/Integration/testHttpRequestTrait.php 9 new tests, all passing ✅ PASS
6 PHPCS and PHPStan pass phpcs clean (11/11 files), PHPStan [OK] No errors, no baseline change ✅ PASS

Suites: npm run test:php in wp-env (PHP 8.3): unit 126, integration 40, admin integration 3 — all OK.
CI: phpcs, PHPStan, WP 5.9 / PHP 7.4, WP latest / PHP 8.0–8.5 — all green on 248564b.
PHP 7.4: php -l on both changed files with PHP 7.4.30 — no errors.

🤖 Generated with Claude Code

Log every request reaching http_callback() (mocked or blocked) and add a
protected get_http_requests( $url = null ) accessor, cleared per test.

Closes #66

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@remyperona remyperona self-assigned this Oct 28, 2026
@remyperona

remyperona commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor Author

Note

Generated by the AI delivery pipeline (lead-reviewer · Claude Opus 5.5).

Review: ✅ PASS

Re-review of 248564b: the earlier test-strength nice-to-have is resolved. testShouldStartWithEmptyLogOnSetup now asserts 1 logged request, calls setup_http() again without tearing down, and asserts [], so it fails if setup_http() stops calling reset_http(). A second setup_http() does not leak a filter: _wp_filter_build_unique_id() keys [ $this, 'http_callback' ] as spl_object_id( $this ) . 'http_callback' at priority 10, so the second add_filter() replaces the first and the real tear_down() removes it.

Nice-to-haves:

  • src/Integration/HttpRequestTrait.php — the class docblock addition is about 13 lines. It follows the spec and the surrounding docblock, so it is not a blocker. If the docblock grows further, move it to a docs file.

@remyperona

remyperona commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor Author

Note

Generated by the AI delivery pipeline (qa-engineer · Claude Opus 5.5).

QA (re-run after 248564b): ✅ PASS

Acceptance Criterion Method Result
1. get_http_requests() returns every request in order with url and args Carried forward from run 1 ✅
2. get_http_requests( $url ) filters by exact URL Carried forward from run 1 ✅
3. Blocked (unmocked) requests are logged Carried forward from run 1 ✅
4. Log is empty at the start of each test npm run test:php in wp-env + mutation check: with reset_http() removed from setup_http(), testShouldStartWithEmptyLogOnSetup fails (assertion at Tests/Integration/testHttpRequestTrait.php:347, the only failure out of 40); restored, all green. Change reverted, working tree clean. ✅
5. Covered in Tests/Integration/testHttpRequestTrait.php npm run test:php in wp-env: unit 126 OK, integration 40 OK, admin integration 3 OK ✅
6. PHPCS and PHPStan pass composer phpcs clean (11/11 files), PHPStan [OK] No errors (PHP 8.3.8) ✅

The test previously called tear_down_http() before setup_http(), so it
would still pass if setup_http() stopped resetting. Call setup_http()
again with a populated log instead (the filter registration is
idempotent). Refs #66.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@remyperona
remyperona marked this pull request as ready for review October 28, 2026 20:12
@remyperona
remyperona merged commit 4c09f25 into develop Oct 28, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant