From 71f3aefed1de5dcc1c874f3ec0a2e9730349f769 Mon Sep 17 00:00:00 2001 From: Arcadius Ahouansou Date: Wed, 3 Jun 2026 21:46:55 +0100 Subject: [PATCH 1/2] Restriction int tests fix --- .../hearing/it/CourtListRestrictionIT.java | 36 +++++++++++++++++++ .../steps/CourtListRestrictionSteps.java | 34 ++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/it/CourtListRestrictionIT.java b/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/it/CourtListRestrictionIT.java index 00ea86154..6c3b8d64b 100644 --- a/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/it/CourtListRestrictionIT.java +++ b/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/it/CourtListRestrictionIT.java @@ -71,6 +71,10 @@ public void shouldRequestToPublishCourtListWithCaseRestriction() throws Exceptio withJsonPath("$.caseIds", hasSize(1)), withJsonPath("$.restrictCourtList", is(true))))); + // Wait for the restriction projection to land before publishing + courtListRestrictionSteps.waitForRestrictionProjection(courtCentreId, eventTime.toLocalDate(), + withJsonPath("$.court.courtSites[0].courtRooms[0].cases.casesDetails", hasSize(0))); + JsonObject publishCourtListJsonObject = buildPublishCourtListJsonString(courtCentreId, "26"); final PublishCourtListSteps publishCourtListSteps = new PublishCourtListSteps(); @@ -96,6 +100,10 @@ public void shouldRequestToPublishCourtListWithCaseRestriction() throws Exceptio withJsonPath("$.caseIds", hasSize(1)), withJsonPath("$.restrictCourtList", is(false))))); + // Wait for the un-restriction projection to land before publishing + courtListRestrictionSteps.waitForRestrictionProjection(courtCentreId, eventTime.toLocalDate(), + withJsonPath("$.court.courtSites[0].courtRooms[0].cases.casesDetails", hasSize(1))); + publishCourtListJsonObject = buildPublishCourtListJsonString(courtCentreId, "26"); courtCentreId = sendPublishCourtListCommand(publishCourtListJsonObject, courtCentreId); @@ -127,6 +135,10 @@ public void shouldRequestToPublishCourtListWithDefendantRestrictionOnOff() throw withJsonPath("$.defendantIds", hasSize(1)), withJsonPath("$.restrictCourtList", is(true))))); + // Wait for defendant restriction to land in the projection before publishing + courtListRestrictionSteps.waitForRestrictionProjection(courtCentreId, eventTime.toLocalDate(), + withJsonPath("$.court.courtSites[0].courtRooms[0].cases.casesDetails[0].defendants", hasSize(0))); + final JsonObject publishCourtListJsonObject = buildPublishCourtListJsonString(courtCentreId, "26"); final PublishCourtListSteps publishCourtListSteps = new PublishCourtListSteps(); @@ -155,6 +167,10 @@ public void shouldRequestToPublishCourtListWithDefendantRestrictionOnOff() throw withJsonPath("$.defendantIds", hasSize(1)), withJsonPath("$.restrictCourtList", is(false))))); + // Wait for defendant un-restriction to land in the projection before publishing + courtListRestrictionSteps.waitForRestrictionProjection(courtCentreId, eventTime.toLocalDate(), + withJsonPath("$.court.courtSites[0].courtRooms[0].cases.casesDetails[0].defendants", hasSize(1))); + courtCentreId = sendPublishCourtListCommand(publishCourtListJsonObject, courtCentreId); publishCourtListSteps.verifyCourtListPublishStatusReturnedWhenQueryingFromAPI(courtCentreId); @@ -191,6 +207,10 @@ public void shouldRequestToPublishCourtListForApplicationRestrictionOnOff() thro withJsonPath("$.courtApplicationIds", hasSize(1)), withJsonPath("$.restrictCourtList", is(true))))); + // Wait for application restriction to land in the projection before publishing + courtListRestrictionSteps.waitForRestrictionProjection(courtCentreId, eventTime.toLocalDate(), + withJsonPath("$.court.courtSites[0].courtRooms[0].cases.casesDetails", hasSize(0))); + JsonObject publishCourtListJsonObject = buildPublishCourtListJsonString(courtCentreId, "26"); final PublishCourtListSteps publishCourtListSteps = new PublishCourtListSteps(); @@ -216,6 +236,10 @@ public void shouldRequestToPublishCourtListForApplicationRestrictionOnOff() thro withJsonPath("$.courtApplicationIds", hasSize(1)), withJsonPath("$.restrictCourtList", is(false))))); + // Wait for application un-restriction to land in the projection before publishing + courtListRestrictionSteps.waitForRestrictionProjection(courtCentreId, eventTime.toLocalDate(), + withJsonPath("$.court.courtSites[0].courtRooms[0].cases.casesDetails", hasSize(1))); + publishCourtListJsonObject = buildPublishCourtListJsonString(courtCentreId, "26"); courtCentreId = sendPublishCourtListCommand(publishCourtListJsonObject, courtCentreId); @@ -249,6 +273,10 @@ public void shouldRequestToPublishCourtListForApplicationApplicantRestrictionOnO withJsonPath("$.courtApplicationApplicantIds", hasSize(1)), withJsonPath("$.restrictCourtList", is(true))))); + // Wait for applicant restriction to land in the projection before publishing + courtListRestrictionSteps.waitForRestrictionProjection(courtCentreId, eventTime.toLocalDate(), + withJsonPath("$.court.courtSites[0].courtRooms[0].cases.casesDetails[0].defendants[0].firstName", org.hamcrest.CoreMatchers.nullValue())); + JsonObject publishCourtListJsonObject = buildPublishCourtListJsonString(courtCentreId, "26"); final PublishCourtListSteps publishCourtListSteps = new PublishCourtListSteps(); @@ -274,6 +302,10 @@ public void shouldRequestToPublishCourtListForApplicationApplicantRestrictionOnO withJsonPath("$.courtApplicationApplicantIds", hasSize(1)), withJsonPath("$.restrictCourtList", is(false))))); + // Wait for applicant un-restriction to land in the projection before publishing + courtListRestrictionSteps.waitForRestrictionProjection(courtCentreId, eventTime.toLocalDate(), + withJsonPath("$.court.courtSites[0].courtRooms[0].cases.casesDetails[0].defendants[0].firstName", org.hamcrest.CoreMatchers.notNullValue())); + publishCourtListJsonObject = buildPublishCourtListJsonString(courtCentreId, "26"); courtCentreId = sendPublishCourtListCommand(publishCourtListJsonObject, courtCentreId); @@ -308,6 +340,10 @@ public void shouldRequestToPublishCourtListWhenYoungDefendantIsRestrictedOnIniti caseId, randomUUID(), courtRoom2Id, randomUUID().toString(), OPEN_CASE_PROSECUTION_EVENT_DEFINITION_ID, eventTime, of(hearingTypeId), courtCentreId, eventTime.toLocalDate()); + // Wait for the young-defendant restriction to land in the projection before publishing + courtListRestrictionSteps.waitForRestrictionProjection(courtCentreId, eventTime.toLocalDate(), + withJsonPath("$.court.courtSites[0].courtRooms[0].cases.casesDetails[0].defendants", hasSize(0))); + final JsonObject publishCourtListJsonObject = buildPublishCourtListJsonString(courtCentreId, "26"); final PublishCourtListSteps publishCourtListSteps = new PublishCourtListSteps(); diff --git a/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/steps/CourtListRestrictionSteps.java b/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/steps/CourtListRestrictionSteps.java index 65423c2ed..aa7743c5a 100644 --- a/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/steps/CourtListRestrictionSteps.java +++ b/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/steps/CourtListRestrictionSteps.java @@ -3,11 +3,21 @@ import static com.google.common.collect.Lists.newArrayList; import static com.jayway.jsonpath.matchers.JsonPathMatchers.isJson; import static com.jayway.jsonpath.matchers.JsonPathMatchers.withJsonPath; +import static java.text.MessageFormat.format; import static java.util.UUID.fromString; import static java.util.UUID.randomUUID; +import static java.util.concurrent.TimeUnit.SECONDS; +import static javax.ws.rs.core.Response.Status.OK; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; +import static uk.gov.justice.services.common.http.HeaderConstants.USER_ID; +import static uk.gov.justice.services.test.utils.core.http.BaseUriProvider.getBaseUri; +import static uk.gov.justice.services.test.utils.core.http.RequestParamsBuilder.requestParams; +import static uk.gov.justice.services.test.utils.core.http.RestPoller.poll; +import static uk.gov.justice.services.test.utils.core.matchers.ResponsePayloadMatcher.payload; +import static uk.gov.justice.services.test.utils.core.matchers.ResponseStatusMatcher.status; +import static uk.gov.moj.cpp.hearing.utils.WireMockStubUtils.setupAsAuthorizedAndSystemUser; import static uk.gov.justice.hearing.courts.CourtListRestricted.courtListRestricted; import static uk.gov.justice.services.test.utils.core.messaging.MetadataBuilderFactory.metadataWithRandomUUID; import static uk.gov.moj.cpp.hearing.it.UseCases.asDefault; @@ -87,6 +97,30 @@ public JsonPath hearingEventsCourtListRestrictedReceived(final Matcher matche } } + /** + * Polls the publish-side query {@code hearing.latest-hearings-by-court-centres} until the + * restriction projection has reached the expected state. The publish flow internally consumes + * the same query — once it reflects the toggle, the next {@code publish-court-list} command is + * guaranteed to see the same state. + *

