diff --git a/cwms-data-api/src/test/java/cwms/cda/api/location/kind/GateChangeControllerTestIT.java b/cwms-data-api/src/test/java/cwms/cda/api/location/kind/GateChangeControllerTestIT.java index 15359bf36..c5f6d1ca8 100644 --- a/cwms-data-api/src/test/java/cwms/cda/api/location/kind/GateChangeControllerTestIT.java +++ b/cwms-data-api/src/test/java/cwms/cda/api/location/kind/GateChangeControllerTestIT.java @@ -57,6 +57,7 @@ import static cwms.cda.security.ApiKeyIdentityProvider.AUTH_HEADER; import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertNotNull; @Tag("integration") @@ -116,6 +117,9 @@ class GateChangeControllerTestIT extends BaseOutletDaoIT { buildTestGateSetting(CONDUIT_GATE_2_ID, 3, 4)); private static final GateChange CHANGE_3 = buildTestGateChange(PROJECT_1_ID, JAN_THIRD); + private static final GateChange UNPROTECTED_CHANGE_1 = buildUnprotectedTestGateChange(PROJECT_1_ID, JAN_FIRST, + buildTestGateSetting(CONDUIT_GATE_1_ID, 12, 20)); + @BeforeAll static void setup() throws Exception { setupProject(); @@ -348,6 +352,72 @@ void test_changes_create_from_file() throws Exception { .statusCode(is(HttpServletResponse.SC_NO_CONTENT)); } + @Test + void test_override_protection() + { + String json = Formats.format(Formats.parseHeader(Formats.JSONV1, GateChange.class), List.of(CHANGE_1), GateChange.class); + + //Create the gate changes + given() + .log().ifValidationFails(LogDetail.ALL, true) + .contentType(Formats.JSONV1) + .body(json) + .header(AUTH_HEADER, USER.toHeaderValue()) + .queryParam(OVERRIDE_PROTECTION, "true") + .when() + .redirects().follow(true) + .redirects().max(3) + .post("projects/gate-changes") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + + String unprotectedJson = Formats.format(Formats.parseHeader(Formats.JSONV1, GateChange.class), List.of(UNPROTECTED_CHANGE_1), GateChange.class); + + //Try creating it again with OVERRIDE_PROTECTION=false, this should fail. + given() + .log().ifValidationFails(LogDetail.ALL, true) + .contentType(Formats.JSONV1) + .body(unprotectedJson) + .header(AUTH_HEADER, USER.toHeaderValue()) + .queryParam(OVERRIDE_PROTECTION, "false") + .when() + .redirects().follow(true) + .redirects().max(3) + .post("projects/gate-changes") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_CREATED)); + + String allJson = given().log() + .ifValidationFails(LogDetail.ALL, true) + .contentType(Formats.JSONV1) + .accept(Formats.DEFAULT) + .when() + .redirects() + .follow(true) + .redirects() + .max(3) + .queryParam(BEGIN, JAN_FIRST.toString()) + .queryParam(END, JAN_SECOND.toString()) + .queryParam(START_TIME_INCLUSIVE, true) + .queryParam(END_TIME_INCLUSIVE, true) + .get("projects/" + OFFICE_ID + "/" + PROJECT_1_ID.getName() + "/gate-changes") + .then() + .log().ifValidationFails(LogDetail.ALL, true) + .assertThat() + .statusCode(is(HttpServletResponse.SC_OK)) + .extract() + .body() + .asString(); + List changes = Formats.parseContentList(Formats.parseHeader(Formats.JSONV1, GateChange.class), + allJson, GateChange.class); + + DTOMatch.assertContainsDto(changes, CHANGE_1, this::isSimilar, DTOMatch::assertMatch, "Does not contain change for " + CHANGE_1.getChangeDate()); + } + private boolean isSimilar(GateChange left, GateChange right) { boolean output = false; @@ -409,6 +479,43 @@ static GateChange buildTestGateChange(CwmsId projectId, Instant changeDate, Gate .build(); } + static GateChange buildUnprotectedTestGateChange(CwmsId projectId, Instant changeDate, GateSetting... settingVargs) { + LookupType dischargeComputationType = new LookupType.Builder().withActive(true) + .withDisplayValue("A") + .withTooltip("Adjusted by an automated method") + .withOfficeId(OFFICE_ID) + .build(); + LookupType reasonType = new LookupType.Builder().withActive(true) + .withDisplayValue("O") + .withTooltip("Other release") + .withOfficeId(OFFICE_ID) + .build(); + boolean isProtected = false; + Double newTotalDischargeOverride = 1.0; + Double oldTotalDischargeOverride = 2.0; + String dischargeUnits = "cfs"; + Double poolElevation = 3.0; + Double tailwaterElevation = 4.0; + String elevationUnits = "ft"; + String notes = "Test notes"; + List settings = Arrays.asList(settingVargs); + + return new GateChange.Builder().withProjectId(projectId) + .withDischargeComputationType(dischargeComputationType) + .withReasonType(reasonType) + .withProtected(isProtected) + .withNewTotalDischargeOverride(newTotalDischargeOverride) + .withOldTotalDischargeOverride(oldTotalDischargeOverride) + .withDischargeUnits(dischargeUnits) + .withPoolElevation(poolElevation) + .withTailwaterElevation(tailwaterElevation) + .withElevationUnits(elevationUnits) + .withNotes(notes) + .withChangeDate(changeDate) + .withSettings(settings) + .build(); + } + static GateSetting buildTestGateSetting(CwmsId locationId, double opening, double invertElev) { return new GateSetting.Builder().withLocationId(locationId) .withOpening(opening)