Skip to content

Add flash, service-mock, query-count, messenger-transport and console… - #247

Merged
TavoNiievez merged 1 commit into
Codeception:mainfrom
TavoNiievez:dominant-assertions-v2
Sep 3, 2026
Merged

Add flash, service-mock, query-count, messenger-transport and console…#247
TavoNiievez merged 1 commit into
Codeception:mainfrom
TavoNiievez:dominant-assertions-v2

Conversation

@TavoNiievez

Copy link
Copy Markdown
Member

Closes the small set of gaps that today push a Symfony developer toward a separate, non-Codeception package. Two buckets: assertions Symfony ships in its own Test\* traits that the module had not inherited yet, and capabilities absent from both Symfony core and the Codeception module ecosystem.

Charter inheritance (Symfony ports)

  • assertSessionHasFlashMessage() (SessionAssertionsTrait) — port of Symfony 8.1's BrowserKit assertion of the same name. When one or more messages are given it passes if any of them is present in the type's channel (matching Symfony's SessionHasFlashMessage constraint). The flash bag is read with peek(), so it is non-destructive and needs no extra dependency or version guard.
  • runCommand() + assertCommandIsSuccessful() / assertCommandFailed() / assertCommandIsInvalid() / assertCommandResultEquals() (ConsoleAssertionsTrait) — port of Symfony 8.1's ConsoleCommandAssertionsTrait. runCommand() returns an ExecutionResult exposing the status code together with the separate standard and error output, which runSymfonyConsoleCommand() cannot. Guarded with class_exists(ExecutionResult::class); runSymfonyConsoleCommand() stays the pre-8.1 path, and the unit tests skip below 8.1.

Competitive gaps (module-native)

  • mockService() / unmockService() (ServicesAssertionsTrait) — swap a container service for a test double (mock, stub, MockHttpClient, MockClock, ...) on the existing persistent-service rails, so the replacement survives kernel reboots. The double is built with Codeception Stub, PHPUnit or Mockery; the module only supplies the replacement.
  • seeNumQueriesIsLessThan() / dontSeeDuplicateQueries() (DoctrineAssertionsTrait) — N+1 guard reading the Doctrine db profiler collector (new DataCollectorName::DB, typed through grabCollector()). symfony/doctrine-bridge is added as a dev dependency to type the collector; it spans Symfony 5.4–8.1 so every CI row stays green.
  • grabMessengerTransport() / seeMessengerTransportContains() / seeMessengerQueueCount() / consumeMessengerMessages() (MessengerAssertionsTrait) — inspect and process the real message objects on a Symfony in-memory transport, complementing the existing profiler-based dispatch assertions. seeMessengerQueueCount() counts the pending queue (sent minus acked/rejected). consumeMessengerMessages() handles queued envelopes through the routable message bus in-process (with a ReceivedStamp + ConsumedByWorkerStamp), which works with the in-memory transport where messenger:consume does not. The unit tests skip below 6.3 (modern in-memory transport).

Scope discipline

No new trait, no new config knob, and nothing added to the Symfony.php facade except the two new services Part entries. Capabilities reachable by composing a sibling Codeception module (module-rest, module-webdriver, module-doctrine, module-datafactory) are deliberately left out.

Validation

composer phpstan (level max), composer cs-check and vendor/bin/phpunit tests all pass, across the Symfony 5.4 / 6.4 / 7.4 / 8.1 CI matrix.

A matching functional test is opened separately in Codeception/symfony-module-tests, per CONTRIBUTING.md.

…-result assertions

Close the small set of gaps that today push a Symfony developer toward a
separate, non-Codeception package, in two buckets: assertions Symfony ships
in its own Test\* traits that the module had not inherited yet, and
capabilities absent from both Symfony core and the Codeception module
ecosystem.

Symfony ports:

- assertSessionHasFlashMessage() (SessionAssertionsTrait), a port of Symfony
  8.1's BrowserKit assertion of the same name. Given one or more messages it
  passes if any of them is present in the type's channel, matching Symfony's
  SessionHasFlashMessage constraint, and reads the flash bag with peek() so
  it stays non-destructive. Symfony 5.4 has no
  FlashBagAwareSessionInterface, so the concrete Session class is accepted
  as well.
- runCommand() plus assertCommandIsSuccessful(), assertCommandFailed(),
  assertCommandIsInvalid() and assertCommandResultEquals()
  (ConsoleAssertionsTrait), a port of Symfony 8.1's
  ConsoleCommandAssertionsTrait. runCommand() returns an ExecutionResult
  exposing the status code together with the separate standard and error
  output, which runSymfonyConsoleCommand() cannot. It is guarded with
  class_exists(ExecutionResult::class), and runSymfonyConsoleCommand()
  remains the pre-8.1 path.

Module-native:

- mockService() / unmockService() (ServicesAssertionsTrait) swap a container
  service for a test double on the existing persistent-service rails, so the
  replacement survives kernel reboots. The double is built with Codeception
  Stub, PHPUnit or Mockery; the module only supplies the replacement.
- seeNumQueriesIsLessThan() / dontSeeDuplicateQueries()
  (DoctrineAssertionsTrait) guard against N+1 queries by reading the
  Doctrine db profiler collector, typed through the new
  DataCollectorName::DB. symfony/doctrine-bridge is added as a dev
  dependency to type the collector; it spans Symfony 5.4 to 8.1, so every
  CI row stays green.
- grabMessengerTransport(), seeMessengerTransportContains(),
  seeMessengerQueueCount() and consumeMessengerMessages()
  (MessengerAssertionsTrait) inspect and process the real message objects on
  a Symfony in-memory transport, complementing the existing profiler-based
  dispatch assertions. seeMessengerQueueCount() counts the pending queue
  (sent minus acknowledged or rejected), and consumeMessengerMessages()
  handles queued envelopes through the routable message bus in-process,
  which works with the in-memory transport where messenger:consume does not.
  They resolve the transport from the Transport\InMemory namespace, so on
  older versions they report a symfony/messenger >= 6.3 requirement.

No new trait, no new config knob, and nothing added to the Symfony facade
except the two new services Part entries.

Also stop the functional CI job from installing a second copy of the module
into the app: it removed codeception/module-symfony with --no-update and
then ran `composer install`, which reinstalls from the app's lockfile, so
the module source under test and a stale released copy were both
autoloaded.

Includes the internal-domain deduplication carried on this branch: build the
domain set keyed by host regex instead of array_unique() over a growing
list, so grabbing the internal domains is O(N) rather than O(N^2).
@TavoNiievez
TavoNiievez merged commit 301475b into Codeception:main Sep 3, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant