Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
9321582
build: support PHPUnit 9–13 and PHP 7.4+ (composer range + dual configs)
unfulvio Jun 23, 2026
449dd59
refactor: IsEqualHtml uses matches()/toString(), drop IsEqual coupling
unfulvio Jun 23, 2026
ce80705
refactor!: drop removed PHPUnit-10+ internals from TestCase + depreca…
unfulvio Jun 23, 2026
fb21c79
test: dual-declare PHPUnit attributes for PHPUnit 9–13 compatibility
unfulvio Jun 23, 2026
953afa7
chore: phpstan v2 baseline + harden IsEqualHtml::matches() for level max
unfulvio Jun 23, 2026
09323ea
ci: test PHP 7.4–8.4 × PHPUnit 9–13 matrix; phpcs testVersion 7.4-
unfulvio Jun 23, 2026
134eeba
docs: document PHPUnit 9–13 support, assertOutputEqualsHtml, and 2.0.…
unfulvio Jun 23, 2026
0398494
test: restore the Behat suite (broken since ~1.1.0)
unfulvio Jun 23, 2026
1c71d45
fix: expectFilterNotAdded() default $args 10 -> 1 so it actually guar…
unfulvio Jun 23, 2026
69b0a64
ci: upload Coveralls from a single leg, consistent with origin
unfulvio Jun 23, 2026
c297cc0
chore: keep the phpstan v2 baseline lean so the migration adds no debt
unfulvio Jun 23, 2026
dc80714
docs: point the 2.0.0 changelog compare link at the 2.0.0 tag
unfulvio Jun 23, 2026
5332841
fix(ci): named deprecation-test fixture + raise patchwork floor for p…
unfulvio Jun 23, 2026
7b053ab
ci: measure coverage on the PHPUnit 9 leg (consistent with origin)
unfulvio Jun 23, 2026
3bc10a5
feat!: drop PHPUnit 9, raise floor to PHP 8.1 / PHPUnit 10
unfulvio Jun 24, 2026
221736a
refactor(tests): shape getDeprecatedMethodCalls() return type
unfulvio Jun 24, 2026
09616d7
fix(deprecation): tidy DeprecatedMethodListener message + widen @throws
unfulvio Jul 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 62 additions & 37 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,41 @@ on:
jobs:
php-tests:
runs-on: ${{ matrix.os }}
name: ${{ matrix.label }}
strategy:
matrix:
include:
- php: '8.4'
os: 'ubuntu-latest'
config: 'phpunit.xml.dist'
label: 'PHP 8.4 · PHPUnit 13'
- php: '8.3'
os: 'ubuntu-latest'
config: 'phpunit.xml.dist'
label: 'PHP 8.3 · PHPUnit 12'
- php: '8.2'
os: 'ubuntu-latest'
config: 'phpunit.xml.dist'
label: 'PHP 8.2 · PHPUnit 11'
- php: '8.1'
os: 'ubuntu-latest'
config: 'phpunit.xml.dist'
label: 'PHP 8.1 · PHPUnit 10'
- php: '8.0'
os: 'ubuntu-24.04'
config: 'phpunit9.xml.dist'
label: 'PHP 8.0 · PHPUnit 9'
- php: '7.4'
os: 'ubuntu-24.04'
config: 'phpunit9.xml.dist'
label: 'PHP 7.4 · PHPUnit 9'
- php: '7.4'
os: 'ubuntu-24.04'
config: 'phpunit9.xml.dist'
composer_flags: '--prefer-lowest'
label: 'PHP 7.4 · PHPUnit 9 (lowest deps)'
fail-fast: false
env:
COVERAGE_CACHE_PATH: phpunit-coverage-cache
PHP_VERSION: ${{ matrix.php }}

steps:
Expand All @@ -39,86 +58,92 @@ jobs:

- name: Get Composer cache directory
id: composer-cache
run: |
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
key: ${{ runner.os }}-php${{ matrix.php }}-composer-${{ matrix.composer_flags }}-${{ hashFiles('composer.json') }}
restore-keys: |
${{ runner.os }}-composer-
${{ runner.os }}-php${{ matrix.php }}-composer-

# Resolve dependencies per PHP version: a single committed lock cannot satisfy
# every supported PHP/PHPUnit pair (PHPUnit 9–13 span PHP 7.4–8.4), so each leg
# updates to the highest PHPUnit its PHP allows (Composer picks 9/10/11/12/13).
- name: Install dependencies
run: composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
run: composer update ${{ matrix.composer_flags }} --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist

- name: Restore phpunit coverage cache
uses: actions/cache@v4
with:
path: ${{ env.COVERAGE_CACHE_PATH }}
key: ${{ runner.os }}-coverage-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-coverage-${{ github.ref }}-
${{ runner.os }}-coverage-
# Tests should be run randomly to catch any test dependency issue.
- name: Execute tests with PHPUnit
if: ${{ matrix.php != '8.0' }}
run: vendor/bin/phpunit -c ${{ matrix.config }} --order-by=random

