-
Notifications
You must be signed in to change notification settings - Fork 27
Feature/ultimate owner system tests #1782
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mohan06-mbrd
wants to merge
19
commits into
eclipse-tractusx:main
Choose a base branch
from
mohan06-mbrd:feature/ultimate-owner-system-tests
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+304
−0
Open
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
862700d
fix(pool): enforce missing star-topology rule for alternative headqua…
mohan06-mbrd 2cec18e
fix(pool): validate overlapping relations by relation id to keep alt-…
mohan06-mbrd bb3850f
feat(pool): distribute ultimateOwnerBpnl to alternative headquarters …
mohan06-mbrd 919b611
test(pool): wrap alternative headquarter relation creation in transac…
mohan06-mbrd fa96d11
fix(pool): resolve alternatives via main only and ignore stale IsOwne…
mohan06-mbrd 6821080
Merge branch 'main' into alternate_headquarter_expansion
mohan06-mbrd 795610c
fix: add AlternativeHeadquarterCannotOwnUltimately error mapping and …
mohan06-mbrd f640dac
Merge branch 'main' into alternate_headquarter_expansion
mohan06-mbrd 8338382
refactor(pool): address code review feedback for alternative headquar…
mohan06-mbrd 1827c62
test(system-tester): add ultimate owner distribution feature tests
mohan06-mbrd 72edbb4
added step defn for ultimate owner
mohan06-mbrd 747c1cd
feat(system-tester): implement ultimate owner distribution step defin…
mohan06-mbrd 6cf7083
fix: use regex pattern for cucumber step definition instead of invali…
mohan06-mbrd 21b9655
fix: remove duplicate step definition annotations
mohan06-mbrd 0c65a68
Merge branch 'main' into feature/ultimate-owner-system-tests
mohan06-mbrd 52fccd4
refactor: improve ultimate owner tests with business language and pro…
mohan06-mbrd 3e4f885
fix: use correct Gate API input DTO for ultimate owner marking
mohan06-mbrd 1ee1eee
fix: correct property names for legal entity representation
mohan06-mbrd 32fa244
fix: use empty states collection for Gate API compatibility
mohan06-mbrd File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
173 changes: 173 additions & 0 deletions
173
...rg/eclipse/tractusx/bpdm/test/system/stepdefinations/UltimateOwnerDistributionStepDefs.kt
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| /******************************************************************************* | ||
| * Copyright (c) 2021 Contributors to the Eclipse Foundation | ||
| * | ||
| * See the NOTICE file(s) distributed with this work for additional | ||
| * information regarding copyright ownership. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Apache License, Version 2.0 which is available at | ||
| * https://www.apache.org/licenses/LICENSE-2.0. | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
| * License for the specific language governing permissions and limitations | ||
| * under the License. | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| ******************************************************************************/ | ||
|
|
||
| package org.eclipse.tractusx.bpdm.test.system.stepdefinations | ||
|
|
||
| import io.cucumber.java.en.And | ||
| import io.cucumber.java.en.Then | ||
| import io.cucumber.java.en.When | ||
| import mu.KotlinLogging | ||
| import org.assertj.core.api.Assertions.assertThat | ||
| import org.eclipse.tractusx.bpdm.gate.api.client.GateClient | ||
| import org.eclipse.tractusx.bpdm.gate.api.model.response.LegalEntityRepresentationInputDto | ||
| import org.eclipse.tractusx.bpdm.pool.api.client.PoolApiClient | ||
| import org.eclipse.tractusx.bpdm.pool.api.model.LegalEntityDto | ||
| import org.eclipse.tractusx.bpdm.pool.api.model.request.LegalEntityPartnerUpdateRequest | ||
| import org.eclipse.tractusx.bpdm.test.system.utils.ScenarioContext | ||
| import tools.jackson.databind.json.JsonMapper | ||
|
|
||
| /** | ||
| * Steps for the "Ultimate Owner Distribution" feature. | ||
| * | ||
| * These steps handle marking legal entities as ultimate owners and verifying that the | ||
| * ultimateOwnerBpnl is correctly reflected in the output of owned entities. | ||
| */ | ||
| class UltimateOwnerDistributionStepDefs( | ||
| private val gateClient: GateClient, | ||
| private val poolClient: PoolApiClient, | ||
| private val jsonMapper: JsonMapper | ||
| ) : SpringTestRunConfiguration() { | ||
|
|
||
| companion object { | ||
| private val logger = KotlinLogging.logger {} | ||
| } | ||
|
|
||
| /** | ||
| * Sharing member marks an entity as the ultimate owner via the Gate. | ||
| * This uploads the ultimate owner flag to the Gate input. | ||
| */ | ||
| @When("the sharing member marks {string} as the ultimate owner") | ||
| fun sharingMemberMarksAsUltimateOwner(entityId: String) { | ||
| logger.info { "Sharing member marks '$entityId' as the ultimate owner" } | ||
|
|
||
| val context = ScenarioContext.current() ?: error("No active scenario context") | ||
|
|
||
| // Get the legal entity from context | ||
| val legalEntityWithAddress = context.legalEntities[entityId] | ||
| ?: error("Legal entity '$entityId' not found in scenario context") | ||
|
|
||
| // Create the Gate input representation with ultimate owner flag | ||
| val legalEntityInput = LegalEntityRepresentationInputDto( | ||
| legalEntityBpn = legalEntityWithAddress.header.bpnl, | ||
| legalName = legalEntityWithAddress.header.legalName, | ||
| shortName = legalEntityWithAddress.header.legalShortName, | ||
| legalForm = legalEntityWithAddress.header.legalFormVerbose?.technicalKey, | ||
| ownershipUltimate = true, | ||
| states = emptyList() | ||
| ) | ||
|
|
||
| // Upload to Gate via upsertBusinessPartnersInput | ||
| val inputRequest = context.inputData[entityId]?.copy( | ||
| externalId = context.runId(entityId), | ||
| legalEntity = legalEntityInput | ||
| ) ?: error("Input data for '$entityId' not found in scenario context") | ||
|
|
||
| gateClient.businessParters.upsertBusinessPartnersInput(listOf(inputRequest)) | ||
| logger.info { "Successfully uploaded '$entityId' as ultimate owner to Gate" } | ||
| } | ||
|
|
||
| /** | ||
| * Golden record process confirms an entity as the ultimate owner. | ||
| * This updates the Pool with the ultimate owner flag from the golden record. | ||
| */ | ||
| @And("the golden record process confirms {string} as the ultimate owner") | ||
| fun goldenRecordConfirmsAsUltimateOwner(entityId: String) { | ||
| logger.info { "Golden record process confirms '$entityId' as the ultimate owner" } | ||
|
|
||
| val context = ScenarioContext.current() ?: error("No active scenario context") | ||
|
|
||
| // Get the legal entity from context | ||
| val legalEntityWithAddress = context.legalEntities[entityId] | ||
| ?: error("Legal entity '$entityId' not found in scenario context") | ||
|
|
||
| // Convert verbose DTO to non-verbose DTO using JSON serialization | ||
| val verboseJson = jsonMapper.writeValueAsString(legalEntityWithAddress) | ||
| val legalEntity = jsonMapper.readValue(verboseJson, LegalEntityDto::class.java) | ||
|
|
||
| // Update the legal entity to mark it as ultimate owner | ||
| val updatedLegalEntity = legalEntity.copy( | ||
| header = legalEntity.header.copy( | ||
| ownershipUltimate = true | ||
| ) | ||
| ) | ||
|
|
||
| // Update the legal entity in the Pool to mark it as ultimate owner | ||
| val updateRequest = LegalEntityPartnerUpdateRequest( | ||
| bpnl = legalEntityWithAddress.header.bpnl, | ||
| legalEntity = updatedLegalEntity | ||
| ) | ||
|
|
||
| poolClient.legalEntities.updateBusinessPartners(listOf(updateRequest)) | ||
| logger.info { "Successfully confirmed '$entityId' as ultimate owner in Pool" } | ||
| } | ||
|
|
||
| /** | ||
| * Asserts that a record's output reflects a specific entity as the ultimate owner. | ||
| */ | ||
| @Then("{string} output reflects {string} as the ultimate owner") | ||
| fun assertUltimateOwner(recordId: String, expectedOwnerRecordId: String) { | ||
| logger.info { "Asserting that '$recordId' output reflects '$expectedOwnerRecordId' as the ultimate owner" } | ||
|
|
||
| val context = ScenarioContext.current() ?: error("No active scenario context") | ||
|
|
||
| // Get the output from the Gate | ||
| val runId = context.runId(recordId) | ||
| val outputPage = gateClient.businessParters.getBusinessPartnersOutput(listOf(runId)) | ||
| val output = outputPage.content.firstOrNull() | ||
| ?: error("No output found for record '$recordId'") | ||
|
|
||
| // Get the expected owner's BPNL | ||
| val expectedOwnerRunId = context.runId(expectedOwnerRecordId) | ||
| val ownerOutputPage = gateClient.businessParters.getBusinessPartnersOutput(listOf(expectedOwnerRunId)) | ||
| val ownerOutput = ownerOutputPage.content.firstOrNull() | ||
| ?: error("No output found for owner record '$expectedOwnerRecordId'") | ||
|
|
||
| val expectedBpnl = ownerOutput.legalEntity.legalEntityBpn | ||
|
|
||
| // Assert the ultimateOwnerBpnl matches | ||
| assertThat(output.legalEntity.ultimateOwnerBpnl) | ||
| .withFailMessage("Expected '$recordId' to have ultimate owner '$expectedBpnl' but was '${output.legalEntity.ultimateOwnerBpnl}'") | ||
| .isEqualTo(expectedBpnl) | ||
|
|
||
| logger.info { "Successfully asserted '$recordId' has ultimate owner '$expectedOwnerRecordId'" } | ||
| } | ||
|
|
||
| /** | ||
| * Asserts that a record's output has no ultimate owner (null). | ||
| */ | ||
| @Then("{string} output has no ultimate owner") | ||
| fun assertNoUltimateOwner(recordId: String) { | ||
| logger.info { "Asserting that '$recordId' output has no ultimate owner" } | ||
|
|
||
| val context = ScenarioContext.current() ?: error("No active scenario context") | ||
|
|
||
| // Get the output from the Gate | ||
| val runId = context.runId(recordId) | ||
| val outputPage = gateClient.businessParters.getBusinessPartnersOutput(listOf(runId)) | ||
| val output = outputPage.content.firstOrNull() | ||
| ?: error("No output found for record '$recordId'") | ||
|
|
||
| // Assert the ultimateOwnerBpnl is null | ||
| assertThat(output.legalEntity.ultimateOwnerBpnl) | ||
| .withFailMessage("Expected '$recordId' to have no ultimate owner but was '${output.legalEntity.ultimateOwnerBpnl}'") | ||
| .isNull() | ||
|
|
||
| logger.info { "Successfully asserted '$recordId' has no ultimate owner" } | ||
| } | ||
| } | ||
131 changes: 131 additions & 0 deletions
131
bpdm-system-tester/src/main/resources/cucumber/ultimate_owner_distribution.feature
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| # This feature covers how the ultimate owner flag is distributed through the business partner | ||
| # ownership hierarchy. When a legal entity is marked as the ultimate owner, this flag should be | ||
| # reflected in the output of all entities that are owned by it (directly or indirectly). | ||
| # | ||
| # The ultimate owner resolution follows these rules: | ||
| # - An entity marked with ownershipUltimate = true is its own ultimate owner | ||
| # - An entity owned by an ultimate owner inherits that ultimate owner's BPNL | ||
| # - When no ultimate owner exists in the chain, entities report null | ||
| @CXTPM-1743 | ||
| Feature: Ultimate Owner Distribution | ||
|
|
||
| #h3. Test Objective: | ||
| # | ||
| #* Verify that when a legal entity is marked as ultimate owner, owned entities report this ultimate owner. | ||
| # | ||
| #h3. Preconditions: | ||
| # | ||
| ## A legal entity hierarchy exists with an owner and owned entity. | ||
| # | ||
| #h3. Description: | ||
| # | ||
| ## The owner entity is marked as ownershipUltimate = true in the golden record. | ||
| ## An IsOwnedBy relation is established from the child to the parent. | ||
| ## The golden record process processes the updates. | ||
| ## The child entity reports the parent's BPNL as its ultimate owner. | ||
| @TEST_CXTPM-1743-001 @BPDM | ||
| Scenario: Owned entity reports ultimate owner from ownership chain | ||
| Given record "parent-record" reflects legal entity "parent" | ||
| And record "child-record" reflects legal entity "child" | ||
| When the sharing member shares relation "ownership" of type "IsOwnedBy" from "child-record" to "parent-record" | ||
| And the golden record process establishes relation "ownership" | ||
| And the sharing member marks "parent" as the ultimate owner | ||
| And the golden record process confirms "parent" as the ultimate owner | ||
| Then "child-record" output reflects "parent" as the ultimate owner | ||
|
|
||
| #h3. Test Objective: | ||
| # | ||
| #* Verify that ultimate owner flag propagates through multi-level ownership hierarchy. | ||
| # | ||
| #h3. Preconditions: | ||
| # | ||
| ## A multi-level legal entity hierarchy exists (grandparent -> parent -> child). | ||
| # | ||
| #h3. Description: | ||
| # | ||
| ## The grandparent entity is marked as ownershipUltimate = true. | ||
| ## IsOwnedBy relations connect child -> parent -> grandparent. | ||
| ## The golden record process processes the updates. | ||
| ## Both parent and child report the grandparent's BPNL as ultimate owner. | ||
| @TEST_CXTPM-1743-002 @BPDM | ||
| Scenario: Ultimate owner propagates through multi-level hierarchy | ||
| Given record "grandparent-record" reflects legal entity "grandparent" | ||
| And record "parent-record" reflects legal entity "parent" | ||
| And record "child-record" reflects legal entity "child" | ||
| When the sharing member shares relation "parent-ownership" of type "IsOwnedBy" from "parent-record" to "grandparent-record" | ||
| And the golden record process establishes relation "parent-ownership" | ||
| And the sharing member shares relation "child-ownership" of type "IsOwnedBy" from "child-record" to "parent-record" | ||
| And the golden record process establishes relation "child-ownership" | ||
| And the sharing member marks "grandparent" as the ultimate owner | ||
| And the golden record process confirms "grandparent" as the ultimate owner | ||
| Then "parent-record" output reflects "grandparent" as the ultimate owner | ||
| And "child-record" output reflects "grandparent" as the ultimate owner | ||
|
|
||
| #h3. Test Objective: | ||
| # | ||
| #* Verify that when no ultimate owner exists in the ownership chain, entities report null. | ||
| # | ||
| #h3. Preconditions: | ||
| # | ||
| ## A legal entity hierarchy exists with no entity marked as ultimate owner. | ||
| # | ||
| #h3. Description: | ||
| # | ||
| ## No entity in the hierarchy is marked as ownershipUltimate = true. | ||
| ## IsOwnedBy relations are established between the entities. | ||
| ## The golden record process processes the hierarchy. | ||
| ## All entities report null as their ultimate owner. | ||
| @TEST_CXTPM-1743-003 @BPDM | ||
| Scenario: No ultimate owner reported when flag holder does not exist in chain | ||
| Given record "parent-record" reflects legal entity "parent" | ||
| And record "child-record" reflects legal entity "child" | ||
| When the sharing member shares relation "ownership" of type "IsOwnedBy" from "child-record" to "parent-record" | ||
| And the golden record process establishes relation "ownership" | ||
| Then "child-record" output has no ultimate owner | ||
| And "parent-record" output has no ultimate owner | ||
|
|
||
| #h3. Test Objective: | ||
| # | ||
| #* Verify that an entity marked as ultimate owner reports itself as the ultimate owner. | ||
| # | ||
| #h3. Preconditions: | ||
| # | ||
| ## A legal entity is marked as ownershipUltimate = true in the golden record. | ||
| # | ||
| #h3. Description: | ||
| # | ||
| ## The entity is marked as ownershipUltimate = true in the golden record. | ||
| ## The golden record process processes the update. | ||
| ## The entity reports its own BPNL as the ultimate owner. | ||
| @TEST_CXTPM-1743-004 @BPDM | ||
| Scenario: Entity marked as ultimate owner reports itself | ||
| Given record "self-owner-record" reflects legal entity "self-owner" | ||
| When the sharing member marks "self-owner" as the ultimate owner | ||
| And the golden record process confirms "self-owner" as the ultimate owner | ||
| Then "self-owner-record" output reflects "self-owner" as the ultimate owner | ||
|
|
||
| #h3. Test Objective: | ||
| # | ||
| #* Verify that ultimate owner flag change propagates to already-owned entities. | ||
| # | ||
| #h3. Preconditions: | ||
| # | ||
| ## A legal entity hierarchy exists with no entity marked as ultimate owner initially. | ||
| # | ||
| #h3. Description: | ||
| # | ||
| ## Initially, no entity is marked as ultimate owner. | ||
| ## IsOwnedBy relations are established. | ||
| ## Later, the parent entity is marked as ownershipUltimate = true. | ||
| ## The golden record process processes the update. | ||
| ## The child entity now reports the parent's BPNL as ultimate owner. | ||
| @TEST_CXTPM-1743-005 @BPDM | ||
| Scenario: Ultimate owner flag change propagates to existing owned entities | ||
| Given record "parent-record" reflects legal entity "parent" | ||
| And record "child-record" reflects legal entity "child" | ||
| When the sharing member shares relation "ownership" of type "IsOwnedBy" from "child-record" to "parent-record" | ||
| And the golden record process establishes relation "ownership" | ||
| And the sharing member marks "parent" as the ultimate owner | ||
| And the golden record process confirms "parent" as the ultimate owner | ||
| Then "child-record" output reflects "parent" as the ultimate owner | ||
| And "parent-record" output reflects "parent" as the ultimate owner |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not representative of the user flow. In a E2E scenario the sharing member designates an ultimate owner over the gate. This should be done here as well instead of taking an unrepresentative shortcut.