← ClaudeAtlas

wp-phpunit-redirect-harnesslisted

Use when WordPress PHPUnit tests exercise code that calls wp_safe_redirect()/wp_redirect() followed by exit/die, or when the suite mysteriously stops early and prints no "Tests:" summary. Installs a throwing-filter harness so redirect+exit paths become assertable.
mralaminahamed/wp-dev-skills · ★ 3 · Testing & QA · score 76
Install: claude install-skill mralaminahamed/wp-dev-skills
# PHPUnit Harness for `wp_safe_redirect(); exit;` ## The problem Production code commonly does: ```php wp_safe_redirect( $url ); exit; ``` Under PHPUnit, `add_filter( 'wp_redirect', '__return_false' )` stops the header but **does NOT stop `exit`** — the next statement runs and terminates the whole PHP process. PHPUnit dies mid-run: exit code 0, no `Tests: N` summary, and every test after the first redirect test silently never runs. Symptom: "the suite passes but prints no summary" or "stops at ~N%". ## The fix — throw instead of redirect, catch instead of exit Throwing from the `wp_redirect` filter unwinds the stack **before** `exit;` is reached. ### 1. A shared exception (own PSR-4 file so both unit + integration tests can use it) ```php namespace MyPlugin\Test; class Redirect extends \Exception { public string $location; public function __construct( string $location ) { parent::__construct( 'redirect' ); $this->location = $location; } } ``` Put it in its own file (e.g. `tests/.../Redirect.php`) so the autoloader finds it regardless of which test file loads first — never inline in one test file. ### 2. Throwing filter in `set_up`, removed in `tear_down` ```php $this->redirect_filter = static function ( $location ) { throw new Redirect( (string) $location ); }; add_filter( 'wp_redirect', $this->redirect_filter, 10, 1 ); // tear_down: remove_filter( 'wp_redirect', $this->redirect_filter, 10 ); ``` ### 3. A run helper that catches it