- name: Execute tests with PHPUnit and output code coverage report
env:
DB_CONNECTION: sqlite
DB_DATABASE: database/database.sqlite
# Generate coverage file, so it can be uploaded later if we choose.
# Otherwise, current coverage can be viewed in the action output.
# Tests should be run randomly to catch any test dependency issue.
run: |
vendor/bin/phpunit --order-by="random" --coverage-cache="$COVERAGE_CACHE_PATH" --coverage-clover=./clover.xml --coverage-text
if: ${{ matrix.php == '8.0' }}
run: vendor/bin/phpunit -c ${{ matrix.config }} --order-by=random --coverage-clover=./clover.xml --coverage-text

- name: Upload test coverage results to Coveralls
if: ${{ env.PHP_VERSION == '8.1' }}
if: ${{ matrix.php == '8.0' }}
env:
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
vendor/bin/php-coveralls --coverage_clover="./clover.xml" --json_path="./coveralls-upload.json" -v
run: vendor/bin/php-coveralls --coverage_clover="./clover.xml" --json_path="./coveralls-upload.json" -v

php-compatibility:
runs-on: ubuntu-latest
name: PHP compatibility (7.4+)

steps:
- uses: actions/checkout@v4

- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
coverage: none

- name: Get Composer Cache Directory
id: composer-cache
run: |
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
key: ${{ runner.os }}-phpcompat-composer-${{ hashFiles('composer.json') }}
restore-keys: |
${{ runner.os }}-composer-
${{ runner.os }}-phpcompat-composer-

- name: Install Dependencies
run: composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --ignore-platform-req php
run: composer update --no-ansi --no-interaction --no-progress --prefer-dist --ignore-platform-req=php

- name: Run PHP Code Sniffer using the PHPCompatibility standard
run: vendor/bin/phpcs

php-static-analysis:
runs-on: ubuntu-latest
name: Static analysis

steps:
- uses: actions/checkout@v4

- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
coverage: none

- name: Get Composer Cache Directory
id: composer-cache
run: |
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
key: ${{ runner.os }}-phpstan-composer-${{ hashFiles('composer.json') }}
restore-keys: |
${{ runner.os }}-composer-
${{ runner.os }}-phpstan-composer-

- name: Install Dependencies
run: |
composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
run: composer update --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist

