feat(assert): add comparison modifiers and new checks to the string assertions - #367
Merged
Merged
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
roxblnfk
force-pushed
the
feat/string-ignoring-modifiers
branch
3 times, most recently
from
September 26, 2026 11:50
5574412 to
c573a7b
Compare
`Assert::string()` gains `ignoringCase()`, `ignoringLineEndings()`, `ignoringWhitespace()`, `ignoringBlankLines()` and `ignoringAnsi()`. Each returns a new chain whose checks compare against a subject normalized once from the original value, and normalizes every check argument the same way; the original chain stays strict. An argument that normalizes to an empty string is rejected, since it would match anything. Patterns see every mode but the case one. Failure messages now spell out control characters of asserted strings, so escape codes no longer restyle the terminal. Case-insensitive comparison uses `mb_strtolower()`, so the assert plugin now requires symfony/polyfill-mbstring. Assisted-By: Claude Opus 5.5 <noreply@anthropic.com>
`Assert::string()` gains `same()` and `notSame()`, a strict `===` of the normalized string against the normalized expected one, so the comparison modifiers apply to whole strings too. Numeric strings are never compared as numbers. A `same()` failure carries the normalized strings for the diff and quotes the original ones in the message. Assisted-By: Claude Opus 5.5 <noreply@anthropic.com>
…ertions The negated prefix and suffix checks follow the comparison modifiers like the other substring checks, including the rejection of an argument that normalizes to an empty string. Assisted-By: Claude Opus 5.5 <noreply@anthropic.com>
…line endings or whitespace PHPUnit's `assertStringContainsStringIgnoringCase`, its negation, `assertStringContainsStringIgnoringLineEndings`, `assertStringEqualsStringIgnoringLineEndings`, the whitespace-insensitive equality pair and, for two strings, `assertEqualsIgnoringCase` and its negation become `Assert::string()` chains with the matching modifier and `contains()`, `notContains()`, `same()` or `notSame()`, and back. A plain `same()`/`notSame()` becomes `assertSame`/`assertNotSame`, and `assertStringStartsNotWith`/`assertStringEndsNotWith` convert to and from `notStartsWith()`/`notEndsWith()`. The combinations PHPUnit has no assertion for leave a chain untouched. Adjacent chains merge only when they open with the same modifiers, so no check changes its mode. Assisted-By: Claude Opus 5.5 <noreply@anthropic.com>
…recate `withMessagePattern()` The regex string checks are renamed to `matchesRegex()` and `notMatchesRegex()`. `withMessagePattern()` is deprecated in favour of `withMessageMatchingRegex()`, which behaves the same. Assisted-By: Claude Opus 5.5 <noreply@anthropic.com>
`TestoRectorSetList::TESTO_SHIFT` moves code off deprecated Testo API onto its replacement; every future deprecation adds its migration there. The first entry renames `withMessagePattern()` to `withMessageMatchingRegex()` on the exception expectation through Rector's `RenameMethodRector`. The fixture runner can now import set files, which runs the set's fixtures. Assisted-By: Claude Opus 5.5 <noreply@anthropic.com>
The PHPUnit mirror skipped every test whose exception expectation used `withMessageContaining()`, although the Testo to PHPUnit conversion maps it to `expectExceptionMessage()`. Such tests now run under PHPUnit too. Assisted-By: Claude Opus 5.5 <noreply@anthropic.com>
roxblnfk
force-pushed
the
feat/string-ignoring-modifiers
branch
from
September 26, 2026 12:01
c573a7b to
1d3582c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔍 What was changed
Assert::string()gainsignoringCase(),ignoringLineEndings(),ignoringWhitespace(bool $lineBreaks = false),ignoringBlankLines()andignoringAnsi(). Each returns a new chain; the original stays strict. Subject and check arguments are normalized by the same rules in a fixed order (ANSI, line endings, whitespace, blank lines, case). Regex checks see every mode except case; the pattern itself is never changed.same()/notSame()(strict===of the normalized strings, never numeric juggling; asame()failure diffs the normalized strings) andnotStartsWith()/notEndsWith().non-empty-string; one that is not empty but normalizes to an empty string throwsInvalidArgumentException.same('')stays a valid check.matchesPattern()/notMatchesPattern()are renamed tomatchesRegex()/notMatchesRegex().Expect::exception()gainswithMessageMatchingRegex();withMessagePattern()stays as a deprecated alias.assertStringEqualsStringIgnoringWhitespaceand its negation,assertEqualsIgnoringCase/assertNotEqualsIgnoringCasefor two strings,assertStringStartsNotWith/assertStringEndsNotWith, plainsame()/notSame()toassertSame/assertNotSame. Combinations with no PHPUnit form stay unconverted and are listed in TODO.md.TestoRectorSetList::TESTO_SHIFTfor deprecated Testo API, first entrywithMessagePattern()→withMessageMatchingRegex(). AGENTS.md now asks every deprecation to add its migration there.withMessageContaining(), which the Testo → PHPUnit conversion maps.Review notes
MergeAssertChainRectormerges string chains only when they open with the same modifier set, arguments compared as written. Without this guard, convertingassertStringContainsStringIgnoringCasenext to a plainassertStringContainsStringwould make the strict check case-insensitive.testo/assertand the root package now requiresymfony/polyfill-mbstring.Support::stringify()now escapes control characters other than tab and line breaks (\e,\x07), for every assertion. Raw ANSI in a failure message used to restyle the terminal.Support::dump()(used for diffs) is unchanged.testo-shiftset configures Rector'sRenameMethodRector, so it has no rule class for#[TestRectorFixtures].RectorRunnercan now import set files, andtests/Unit/TestoShiftSetTest.phpruns the fixtures kept inconfig/testo-shift/.Checklist
tools/revoltinstall that is missing locallytesto-shiftset