Skip to content

Commit

Permalink
Merge pull request #906 from catenax-ng/feat/567-update-message
Browse files Browse the repository at this point in the history
feat(impl):[#567] fix message when wrong direction
  • Loading branch information
ds-ext-kmassalski authored May 2, 2024
2 parents f727d85 + d5b996e commit 16fa62e
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ end note
"bomLifecycle": "asPlannned",
"collectAspects": true,
"depth": 1,
"direction": "upwards",
"direction": "upward",
"keys": [
{
"bpn": "BPNL0123456789XX",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import static org.eclipse.tractusx.irs.util.TestMother.registerJobWithoutDepthAndAspect;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
Expand Down Expand Up @@ -74,6 +75,7 @@
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
Expand All @@ -91,9 +93,13 @@

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = { "digitalTwinRegistry.type=central" })
@ActiveProfiles(profiles = { "test", "local" })
@ActiveProfiles(profiles = { "test",
"local"
})
@Import(TestConfig.class)
@ExtendWith({ MockitoExtension.class, SpringExtension.class })
@ExtendWith({ MockitoExtension.class,
SpringExtension.class
})
class IrsControllerTest extends ControllerTest {

private final UUID jobId = UUID.randomUUID();
Expand Down Expand Up @@ -129,42 +135,91 @@ void initiateJobForGlobalAssetId() {
final UUID returnedJob = UUID.randomUUID();
Mockito.when(service.registerItemJob(any())).thenReturn(JobHandle.builder().id(returnedJob).build());

given().port(port).contentType(ContentType.JSON).body(registerJobWithoutDepthAndAspect()).post("/irs/jobs")
.then().statusCode(CREATED.value()).body("id", is(returnedJob.toString()));
given().port(port)
.contentType(ContentType.JSON)
.body(registerJobWithoutDepthAndAspect())
.post("/irs/jobs")
.then()
.statusCode(CREATED.value())
.body("id", is(returnedJob.toString()));
}

@Test
void shouldReturnUnauthorizedStatusWhenAuthenticationIsMissing() {
Mockito.when(authenticationService.getAuthentication(any(HttpServletRequest.class)))
.thenThrow(new BadCredentialsException("Wrong ApiKey"));

given().port(port).contentType(ContentType.JSON).body(registerJobWithoutDepthAndAspect()).post("/irs/jobs")
.then().statusCode(UNAUTHORIZED.value());
.thenThrow(new BadCredentialsException("Wrong ApiKey"));

given().port(port)
.contentType(ContentType.JSON)
.body(registerJobWithoutDepthAndAspect())
.post("/irs/jobs")
.then()
.statusCode(UNAUTHORIZED.value());
}

@Test
void shouldReturnForbiddenStatusWhenRequiredAuthorityIsMissing() {
authenticateWith("view_irs_wrong_authority");

given().port(port).contentType(ContentType.JSON).body(registerJobWithoutDepthAndAspect()).post("/irs/jobs")
.then().statusCode(FORBIDDEN.value());
given().port(port)
.contentType(ContentType.JSON)
.body(registerJobWithoutDepthAndAspect())
.post("/irs/jobs")
.then()
.statusCode(FORBIDDEN.value());
}

@ParameterizedTest
@MethodSource("corruptedJobs")
void shouldReturnBadRequestWhenRegisterJobBodyNotValid(final RegisterJob registerJob) {
authenticateWith(IrsRoles.VIEW_IRS);

given().port(port).contentType(ContentType.JSON).body(registerJob).post("/irs/jobs")
.then().statusCode(BAD_REQUEST.value());
given().port(port)
.contentType(ContentType.JSON)
.body(registerJob)
.post("/irs/jobs")
.then()
.statusCode(BAD_REQUEST.value());
}

@ParameterizedTest
@ValueSource(strings = { "upwards",
"downwards"
})
void shouldReturnBadRequestWhenRegisterJobWithInvalidDirection(String invalidDirection) {
authenticateWith(IrsRoles.VIEW_IRS);

given().port(port)
.contentType(ContentType.JSON)
.body("""
{
"key": {
"globalAssetId": "urn:uuid:c6d2d642-a055-4ddf-87e3-1a3b02c689e3",
"bpn": "BPNL00000000BJTL"
},
"direction": "<DIRECTION>",
"lookupBPNs": true
}
""".replace("<DIRECTION>", invalidDirection))
.post("/irs/jobs")
.then()
.statusCode(BAD_REQUEST.value())
.body("error", containsString("Unsupported direction"))
.body("error", containsString("Must be one of: upward, downward"))
// error message should not contain unvalidated user input for security reasons
.body("error", not(containsString(invalidDirection)));
}

@Test
void shouldReturnBadRequestWhenRegisterJobHasWrongCallbackUrl() {
authenticateWith(IrsRoles.VIEW_IRS);

given().port(port).contentType(ContentType.JSON).body(registerJobWithUrl("hhh://example.com")).post("/irs/jobs")
.then().statusCode(BAD_REQUEST.value());
given().port(port)
.contentType(ContentType.JSON)
.body(registerJobWithUrl("hhh://example.com"))
.post("/irs/jobs")
.then()
.statusCode(BAD_REQUEST.value());
}

@Test
Expand All @@ -174,8 +229,12 @@ void shouldAcceptCorrectCallbackUrl() {
final UUID returnedJob = UUID.randomUUID();
Mockito.when(service.registerItemJob(any())).thenReturn(JobHandle.builder().id(returnedJob).build());

given().port(port).contentType(ContentType.JSON).body(registerJobWithUrl("https://example.com")).post("/irs/jobs")
.then().statusCode(CREATED.value());
given().port(port)
.contentType(ContentType.JSON)
.body(registerJobWithUrl("https://example.com"))
.post("/irs/jobs")
.then()
.statusCode(CREATED.value());
}

@Test
Expand All @@ -191,18 +250,20 @@ void getJobsByState() throws Exception {

final String returnJobAsString = objectMapper.writeValueAsString(returnedJob);

Mockito.when(service.getJobsByState(any(), any())).thenReturn(
new PageResult(new PagedListHolder<>(List.of(returnedJob))));
Mockito.when(service.getJobsByState(any(), any()))
.thenReturn(new PageResult(new PagedListHolder<>(List.of(returnedJob))));

given().port(port).get("/irs/jobs")
.then().statusCode(OK.value())
given().port(port)
.get("/irs/jobs")
.then()
.statusCode(OK.value())
.body(containsString(returnJobAsString))
.body(containsString(returnedJob.getId().toString()))
.body(containsString(returnedJob.getState().toString()))
.body(containsString(returnedJob.getStartedOn().format(DateTimeFormatter.ofPattern(
"yyyy-MM-dd'T'HH:mm:ss.SSS"))))
.body(containsString(returnedJob.getCompletedOn().format(DateTimeFormatter.ofPattern(
"yyyy-MM-dd'T'HH:mm:ss.SSS"))));
.body(containsString(
returnedJob.getStartedOn().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS"))))
.body(containsString(
returnedJob.getCompletedOn().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS"))));
}

@Test
Expand All @@ -212,19 +273,17 @@ void cancelJobById() {
final Job canceledJob = Job.builder().id(jobId).state(JobState.CANCELED).build();
Mockito.when(this.service.cancelJobById(jobId)).thenReturn(canceledJob);

given().port(port).put("/irs/jobs/" + jobId)
.then().statusCode(OK.value());
given().port(port).put("/irs/jobs/" + jobId).then().statusCode(OK.value());
}

@Test
void cancelJobById_throwEntityNotFoundException() {
authenticateWith(IrsRoles.VIEW_IRS);

BDDMockito.given(this.service.cancelJobById(jobId)).willThrow(
new ResponseStatusException(HttpStatus.NOT_FOUND, "No job exists with id " + jobId));
BDDMockito.given(this.service.cancelJobById(jobId))
.willThrow(new ResponseStatusException(HttpStatus.NOT_FOUND, "No job exists with id " + jobId));

given().port(port).put("/irs/jobs/" + jobId)
.then().statusCode(NOT_FOUND.value());
given().port(port).put("/irs/jobs/" + jobId).then().statusCode(NOT_FOUND.value());
}

@Test
Expand All @@ -233,8 +292,7 @@ void getJobWithMalformedIdShouldReturnBadRequest() {

final String jobIdMalformed = UUID.randomUUID() + "MALFORMED";

given().port(port).get("/irs/jobs/" + jobIdMalformed)
.then().statusCode(BAD_REQUEST.value());
given().port(port).get("/irs/jobs/" + jobIdMalformed).then().statusCode(BAD_REQUEST.value());
}

@Test
Expand All @@ -244,19 +302,23 @@ void shouldReturnBadRequestWhenRegisterJobWithMalformedAspectJson() {
Mockito.when(service.registerItemJob(any())).thenThrow(IllegalArgumentException.class);
final String requestBody = "{ \"aspects\": [ \"MALFORMED\" ], \"globalAssetId\": \"urn:uuid:8a61c8db-561e-4db0-84ec-a693fc5ffdf6\" }";

given().port(port).contentType(ContentType.JSON).body(requestBody).post("/irs/jobs")
.then().statusCode(BAD_REQUEST.value());
given().port(port)
.contentType(ContentType.JSON)
.body(requestBody)
.post("/irs/jobs")
.then()
.statusCode(BAD_REQUEST.value());
}

@Test
void shouldReturnBadRequestWhenCancelingAlreadyCompletedJob() {
authenticateWith(IrsRoles.VIEW_IRS);

BDDMockito.given(this.service.cancelJobById(jobId)).willThrow(new IllegalStateException(
format("Cannot transition from state %s to %s", JobState.COMPLETED, JobState.CANCELED)));
BDDMockito.given(this.service.cancelJobById(jobId))
.willThrow(new IllegalStateException(
format("Cannot transition from state %s to %s", JobState.COMPLETED, JobState.CANCELED)));

given().port(port).put("/irs/jobs/" + jobId)
.then().statusCode(BAD_REQUEST.value());
given().port(port).put("/irs/jobs/" + jobId).then().statusCode(BAD_REQUEST.value());
}

@Test
Expand All @@ -278,8 +340,14 @@ void shouldReturnAspectModels() throws Exception {

BDDMockito.given(this.semanticHubService.getAllAspectModels()).willReturn(aspectModels);

final AspectModels response = given().port(port).get("/irs/aspectmodels")
.then().statusCode(OK.value()).and().extract().response().as(AspectModels.class);
final AspectModels response = given().port(port)
.get("/irs/aspectmodels")
.then()
.statusCode(OK.value())
.and()
.extract()
.response()
.as(AspectModels.class);

assertEquals(aspectModels, response);
}
Expand All @@ -288,8 +356,7 @@ void shouldReturnAspectModels() throws Exception {
void shouldReturnForbiddenStatusForAspectModelsWhenRequiredAuthorityIsMissing() {
authenticateWith("view_irs_wrong_authority");

given().port(port).get("/irs/aspectmodels")
.then().statusCode(FORBIDDEN.value());
given().port(port).get("/irs/aspectmodels").then().statusCode(FORBIDDEN.value());
}

@Test
Expand All @@ -300,10 +367,16 @@ void shouldReturnPartialWhenJobCompleted() {

Mockito.when(this.service.getJobForJobId(eq(jobId), anyBoolean())).thenReturn(runningJob);

given().port(port).queryParam("returnUncompletedJob", true).get("/irs/jobs/" + jobId)
.then().statusCode(PARTIAL_CONTENT.value());
given().port(port).queryParam("returnUncompletedJob", false).get("/irs/jobs/" + jobId)
.then().statusCode(PARTIAL_CONTENT.value());
given().port(port)
.queryParam("returnUncompletedJob", true)
.get("/irs/jobs/" + jobId)
.then()
.statusCode(PARTIAL_CONTENT.value());
given().port(port)
.queryParam("returnUncompletedJob", false)
.get("/irs/jobs/" + jobId)
.then()
.statusCode(PARTIAL_CONTENT.value());
}

@Test
Expand All @@ -314,10 +387,16 @@ void shouldReturnOkWhenJobCompleted() {

Mockito.when(this.service.getJobForJobId(eq(jobId), anyBoolean())).thenReturn(completedJob);

given().port(port).queryParam("returnUncompletedJob", true).get("/irs/jobs/" + jobId)
.then().statusCode(OK.value());
given().port(port).queryParam("returnUncompletedJob", false).get("/irs/jobs/" + jobId)
.then().statusCode(OK.value());
given().port(port)
.queryParam("returnUncompletedJob", true)
.get("/irs/jobs/" + jobId)
.then()
.statusCode(OK.value());
given().port(port)
.queryParam("returnUncompletedJob", false)
.get("/irs/jobs/" + jobId)
.then()
.statusCode(OK.value());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
********************************************************************************/
package org.eclipse.tractusx.irs.component.enums;

import java.util.NoSuchElementException;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fasterxml.jackson.annotation.JsonCreator;
Expand Down Expand Up @@ -62,7 +64,12 @@ public static Direction fromValue(final String value) {
return Stream.of(Direction.values())
.filter(direction -> direction.name.equals(value))
.findFirst()
.orElseThrow();
.orElseThrow(() -> new NoSuchElementException(
"Unsupported direction. Must be one of: " + supportedDirections()));
}

private static String supportedDirections() {
return Stream.of(Direction.values()).map(direction -> direction.name).collect(Collectors.joining(", "));
}

/**
Expand Down

0 comments on commit 16fa62e

Please sign in to comment.