- name: Run phpstan
run: vendor/bin/phpstan
run: vendor/bin/phpstan analyse --no-progress
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,28 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.0.0](https://github.com/10up/wp_mock/compare/1.1.1...2.0.0) - Unreleased

WP_Mock now supports PHPUnit 9.6, 10, 11, 12 and 13 from a single codebase. The minimum PHP version is unchanged (7.4); Composer installs the highest PHPUnit version your PHP allows. Most projects can upgrade by bumping only `10up/wp_mock` — see [UPGRADE.md](https://github.com/10up/wp_mock/blob/trunk/UPGRADE.md).

### Added
- Support for PHPUnit 10, 11, 12 and 13 (in addition to 9.6)
- `TestCase::assertOutputEqualsHtml(string $expectedHtml, callable $callback)` for whitespace-insensitive assertions on echoed HTML output

### Changed
- **BREAKING:** deprecated WP_Mock methods now emit a native `E_USER_DEPRECATED` notice (via `trigger_error()`) instead of forcing a test to be marked "risky". To fail tests on these, set `failOnDeprecation="true"` (PHPUnit 10+) or `convertDeprecationsToExceptions="true"` (PHPUnit 9) in your configuration.
- **BREAKING:** removed the implicit output filtering and the `@stripTabsAndNewlinesFromOutput` annotation — including the `TestCase::expectOutputString()` override — because PHPUnit 10 removed `setOutputCallback()` and made `expectOutputString()` `final`. Use `assertOutputEqualsHtml()` (or PHPUnit's native `expectOutputString()` for exact matches).
- `IsEqualHtml` now implements `matches()`/`toString()` and takes a single constructor argument
- Raised minimum dependencies: `mockery/mockery ^1.6.12`, PHPStan tooling to `^2`
- Test runner configuration is split into `phpunit.xml.dist` (PHPUnit 10+) and `phpunit9.xml.dist` (PHPUnit 9)

### Removed
- The abandoned `sempro/phpunit-pretty-print` dev dependency (use `--testdox`)
- `DeprecatedMethodListener::setTestResult()`, `setTestCase()`, `checkCalls()` and the `TestCase::run()` override (relied on PHPUnit's removed `TestResult`/`RiskyTestError`)

### Fixed
- `WP_Mock::expectFilterNotAdded()` defaulted `$args` to `10` instead of `1`, so the "not added" expectation never matched a standard `add_filter()` call and silently passed; it now correctly guards the hook

## [1.1.1](https://github.com/10up/wp_mock/compare/1.1.0...1.1.1) - 2025-12-03
### Fixed
- Address PHP deprecation warnings about implicitly nullable parameters
Expand Down
66 changes: 66 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Upgrade Guide

## 1.x → 2.0

WP_Mock 2.0 adds support for **PHPUnit 10, 11, 12 and 13** alongside the existing PHPUnit 9.6, from a single codebase. The **minimum PHP version is unchanged (7.4)**.

Composer installs the highest PHPUnit version compatible with your PHP:

| Your PHP | PHPUnit installed |
|----------|-------------------|
| 7.4 | 9 |
| 8.0 | 9 |
| 8.1 | 10 |
| 8.2 | 11 |
| 8.3 | 12 |
| 8.4 | 13 |

For most projects, upgrading is just:

```shell
composer require --dev 10up/wp_mock:^2.0
```

You do **not** have to change your PHPUnit version to adopt 2.0 — if you stay on PHPUnit 9, WP_Mock 2.0 still works. The public assertion API (`assertConditionsMet()`, `assertHooksAdded()`, `assertActionsCalled()`, `assertEqualsHtml()`, `mockStaticMethod()`, …) is unchanged.

There are two behavior changes to be aware of.

### 1. Deprecated-method detection

If you (or your tooling) relied on WP_Mock marking a test **risky** when a deprecated WP_Mock method was called, that signal is now a native PHP **deprecation** (`E_USER_DEPRECATED`) surfaced through PHPUnit's own deprecation reporting.

To make these fail your test suite, enable strict deprecation handling in your PHPUnit configuration:

- **PHPUnit 10+:** `failOnDeprecation="true"`
- **PHPUnit 9:** `convertDeprecationsToExceptions="true"`

With default configuration, the deprecation is reported but does not fail the run.

### 2. Output assertions

Earlier versions overrode PHPUnit's `expectOutputString()` to automatically strip tabs and newlines from output (toggled with the `@stripTabsAndNewlinesFromOutput` annotation). PHPUnit 10 removed `setOutputCallback()` and made `expectOutputString()` `final`, so this is no longer possible.

If you relied on that whitespace-insensitive output matching, switch to the new helper:

```php
// Before (1.x): output was silently stripped of tabs/newlines before comparison
$this->expectOutputString('<div>Test</div>');
my_function_that_echoes_html();

// After (2.0): wrap the output-producing code in a callback
$this->assertOutputEqualsHtml('<div>Test</div>', static function () {
my_function_that_echoes_html();
});
```

PHPUnit's native `expectOutputString()` is still available if you want an **exact** (whitespace-sensitive) match.

### Removed internals

These were internal/rarely-used and are gone in 2.0 (they depended on PHPUnit APIs removed in PHPUnit 10):

- `WP_Mock\DeprecatedMethodListener::setTestResult()`, `setTestCase()`, `checkCalls()`
- The `WP_Mock\Tools\TestCase::run()` override
- The `@stripTabsAndNewlinesFromOutput` annotation and `TestCase::stripTabsAndNewlines()`

`WP_Mock::getDeprecatedMethodListener()` and `DeprecatedMethodListener::logDeprecatedCall()` remain available.
26 changes: 11 additions & 15 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,23 @@
"license": "BSD-3-Clause",
"prefer-stable": true,
"require": {
"php": ">=7.4 < 9",
"phpunit/phpunit": "^9.6",
"mockery/mockery": "^1.6",
"antecedent/patchwork": "^2.1"
"php": ">=7.4",
"phpunit/phpunit": "^9.6 || ^10 || ^11 || ^12 || ^13",
"mockery/mockery": "^1.6.12",
"antecedent/patchwork": "^2.1.27"
},
"require-dev": {
"behat/behat": "^v3.11.0",
"sebastian/comparator": "^4.0.8",
"sebastian/comparator": ">=4.0.8",
"php-coveralls/php-coveralls": "^v2.7",
"sempro/phpunit-pretty-print": "^1.4",
"phpstan/phpstan": "^1.10",
"phpstan/phpstan-phpunit": "^1.3",
"phpstan/phpstan-mockery": "^1.1",
"phpstan/phpstan": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-mockery": "^2.0",
"phpcompatibility/php-compatibility": "^9.3",
"php-stubs/wordpress-globals": "^0.2",
"php-stubs/wordpress-stubs": "^6.3",
"friendsofphp/php-cs-fixer": "^3.4",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7"
"dealerdirect/phpcodesniffer-composer-installer": "^1.0"
},
"autoload": {
"psr-4": {
Expand All @@ -40,17 +39,14 @@
]
},
"config": {
"platform": {
"php": "7.4"
},
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"scripts": {
"test:behat": "behat",
"test:phpunit": "phpunit",
"test:phpunitcov": "phpunit --coverage-clover build/logs/clover.xml",
"test:phpunit": "phpunit --testdox",
"test:phpunitcov": "phpunit --testdox --coverage-clover build/logs/clover.xml",
"test": [
"@test:behat",
"@test:phpunit"
Expand Down
Loading
Loading