Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 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
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
100 changes: 59 additions & 41 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,34 @@ 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'
coverage: true
label: 'PHP 8.1 · PHPUnit 10'
- php: '8.1'
os: 'ubuntu-latest'
- php: '8.0'
os: 'ubuntu-24.04'
- php: '7.4'
os: 'ubuntu-24.04'
config: 'phpunit.xml.dist'
composer_flags: '--prefer-lowest'
label: 'PHP 8.1 · PHPUnit 10 (lowest deps)'
fail-fast: false
env:
COVERAGE_CACHE_PATH: phpunit-coverage-cache
PHP_VERSION: ${{ matrix.php }}

steps:
Expand All @@ -39,86 +51,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 10–13 span PHP 8.1–8.4), so each leg
# updates to the highest PHPUnit its PHP allows (Composer picks 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.coverage }}
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.coverage }}
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.coverage }}
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 (8.1+)

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 2.0 modernizes the test harness for current PHPUnit. It now **requires PHP 8.1+ and PHPUnit 10+**, and supports **PHPUnit 10, 11, 12 and 13** from a single codebase; Composer installs the highest PHPUnit version your PHP allows. The public assertion API is unchanged, so most projects on a supported PHP/PHPUnit upgrade by bumping only `10up/wp_mock` — see [UPGRADE.md](https://github.com/10up/wp_mock/blob/trunk/UPGRADE.md).

### Added
- `TestCase::assertOutputEqualsHtml(string $expectedHtml, callable $callback)` for whitespace-insensitive assertions on echoed HTML output

### Changed
- **BREAKING:** raised the minimum PHP version to **8.1** (was 7.4) and dropped support for **PHPUnit 9**. Projects on PHP 7.4/8.0, or pinned to PHPUnit 9, should stay on WP_Mock 1.x.
- **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". Set `failOnDeprecation="true"` in your PHPUnit configuration to fail tests on these.
- **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
- Internal test metadata moved to PHP 8 attributes (`#[DataProvider]`, `#[CoversClass]`, …); doc-comment annotations were removed (they no longer work on PHPUnit 12+)
- Raised minimum dependencies: `mockery/mockery ^1.6.12`, PHPStan tooling to `^2`

### 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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

> WP_Mock is an API mocking framework, built and maintained by [10up](https://10up.com) and [GoDaddy](https://godaddy.com) for the purpose of making it possible to properly unit test within a WordPress project.

![Support Level][support-level-image] ![PHP 7.4+][php-image] [![Coverage Status][coveralls-image]][coveralls-url] [![Packagist][packagist-image]][packagist-url] [![BSD-3-Clause License][license-image]][license-url]
![Support Level][support-level-image] ![PHP 8.1+][php-image] [![Coverage Status][coveralls-image]][coveralls-url] [![Packagist][packagist-image]][packagist-url] [![BSD-3-Clause License][license-image]][license-url]

## Installation

Expand Down Expand Up @@ -39,7 +39,7 @@ A special thanks to all [WP_Mock contributors](https://github.com/10up/wp_mock/b
<a href="http://10up.com/contact/"><img src="https://10up.com/uploads/2016/10/10up-Github-Banner.png" width="850"></a>

[support-level-image]: https://img.shields.io/badge/support-active-green.svg
[php-image]: https://img.shields.io/badge/php-7.4%2B-green.svg
[php-image]: https://img.shields.io/badge/php-8.1%2B-green.svg
[packagist-image]: https://img.shields.io/packagist/dt/10up/wp_mock.svg
[packagist-url]: https://packagist.org/packages/10up/wp_mock
[coveralls-image]: https://coveralls.io/repos/github/10up/wp_mock/badge.svg?branch=trunk
Expand Down
62 changes: 62 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Upgrade Guide

## 1.x → 2.0

WP_Mock 2.0 modernizes the test harness for current PHPUnit. The headline change is a higher floor:

> **WP_Mock 2.0 requires PHP 8.1+ and PHPUnit 10+.**
> If your project runs on **PHP 7.4 or 8.0**, or is pinned to **PHPUnit 9**, stay on WP_Mock **1.x** — it continues to work. WP_Mock 2.0 supports PHPUnit 10, 11, 12 and 13 from a single codebase.

Composer installs the highest PHPUnit version compatible with your PHP:

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

For most projects on a supported PHP/PHPUnit, upgrading is just:

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

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, set `failOnDeprecation="true"` on the root `<phpunit>` element of your configuration. 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.
25 changes: 10 additions & 15 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,22 @@
"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": ">=8.1",
"phpunit/phpunit": "^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",
"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 +38,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