test: migrate elasticsearch/security/serializer/mongodb behat suites to ApiTestCase#8202
Merged
Conversation
Reads each `Scenario:` block, extracts the HTTP request, headers, status, expected JSON body or schema, and emits one `testXxx(): void` per scenario. Used to scaffold the migration of the remaining Behat suites (elasticsearch, security, serializer, mongodb) to phpunit functional tests.
Port the four Elasticsearch behat features to PHPUnit functional tests, each scenario becoming a `test*()` method. - features/elasticsearch/read.feature → ReadTest (10) - features/elasticsearch/match_filter.feature → MatchFilterTest (9) - features/elasticsearch/order_filter.feature → OrderFilterTest (12) - features/elasticsearch/term_filter.feature → TermFilterTest (14) `ElasticsearchSetupTrait` reproduces the behat ElasticsearchContext: on first use it deletes the indexes declared in `tests/Fixtures/Elasticsearch/Mappings`, recreates them and bulk-loads the JSON fixtures from `tests/Fixtures/Elasticsearch/Fixtures`. Tests skip themselves when `APP_ENV` is not `elasticsearch` (or `opensearch`), so default `vendor/bin/phpunit` keeps a clean run. The elasticsearch and opensearch CI jobs now invoke `vendor/bin/phpunit tests/Functional/Elasticsearch/` instead of behat profiles. Drop the now-unused `tests/Behat/ElasticsearchContext.php`, the matching service definitions in `config_elasticsearch.yml` / `config_opensearch.yml`, the `elasticsearch` / `opensearch` / `elasticsearch-coverage` profiles from `behat.yml.dist`, and the now-empty `misc` behat shard (all its paths have been migrated to phpunit).
Port the security behat suite to PHPUnit functional tests.
- send_security_headers.feature → SecurityHeadersTest (3)
- strong_typing.feature → StrongTypingTest (9)
- validate_incoming_content-types.feature \
validate_response_types.feature → ContentNegotiationErrorsTest (6)
`unknown_attributes.feature` is a duplicate of the first
strong_typing scenario and is already covered by
`StrongTypingTest::testIgnoreUnsupportedAttributes`, so its feature
file is dropped without a separate test class.
Behat directives like `I add "Content-Type" header equal to`, `I send
a POST/PUT/PATCH request to ... with body:`, and `the JSON node
"X" should be equal to "Y"` map to the equivalent
`assertResponseHeaderSame` / `assertJsonContains` calls, keeping the
exact response status, content-type and `detail` strings asserted
by the original scenarios.
Port the serializer behat suite (7 feature files, 48 scenarios) to PHPUnit functional tests. - property_filter.feature → PropertyFilterTest (11) - group_filter.feature → GroupFilterTest (26) - vo_relations.feature → ValueObjectRelationsTest (6) - empty_array_as_object.feature → EmptyArrayAsObjectTest (1) - groups_related.feature → GroupsRelatedTest (3) - deserialize_objects_using_constructor.feature → ConstructorDeserializationTest (1) - dynamic_groups.feature → DynamicGroupsTest (1) The two large filter feature files (property_filter, group_filter) preserve behat ID expectations across scenarios; their `Given there are N dummy * objects` fixture step is reproduced via a class-level `loadFixtures()` guarded by a `static $fixturesLoaded` flag so the schema and data persist across all tests in the class and POST scenarios continue to see the chained `dummy_properties/11`, `dummy_properties/12`... identifiers. `vo_relations.feature` JSON-schema constraint blocks are translated to `assertMatchesJsonSchema`; equality blocks use `assertJsonEquals`. The `unknown_attributes.feature` scenario is identical to the first `strong_typing` POST scenario already covered in the security migration, so no additional test class is added. The five tests that rely on direct Doctrine ORM `EntityManager` persistence (ConstructorDeserialization, GroupFilter, PropertyFilter, ValueObjectRelations, GroupsRelated) skip on the `mongodb` env where the underlying fixtures either lack a Document counterpart or where the `Entity` → `Document` namespace rewrite mangles class names containing the substring `Entity`.
Port the remaining mongodb behat features to PHPUnit functional
tests and pull `doctrine/mongodb-odm{,-bundle}` into composer
require-dev so the ODM fixtures resolve in the default phpunit
run (existing tests skip on non-mongodb environments via
`isMongoDB()`).
- deserialize_embed_many_without_target_document.feature \
→ EmbedManyWithoutTargetDocumentTest (1)
- filters.feature → NestedReferenceFilterErrorTest (2)
Both classes gate themselves on `isMongoDB()` so they skip in any
non-mongodb environment. `NestedReferenceFilterErrorTest::setUp`
re-creates the `Dummy + RelatedDummy + ThirdLevel + FourthLevel`
graph that the behat `there is a dummy object with a fourth level
relation` step used to build via the DoctrineContext.
`EmbedManyWithoutTargetDocumentTest` ships skipped pending a
serializer fix for union-typed `array|Collection` EmbedMany
properties (which currently report
`Could not denormalize object of type Collection`).
Migration scaffolder added a defensive markTestSkipped citing a serializer fix that is not actually required. The test passes against mongo:6 once the schema is recreated in setUp.
The Behat scenarios for strong_typing #1 and unknown_attributes used "JSON should be equal to" against the full 20-key Hydra body. The migration mapped that to assertJsonContains on 3 keys, dropping regression coverage for accidental field drops or default-value drift in DENORMALIZATION_EXTRA_ATTRIBUTES. Switch back to assertJsonEquals with the full body.
The scaffolder appended numeric suffixes when Behat scenario titles collided. Replace these with semantic suffixes derived from the request URL: WithMultipleValues for array-shaped query params, ReturningNoMatch for the empty-result variants, and the whitelisted nested filter name for the property filter duplicate.
- Drop hardcoded skipIfNotElasticsearch/initializeElasticsearch default; emit nothing when no --setup hook is given. - Parse `JSON node "X" should be equal to "Y"` and `JSON node "X" should exist`, emitting assertJsonContains and assertArrayHasKey respectively. - Only assign $response when an assertion needs it.
soyuka
added a commit
that referenced
this pull request
May 28, 2026
The Behat→PHPUnit migration scaffolder under `tools/` was a one-shot helper; it has no place in the published source tree. `doctrine/mongodb-odm` and `doctrine/mongodb-odm-bundle` are installed on demand by the `mongodb` CI job (and likewise on contributor machines), not via require-dev — the lines added in #8202 made them load unconditionally and bloated the install footprint for everyone else.
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.
Summary
Continues the Behat → PHPUnit migration started in #7971/#8198 by porting the remaining four behat suites — elasticsearch, security, serializer, mongodb — to
ApiTestCasefunctional tests. After this PR there are no behat scenarios left for these areas; the matching feature files, fixture context, and behat profiles are removed.ElasticsearchSetupTraitmirrorsElasticsearchContext(index/fixture bulk load); ES + OpenSearch CI jobs switch fromvendor/bin/behat --profile=elasticsearch/opensearchtovendor/bin/phpunit tests/Functional/Elasticsearch/unknown_attributesis identical to firststrong_typingscenario, kept onceproperty_filter+group_filterretain chained POST IDs via a class-levelloadFixtures()guarded by astatic $fixturesLoadedflagAPP_ENVis notmongodbAlso added
tools/feature_to_phpunit.php: a small converter used to scaffold eachtestXxx(): voidfrom the existing behat scenarios (HTTP request, headers, status, JSON body or schema).Test plan
phpunitjob stays green (45 ES tests skipped by default, plus other already-skipped mongodb/postgres-only ones)elasticsearchjob runs the newtests/Functional/Elasticsearch/suite against ES 7.17 / 8.4 / 9.x (45 tests)opensearchjob runs the same suite against OpenSearch 2.xmongodbjob picks up the newtests/Functional/MongoDb/casesfeatures/elasticsearch,features/security,features/serializer,features/mongodbleft in the treetests/Behat/ElasticsearchContext.phpremoved, noApiPlatform\\Tests\\Behat\\ElasticsearchContextreference left in any kernel config or behat profilePost-review fixes
Following a parity audit against the original behat scenarios:
EmbedManyWithoutTargetDocumentTestwas scaffold-skipped with a "pending serializer fix" note that turned out to be unnecessary — it now actively runs (recreateSchemainsetUp) and passes against mongo:6.StrongTypingTest::testIgnoreUnsupportedAttributesis back to a strictassertJsonEqualsagainst the full 20-key Hydra body, matching the originalJSON should be equal tosemantics; the migration had downgraded it to a 3-keyassertJsonContainsand dropped regression coverage for accidental field drops inDENORMALIZATION_EXTRA_ATTRIBUTES.…2suffixes after duplicate behat scenario titles are now semantic —WithMultipleValuesfor array-shaped query params,ReturningNoMatchfor the empty-result variants, and thewhitelistedNestedPropertiesfilter name for the property filter duplicate.tools/feature_to_phpunit.phpdropped its hardcodedskipIfNotElasticsearch/initializeElasticsearchdefault setup, learnedJSON node "X" should be equal to "Y"andJSON node "X" should exist, and only assigns$responsewhen an assertion needs it.Notes
composer.jsonis untouched; the elasticsearch/mongodb PHP libraries are already declared as dev dependencies.features/doctrine,features/files,features/graphql, plus the helpers shared by GraphQL tests; nothing in this PR removes them.