Skip to content

Commit efddd33

Browse files
committed
Adding PactProvider for verifying consumer contrcat
1 parent aa44fc2 commit efddd33

File tree

8 files changed

+208
-30
lines changed

8 files changed

+208
-30
lines changed

.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
SERVER_PORT=4550
22
BASE_IMAGE=openjdk:21-jdk-slim
3+
PACT_BROKER_URL=https://hmcts-dts.pactflow.io
4+
PACT_BROKER_TOKEN=eOmnLAeYytphFMQZIj7hUg
5+
PACT_ENV=dev/pactTest

build.gradle

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ plugins {
77
id 'maven-publish'
88
id "com.github.ben-manes.versions" version "0.52.0"
99
id "org.cyclonedx.bom" version "2.3.1"
10+
id "au.com.dius.pact" version "4.6.17"
1011
}
1112

1213
group = 'uk.gov.hmcts.cp'
@@ -231,7 +232,7 @@ application {
231232
}
232233

233234
ext {
234-
apiCourtScheduleVersion = "0.3.3"
235+
apiCourtScheduleVersion = "0.4.1"
235236
log4JVersion = "2.24.3"
236237
logbackVersion = "1.5.18"
237238
lombokVersion = "1.18.38"
@@ -273,4 +274,17 @@ dependencies {
273274
exclude group: 'junit', module: 'junit'
274275
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
275276
}
277+
278+
testImplementation 'au.com.dius.pact.provider:junit5:4.6.17'
279+
testImplementation 'au.com.dius.pact.provider:spring6:4.6.17'
280+
281+
test{
282+
systemProperty 'pact.verifier.publishResults', System.getProperty('pact.verifier.publishResults')
283+
systemProperty 'pact.provider.version', System.getProperty('pact.provider.version')
284+
systemProperty("pact.provider.branch", "dev/pactTest")
285+
systemProperty 'PACT_BROKER_TOKEN', System.getProperty('PACT_BROKER_TOKEN')
286+
systemProperty 'PACT_BROKER_HOST', System.getProperty('PACT_BROKER_HOST')
287+
//systemProperty 'GIT_BRANCH', System.getProperty('GIT_BRANCH')
288+
289+
}
276290
}

publish-pacts.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/bin/bash
2+
3+
# Load env vars from .env if available
4+
if [ -f .env ]; then
5+
set -a
6+
source .env
7+
set +a
8+
fi
9+
10+
# Export Git metadata
11+
export GIT_COMMIT=$(git rev-parse HEAD)
12+
13+
if [ -n "$GIT_BRANCH" ]; then
14+
BRANCH_NAME="$GIT_BRANCH"
15+
else
16+
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
17+
fi
18+
19+
export GIT_BRANCH="$BRANCH_NAME"
20+
21+
# Run provider verification with results published
22+
./gradlew test \
23+
-Dpact.provider.version="$GIT_COMMIT" \
24+
-Dpact.verifier.publishResults=true \
25+
-Dpact.provider.branch="$GIT_BRANCH" \
26+
-DPACT_BROKER_TOKEN="$PACT_BROKER_TOKEN" \
27+
-DPACT_BROKER_HOST="$PACT_BROKER_URL"
28+
29+
# Optional: tag provider in the broker
30+
pact-broker create-version-tag \
31+
--pacticipant "VPCourtSchedulePactProvider" \
32+
--version "$GIT_COMMIT" \
33+
--tag "$PACT_ENV" \
34+
--broker-base-url "$PACT_BROKER_URL" \
35+
--broker-token "$PACT_BROKER_TOKEN"

src/main/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepository.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
import org.springframework.stereotype.Repository;
44
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse;
55

