Skip to content
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

Feat/518 policy store API integration tests #577

Closed
Show file tree
Hide file tree
Changes from 54 commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
0cc093c
feat(impl): [#518] add builder to CreatePolicyRequest and UpdatePolic…
dsmf Apr 23, 2024
a1eb42f
feat(impl): [#518] add helper class for policy tests
dsmf Apr 23, 2024
143d44d
feat(impl): [#518] add helper method PolicyTestHelper.jsonFromString
dsmf Apr 23, 2024
ba375c4
feat(impl): [#518] add irs-policy-store as dependency
dsmf Apr 23, 2024
21e9b3c
feat(impl): [#518] add E2E test step definitions for policy store
dsmf Apr 23, 2024
e080e95
feat(impl): [#518] extract PropertyNotFoundException to separate class
dsmf Apr 23, 2024
a31b816
feat(impl): [#518] add policy-store.feature (temporarily)
dsmf Apr 23, 2024
c57d86b
feat(impl): [#518] rename method
dsmf Apr 23, 2024
8833745
feat(impl): [#518] improvements and test for update policy
dsmf Apr 23, 2024
b5923fc
feat(impl): [#518] improve / correct tests
dsmf Apr 24, 2024
604c916
feat(impl): [#518] complete tests from story
dsmf Apr 24, 2024
5ceb3fb
feat(impl): [#518] add forgotten step def
dsmf Apr 24, 2024
0f77425
feat(impl): [#518] split up test step def classes and update todos
dsmf Apr 24, 2024
4b1ae1e
feat(impl): [#518] improvements
dsmf Apr 24, 2024
b7ab223
feat(impl): [#518] improvements
dsmf Apr 24, 2024
a24f4a9
feat(impl): [#518] improvements/fixes
dsmf Apr 24, 2024
33ba65d
feat(impl): [#518] improvements/fixes
dsmf Apr 24, 2024
48dc00d
feat(impl): [#518] correct naming, add step definition
dsmf Apr 24, 2024
aad2e1e
feat(impl): [#518] cleanup
dsmf Apr 24, 2024
1041b0e
feat(impl): [#518] improve IDs and years for better readability and a…
dsmf Apr 25, 2024
dcec256
feat(impl): [#518] improvement
dsmf Apr 25, 2024
1b82620
feat(impl): [#518] new step definitions with PolicyRecordBuilder
dsmf Apr 25, 2024
8a7a4de
feat(impl): [#518] improved by using the steps with PolicyRecordBuilder
dsmf Apr 25, 2024
e7fb865
feat(impl): [#518] remove dependency to irs-policy-store
dsmf Apr 25, 2024
47bc158
feat(impl): [#518] fix dependency issues
dsmf Apr 25, 2024
ff265fb
feat(impl): [#518] cleanup
dsmf Apr 25, 2024
348ba8b
Merge branch 'refs/heads/main' into feat/518-policy-store-integration…
dsmf Apr 25, 2024
a0a14c2
feat(impl): [#518] fix NPE
dsmf Apr 29, 2024
c506417
feat(impl): [#518] move helper code to helper classes
dsmf Apr 29, 2024
88a25ef
feat(impl): [#518] move some code to helper class
dsmf Apr 29, 2024
b05ab1b
feat(impl): [#518] move ObjectMapper to common test helper
dsmf Apr 29, 2024
57dedc8
feat(impl): [#518] move some code to PolicyTestHelper
dsmf Apr 29, 2024
e8a3bc1
feat(impl): [#518] add todo for later
dsmf Apr 29, 2024
5950a1c
feat(impl): [#518] add javadoc
dsmf Apr 29, 2024
a554b9c
feat(impl): [#518] some renaming, import cleanup, javadoc
dsmf Apr 29, 2024
2cb5953
feat(impl): [#518] re-use common code
dsmf Apr 29, 2024
605fb3a
feat(impl): [#518] update todos
dsmf Apr 29, 2024
4000f24
feat(impl): [#518] fix warnings
dsmf Apr 29, 2024
5823260
feat(impl): [#518] rename list to plural
dsmf Apr 29, 2024
c7fe7bb
feat(impl): [#518] add helper method
dsmf Apr 29, 2024
0652a15
feat(impl): [#518] improvements
dsmf Apr 29, 2024
6643033
feat(impl): [#518] add scenario
dsmf Apr 30, 2024
8bb136f
Merge branch 'refs/heads/main' into feat/518-policy-store-integration…
dsmf Apr 30, 2024
00fdf4d
feat(impl): [#518] rename step definition class
dsmf Apr 30, 2024
bc5abde
feat(impl): [#518] update todos and link with PBIs
dsmf Apr 30, 2024
a9597bc
feat(impl): [#518] remove policy-store.feature file
dsmf Apr 30, 2024
4d6afa6
feat(impl): [#518] update CHANGELOG.md
dsmf Apr 30, 2024
a20e430
Update integration-test-DEV.yaml
dsmf Apr 30, 2024
9365226
Update integration-test-DEV.yaml
dsmf Apr 30, 2024
6a0306a
Merge branch 'main' into feat/518-policy-store-integration-tests--rew…
dsmf Apr 30, 2024
5b7d930
feat(impl): [#518] revert addition of unused builder
dsmf May 2, 2024
e38180c
feat(impl): [#518] move content of constant POLICY_TEMPLATE to a file
dsmf May 2, 2024
1975a1f
feat(impl): [#518] removed unused attribute authProperties
dsmf May 2, 2024
4f978fe
Merge branch 'refs/heads/main' into feat/518-policy-store-integration…
dsmf May 2, 2024
1205592
feat(impl): [#518] update CHANGELOG.md
dsmf May 2, 2024
d4580df
Merge branch 'refs/heads/main' into feat/518-policy-store-integration…
dsmf May 2, 2024
424f36d
chore(workflows): [#518] temporarily set other exportFilter
dsmf May 2, 2024
d81199d
chore(workflows): [#518] configure RestAssured request and response l…
dsmf May 2, 2024
cb3e08a
Undo temporarily setting other exportFilter
dsmf May 2, 2024
0cc5296
feat(impl):[#585] newest dataset reduced
ds-ext-kmassalski May 3, 2024
4c630db
Merge pull request #918 from eclipse-tractusx/main
ds-jhartmann May 6, 2024
bf49266
Merge pull request #917 from catenax-ng/feat/585-newest-dataset-reduced
ds-ext-kmassalski May 6, 2024
b5eaecd
Merge pull request #919 from eclipse-tractusx/main
dsmf May 6, 2024
56a5e60
chore(docs): [#518] fix merge conflict
dsmf May 6, 2024
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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ _**For better traceability add the corresponding GitHub issue number in each cha

## [Unreleased]

### Changed
## Added

- Cucumber test step definitions for Policy Store API (Happy Path). #518

## Changed

- Removed obsolete entries from acceptedPolicies configuration. #530
- Support of building relationships based on SingleLevelUsageAsBuilt v3.0.0 #558
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/********************************************************************************
* Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
* Copyright (c) 2021,2024 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.irs.cucumber;

import static io.restassured.RestAssured.given;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.function.Predicate;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import io.restassured.specification.RequestSpecification;
import org.apache.commons.lang3.StringUtils;

/**
* Common helper class for E2E tests.
*/
public class E2ETestHelper {

public static final ObjectMapper objectMapper;

static {
objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
}

public static File getExpectedFile(final String fileName) {
return getFile("expected-files/" + fileName);
}

public static String getTemplateFileContent(final String fileName) throws IOException {
final File file = getTemplateFile(fileName);
byte[] bytes = Files.readAllBytes(file.toPath());
return new String(bytes, StandardCharsets.UTF_8);
}

public static File getTemplateFile(final String fileName) {
return getFile("templates/" + fileName);
}

public static File getFile(final String path) {
final ClassLoader classLoader = E2ETestHelper.class.getClassLoader();
final URL ressource = classLoader.getResource(path);
return new File(ressource.getFile());
}

public static RequestSpecification givenAuthentication(
AuthenticationProperties.AuthenticationPropertiesBuilder authBuilder) {
final AuthenticationProperties authProperties = authBuilder.build();
return given().log().all().spec(authProperties.getNewAuthenticationRequestSpecification());
}

static Predicate<String> startingWith(final String prefix) {
return s -> StringUtils.startsWith(s, prefix);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
/********************************************************************************
* Copyright (c) 2022,2024 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
* Copyright (c) 2021,2024 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.irs.cucumber;

import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.tractusx.irs.cucumber.E2ETestHelper.givenAuthentication;
import static org.eclipse.tractusx.irs.cucumber.E2ETestHelper.objectMapper;

import java.io.IOException;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.cucumber.java.DataTableType;
import io.restassured.http.ContentType;
import io.restassured.response.ValidatableResponse;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.tractusx.irs.cucumber.AuthenticationProperties.AuthenticationPropertiesBuilder;
import org.eclipse.tractusx.irs.cucumber.E2ETestHelperForPolicyStoreApi.CreatePolicyRequest.CreatePolicyRequestBuilder;
import org.springframework.http.HttpStatus;

/**
* Helper class for Policy Store API tests.
*/
public class E2ETestHelperForPolicyStoreApi {

public static final String URL_IRS_POLICIES = "/irs/policies";

public static final String QUERYPARAM_BUSINESS_PARTNER_NUMBERS = "businessPartnerNumbers";

public static String getPolicyTemplate() throws IOException {
return E2ETestHelper.getTemplateFileContent("policy-for-e2e-tests.json");
}

@SuppressWarnings("unchecked")
public static Map<String, ArrayList<LinkedHashMap<String, ?>>> fetchPoliciesForBpn(
final AuthenticationPropertiesBuilder authenticationPropertiesBuilder, final String bpn) {

return givenAuthentication(authenticationPropertiesBuilder).queryParam(QUERYPARAM_BUSINESS_PARTNER_NUMBERS, bpn)
.when()
.get(URL_IRS_POLICIES)
.then()
.log()
.all()
.statusCode(HttpStatus.OK.value())
.extract()
.body()
.as(Map.class);
}

public static ValidatableResponse fetchAllPolicies(
final AuthenticationPropertiesBuilder authenticationPropertiesBuilder) {
return givenAuthentication(authenticationPropertiesBuilder).when().get(URL_IRS_POLICIES).then().log().all();
}

@Builder
public record CreatePolicyRequest(OffsetDateTime validUntil, String businessPartnerNumber, JsonNode payload) {
}

@Builder
public record UpdatePolicyRequest(OffsetDateTime validUntil, List<String> businessPartnerNumbers,
List<String> policyIds) {
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public static class BpnToPolicyId {
private String bpn;
private String policyId;
}

@DataTableType
public BpnToPolicyId bpnToPolicyEntryTransformer(final Map<String, String> row) {
return new BpnToPolicyId(row.get("BPN"), row.get("policyId"));
}

public static HashMap<String, HashSet<String>> getExpectedBpnToPolicyIdsMapping(
final List<BpnToPolicyId> bpnToPolicyIdTable) {

final HashMap<String, HashSet<String>> expectedBpnToPolicyIdsMapping = new HashMap<>();
bpnToPolicyIdTable.forEach(entry -> {

HashSet<String> policyIds = expectedBpnToPolicyIdsMapping.get(entry.getBpn());
if (policyIds == null) {
policyIds = new HashSet<>();
}

policyIds.add(entry.getPolicyId());

expectedBpnToPolicyIdsMapping.put(entry.getBpn(), policyIds);
});
return expectedBpnToPolicyIdsMapping;
}

public static Stream<String> extractPolicyIdsForBpn(
final Map<String, ArrayList<LinkedHashMap<String, ?>>> bpnToPoliciesMap, final String bpn) {
return extractPolicyIds(bpnToPoliciesMap.get(bpn).stream());
}

@SuppressWarnings("rawtypes")
public static Stream<LinkedHashMap> extractPoliciesForBpn(
final Map<String, ArrayList<LinkedHashMap<String, ?>>> bpnToPoliciesMap, final String bpn) {
return extractPolicy(bpnToPoliciesMap.get(bpn).stream());
}

public static Stream<String> extractPolicyIdsStartingWith(
final Map<String, ArrayList<LinkedHashMap<String, ?>>> bpnToPoliciesMap, final String policyIdPrefix) {
return extractPolicyIds(bpnToPoliciesMap).filter(policyId -> StringUtils.startsWith(policyId, policyIdPrefix));
}

public static Stream<String> extractPolicyIds(
final Map<String, ArrayList<LinkedHashMap<String, ?>>> bpnToPoliciesMap) {
return extractPolicyIds(bpnToPoliciesMap.values().stream().flatMap(Collection::stream));
}

private static Stream<String> extractPolicyIds(final Stream<LinkedHashMap<String, ?>> linkedHashMapStream) {
return extractPolicy(linkedHashMapStream).map(v -> (String) v.get("policyId"));
}

@SuppressWarnings("rawtypes")
private static Stream<LinkedHashMap> extractPolicy(final Stream<LinkedHashMap<String, ?>> linkedHashMapStream) {
return extractPolicyPayloads(linkedHashMapStream).map(v -> (LinkedHashMap) v.get("policy"));
}

@SuppressWarnings("rawtypes")
private static Stream<LinkedHashMap> extractPolicyPayloads(
final Stream<LinkedHashMap<String, ?>> linkedHashMapStream) {
return linkedHashMapStream.map(v -> (LinkedHashMap) v.get("payload"));
}

public static JsonNode jsonFromString(final ObjectMapper objectMapper, final String jsonObjectStr)
throws JsonProcessingException {
return objectMapper.readTree(jsonObjectStr);
}

public static ValidatableResponse updatePolicies(
final AuthenticationPropertiesBuilder authenticationPropertiesBuilder, final List<String> policyIds,
final List<String> businessPartnerNumbers, final String validUntil) {

final var updatePolicyRequest = UpdatePolicyRequest.builder()
.policyIds(policyIds)
.businessPartnerNumbers(businessPartnerNumbers)
.validUntil(OffsetDateTime.parse(validUntil))
.build();
return givenAuthentication(authenticationPropertiesBuilder).contentType(ContentType.JSON)
.body(updatePolicyRequest)
.when()
.put(URL_IRS_POLICIES)
.then()
.log()
.all();
}

public static ValidatableResponse registerPolicyForBpn(
final AuthenticationPropertiesBuilder authenticationPropertiesBuilder, final String policyJson,
final String bpn, final String validUntil) {

final CreatePolicyRequest createPolicyRequest;
try {
CreatePolicyRequestBuilder builder = CreatePolicyRequest.builder();
if (validUntil != null) {
builder = builder.validUntil(OffsetDateTime.parse(validUntil));
}
createPolicyRequest = builder.businessPartnerNumber(bpn)
.payload(E2ETestHelperForPolicyStoreApi.jsonFromString(objectMapper,
policyJson))
.build();
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}

return givenAuthentication(authenticationPropertiesBuilder).contentType(ContentType.JSON)
.body(createPolicyRequest)
.when()
.post(URL_IRS_POLICIES)
.then()
.log()
.all();

}

public static ValidatableResponse fetchPoliciesForBusinessPartnerNumbers(
final AuthenticationPropertiesBuilder authenticationPropertiesBuilder,
final List<String> businessPartnerNumbers) {

return givenAuthentication(authenticationPropertiesBuilder).queryParam(QUERYPARAM_BUSINESS_PARTNER_NUMBERS,
businessPartnerNumbers).when().get(URL_IRS_POLICIES).then().log().all();
}

public static void cleanupPolicyIdsByPrefix(final AuthenticationPropertiesBuilder authenticationPropertiesBuilder,
final String policyIdPrefix) {
fetchPolicyIdsByPrefixSuccessfully(authenticationPropertiesBuilder, policyIdPrefix).forEach(
policyId -> cleanupPolicy(authenticationPropertiesBuilder, policyId));
}

public static List<String> fetchPolicyIdsByPrefixSuccessfully(
final AuthenticationPropertiesBuilder authenticationPropertiesBuilder, final String policyIdPrefix) {
final Map<String, ArrayList<LinkedHashMap<String, ?>>> bpnToPoliciesMap = E2ETestHelperForPolicyStoreApi.fetchAllPoliciesSuccessfully(
authenticationPropertiesBuilder);
return E2ETestHelperForPolicyStoreApi.extractPolicyIdsStartingWith(bpnToPoliciesMap, policyIdPrefix).toList();
}

@SuppressWarnings("unchecked")
public static Map<String, ArrayList<LinkedHashMap<String, ?>>> fetchAllPoliciesSuccessfully(
final AuthenticationPropertiesBuilder authenticationPropertiesBuilder) {
final ValidatableResponse getAllPoliciesResponse = fetchAllPolicies(authenticationPropertiesBuilder);
return getAllPoliciesResponse.statusCode(HttpStatus.OK.value()).extract().body().as(Map.class);
}

public static void cleanupPolicy(final AuthenticationPropertiesBuilder authenticationPropertiesBuilder,
final String policyId) {

final ValidatableResponse deleteResponse = deletePolicy(authenticationPropertiesBuilder, policyId);
final int status = deleteResponse.extract().statusCode();

assertThat(List.of(HttpStatus.OK.value(), HttpStatus.NOT_FOUND.value())).describedAs(
"Should either return status 200 OK or 404 NOT_FOUND").contains(status);
}

public static ValidatableResponse deletePolicy(
final AuthenticationPropertiesBuilder authenticationPropertiesBuilder, final String policyId) {
return givenAuthentication(authenticationPropertiesBuilder).pathParam("policyId", policyId)
.when()
.delete(URL_IRS_POLICIES + "/{policyId}")
.then()
.log()
.all();
}

@Data
@NoArgsConstructor
public static final class PolicyAttributes {
private String policyId;
private List<String> bpnls;

Check notice

Code scanning / CodeQL

Exposing internal representation Note test

getBpnls exposes the internal representation stored in field bpnls. The value may be modified
after this call to getBpnls
.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is ok for test IMHO

private String validUntil;
}
}
Loading
Loading