+ * Required because {@link #hearingEventsCourtListRestrictedReceived(Matcher)} only confirms the + * hearing event was emitted; the listener that projects it into the JPA entity runs in a + * separate transaction and may lag behind the publish command if not waited for. + */ + public void waitForRestrictionProjection(final String courtCentreId, + final LocalDate hearingDate, + final Matcher expectedPayload) { + setupAsAuthorizedAndSystemUser(USER_ID_VALUE_AS_ADMIN); + final String queryPart = format(ENDPOINT_PROPERTIES.getProperty("hearing.latest-hearings-by-court-centres"), courtCentreId, hearingDate); + final String searchCourtListUrl = String.format("%s/%s", getBaseUri(), queryPart); + + poll(requestParams(searchCourtListUrl, "application/vnd.hearing.latest-hearings-by-court-centres+json") + .withHeader(USER_ID, getLoggedInSystemUserHeader())) + .timeout(60, SECONDS) + .pollInterval(1, SECONDS) + .until(status().is(OK), payload().isJson(expectedPayload)); + } + private void sendListingPublicEvent(final JsonObject restrictCourtListDataObject) { sendMessage( getPublicTopicInstance().createProducer(), From af3df32e2493a5b89c7c100d6fba12deeff02610 Mon Sep 17 00:00:00 2001 From: Arcadius Ahouansou Date: Thu, 4 Jun 2026 09:10:33 +0100 Subject: [PATCH 2/2] further int test fixes --- .../hearing/it/CourtListRestrictionIT.java | 27 ++++++++++++++++++- .../gov/moj/cpp/hearing/utils/WebDavStub.java | 20 ++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/it/CourtListRestrictionIT.java b/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/it/CourtListRestrictionIT.java index 6c3b8d64b..44ad0c3c2 100644 --- a/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/it/CourtListRestrictionIT.java +++ b/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/it/CourtListRestrictionIT.java @@ -1,5 +1,6 @@ package uk.gov.moj.cpp.hearing.it; +import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasNoJsonPath; import static com.jayway.jsonpath.matchers.JsonPathMatchers.isJson; import static com.jayway.jsonpath.matchers.JsonPathMatchers.withJsonPath; import static java.util.Optional.of; @@ -11,6 +12,10 @@ import static org.hamcrest.Matchers.is; import static uk.gov.moj.cpp.hearing.it.PublishLatestCourtCentreHearingEventsIT.XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26; import static uk.gov.moj.cpp.hearing.steps.HearingEventStepDefinitions.OPEN_CASE_PROSECUTION_EVENT_DEFINITION_ID; +import static uk.gov.moj.cpp.hearing.utils.WebDavStub.awaitNewFile; +import static uk.gov.moj.cpp.hearing.utils.WebDavStub.awaitNewSentXmlForPubDisplay; +import static uk.gov.moj.cpp.hearing.utils.WebDavStub.countFilesAt; +import static uk.gov.moj.cpp.hearing.utils.WebDavStub.countSentXmlForPubDisplay; import static uk.gov.moj.cpp.hearing.utils.WebDavStub.getFileForPath; import static uk.gov.moj.cpp.hearing.utils.WebDavStub.getSentXmlForPubDisplay; @@ -106,9 +111,14 @@ public void shouldRequestToPublishCourtListWithCaseRestriction() throws Exceptio publishCourtListJsonObject = buildPublishCourtListJsonString(courtCentreId, "26"); + final int webPageCountBeforeSecondPublish = countFilesAt(XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26); + final int pubDisplayCountBeforeSecondPublish = countSentXmlForPubDisplay(); + courtCentreId = sendPublishCourtListCommand(publishCourtListJsonObject, courtCentreId); publishCourtListSteps.verifyCourtListPublishStatusReturnedWhenQueryingFromAPI(courtCentreId); + awaitNewFile(XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26, webPageCountBeforeSecondPublish); + awaitNewSentXmlForPubDisplay(pubDisplayCountBeforeSecondPublish); filePayload = getFileForPath(XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26); filePayloadForPubDisplay = getSentXmlForPubDisplay(); @@ -171,8 +181,13 @@ public void shouldRequestToPublishCourtListWithDefendantRestrictionOnOff() throw courtListRestrictionSteps.waitForRestrictionProjection(courtCentreId, eventTime.toLocalDate(), withJsonPath("$.court.courtSites[0].courtRooms[0].cases.casesDetails[0].defendants", hasSize(1))); + final int webPageCountBeforeSecondPublish = countFilesAt(XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26); + final int pubDisplayCountBeforeSecondPublish = countSentXmlForPubDisplay(); + courtCentreId = sendPublishCourtListCommand(publishCourtListJsonObject, courtCentreId); publishCourtListSteps.verifyCourtListPublishStatusReturnedWhenQueryingFromAPI(courtCentreId); + awaitNewFile(XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26, webPageCountBeforeSecondPublish); + awaitNewSentXmlForPubDisplay(pubDisplayCountBeforeSecondPublish); filePayload = getFileForPath(XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26); filePayloadForPubDisplay = getSentXmlForPubDisplay(); @@ -242,9 +257,14 @@ public void shouldRequestToPublishCourtListForApplicationRestrictionOnOff() thro publishCourtListJsonObject = buildPublishCourtListJsonString(courtCentreId, "26"); + final int webPageCountBeforeSecondPublish = countFilesAt(XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26); + final int pubDisplayCountBeforeSecondPublish = countSentXmlForPubDisplay(); + courtCentreId = sendPublishCourtListCommand(publishCourtListJsonObject, courtCentreId); publishCourtListSteps.verifyCourtListPublishStatusReturnedWhenQueryingFromAPI(courtCentreId); + awaitNewFile(XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26, webPageCountBeforeSecondPublish); + awaitNewSentXmlForPubDisplay(pubDisplayCountBeforeSecondPublish); filePayload = getFileForPath(XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26); filePayloadForPubDisplay = getSentXmlForPubDisplay(); @@ -275,7 +295,7 @@ public void shouldRequestToPublishCourtListForApplicationApplicantRestrictionOnO // Wait for applicant restriction to land in the projection before publishing courtListRestrictionSteps.waitForRestrictionProjection(courtCentreId, eventTime.toLocalDate(), - withJsonPath("$.court.courtSites[0].courtRooms[0].cases.casesDetails[0].defendants[0].firstName", org.hamcrest.CoreMatchers.nullValue())); + hasNoJsonPath("$.court.courtSites[0].courtRooms[0].cases.casesDetails[0].defendants[0].firstName")); JsonObject publishCourtListJsonObject = buildPublishCourtListJsonString(courtCentreId, "26"); @@ -308,9 +328,14 @@ public void shouldRequestToPublishCourtListForApplicationApplicantRestrictionOnO publishCourtListJsonObject = buildPublishCourtListJsonString(courtCentreId, "26"); + final int webPageCountBeforeSecondPublish = countFilesAt(XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26); + final int pubDisplayCountBeforeSecondPublish = countSentXmlForPubDisplay(); + courtCentreId = sendPublishCourtListCommand(publishCourtListJsonObject, courtCentreId); publishCourtListSteps.verifyCourtListPublishStatusReturnedWhenQueryingFromAPI(courtCentreId); + awaitNewFile(XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26, webPageCountBeforeSecondPublish); + awaitNewSentXmlForPubDisplay(pubDisplayCountBeforeSecondPublish); filePayload = getFileForPath(XHIBIT_GATEWAY_SEND_WEB_PAGE_TO_XHIBIT_FILE_NAME_26); filePayloadForPubDisplay = getSentXmlForPubDisplay(); diff --git a/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/utils/WebDavStub.java b/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/utils/WebDavStub.java index 7c30374ed..8411194ea 100644 --- a/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/utils/WebDavStub.java +++ b/hearing-integration-test/src/test/java/uk/gov/moj/cpp/hearing/utils/WebDavStub.java @@ -7,11 +7,13 @@ import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching; import static javax.ws.rs.core.Response.Status.OK; +import static org.awaitility.Durations.ONE_MINUTE; import java.util.List; import java.util.UUID; import com.github.tomakehurst.wiremock.verification.LoggedRequest; +import org.awaitility.Awaitility; public class WebDavStub { @@ -35,4 +37,22 @@ public static String getFileForPath(final String filePath) { return loggedRequest.getBodyAsString(); } + + public static int countFilesAt(final String filePath) { + return findAll(putRequestedFor(urlPathMatching(filePath))).size(); + } + + public static int countSentXmlForPubDisplay() { + return countFilesAt(XHIBIT_GATEWAY_SEND_PUB_DISP_TO_XHIBIT_FILE_PATH_REG_EX); + } + + public static void awaitNewFile(final String filePath, final int previousCount) { + Awaitility.await() + .atMost(ONE_MINUTE) + .until(() -> countFilesAt(filePath) > previousCount); + } + + public static void awaitNewSentXmlForPubDisplay(final int previousCount) { + awaitNewFile(XHIBIT_GATEWAY_SEND_PUB_DISP_TO_XHIBIT_FILE_PATH_REG_EX, previousCount); + } }