6-
@FunctionalInterface
6+
//@FunctionalInterface
77
@Repository
8-
public interface CourtScheduleRepository {
8+
public interface CourtScheduleRepository {
99

1010
CourtScheduleResponse getCourtScheduleByCaseUrn(String caseUrn);
11+
void saveCourtSchedule(final String caseUrn, final CourtScheduleResponse CourtScheduleResponse);
12+
void clearAll();
1113

1214
}
Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,74 @@
11
package uk.gov.hmcts.cp.repositories;
22

3+
import org.springframework.context.annotation.Profile;
34
import org.springframework.stereotype.Component;
45
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse;
5-
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponseCourtScheduleInner;
6-
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponseCourtScheduleInnerHearingsInner;
7-
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponseCourtScheduleInnerHearingsInnerCourtSittingsInner;
6+
import uk.gov.hmcts.cp.openapi.model.CourtSchedule;
7+
import uk.gov.hmcts.cp.openapi.model.Hearing;
8+
import uk.gov.hmcts.cp.openapi.model.CourtSitting;
89

910
import java.time.OffsetDateTime;
11+
import java.time.ZoneOffset;
12+
import java.time.temporal.ChronoUnit;
1013
import java.util.List;
14+
import java.util.Map;
1115
import java.util.UUID;
16+
import java.util.concurrent.ConcurrentHashMap;
1217

1318
@Component
19+
//@Profile("test")
1420
public class InMemoryCourtScheduleRepositoryImpl implements CourtScheduleRepository {
1521

22+
private final Map<String, CourtScheduleResponse> courtScheduleResponseMap = new ConcurrentHashMap<>();
23+
24+
public void saveCourtSchedule(final String caseUrn, final CourtScheduleResponse CourtScheduleResponse) {
25+
courtScheduleResponseMap.put(caseUrn, CourtScheduleResponse);
26+
}
27+
1628
public CourtScheduleResponse getCourtScheduleByCaseUrn(final String caseUrn) {
17-
final CourtScheduleResponseCourtScheduleInnerHearingsInner courtScheduleHearing = CourtScheduleResponseCourtScheduleInnerHearingsInner.builder()
29+
if (!courtScheduleResponseMap.containsKey(caseUrn)) {
30+
saveCourtSchedule(caseUrn, createCourtScheduleResponse());
31+
}
32+
return courtScheduleResponseMap.get(caseUrn);
33+
}
34+
35+
public void clearAll() {
36+
courtScheduleResponseMap.clear();
37+
}
38+
39+
private CourtScheduleResponse createCourtScheduleResponse() {
40+
41+
OffsetDateTime sittingStartTime = OffsetDateTime.now(ZoneOffset.UTC)
42+
.truncatedTo(ChronoUnit.SECONDS);
43+
44+
final Hearing hearing = Hearing.builder()
1845
.hearingId(UUID.randomUUID().toString())
1946
.listNote("Requires interpreter")
2047
.hearingDescription("Sentencing for theft case")
2148
.hearingType("Trial")
2249
.courtSittings(List.of(
23-
CourtScheduleResponseCourtScheduleInnerHearingsInnerCourtSittingsInner.builder()
50+
CourtSitting.builder()
2451
.courtHouse("Central Criminal Court")
25-
.sittingStart(OffsetDateTime.now())
26-
.sittingEnd(OffsetDateTime.now().plusMinutes(60))
52+
.sittingStart(sittingStartTime)
53+
.sittingEnd(sittingStartTime.plusMinutes(60))
2754
.judiciaryId(UUID.randomUUID().toString())
2855
.build())
2956
).build();
3057

3158
return CourtScheduleResponse.builder()
3259
.courtSchedule(List.of(
33-
CourtScheduleResponseCourtScheduleInner.builder()
34-
.hearings(List.of(courtScheduleHearing)
60+
CourtSchedule.builder()
61+
.hearings(List.of(hearing)
3562
).build()
3663
)
3764
).build();
3865
}
3966

67+
68+
public static void main(String[] args) {
69+
OffsetDateTime sittingStartTime = OffsetDateTime.now(ZoneOffset.UTC)
70+
.truncatedTo(ChronoUnit.SECONDS);
71+
System.out.println(sittingStartTime);
72+
73+
}
4074
}

src/test/java/uk/gov/hmcts/cp/controllers/CourtScheduleControllerTest.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
import org.springframework.http.HttpStatus;
88
import org.springframework.http.ResponseEntity;
99
import org.springframework.web.server.ResponseStatusException;
10+
import uk.gov.hmcts.cp.openapi.model.CourtSchedule;
1011
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse;
11-
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponseCourtScheduleInner;
12-
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponseCourtScheduleInnerHearingsInner;
13-
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponseCourtScheduleInnerHearingsInnerCourtSittingsInner;
12+
13+
import uk.gov.hmcts.cp.openapi.model.CourtSitting;
14+
import uk.gov.hmcts.cp.openapi.model.Hearing;
1415
import uk.gov.hmcts.cp.repositories.CourtScheduleRepository;
1516
import uk.gov.hmcts.cp.repositories.InMemoryCourtScheduleRepositoryImpl;
1617
import uk.gov.hmcts.cp.services.CourtScheduleService;
@@ -52,24 +53,24 @@ void getJudgeById_ShouldReturnJudgesWithOkStatus() {
5253
assertNotNull(responseBody.getCourtSchedule());
5354
assertEquals(1, responseBody.getCourtSchedule().size());
5455

55-
CourtScheduleResponseCourtScheduleInner schedule = responseBody.getCourtSchedule().get(0);
56-
assertNotNull(schedule.getHearings());
57-
assertEquals(1, schedule.getHearings().size());
56+
CourtSchedule courtSchedule = responseBody.getCourtSchedule().get(0);
57+
assertNotNull(courtSchedule.getHearings());
58+
assertEquals(1, courtSchedule.getHearings().size());
5859

59-
CourtScheduleResponseCourtScheduleInnerHearingsInner hearing = schedule.getHearings().get(0);
60+
Hearing hearing = courtSchedule.getHearings().get(0);
6061
assertNotNull(hearing.getHearingId());
6162
assertEquals("Requires interpreter", hearing.getListNote());
6263
assertEquals("Sentencing for theft case", hearing.getHearingDescription());
6364
assertEquals("Trial", hearing.getHearingType());
6465
assertNotNull(hearing.getCourtSittings());
6566
assertEquals(1, hearing.getCourtSittings().size());
6667

67-
CourtScheduleResponseCourtScheduleInnerHearingsInnerCourtSittingsInner sitting =
68+
CourtSitting courtSitting =
6869
hearing.getCourtSittings().get(0);
69-
assertEquals("Central Criminal Court", sitting.getCourtHouse());
70-
assertNotNull(sitting.getSittingStart());
71-
assertTrue(sitting.getSittingEnd().isAfter(sitting.getSittingStart()));
72-
assertNotNull(sitting.getJudiciaryId());
70+
assertEquals("Central Criminal Court", courtSitting.getCourtHouse());
71+
assertNotNull(courtSitting.getSittingStart());
72+
assertTrue(courtSitting.getSittingEnd().isAfter(courtSitting.getSittingStart()));
73+
assertNotNull(courtSitting.getJudiciaryId());
7374

7475
}
7576

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package uk.gov.hmcts.cp.pact.provider;
2+
3+
import au.com.dius.pact.provider.junit5.HttpTestTarget;
4+
import au.com.dius.pact.provider.junit5.PactVerificationContext;
5+
import au.com.dius.pact.provider.junit5.PactVerificationInvocationContextProvider;
6+
import au.com.dius.pact.provider.junitsupport.Provider;
7+
import au.com.dius.pact.provider.junitsupport.State;
8+
import au.com.dius.pact.provider.junitsupport.loader.PactBroker;
9+
import au.com.dius.pact.provider.junitsupport.loader.PactBrokerAuth;
10+
import org.junit.jupiter.api.BeforeEach;
11+
import org.junit.jupiter.api.TestTemplate;
12+
import org.junit.jupiter.api.extension.ExtendWith;
13+
import org.springframework.beans.factory.annotation.Autowired;
14+
import org.springframework.boot.test.context.SpringBootTest;
15+
import org.springframework.boot.test.web.server.LocalServerPort;
16+
import org.springframework.test.context.junit.jupiter.SpringExtension;
17+
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse;
18+
import uk.gov.hmcts.cp.openapi.model.CourtSchedule;
19+
import uk.gov.hmcts.cp.openapi.model.Hearing;
20+
import uk.gov.hmcts.cp.openapi.model.CourtSitting;
21+
import uk.gov.hmcts.cp.repositories.CourtScheduleRepository;
22+
23+
import java.time.OffsetDateTime;
24+
import java.util.List;
25+
import java.util.UUID;
26+
27+
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
28+
//@ActiveProfiles("test") // important: use the in-memory repo!
29+
@ExtendWith({SpringExtension.class, PactVerificationInvocationContextProvider.class})
30+
@Provider("VPCourtSchedulePactProvider")
31+
@PactBroker(
32+
scheme = "https",
33+
host = "hmcts-dts.pactflow.io",
34+
providerBranch = "dev/pactTest",
35+
authentication = @PactBrokerAuth(token = "eOmnLAeYytphFMQZIj7hUg")
36+
)
37+
public class CourtScheduleProviderPactTest {
38+
39+
@Autowired
40+
private CourtScheduleRepository courtScheduleRepository;
41+
42+
@LocalServerPort
43+
private int port;
44+
45+
@BeforeEach
46+
void setupTarget(PactVerificationContext context) {
47+
System.out.println("Running test on port: " + port);
48+
context.setTarget(new HttpTestTarget("localhost", port));
49+
System.out.println("pact.verifier.publishResults: " + System.getProperty("pact.verifier.publishResults"));
50+
}
51+
52+
/* @BeforeEach
53+
public void setupTestTarget(PactVerificationContext context) {
54+
context.setTarget(new HttpTestTarget("localhost", 8080));
55+
}*/
56+
57+
@State("court schedule for case 456789 exists")
58+
public void setupCourtSchedule() {
59+
courtScheduleRepository.clearAll();
60+
var courtSitting = CourtSitting.builder()
61+
.courtHouse("Central Criminal Court")
62+
.sittingStart(OffsetDateTime.now())
63+
.sittingEnd(OffsetDateTime.now().plusMinutes(60))
64+
.judiciaryId(UUID.randomUUID().toString())
65+
.build();
66+
var hearing = Hearing.builder()
67+
.hearingId(UUID.randomUUID().toString())
68+
.listNote("Requires interpreter")
69+
.hearingDescription("Sentencing for theft case")
70+
.hearingType("Trial")
71+
.courtSittings(List.of(courtSitting))
72+
.build();
73+
74+
var schedule = CourtSchedule.builder()
75+
.hearings(List.of(hearing))
76+
.build();
77+
78+
var response = CourtScheduleResponse.builder()
79+
.courtSchedule(List.of(schedule))
80+
.build();
81+
82+
courtScheduleRepository.saveCourtSchedule("456789", response);
83+
}
84+
85+
@TestTemplate
86+
void pactVerificationTestTemplate(PactVerificationContext context) {
87+
context.verifyInteraction();
88+
}
89+
}

src/test/java/uk/gov/hmcts/cp/repositories/CourtScheduleRepositoryTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
import org.junit.jupiter.api.BeforeEach;
44
import org.junit.jupiter.api.Test;
5+
import uk.gov.hmcts.cp.openapi.model.CourtSchedule;
56
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponse;
6-
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponseCourtScheduleInner;
7-
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponseCourtScheduleInnerHearingsInner;
8-
import uk.gov.hmcts.cp.openapi.model.CourtScheduleResponseCourtScheduleInnerHearingsInnerCourtSittingsInner;
7+
import uk.gov.hmcts.cp.openapi.model.CourtSitting;
8+
import uk.gov.hmcts.cp.openapi.model.Hearing;
99

1010
import java.util.UUID;
1111

@@ -30,19 +30,19 @@ void getCourtScheduleByCaseUrn_shouldReturnCourtScheduleResponse() {
3030
assertNotNull(response.getCourtSchedule());
3131
assertEquals(1, response.getCourtSchedule().size());
3232

33-
CourtScheduleResponseCourtScheduleInner schedule = response.getCourtSchedule().get(0);
33+
CourtSchedule schedule = response.getCourtSchedule().get(0);
3434
assertNotNull(schedule.getHearings());
3535
assertEquals(1, schedule.getHearings().size());
3636

37-
CourtScheduleResponseCourtScheduleInnerHearingsInner hearing = schedule.getHearings().get(0);
37+
Hearing hearing = schedule.getHearings().get(0);
3838
assertNotNull(hearing.getHearingId());
3939
assertEquals("Requires interpreter", hearing.getListNote());
4040
assertEquals("Sentencing for theft case", hearing.getHearingDescription());
4141
assertEquals("Trial", hearing.getHearingType());
4242
assertNotNull(hearing.getCourtSittings());
4343
assertEquals(1, hearing.getCourtSittings().size());
4444

45-
CourtScheduleResponseCourtScheduleInnerHearingsInnerCourtSittingsInner sitting =
45+
CourtSitting sitting =
4646
hearing.getCourtSittings().get(0);
4747
assertEquals("Central Criminal Court", sitting.getCourtHouse());
4848
assertNotNull(sitting.getSittingStart());

0 commit comments

Comments
 (0)