From 1872a688471db085293994d7219c5c98621dab88 Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Tue, 27 Aug 2024 16:51:05 +0200 Subject: [PATCH 01/21] Pact Build Dire redefined in test base --- .../com/bottega/promoter/fixtures/FrameworkTestBase.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/services/Promoter/src/test/java/com/bottega/promoter/fixtures/FrameworkTestBase.java b/services/Promoter/src/test/java/com/bottega/promoter/fixtures/FrameworkTestBase.java index c0b04e2d..7f46cc0f 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/fixtures/FrameworkTestBase.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/fixtures/FrameworkTestBase.java @@ -5,13 +5,17 @@ import org.apache.groovy.util.Maps; import org.apache.kafka.clients.admin.AdminClient; import org.apache.kafka.clients.producer.ProducerConfig; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.*; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.KafkaContainer; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.utility.DockerImageName; + import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT; import static org.testcontainers.shaded.org.awaitility.Awaitility.await; @@ -54,6 +58,7 @@ static void kafkaProperties(DynamicPropertyRegistry registry) { @BeforeEach public void beforeEach() { + System.setProperty("pact.rootDir", "build/pacts"); kafkaContainerFixtures.beforeEach(); } From cad058cfb8f80a7b66a3a35a072fb80e8754521d Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Tue, 27 Aug 2024 16:53:57 +0200 Subject: [PATCH 02/21] Pact Live: consumer test implemented --- .../PactFrameworkTestBase_liveCoding.java | 21 ++++++++++ ..._applyDiscount_liveCoding_pactDepTest.java | 42 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 services/Promoter/src/test/java/com/bottega/promoter/fixtures/PactFrameworkTestBase_liveCoding.java create mode 100644 services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_pactDepTest.java diff --git a/services/Promoter/src/test/java/com/bottega/promoter/fixtures/PactFrameworkTestBase_liveCoding.java b/services/Promoter/src/test/java/com/bottega/promoter/fixtures/PactFrameworkTestBase_liveCoding.java new file mode 100644 index 00000000..aead0fba --- /dev/null +++ b/services/Promoter/src/test/java/com/bottega/promoter/fixtures/PactFrameworkTestBase_liveCoding.java @@ -0,0 +1,21 @@ +package com.bottega.promoter.fixtures; + +import au.com.dius.pact.consumer.junit5.PactConsumerTestExt; +import au.com.dius.pact.consumer.junit5.PactTestFor; +import au.com.dius.pact.core.model.PactSpecVersion; +import com.bottega.promoter.concert.fixtures.PricingPactFixtures; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; + +@ExtendWith(PactConsumerTestExt.class) +@PactTestFor(providerName = PactFrameworkTestBase_liveCoding.PACT_PRICING_LIVE_CODING, port = "8181", pactVersion = PactSpecVersion.V3) +@SuppressWarnings("deprecation") +public class PactFrameworkTestBase_liveCoding extends FrameworkTestBase { + + public static final String PACT_PROMOTER_LIVE_CODING = "LiveCoding.Tickets.Promoter"; + public static final String PACT_PRICING_LIVE_CODING = "LiveCoding.Tickets.Pricing"; + + @Autowired + protected PricingPactFixtures pricingPactFixtures; + +} diff --git a/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_pactDepTest.java b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_pactDepTest.java new file mode 100644 index 00000000..48a5fb94 --- /dev/null +++ b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_pactDepTest.java @@ -0,0 +1,42 @@ +package com.bottega.promoter.infra.client.pricing; + +import au.com.dius.pact.consumer.dsl.PactDslWithProvider; +import au.com.dius.pact.core.model.RequestResponsePact; +import au.com.dius.pact.core.model.annotations.Pact; +import com.bottega.promoter.concert.domain.ConcertId; +import com.bottega.promoter.fixtures.FakePricingClient; +import com.bottega.promoter.fixtures.PactFrameworkTestBase_liveCoding; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class PricingClient_applyDiscount_liveCoding_pactDepTest extends PactFrameworkTestBase_liveCoding { + + FakePricingClient fakePricingClient; + PricingClient httpPricingClient; + + + @BeforeEach + void setUp() { + fakePricingClient = new FakePricingClient(); + httpPricingClient = concertFixtures.pricingClient; + } + + @Pact(consumer = PACT_PROMOTER_LIVE_CODING) + @SuppressWarnings("unused") + public RequestResponsePact applyPercentageDiscount(PactDslWithProvider builder) { + return pricingPactFixtures.applyPercentageDiscount(builder); + } + + @Test + public void applyDiscount_isValid() { + + //when + var result = httpPricingClient.applyPercentageDiscount(new ConcertId("123"), 10); + + //then + assertThat(result.get().getFirst().getPrice().toInt()).isEqualTo(90_00); + } + +} From b32c8c17190e3636327fb041d7f7f9079f9dbeca Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Tue, 27 Aug 2024 17:00:45 +0200 Subject: [PATCH 03/21] Pact Live: wiremock test implemented --- ...lyDiscount_liveCoding_wiremockDepTest.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java diff --git a/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java new file mode 100644 index 00000000..a83c1e9e --- /dev/null +++ b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java @@ -0,0 +1,51 @@ +package com.bottega.promoter.infra.client.pricing; + +import com.bottega.promoter.concert.domain.ConcertId; +import com.bottega.promoter.fixtures.FrameworkTestBase; +import com.github.tomakehurst.wiremock.client.WireMock; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; + +import static org.assertj.core.api.Assertions.assertThat; + +@AutoConfigureWireMock(port = 8181) +public class PricingClient_applyDiscount_liveCoding_wiremockDepTest extends FrameworkTestBase { + + PricingClient httpPricingClient; + + @BeforeEach + void setUp() { + httpPricingClient = concertFixtures.pricingClient; + WireMock.reset(); + } + + @Test + public void applyDiscount_isValid() { + //given + WireMock.stubFor(WireMock.post(WireMock.urlEqualTo("/api/v1/item/123/price-factor/percentage")) + .willReturn(WireMock.aResponse() + .withStatus(200) + .withHeader("Content-Type", "application/json") + .withBody(""" + [ + { + "price": 9000, + "factors": [ + { + "type": "PERCENTAGE", + "value": 10 + } + ] + } + ] + """))); + + //when + var result = httpPricingClient.applyPercentageDiscount(new ConcertId("123"), 10); + + //then + assertThat(result.get().getFirst().getPrice().toInt()).isEqualTo(90_00); + } + +} From e20cce0f8bdf1aa3040f08d082490bf852654f32 Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Tue, 27 Aug 2024 20:48:14 +0200 Subject: [PATCH 04/21] Pact Live: wiremock stub aligned with pact stub --- .../concert/fixtures/PricingPactFixtures.java | 44 ------------ .../concert/fixtures/PricingStubs.java | 68 +++++++++++++++++++ .../fixtures/PactFrameworkTestBase.java | 12 ++-- .../PactFrameworkTestBase_liveCoding.java | 4 +- ..._applyDiscount_liveCoding_pactDepTest.java | 4 +- ...lyDiscount_liveCoding_wiremockDepTest.java | 23 ++----- 6 files changed, 85 insertions(+), 70 deletions(-) delete mode 100644 services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingPactFixtures.java create mode 100644 services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingPactFixtures.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingPactFixtures.java deleted file mode 100644 index 19016eb9..00000000 --- a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingPactFixtures.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.bottega.promoter.concert.fixtures; - -import java.util.Map; - -import au.com.dius.pact.consumer.dsl.PactDslWithProvider; -import au.com.dius.pact.core.model.RequestResponsePact; -import org.springframework.stereotype.Component; - -@Component -public class PricingPactFixtures { - - public RequestResponsePact applyPercentageDiscount(PactDslWithProvider builder) { - - return builder - .given("price for item exists", "itemId", "123") - .uponReceiving("a discount request") - .path("/api/v1/item/123/price-factor/percentage") - .method("POST") - .headers(Map.of("Content-Type", "application/json")) - .body(""" - { - "percentage": 10 - } - """) - .willRespondWith() - .status(200) - .headers(Map.of("Content-Type", "application/json")) - .body(""" - [ - { - "price": 9000, - "factors": [ - { - "type": "PERCENTAGE", - "value": 10 - } - ] - } - ] - """) - .toPact(); - } - -} diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java new file mode 100644 index 00000000..08d45225 --- /dev/null +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java @@ -0,0 +1,68 @@ +package com.bottega.promoter.concert.fixtures; + +import au.com.dius.pact.consumer.dsl.PactDslWithProvider; +import au.com.dius.pact.core.model.RequestResponsePact; +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.http.HttpHeader; +import com.github.tomakehurst.wiremock.http.HttpHeaders; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.stream.Collectors; + +import static com.github.tomakehurst.wiremock.http.HttpHeader.httpHeader; + +@Component +public class PricingStubs { + + public static final String PATH = "/api/v1/item/123/price-factor/percentage"; + public static final String METHOD = "POST"; + public static final int RES_STATUS = 200; + public static final HttpHeaders HEADERS = new HttpHeaders(httpHeader("Content-Type", "application/json")); + public static final String REQ_BODY = """ + { + "percentage": 10 + } + """; + public static final String RESP_BODY = """ + [ + { + "price": 9000, + "factors": [ + { + "type": "PERCENTAGE", + "value": 10 + } + ] + } + ] + """; + + public RequestResponsePact stubApplyPercentageDiscount(PactDslWithProvider builder) { + + Map headersMap = HEADERS.all().stream() + .collect(Collectors.toMap(HttpHeader::key, HttpHeader::firstValue)); + + return builder + .given("price for item exists", "itemId", "123") + .uponReceiving("a discount request") + .path(PATH) + .method(METHOD) + .headers(headersMap) + .body(REQ_BODY) + .willRespondWith() + .status(RES_STATUS) + .headers(headersMap) + .body(RESP_BODY) + .toPact(); + } + + public void stubApplyPercentageDiscount() { + WireMock.stubFor(WireMock.request(METHOD, WireMock.urlEqualTo(PATH)) + .withRequestBody(WireMock.equalToJson(REQ_BODY)) + .willReturn(WireMock.aResponse() + .withStatus(RES_STATUS) + .withHeaders(HEADERS) + .withBody(RESP_BODY))); + } +} diff --git a/services/Promoter/src/test/java/com/bottega/promoter/fixtures/PactFrameworkTestBase.java b/services/Promoter/src/test/java/com/bottega/promoter/fixtures/PactFrameworkTestBase.java index 54e1737d..3220ef02 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/fixtures/PactFrameworkTestBase.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/fixtures/PactFrameworkTestBase.java @@ -1,10 +1,12 @@ package com.bottega.promoter.fixtures; import au.com.dius.pact.consumer.dsl.PactDslWithProvider; -import au.com.dius.pact.consumer.junit5.*; -import au.com.dius.pact.core.model.*; +import au.com.dius.pact.consumer.junit5.PactConsumerTestExt; +import au.com.dius.pact.consumer.junit5.PactTestFor; +import au.com.dius.pact.core.model.PactSpecVersion; +import au.com.dius.pact.core.model.RequestResponsePact; import au.com.dius.pact.core.model.annotations.Pact; -import com.bottega.promoter.concert.fixtures.PricingPactFixtures; +import com.bottega.promoter.concert.fixtures.PricingStubs; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -18,7 +20,7 @@ public class PactFrameworkTestBase extends FrameworkTestBase { public static final String PACT_PRICING = "Tickets.Pricing"; @Autowired - protected PricingPactFixtures pricingPactFixtures; + protected PricingStubs pricingStubs; @BeforeEach void setUp() { @@ -28,6 +30,6 @@ void setUp() { @Pact(consumer = PACT_PROMOTER) public RequestResponsePact applyPercentageDiscount(PactDslWithProvider builder) { - return pricingPactFixtures.applyPercentageDiscount(builder); + return pricingStubs.stubApplyPercentageDiscount(builder); } } diff --git a/services/Promoter/src/test/java/com/bottega/promoter/fixtures/PactFrameworkTestBase_liveCoding.java b/services/Promoter/src/test/java/com/bottega/promoter/fixtures/PactFrameworkTestBase_liveCoding.java index aead0fba..39abebfe 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/fixtures/PactFrameworkTestBase_liveCoding.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/fixtures/PactFrameworkTestBase_liveCoding.java @@ -3,7 +3,7 @@ import au.com.dius.pact.consumer.junit5.PactConsumerTestExt; import au.com.dius.pact.consumer.junit5.PactTestFor; import au.com.dius.pact.core.model.PactSpecVersion; -import com.bottega.promoter.concert.fixtures.PricingPactFixtures; +import com.bottega.promoter.concert.fixtures.PricingStubs; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -16,6 +16,6 @@ public class PactFrameworkTestBase_liveCoding extends FrameworkTestBase { public static final String PACT_PRICING_LIVE_CODING = "LiveCoding.Tickets.Pricing"; @Autowired - protected PricingPactFixtures pricingPactFixtures; + protected PricingStubs pricingStubs; } diff --git a/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_pactDepTest.java b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_pactDepTest.java index 48a5fb94..6f907d98 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_pactDepTest.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_pactDepTest.java @@ -25,8 +25,8 @@ void setUp() { @Pact(consumer = PACT_PROMOTER_LIVE_CODING) @SuppressWarnings("unused") - public RequestResponsePact applyPercentageDiscount(PactDslWithProvider builder) { - return pricingPactFixtures.applyPercentageDiscount(builder); + public RequestResponsePact stubApplyPercentageDiscount(PactDslWithProvider builder) { + return pricingStubs.stubApplyPercentageDiscount(builder); } @Test diff --git a/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java index a83c1e9e..dfcdd042 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java @@ -1,10 +1,12 @@ package com.bottega.promoter.infra.client.pricing; import com.bottega.promoter.concert.domain.ConcertId; +import com.bottega.promoter.concert.fixtures.PricingStubs; import com.bottega.promoter.fixtures.FrameworkTestBase; import com.github.tomakehurst.wiremock.client.WireMock; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; import static org.assertj.core.api.Assertions.assertThat; @@ -14,6 +16,9 @@ public class PricingClient_applyDiscount_liveCoding_wiremockDepTest extends Fram PricingClient httpPricingClient; + @Autowired + PricingStubs pricingStubs; + @BeforeEach void setUp() { httpPricingClient = concertFixtures.pricingClient; @@ -23,23 +28,7 @@ void setUp() { @Test public void applyDiscount_isValid() { //given - WireMock.stubFor(WireMock.post(WireMock.urlEqualTo("/api/v1/item/123/price-factor/percentage")) - .willReturn(WireMock.aResponse() - .withStatus(200) - .withHeader("Content-Type", "application/json") - .withBody(""" - [ - { - "price": 9000, - "factors": [ - { - "type": "PERCENTAGE", - "value": 10 - } - ] - } - ] - """))); + pricingStubs.stubApplyPercentageDiscount(); //when var result = httpPricingClient.applyPercentageDiscount(new ConcertId("123"), 10); From e8b3050df0017d2632c1fd8132860ae2a204e932 Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Tue, 27 Aug 2024 20:57:05 +0200 Subject: [PATCH 05/21] Pact Live: provider verification test --- .../pricing/fixtures/FrameworkTestBase.java | 11 +++-- ...desApiContract_liveCoding_pactApiTest.java | 47 +++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 services/Pricing/src/test/java/com/bottega/pricing/price/api/rest/Pricing_providesApiContract_liveCoding_pactApiTest.java diff --git a/services/Pricing/src/test/java/com/bottega/pricing/fixtures/FrameworkTestBase.java b/services/Pricing/src/test/java/com/bottega/pricing/fixtures/FrameworkTestBase.java index 4668060d..7fa7bcff 100644 --- a/services/Pricing/src/test/java/com/bottega/pricing/fixtures/FrameworkTestBase.java +++ b/services/Pricing/src/test/java/com/bottega/pricing/fixtures/FrameworkTestBase.java @@ -4,14 +4,18 @@ import org.apache.groovy.util.Maps; import org.apache.kafka.clients.admin.AdminClient; import org.apache.kafka.clients.producer.ProducerConfig; -import org.junit.jupiter.api.*; -import org.springframework.beans.factory.annotation.*; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.contract.stubrunner.spring.AutoConfigureStubRunner; -import org.springframework.test.context.*; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.KafkaContainer; import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.utility.DockerImageName; + import static com.bottega.sharedlib.config.CdcStubs.CDC_STUB_ID_PROMOTER; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT; import static org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties.StubsMode.LOCAL; @@ -58,6 +62,7 @@ static void kafkaProperties(DynamicPropertyRegistry registry) { @BeforeEach public void beforeEach() { + System.setProperty("pact.rootDir", "build/pacts"); kafkaContainerFixtures.beforeEach(); } diff --git a/services/Pricing/src/test/java/com/bottega/pricing/price/api/rest/Pricing_providesApiContract_liveCoding_pactApiTest.java b/services/Pricing/src/test/java/com/bottega/pricing/price/api/rest/Pricing_providesApiContract_liveCoding_pactApiTest.java new file mode 100644 index 00000000..89496e48 --- /dev/null +++ b/services/Pricing/src/test/java/com/bottega/pricing/price/api/rest/Pricing_providesApiContract_liveCoding_pactApiTest.java @@ -0,0 +1,47 @@ +package com.bottega.pricing.price.api.rest; + +import au.com.dius.pact.provider.junit5.HttpTestTarget; +import au.com.dius.pact.provider.junit5.PactVerificationContext; +import au.com.dius.pact.provider.junit5.PactVerificationInvocationContextProvider; +import au.com.dius.pact.provider.junitsupport.IgnoreNoPactsToVerify; +import au.com.dius.pact.provider.junitsupport.Provider; +import au.com.dius.pact.provider.junitsupport.State; +import au.com.dius.pact.provider.junitsupport.loader.PactBroker; +import au.com.dius.pact.provider.junitsupport.loader.PactBrokerAuth; +import com.bottega.pricing.fixtures.FrameworkTestBase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.TestTemplate; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Value; + +@Provider("LiveCoding.Tickets.Pricing") +@PactBroker(url = "https://jacek.pactflow.io", authentication = @PactBrokerAuth(token = "${PACT_BROKER_TOKEN}")) +@IgnoreNoPactsToVerify +public class Pricing_providesApiContract_liveCoding_pactApiTest extends FrameworkTestBase { + + @Value("${server.port}") + int port; + + @BeforeEach + public void setupTestTarget(PactVerificationContext context) { + super.beforeEach(); + if (context != null) { + context.setTarget(new HttpTestTarget("localhost", port)); + } + } + + @TestTemplate + @ExtendWith(PactVerificationInvocationContextProvider.class) + public void pricingPactProviderVerification(PactVerificationContext context) { + if (context != null) { + context.verifyInteraction(); + } + } + + @State("price for item exists") + public void priceForItemDiscount() { + builders.aPrice().priceForItem(100_00, "123").inDb(); + } + + +} \ No newline at end of file From dd7db44be47928ba2dea9c98cd2ea56bdd0b16cc Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Wed, 28 Aug 2024 11:54:47 +0200 Subject: [PATCH 06/21] Pact Live: deployment pipelines --- .github/workflows/ci-pricing-liveCoding.yml | 140 ++++++++++++++++++ .github/workflows/ci-promoter-liveCoding.yml | 139 +++++++++++++++++ ...desApiContract_liveCoding_pactApiTest.java | 1 + 3 files changed, 280 insertions(+) create mode 100644 .github/workflows/ci-pricing-liveCoding.yml create mode 100644 .github/workflows/ci-promoter-liveCoding.yml diff --git a/.github/workflows/ci-pricing-liveCoding.yml b/.github/workflows/ci-pricing-liveCoding.yml new file mode 100644 index 00000000..32493387 --- /dev/null +++ b/.github/workflows/ci-pricing-liveCoding.yml @@ -0,0 +1,140 @@ +name: Pricing CI +run-name: Pricing CI + +on: + push: + paths: + - 'services/Pricing/**' + - 'libs/SharedLib/**' + - '.github/workflows/ci-pricing-liveCoding.yml' + - '.github/workflows/ci-shared-lib.yml' + workflow_dispatch: + repository_dispatch: + types: [pricing-ci-webhook] + +env: + PACT_BROKER_BASE_URL: ${{ vars.PACT_BROKER_BASE_URL }} + PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }} + PACTICIPANT: "LiveCoding.Tickets.Pricing" + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + # Configure Gradle for optimal use in GiHub Actions, including caching of downloaded dependencies. + # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Publish Promoter Spring Cloud Contract to local maven repo + run: >- + cd services/Promoter && + ./gradlew publishToMavenLocal + + - name: Test + run: >- + cd services/Pricing && + ./gradlew + -Dpact.verifier.publishResults=true + -Dpact.provider.version=$PACTICIPANT-${{ github.sha }} + -Dpact.provider.branchName=${{ github.ref_name }} + -Dpact.provider.tag=${{ github.ref_name }} + -Dpact.rootDir=build/pacts + test publishToMavenLocal + +# - name: Publish Pricing Consumer Pacts +# run: >- +# docker run --rm \ +# -w ${PWD} \ +# -v ${PWD}:${PWD} \ +# -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ +# -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ +# pactfoundation/pact-cli:1.1.0.0 \ +# broker publish ${PWD}/services/Pricing/build/pacts --consumer-app-version=$PACTICIPANT-${{ github.sha }} --branch=${{github.ref_name}} --tag-with-git-branch + + dev-can-i-deploy: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Can I deploy to dev? + run: >- + docker run --rm \ + -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ + -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ + pactfoundation/pact-cli:1.1.0.0 \ + broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=dev --version=$PACTICIPANT-${{ github.sha }} + + dev-deployment: + if: ${{ github.ref_name == 'main' }} + needs: build + runs-on: ubuntu-latest + environment: dev + steps: + - uses: actions/checkout@v4 + + - name: Deploy to Dev + run: echo "Deploying to dev" + + - name: Record Pact deployment to dev + run: >- + docker run --rm \ + -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ + -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ + pactfoundation/pact-cli:1.1.0.0 \ + broker record-deployment --pacticipant=$PACTICIPANT --environment=dev --version=$PACTICIPANT-${{ github.sha }} + + + prod-can-i-deploy: + needs: dev-deployment + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Can I deploy to prod? + run: >- + docker run --rm \ + -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ + -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ + pactfoundation/pact-cli:1.1.0.0 \ + broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=prod --version=$PACTICIPANT-${{ github.sha }} --ignore="Tickets.Promoter" + + + prod-deployment: + if: ${{ github.ref_name == 'main' }} + needs: dev-deployment + runs-on: ubuntu-latest + environment: prod + steps: + - uses: actions/checkout@v4 + + - name: Deploy to prod + run: echo "Deploying to prod" + + - name: Record Pact deployment to prod + run: >- + docker run --rm \ + -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ + -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ + pactfoundation/pact-cli:1.1.0.0 \ + broker record-deployment --pacticipant=$PACTICIPANT --environment=prod --version=$PACTICIPANT-${{ github.sha }} + + - name: Record Pact release to prod + run: >- + docker run --rm \ + -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ + -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ + pactfoundation/pact-cli:1.1.0.0 \ + broker record-release --pacticipant=$PACTICIPANT --environment=prod --version=$PACTICIPANT-${{ github.sha }} diff --git a/.github/workflows/ci-promoter-liveCoding.yml b/.github/workflows/ci-promoter-liveCoding.yml new file mode 100644 index 00000000..8ec253ee --- /dev/null +++ b/.github/workflows/ci-promoter-liveCoding.yml @@ -0,0 +1,139 @@ +name: Promoter CI +run-name: Promoter CI + +on: + push: + paths: + - 'services/Promoter/**' + - 'libs/SharedLib/**' + - '.github/workflows/ci-promoter.yml' + - '.github/workflows/ci-promoter-liveCoding.yml' + - '.github/workflows/ci-shared-lib.yml' + workflow_dispatch: + repository_dispatch: + types: [promoter-ci-webhook] + +env: + PACT_BROKER_BASE_URL: ${{ vars.PACT_BROKER_BASE_URL }} + PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }} + PACTICIPANT: "LiveCoding.Tickets.Promoter" + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + # Configure Gradle for optimal use in GiHub Actions, including caching of downloaded dependencies. + # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md + - name: Setup Gradle + uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + + - name: Publish Pricing Spring Cloud Contract to local maven repo + run: >- + cd services/Pricing && + ./gradlew publishToMavenLocal + + - name: Test + run: >- + cd services/Promoter && + ./gradlew +# -Dpact.verifier.publishResults=true +# -Dpact.provider.version=$PACTICIPANT-${{ github.sha }} +# -Dpact.provider.branchName=${{ github.ref_name }} +# -Dpact.provider.tag=${{ github.ref_name }} + -Dpact.rootDir=build/pacts + test publishToMavenLocal + + - name: Publish Promoter Consumer Pacts + run: >- + docker run --rm \ + -w ${PWD} \ + -v ${PWD}:${PWD} \ + -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ + -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ + pactfoundation/pact-cli:1.1.0.0 \ + broker publish ${PWD}/services/Promoter/build/pacts --consumer-app-version=$PACTICIPANT-${{ github.sha }} --branch=${{github.ref_name}} --tag-with-git-branch + + dev-can-i-deploy: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Can I deploy to dev? + run: >- + docker run --rm \ + -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ + -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ + pactfoundation/pact-cli:1.1.0.0 \ + broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=dev --version=$PACTICIPANT-${{ github.sha }} + + dev-deployment: + if: ${{ github.ref_name == 'main' }} + needs: build + runs-on: ubuntu-latest + environment: dev + steps: + - uses: actions/checkout@v4 + + - name: Deploy to Dev + run: echo "Deploying to dev" + + - name: Record Pact deployment to dev + run: >- + docker run --rm \ + -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ + -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ + pactfoundation/pact-cli:1.1.0.0 \ + broker record-deployment --pacticipant=$PACTICIPANT --environment=dev --version=$PACTICIPANT-${{ github.sha }} + + prod-can-i-deploy: + needs: dev-deployment + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Can I deploy to prod? + run: >- + docker run --rm \ + -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ + -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ + pactfoundation/pact-cli:1.1.0.0 \ + broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=prod --version=$PACTICIPANT-${{ github.sha }} + + prod-deployment: + if: ${{ github.ref_name == 'main' }} + needs: dev-deployment + runs-on: ubuntu-latest + environment: prod + steps: + - uses: actions/checkout@v4 + + - name: Deploy to prod + run: echo "Deploying to prod" + + - name: Record Pact deployment to prod + run: >- + docker run --rm \ + -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ + -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ + pactfoundation/pact-cli:1.1.0.0 \ + broker record-deployment --pacticipant=$PACTICIPANT --environment=prod --version=$PACTICIPANT-${{ github.sha }} + + - name: Record Pact release to prod + run: >- + docker run --rm \ + -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ + -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ + pactfoundation/pact-cli:1.1.0.0 \ + broker record-release --pacticipant=$PACTICIPANT --environment=prod --version=$PACTICIPANT-${{ github.sha }} \ No newline at end of file diff --git a/services/Pricing/src/test/java/com/bottega/pricing/price/api/rest/Pricing_providesApiContract_liveCoding_pactApiTest.java b/services/Pricing/src/test/java/com/bottega/pricing/price/api/rest/Pricing_providesApiContract_liveCoding_pactApiTest.java index 89496e48..3a40e7a3 100644 --- a/services/Pricing/src/test/java/com/bottega/pricing/price/api/rest/Pricing_providesApiContract_liveCoding_pactApiTest.java +++ b/services/Pricing/src/test/java/com/bottega/pricing/price/api/rest/Pricing_providesApiContract_liveCoding_pactApiTest.java @@ -28,6 +28,7 @@ public void setupTestTarget(PactVerificationContext context) { if (context != null) { context.setTarget(new HttpTestTarget("localhost", port)); } + System.setProperty("pact.verifier.publishResults", "true"); } @TestTemplate From 81ad3a8867cba09b99554d5a746f45677749d85b Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Wed, 28 Aug 2024 12:03:38 +0200 Subject: [PATCH 07/21] Pact Live: deployment pipelines --- .github/workflows/ci-pricing-liveCoding.yml | 4 ++-- .github/workflows/ci-promoter-liveCoding.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-pricing-liveCoding.yml b/.github/workflows/ci-pricing-liveCoding.yml index 32493387..3ac00a70 100644 --- a/.github/workflows/ci-pricing-liveCoding.yml +++ b/.github/workflows/ci-pricing-liveCoding.yml @@ -1,5 +1,5 @@ -name: Pricing CI -run-name: Pricing CI +name: LiveCoding Pricing CI +run-name: LiveCoding Pricing CI on: push: diff --git a/.github/workflows/ci-promoter-liveCoding.yml b/.github/workflows/ci-promoter-liveCoding.yml index 8ec253ee..89770ca9 100644 --- a/.github/workflows/ci-promoter-liveCoding.yml +++ b/.github/workflows/ci-promoter-liveCoding.yml @@ -1,5 +1,5 @@ -name: Promoter CI -run-name: Promoter CI +name: LiveCoding Promoter CI +run-name: LiveCoding Promoter CI on: push: From 30d5f396744d28d2647aedc4c77d11e7fa37d903 Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Wed, 28 Aug 2024 13:20:02 +0200 Subject: [PATCH 08/21] Pact Live: manual wiremock init --- .../concert/fixtures/PricingStubs.java | 5 +++-- ...lyDiscount_liveCoding_wiremockDepTest.java | 21 ++++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java index 08d45225..ef4dc203 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java @@ -2,6 +2,7 @@ import au.com.dius.pact.consumer.dsl.PactDslWithProvider; import au.com.dius.pact.core.model.RequestResponsePact; +import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; @@ -57,8 +58,8 @@ public RequestResponsePact stubApplyPercentageDiscount(PactDslWithProvider build .toPact(); } - public void stubApplyPercentageDiscount() { - WireMock.stubFor(WireMock.request(METHOD, WireMock.urlEqualTo(PATH)) + public void stubApplyPercentageDiscount(WireMockServer pricingMockServer) { + pricingMockServer.stubFor(WireMock.request(METHOD, WireMock.urlEqualTo(PATH)) .withRequestBody(WireMock.equalToJson(REQ_BODY)) .willReturn(WireMock.aResponse() .withStatus(RES_STATUS) diff --git a/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java index dfcdd042..7ef770b8 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java @@ -3,15 +3,16 @@ import com.bottega.promoter.concert.domain.ConcertId; import com.bottega.promoter.concert.fixtures.PricingStubs; import com.bottega.promoter.fixtures.FrameworkTestBase; -import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.common.ConsoleNotifier; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; import static org.assertj.core.api.Assertions.assertThat; -@AutoConfigureWireMock(port = 8181) public class PricingClient_applyDiscount_liveCoding_wiremockDepTest extends FrameworkTestBase { PricingClient httpPricingClient; @@ -19,16 +20,26 @@ public class PricingClient_applyDiscount_liveCoding_wiremockDepTest extends Fram @Autowired PricingStubs pricingStubs; + static WireMockServer pricingMockServer; + @BeforeEach void setUp() { httpPricingClient = concertFixtures.pricingClient; - WireMock.reset(); + + pricingMockServer = new WireMockServer(options().port(8181) + .notifier(new ConsoleNotifier(true))); + pricingMockServer.start(); + } + + @AfterEach + void tearDown() { + pricingMockServer.stop(); } @Test public void applyDiscount_isValid() { //given - pricingStubs.stubApplyPercentageDiscount(); + pricingStubs.stubApplyPercentageDiscount(pricingMockServer); //when var result = httpPricingClient.applyPercentageDiscount(new ConcertId("123"), 10); From a790955ee62638979667dd9c9f105c18eda847a1 Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Wed, 28 Aug 2024 13:27:27 +0200 Subject: [PATCH 09/21] Pact Live: manual wiremock init --- .github/workflows/ci-promoter-liveCoding.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-promoter-liveCoding.yml b/.github/workflows/ci-promoter-liveCoding.yml index 89770ca9..3e50b4aa 100644 --- a/.github/workflows/ci-promoter-liveCoding.yml +++ b/.github/workflows/ci-promoter-liveCoding.yml @@ -47,12 +47,19 @@ jobs: run: >- cd services/Promoter && ./gradlew + -Dpact.rootDir=build/pacts + test publishToMavenLocal + +# with publish contracts: +# run: >- +# cd services/Promoter && +# ./gradlew # -Dpact.verifier.publishResults=true # -Dpact.provider.version=$PACTICIPANT-${{ github.sha }} # -Dpact.provider.branchName=${{ github.ref_name }} # -Dpact.provider.tag=${{ github.ref_name }} - -Dpact.rootDir=build/pacts - test publishToMavenLocal +# -Dpact.rootDir=build/pacts +# test publishToMavenLocal - name: Publish Promoter Consumer Pacts run: >- From 0d8cc6c0b9bf60c8753e7f88f06a80efab02f088 Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Wed, 28 Aug 2024 16:55:36 +0200 Subject: [PATCH 10/21] Pact Live: record deployment --- .github/workflows/ci-pricing-liveCoding.yml | 4 ++-- .github/workflows/ci-promoter-liveCoding.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-pricing-liveCoding.yml b/.github/workflows/ci-pricing-liveCoding.yml index 3ac00a70..c0215e5a 100644 --- a/.github/workflows/ci-pricing-liveCoding.yml +++ b/.github/workflows/ci-pricing-liveCoding.yml @@ -78,7 +78,7 @@ jobs: broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=dev --version=$PACTICIPANT-${{ github.sha }} dev-deployment: - if: ${{ github.ref_name == 'main' }} +# if: ${{ github.ref_name == 'main' }} needs: build runs-on: ubuntu-latest environment: dev @@ -113,7 +113,7 @@ jobs: prod-deployment: - if: ${{ github.ref_name == 'main' }} +# if: ${{ github.ref_name == 'main' }} needs: dev-deployment runs-on: ubuntu-latest environment: prod diff --git a/.github/workflows/ci-promoter-liveCoding.yml b/.github/workflows/ci-promoter-liveCoding.yml index 3e50b4aa..0d924e8a 100644 --- a/.github/workflows/ci-promoter-liveCoding.yml +++ b/.github/workflows/ci-promoter-liveCoding.yml @@ -86,7 +86,7 @@ jobs: broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=dev --version=$PACTICIPANT-${{ github.sha }} dev-deployment: - if: ${{ github.ref_name == 'main' }} +# if: ${{ github.ref_name == 'main' }} needs: build runs-on: ubuntu-latest environment: dev @@ -119,7 +119,7 @@ jobs: broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=prod --version=$PACTICIPANT-${{ github.sha }} prod-deployment: - if: ${{ github.ref_name == 'main' }} +# if: ${{ github.ref_name == 'main' }} needs: dev-deployment runs-on: ubuntu-latest environment: prod From 9be99396b00f3ba7d8d8eab519e3b940750409ce Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Wed, 28 Aug 2024 17:08:11 +0200 Subject: [PATCH 11/21] Pact Live: can I deploy embedded --- .github/workflows/ci-pricing-liveCoding.yml | 28 ++++++---------- .github/workflows/ci-promoter-liveCoding.yml | 34 ++++++-------------- 2 files changed, 19 insertions(+), 43 deletions(-) diff --git a/.github/workflows/ci-pricing-liveCoding.yml b/.github/workflows/ci-pricing-liveCoding.yml index c0215e5a..6387255e 100644 --- a/.github/workflows/ci-pricing-liveCoding.yml +++ b/.github/workflows/ci-pricing-liveCoding.yml @@ -69,6 +69,13 @@ jobs: steps: - uses: actions/checkout@v4 + dev-deployment: + needs: build + runs-on: ubuntu-latest + environment: dev + steps: + - uses: actions/checkout@v4 + - name: Can I deploy to dev? run: >- docker run --rm \ @@ -77,14 +84,6 @@ jobs: pactfoundation/pact-cli:1.1.0.0 \ broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=dev --version=$PACTICIPANT-${{ github.sha }} - dev-deployment: -# if: ${{ github.ref_name == 'main' }} - needs: build - runs-on: ubuntu-latest - environment: dev - steps: - - uses: actions/checkout@v4 - - name: Deploy to Dev run: echo "Deploying to dev" @@ -96,10 +95,10 @@ jobs: pactfoundation/pact-cli:1.1.0.0 \ broker record-deployment --pacticipant=$PACTICIPANT --environment=dev --version=$PACTICIPANT-${{ github.sha }} - - prod-can-i-deploy: + prod-deployment: needs: dev-deployment runs-on: ubuntu-latest + environment: prod steps: - uses: actions/checkout@v4 @@ -111,15 +110,6 @@ jobs: pactfoundation/pact-cli:1.1.0.0 \ broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=prod --version=$PACTICIPANT-${{ github.sha }} --ignore="Tickets.Promoter" - - prod-deployment: -# if: ${{ github.ref_name == 'main' }} - needs: dev-deployment - runs-on: ubuntu-latest - environment: prod - steps: - - uses: actions/checkout@v4 - - name: Deploy to prod run: echo "Deploying to prod" diff --git a/.github/workflows/ci-promoter-liveCoding.yml b/.github/workflows/ci-promoter-liveCoding.yml index 0d924e8a..fd87358e 100644 --- a/.github/workflows/ci-promoter-liveCoding.yml +++ b/.github/workflows/ci-promoter-liveCoding.yml @@ -71,9 +71,10 @@ jobs: pactfoundation/pact-cli:1.1.0.0 \ broker publish ${PWD}/services/Promoter/build/pacts --consumer-app-version=$PACTICIPANT-${{ github.sha }} --branch=${{github.ref_name}} --tag-with-git-branch - dev-can-i-deploy: + dev-deployment: needs: build runs-on: ubuntu-latest + environment: dev steps: - uses: actions/checkout@v4 @@ -85,14 +86,6 @@ jobs: pactfoundation/pact-cli:1.1.0.0 \ broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=dev --version=$PACTICIPANT-${{ github.sha }} - dev-deployment: -# if: ${{ github.ref_name == 'main' }} - needs: build - runs-on: ubuntu-latest - environment: dev - steps: - - uses: actions/checkout@v4 - - name: Deploy to Dev run: echo "Deploying to dev" @@ -110,37 +103,30 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Can I deploy to prod? - run: >- - docker run --rm \ - -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ - -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ - pactfoundation/pact-cli:1.1.0.0 \ - broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=prod --version=$PACTICIPANT-${{ github.sha }} + prod-deployment: -# if: ${{ github.ref_name == 'main' }} needs: dev-deployment runs-on: ubuntu-latest environment: prod steps: - uses: actions/checkout@v4 - - name: Deploy to prod - run: echo "Deploying to prod" - - - name: Record Pact deployment to prod + - name: Can I deploy to prod? run: >- docker run --rm \ -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ pactfoundation/pact-cli:1.1.0.0 \ - broker record-deployment --pacticipant=$PACTICIPANT --environment=prod --version=$PACTICIPANT-${{ github.sha }} + broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=prod --version=$PACTICIPANT-${{ github.sha }} - - name: Record Pact release to prod + - name: Deploy to prod + run: echo "Deploying to prod" + + - name: Record Pact deployment to prod run: >- docker run --rm \ -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ pactfoundation/pact-cli:1.1.0.0 \ - broker record-release --pacticipant=$PACTICIPANT --environment=prod --version=$PACTICIPANT-${{ github.sha }} \ No newline at end of file + broker record-deployment --pacticipant=$PACTICIPANT --environment=prod --version=$PACTICIPANT-${{ github.sha }} From 6c99fed7308e719b765900fc8d83c1d5fe650d8a Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Wed, 28 Aug 2024 17:15:41 +0200 Subject: [PATCH 12/21] Pact Live: can I deploy embedded --- .github/workflows/ci-pricing-liveCoding.yml | 6 ------ .github/workflows/ci-promoter-liveCoding.yml | 8 -------- 2 files changed, 14 deletions(-) diff --git a/.github/workflows/ci-pricing-liveCoding.yml b/.github/workflows/ci-pricing-liveCoding.yml index 6387255e..b04fcf99 100644 --- a/.github/workflows/ci-pricing-liveCoding.yml +++ b/.github/workflows/ci-pricing-liveCoding.yml @@ -63,12 +63,6 @@ jobs: # pactfoundation/pact-cli:1.1.0.0 \ # broker publish ${PWD}/services/Pricing/build/pacts --consumer-app-version=$PACTICIPANT-${{ github.sha }} --branch=${{github.ref_name}} --tag-with-git-branch - dev-can-i-deploy: - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - dev-deployment: needs: build runs-on: ubuntu-latest diff --git a/.github/workflows/ci-promoter-liveCoding.yml b/.github/workflows/ci-promoter-liveCoding.yml index fd87358e..e62b9fd8 100644 --- a/.github/workflows/ci-promoter-liveCoding.yml +++ b/.github/workflows/ci-promoter-liveCoding.yml @@ -97,14 +97,6 @@ jobs: pactfoundation/pact-cli:1.1.0.0 \ broker record-deployment --pacticipant=$PACTICIPANT --environment=dev --version=$PACTICIPANT-${{ github.sha }} - prod-can-i-deploy: - needs: dev-deployment - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - prod-deployment: needs: dev-deployment runs-on: ubuntu-latest From 98c64504fd50f0d5f7465a285876a15146f428b9 Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Wed, 28 Aug 2024 17:23:09 +0200 Subject: [PATCH 13/21] Pact Live: dedicated devs --- .github/workflows/ci-pricing-liveCoding.yml | 16 ++++------------ .github/workflows/ci-promoter-liveCoding.yml | 8 ++++---- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci-pricing-liveCoding.yml b/.github/workflows/ci-pricing-liveCoding.yml index b04fcf99..349b6743 100644 --- a/.github/workflows/ci-pricing-liveCoding.yml +++ b/.github/workflows/ci-pricing-liveCoding.yml @@ -76,7 +76,7 @@ jobs: -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ pactfoundation/pact-cli:1.1.0.0 \ - broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=dev --version=$PACTICIPANT-${{ github.sha }} + broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=dev-liveCoding --version=$PACTICIPANT-${{ github.sha }} - name: Deploy to Dev run: echo "Deploying to dev" @@ -87,7 +87,7 @@ jobs: -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ pactfoundation/pact-cli:1.1.0.0 \ - broker record-deployment --pacticipant=$PACTICIPANT --environment=dev --version=$PACTICIPANT-${{ github.sha }} + broker record-deployment --pacticipant=$PACTICIPANT --environment=dev-liveCoding --version=$PACTICIPANT-${{ github.sha }} prod-deployment: needs: dev-deployment @@ -102,7 +102,7 @@ jobs: -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ pactfoundation/pact-cli:1.1.0.0 \ - broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=prod --version=$PACTICIPANT-${{ github.sha }} --ignore="Tickets.Promoter" + broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=prod-liveCoding --version=$PACTICIPANT-${{ github.sha }} --ignore="Tickets.Promoter" - name: Deploy to prod run: echo "Deploying to prod" @@ -113,12 +113,4 @@ jobs: -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ pactfoundation/pact-cli:1.1.0.0 \ - broker record-deployment --pacticipant=$PACTICIPANT --environment=prod --version=$PACTICIPANT-${{ github.sha }} - - - name: Record Pact release to prod - run: >- - docker run --rm \ - -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ - -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ - pactfoundation/pact-cli:1.1.0.0 \ - broker record-release --pacticipant=$PACTICIPANT --environment=prod --version=$PACTICIPANT-${{ github.sha }} + broker record-deployment --pacticipant=$PACTICIPANT --environment=prod-liveCoding --version=$PACTICIPANT-${{ github.sha }} \ No newline at end of file diff --git a/.github/workflows/ci-promoter-liveCoding.yml b/.github/workflows/ci-promoter-liveCoding.yml index e62b9fd8..0ebb160e 100644 --- a/.github/workflows/ci-promoter-liveCoding.yml +++ b/.github/workflows/ci-promoter-liveCoding.yml @@ -84,7 +84,7 @@ jobs: -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ pactfoundation/pact-cli:1.1.0.0 \ - broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=dev --version=$PACTICIPANT-${{ github.sha }} + broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=dev-liveCoding --version=$PACTICIPANT-${{ github.sha }} - name: Deploy to Dev run: echo "Deploying to dev" @@ -95,7 +95,7 @@ jobs: -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ pactfoundation/pact-cli:1.1.0.0 \ - broker record-deployment --pacticipant=$PACTICIPANT --environment=dev --version=$PACTICIPANT-${{ github.sha }} + broker record-deployment --pacticipant=$PACTICIPANT --environment=dev-liveCoding --version=$PACTICIPANT-${{ github.sha }} prod-deployment: needs: dev-deployment @@ -110,7 +110,7 @@ jobs: -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ pactfoundation/pact-cli:1.1.0.0 \ - broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=prod --version=$PACTICIPANT-${{ github.sha }} + broker can-i-deploy --pacticipant=$PACTICIPANT --to-environment=prod-liveCoding --version=$PACTICIPANT-${{ github.sha }} - name: Deploy to prod run: echo "Deploying to prod" @@ -121,4 +121,4 @@ jobs: -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ pactfoundation/pact-cli:1.1.0.0 \ - broker record-deployment --pacticipant=$PACTICIPANT --environment=prod --version=$PACTICIPANT-${{ github.sha }} + broker record-deployment --pacticipant=$PACTICIPANT --environment=prod-liveCoding --version=$PACTICIPANT-${{ github.sha }} From a5eccf841d3157559c4475e23a970bedf1f14f8b Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Thu, 29 Aug 2024 13:32:01 +0200 Subject: [PATCH 14/21] Pact Live: Concert service local interface contract --- .../com/bottega/promoter/concert/Price.java | 15 +++++-- .../concert/api/app/ConcertService.java | 22 +++++++--- .../pricing/api/app/PricingService.java | 34 ++++++++++++++++ .../promoter/pricing/infra/PriceRepo.java | 18 +++++++++ ...e_discountConcert_liveCoding_compTest.java | 40 +++++++++++++++++++ .../concert/fixtures/PricingStubs.java | 25 +++++++++++- 6 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 services/Promoter/src/main/java/com/bottega/promoter/pricing/api/app/PricingService.java create mode 100644 services/Promoter/src/main/java/com/bottega/promoter/pricing/infra/PriceRepo.java create mode 100644 services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_liveCoding_compTest.java diff --git a/services/Promoter/src/main/java/com/bottega/promoter/concert/Price.java b/services/Promoter/src/main/java/com/bottega/promoter/concert/Price.java index 26f3731a..f3144a2a 100644 --- a/services/Promoter/src/main/java/com/bottega/promoter/concert/Price.java +++ b/services/Promoter/src/main/java/com/bottega/promoter/concert/Price.java @@ -1,9 +1,12 @@ package com.bottega.promoter.concert; -import java.util.List; - import com.bottega.sharedlib.vo.Money; -import lombok.*; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +import java.util.List; @EqualsAndHashCode @AllArgsConstructor @@ -13,4 +16,10 @@ public class Price { private Money price; private List factors; + + public Price applyFactor(PriceFactor factor) { + this.price = price.subtract(price.percentage(factor.value())); + this.factors.add(factor); + return this; + } } diff --git a/services/Promoter/src/main/java/com/bottega/promoter/concert/api/app/ConcertService.java b/services/Promoter/src/main/java/com/bottega/promoter/concert/api/app/ConcertService.java index 8d65b4b4..ebde1f26 100644 --- a/services/Promoter/src/main/java/com/bottega/promoter/concert/api/app/ConcertService.java +++ b/services/Promoter/src/main/java/com/bottega/promoter/concert/api/app/ConcertService.java @@ -1,24 +1,28 @@ package com.bottega.promoter.concert.api.app; -import java.util.List; - -import com.bottega.promoter.agreements.*; +import com.bottega.promoter.agreements.PromoterAgreement; +import com.bottega.promoter.agreements.PromoterService; import com.bottega.promoter.concert.Price; import com.bottega.promoter.concert.domain.*; import com.bottega.promoter.concert.infra.repo.ConcertRepo; import com.bottega.promoter.infra.client.pricing.PricingClient; +import com.bottega.promoter.pricing.api.app.PricingService; import com.bottega.sharedlib.ddd.ApplicationService; import com.bottega.sharedlib.event.EventPublisher; import com.bottega.sharedlib.vo.error.ErrorResult; import io.vavr.control.Either; -import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +import java.util.List; + import static com.bottega.promoter.concert.domain.PromoterEventFactory.concertCreated; import static com.bottega.sharedlib.vo.error.ErrorResult.notFound; import static com.bottega.sharedlib.vo.error.GenericErrorCode.not_found; import static io.vavr.control.Option.ofOptional; @ApplicationService -@AllArgsConstructor +@RequiredArgsConstructor public class ConcertService { private final ConcertFactory concertFactory; @@ -28,6 +32,8 @@ public class ConcertService { private final TagService tagService; private final CategoryService categoryService; private final PromoterService promoterService; + @Setter + private PricingService pricingService; public Either createConcert(String title, String dateTime, String promoterIdString) { PromoterAgreement promoterAgreement = promoterService.getPromoterAgreement(promoterIdString); @@ -45,4 +51,10 @@ public Either> discountConcert(String concertId, int pe .toEither(notFound(not_found, "Concert with given ID does not exist. ID: " + concertId)) .flatMap(concert -> pricingClient.applyPercentageDiscount(concert.getId(), percentage)); } + + public Either> discountConcertLiveCoding(String concertId, int percentage) { + return ofOptional(concertRepo.findById(new ConcertId(concertId))) + .toEither(notFound(not_found, "Concert with given ID does not exist. ID: " + concertId)) + .flatMap(concert -> pricingService.applyPercentageDiscount(concert.getId(), percentage)); + } } diff --git a/services/Promoter/src/main/java/com/bottega/promoter/pricing/api/app/PricingService.java b/services/Promoter/src/main/java/com/bottega/promoter/pricing/api/app/PricingService.java new file mode 100644 index 00000000..2ca2ed91 --- /dev/null +++ b/services/Promoter/src/main/java/com/bottega/promoter/pricing/api/app/PricingService.java @@ -0,0 +1,34 @@ +package com.bottega.promoter.pricing.api.app; + +import com.bottega.promoter.concert.Price; +import com.bottega.promoter.concert.PriceFactor; +import com.bottega.promoter.concert.domain.ConcertId; +import com.bottega.promoter.pricing.infra.PriceRepo; +import com.bottega.sharedlib.vo.error.ErrorResult; +import io.vavr.control.Either; + +import java.util.List; + +import static com.bottega.sharedlib.vo.error.ErrorResult.notFound; +import static com.bottega.sharedlib.vo.error.GenericErrorCode.not_found; +import static io.vavr.control.Either.left; + +public class PricingService { + + private PriceRepo priceRepo; + + public Either> applyPercentageDiscount(ConcertId concertId, int percentage) { + + List updatedPrices = priceRepo.findByItemId(concertId).stream() + .map(price -> price.applyFactor(new PriceFactor("PERCENTAGE", percentage, null))) + .peek(priceRepo::save) + .toList(); + + if (updatedPrices.isEmpty()) { + return left(notFound(not_found, "No price entries found for requested item. itemId: " + concertId)); + } else { + return Either.right(updatedPrices); + } + } + +} diff --git a/services/Promoter/src/main/java/com/bottega/promoter/pricing/infra/PriceRepo.java b/services/Promoter/src/main/java/com/bottega/promoter/pricing/infra/PriceRepo.java new file mode 100644 index 00000000..74fd0437 --- /dev/null +++ b/services/Promoter/src/main/java/com/bottega/promoter/pricing/infra/PriceRepo.java @@ -0,0 +1,18 @@ +package com.bottega.promoter.pricing.infra; + +import com.bottega.promoter.concert.Price; +import com.bottega.promoter.concert.domain.ConcertId; +import com.bottega.sharedlib.vo.Money; + +import java.util.Collections; +import java.util.List; + +public class PriceRepo { + public List findByItemId(ConcertId concertId) { + return List.of(new Price(new Money(100_00), Collections.emptyList())); + } + + public void save(Price price) { + //who cares + } +} diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_liveCoding_compTest.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_liveCoding_compTest.java new file mode 100644 index 00000000..edc18556 --- /dev/null +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_liveCoding_compTest.java @@ -0,0 +1,40 @@ +package com.bottega.promoter.concert.api.app; + +import com.bottega.promoter.concert.fixtures.ConcertLogicTestBase; +import com.bottega.promoter.concert.fixtures.PricingStubs; +import com.bottega.promoter.pricing.api.app.PricingService; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.mockito.Mockito.mock; + +class ConcertService_discountConcert_liveCoding_compTest extends ConcertLogicTestBase { + + private PricingService pricingServiceMock; + private PricingStubs pricingStubs; + + @Override + @BeforeEach + protected void setUp() { + super.setUp(); + pricingServiceMock = mock(PricingService.class); + concertFixtures.concertService.setPricingService(pricingServiceMock); + + pricingStubs = new PricingStubs(); + } + + @Test + public void applyDiscount_isValid() { + //given + builders.aConcert().withId("123").inDb(); + pricingStubs.stubApplyPercentageDiscount(pricingServiceMock); + + //when + var result = concertFixtures.concertService.discountConcertLiveCoding("123", 10); + + //then + Assertions.assertThat(result.get().getFirst().getPrice().toInt()).isEqualTo(90_00); + } + +} diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java index ef4dc203..3c4bea3c 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java @@ -2,16 +2,24 @@ import au.com.dius.pact.consumer.dsl.PactDslWithProvider; import au.com.dius.pact.core.model.RequestResponsePact; +import com.bottega.promoter.concert.Price; +import com.bottega.promoter.concert.PriceFactor; +import com.bottega.promoter.concert.domain.ConcertId; +import com.bottega.promoter.pricing.api.app.PricingService; +import com.bottega.sharedlib.vo.Money; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.http.HttpHeader; import com.github.tomakehurst.wiremock.http.HttpHeaders; +import io.vavr.control.Either; import org.springframework.stereotype.Component; import java.util.Map; import java.util.stream.Collectors; import static com.github.tomakehurst.wiremock.http.HttpHeader.httpHeader; +import static java.util.List.of; +import static org.mockito.BDDMockito.given; @Component public class PricingStubs { @@ -58,12 +66,25 @@ public RequestResponsePact stubApplyPercentageDiscount(PactDslWithProvider build .toPact(); } - public void stubApplyPercentageDiscount(WireMockServer pricingMockServer) { - pricingMockServer.stubFor(WireMock.request(METHOD, WireMock.urlEqualTo(PATH)) + public void stubApplyPercentageDiscount(WireMockServer pricingWireMockServer) { + pricingWireMockServer.stubFor(WireMock.request(METHOD, WireMock.urlEqualTo(PATH)) .withRequestBody(WireMock.equalToJson(REQ_BODY)) .willReturn(WireMock.aResponse() .withStatus(RES_STATUS) .withHeaders(HEADERS) .withBody(RESP_BODY))); } + + public void stubApplyPercentageDiscount(PricingService pricingServiceMock) { + given(pricingServiceMock.applyPercentageDiscount(new ConcertId("123"), 10)) + .willReturn(Either.right( + of(new Price( + new Money(90_00), + of(new PriceFactor( + "PERCENTAGE", + 10, + null)))) + )); + + } } From 64f2321011d8f544d64279242046f8ff1cd25fb5 Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Thu, 29 Aug 2024 13:35:46 +0200 Subject: [PATCH 15/21] Pact Live: refac --- ...oncertService_discountConcert_liveCoding_compTest.java | 5 +++-- .../promoter/concert/fixtures/asserts/PriceAssert.java | 8 +++++++- ...ricingClient_applyDiscount_liveCoding_pactDepTest.java | 5 +++-- ...ngClient_applyDiscount_liveCoding_wiremockDepTest.java | 5 +++-- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_liveCoding_compTest.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_liveCoding_compTest.java index edc18556..16da74df 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_liveCoding_compTest.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_liveCoding_compTest.java @@ -3,10 +3,10 @@ import com.bottega.promoter.concert.fixtures.ConcertLogicTestBase; import com.bottega.promoter.concert.fixtures.PricingStubs; import com.bottega.promoter.pricing.api.app.PricingService; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static com.bottega.promoter.concert.fixtures.asserts.PriceAssert.assertThatPrice; import static org.mockito.Mockito.mock; class ConcertService_discountConcert_liveCoding_compTest extends ConcertLogicTestBase { @@ -34,7 +34,8 @@ public void applyDiscount_isValid() { var result = concertFixtures.concertService.discountConcertLiveCoding("123", 10); //then - Assertions.assertThat(result.get().getFirst().getPrice().toInt()).isEqualTo(90_00); + assertThatPrice(result.get().getFirst()) + .equalTo(90_00); } } diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/asserts/PriceAssert.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/asserts/PriceAssert.java index 216bf8fa..0ef507d5 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/asserts/PriceAssert.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/asserts/PriceAssert.java @@ -1,8 +1,10 @@ package com.bottega.promoter.concert.fixtures.asserts; -import com.bottega.promoter.concert.*; +import com.bottega.promoter.concert.Price; +import com.bottega.promoter.concert.PriceFactor; import com.bottega.sharedlib.vo.Money; import lombok.RequiredArgsConstructor; + import static org.assertj.core.api.Assertions.assertThat; @RequiredArgsConstructor @@ -23,4 +25,8 @@ public PriceAssert hasFactors(PriceFactor... factors) { assertThat(price.getFactors()).containsExactlyInAnyOrder(factors); return this; } + + public PriceAssert equalTo(int priceValue) { + return equalTo(new Money(priceValue)); + } } diff --git a/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_pactDepTest.java b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_pactDepTest.java index 6f907d98..dccd4e0b 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_pactDepTest.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_pactDepTest.java @@ -9,7 +9,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; +import static com.bottega.promoter.concert.fixtures.asserts.PriceAssert.assertThatPrice; public class PricingClient_applyDiscount_liveCoding_pactDepTest extends PactFrameworkTestBase_liveCoding { @@ -36,7 +36,8 @@ public void applyDiscount_isValid() { var result = httpPricingClient.applyPercentageDiscount(new ConcertId("123"), 10); //then - assertThat(result.get().getFirst().getPrice().toInt()).isEqualTo(90_00); + assertThatPrice(result.get().getFirst()) + .equalTo(90_00); } } diff --git a/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java index 7ef770b8..1a802b3c 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/infra/client/pricing/PricingClient_applyDiscount_liveCoding_wiremockDepTest.java @@ -10,8 +10,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import static com.bottega.promoter.concert.fixtures.asserts.PriceAssert.assertThatPrice; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; -import static org.assertj.core.api.Assertions.assertThat; public class PricingClient_applyDiscount_liveCoding_wiremockDepTest extends FrameworkTestBase { @@ -45,7 +45,8 @@ public void applyDiscount_isValid() { var result = httpPricingClient.applyPercentageDiscount(new ConcertId("123"), 10); //then - assertThat(result.get().getFirst().getPrice().toInt()).isEqualTo(90_00); + assertThatPrice(result.get().getFirst()) + .equalTo(90_00); } } From 6249f711fa322db9eee6fc0a7266daab3aa4088c Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Thu, 29 Aug 2024 13:45:39 +0200 Subject: [PATCH 16/21] Pact Live: PricingServiceTest --- .../pricing/api/app/PricingService.java | 2 ++ .../promoter/pricing/infra/PriceRepo.java | 4 +-- .../pricing/api/app/PricingServiceTest.java | 31 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingServiceTest.java diff --git a/services/Promoter/src/main/java/com/bottega/promoter/pricing/api/app/PricingService.java b/services/Promoter/src/main/java/com/bottega/promoter/pricing/api/app/PricingService.java index 2ca2ed91..fcaf2f8d 100644 --- a/services/Promoter/src/main/java/com/bottega/promoter/pricing/api/app/PricingService.java +++ b/services/Promoter/src/main/java/com/bottega/promoter/pricing/api/app/PricingService.java @@ -6,6 +6,7 @@ import com.bottega.promoter.pricing.infra.PriceRepo; import com.bottega.sharedlib.vo.error.ErrorResult; import io.vavr.control.Either; +import lombok.AllArgsConstructor; import java.util.List; @@ -13,6 +14,7 @@ import static com.bottega.sharedlib.vo.error.GenericErrorCode.not_found; import static io.vavr.control.Either.left; +@AllArgsConstructor public class PricingService { private PriceRepo priceRepo; diff --git a/services/Promoter/src/main/java/com/bottega/promoter/pricing/infra/PriceRepo.java b/services/Promoter/src/main/java/com/bottega/promoter/pricing/infra/PriceRepo.java index 74fd0437..f0bc9e7f 100644 --- a/services/Promoter/src/main/java/com/bottega/promoter/pricing/infra/PriceRepo.java +++ b/services/Promoter/src/main/java/com/bottega/promoter/pricing/infra/PriceRepo.java @@ -4,12 +4,12 @@ import com.bottega.promoter.concert.domain.ConcertId; import com.bottega.sharedlib.vo.Money; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; public class PriceRepo { public List findByItemId(ConcertId concertId) { - return List.of(new Price(new Money(100_00), Collections.emptyList())); + return List.of(new Price(new Money(100_00), new ArrayList<>())); } public void save(Price price) { diff --git a/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingServiceTest.java b/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingServiceTest.java new file mode 100644 index 00000000..c4d392a0 --- /dev/null +++ b/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingServiceTest.java @@ -0,0 +1,31 @@ +package com.bottega.promoter.pricing.api.app; + +import com.bottega.promoter.concert.domain.ConcertId; +import com.bottega.promoter.concert.fixtures.ConcertLogicTestBase; +import com.bottega.promoter.pricing.infra.PriceRepo; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static com.bottega.promoter.concert.fixtures.asserts.PriceAssert.assertThatPrice; + +class PricingServiceTest extends ConcertLogicTestBase { + + private PricingService pricingService; + + @Override + @BeforeEach + protected void setUp() { + super.setUp(); + pricingService = new PricingService(new PriceRepo()); + } + + @Test + void applyPercentageDiscount_returnsDiscountedPrice() { + //when + var result = pricingService.applyPercentageDiscount(new ConcertId("123"), 10); + + //then + assertThatPrice(result.get().getFirst()) + .equalTo(90_00); + } +} \ No newline at end of file From 26db90069a470d6c3affebd2cccea835bb9e61dc Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Tue, 3 Sep 2024 12:20:51 +0200 Subject: [PATCH 17/21] Pact Live: PricingServiceTest --- ...ConcertService_discountConcert_compTest.java | 17 +++++++---------- ...java => PricingService_liveCoding_Test.java} | 2 +- 2 files changed, 8 insertions(+), 11 deletions(-) rename services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/{PricingServiceTest.java => PricingService_liveCoding_Test.java} (92%) diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_compTest.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_compTest.java index 185531ca..d711c7b3 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_compTest.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_compTest.java @@ -1,15 +1,15 @@ package com.bottega.promoter.concert.api.app; -import java.util.List; - -import com.bottega.promoter.concert.*; +import com.bottega.promoter.concert.Price; import com.bottega.promoter.concert.domain.Concert; import com.bottega.promoter.concert.fixtures.ConcertLogicTestBase; import com.bottega.sharedlib.vo.Money; import com.bottega.sharedlib.vo.error.ErrorResult; import io.vavr.control.Either; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; + +import java.util.List; + import static com.bottega.promoter.concert.fixtures.asserts.PriceAssert.assertThatPrice; import static com.bottega.sharedlib.fixtures.ErrorAssert.assertThatError; import static com.bottega.sharedlib.vo.error.ErrorType.NOT_FOUND; @@ -28,12 +28,9 @@ void discountConcert_discountsConcert_onValidInput() { Either> result = concertFixtures.concertService.discountConcert(concert.getId().asString(), 10); //then - assertThat(result).hasRightValueSatisfying(prices -> { - Assertions.assertThat(prices).hasSize(1); - assertThatPrice(prices.getFirst()) - .equalTo(new Money(90_00)) - .hasFactors(new PriceFactor("PERCENTAGE", 10, null)); - }); + assertThatPrice(result.get().getFirst()) + .equalTo(new Money(90_00)); + } @Test diff --git a/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingServiceTest.java b/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingService_liveCoding_Test.java similarity index 92% rename from services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingServiceTest.java rename to services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingService_liveCoding_Test.java index c4d392a0..d7b32dc0 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingServiceTest.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingService_liveCoding_Test.java @@ -8,7 +8,7 @@ import static com.bottega.promoter.concert.fixtures.asserts.PriceAssert.assertThatPrice; -class PricingServiceTest extends ConcertLogicTestBase { +class PricingService_liveCoding_Test extends ConcertLogicTestBase { private PricingService pricingService; From b3b32c048984049c5a30a46f252b0f3fc41156a4 Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Wed, 25 Sep 2024 14:54:35 +0200 Subject: [PATCH 18/21] price factor assert --- .../ConcertService_discountConcert_liveCoding_compTest.java | 3 ++- .../promoter/concert/fixtures/asserts/PriceAssert.java | 5 +++++ .../pricing/api/app/PricingService_liveCoding_Test.java | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_liveCoding_compTest.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_liveCoding_compTest.java index 16da74df..ee0ebeb7 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_liveCoding_compTest.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/api/app/ConcertService_discountConcert_liveCoding_compTest.java @@ -35,7 +35,8 @@ public void applyDiscount_isValid() { //then assertThatPrice(result.get().getFirst()) - .equalTo(90_00); + .equalTo(90_00) + .hasPercentageFactor(10); } } diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/asserts/PriceAssert.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/asserts/PriceAssert.java index 0ef507d5..0c55431b 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/asserts/PriceAssert.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/asserts/PriceAssert.java @@ -26,6 +26,11 @@ public PriceAssert hasFactors(PriceFactor... factors) { return this; } + public PriceAssert hasPercentageFactor(int value) { + assertThat(price.getFactors()).contains(new PriceFactor("PERCENTAGE", value, null)); + return this; + } + public PriceAssert equalTo(int priceValue) { return equalTo(new Money(priceValue)); } diff --git a/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingService_liveCoding_Test.java b/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingService_liveCoding_Test.java index d7b32dc0..3c132b62 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingService_liveCoding_Test.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingService_liveCoding_Test.java @@ -26,6 +26,7 @@ void applyPercentageDiscount_returnsDiscountedPrice() { //then assertThatPrice(result.get().getFirst()) - .equalTo(90_00); + .equalTo(90_00) + .hasPercentageFactor(10); } } \ No newline at end of file From 5a3f2095e92f2891702b076b996c9b71013a9492 Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Wed, 25 Sep 2024 15:47:58 +0200 Subject: [PATCH 19/21] price json assert --- ...ontroller_discountConcert_restApiTest.java | 13 ++++------ .../concert/api/rest/PriceJsonAssert.java | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 services/Promoter/src/test/java/com/bottega/promoter/concert/api/rest/PriceJsonAssert.java diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/api/rest/ConcertRestController_discountConcert_restApiTest.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/api/rest/ConcertRestController_discountConcert_restApiTest.java index 9788a79f..1c675f99 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/concert/api/rest/ConcertRestController_discountConcert_restApiTest.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/api/rest/ConcertRestController_discountConcert_restApiTest.java @@ -1,12 +1,11 @@ package com.bottega.promoter.concert.api.rest; -import au.com.dius.pact.consumer.junit5.*; import com.bottega.promoter.concert.domain.Concert; -import com.bottega.promoter.fixtures.*; +import com.bottega.promoter.fixtures.PactFrameworkTestBase; import io.restassured.response.ValidatableResponse; import org.junit.jupiter.api.Test; -import static org.apache.http.HttpStatus.SC_OK; -import static org.hamcrest.Matchers.*; + +import static com.bottega.promoter.concert.api.rest.PriceJsonAssert.assertThatPrice; public class ConcertRestController_discountConcert_restApiTest extends PactFrameworkTestBase { @@ -18,10 +17,8 @@ public void discountConcert_discounts_onValidRequest() { ValidatableResponse response = concertFixtures.concertHttpClient.discountConcert(concert.getId(), 10); //then - response - .statusCode(SC_OK) - .body("$", hasSize(1)) - .body("[0].price", equalTo(90_00)); + assertThatPrice(response) + .hasSinglePrice(90_00); } } diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/api/rest/PriceJsonAssert.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/api/rest/PriceJsonAssert.java new file mode 100644 index 00000000..9598bcc8 --- /dev/null +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/api/rest/PriceJsonAssert.java @@ -0,0 +1,26 @@ +package com.bottega.promoter.concert.api.rest; + +import io.restassured.response.ValidatableResponse; +import lombok.RequiredArgsConstructor; + +import static org.apache.http.HttpStatus.SC_OK; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; + +@RequiredArgsConstructor +public class PriceJsonAssert { + + private final ValidatableResponse response; + + public static PriceJsonAssert assertThatPrice(ValidatableResponse response) { + return new PriceJsonAssert(response); + } + + public PriceJsonAssert hasSinglePrice(int priceValue) { + response + .statusCode(SC_OK) + .body("$", hasSize(1)) + .body("[0].price", equalTo(priceValue)); + return this; + } +} From f784866d32ac2181ac1635406bb0710399f008cc Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Thu, 26 Sep 2024 09:16:53 +0200 Subject: [PATCH 20/21] workflow cleanup --- .github/workflows/ci-pricing-liveCoding.yml | 9 --------- .github/workflows/ci-promoter-liveCoding.yml | 11 ----------- 2 files changed, 20 deletions(-) diff --git a/.github/workflows/ci-pricing-liveCoding.yml b/.github/workflows/ci-pricing-liveCoding.yml index 349b6743..38bbd355 100644 --- a/.github/workflows/ci-pricing-liveCoding.yml +++ b/.github/workflows/ci-pricing-liveCoding.yml @@ -53,15 +53,6 @@ jobs: -Dpact.rootDir=build/pacts test publishToMavenLocal -# - name: Publish Pricing Consumer Pacts -# run: >- -# docker run --rm \ -# -w ${PWD} \ -# -v ${PWD}:${PWD} \ -# -e PACT_BROKER_BASE_URL=$PACT_BROKER_BASE_URL \ -# -e PACT_BROKER_TOKEN=$PACT_BROKER_TOKEN \ -# pactfoundation/pact-cli:1.1.0.0 \ -# broker publish ${PWD}/services/Pricing/build/pacts --consumer-app-version=$PACTICIPANT-${{ github.sha }} --branch=${{github.ref_name}} --tag-with-git-branch dev-deployment: needs: build diff --git a/.github/workflows/ci-promoter-liveCoding.yml b/.github/workflows/ci-promoter-liveCoding.yml index 0ebb160e..c5492d52 100644 --- a/.github/workflows/ci-promoter-liveCoding.yml +++ b/.github/workflows/ci-promoter-liveCoding.yml @@ -50,17 +50,6 @@ jobs: -Dpact.rootDir=build/pacts test publishToMavenLocal -# with publish contracts: -# run: >- -# cd services/Promoter && -# ./gradlew -# -Dpact.verifier.publishResults=true -# -Dpact.provider.version=$PACTICIPANT-${{ github.sha }} -# -Dpact.provider.branchName=${{ github.ref_name }} -# -Dpact.provider.tag=${{ github.ref_name }} -# -Dpact.rootDir=build/pacts -# test publishToMavenLocal - - name: Publish Promoter Consumer Pacts run: >- docker run --rm \ From 412f010ab8f92c463835b8a8a6a52db8c0992965 Mon Sep 17 00:00:00 2001 From: Jacek Milewski Date: Tue, 19 Nov 2024 10:52:42 +0100 Subject: [PATCH 21/21] priceRepo.savePriceFor("123", 100_00); --- .../com/bottega/promoter/concert/Price.java | 3 +++ .../client/pricing/PriceResponseDto.java | 10 ++++++--- .../promoter/pricing/infra/PriceRepo.java | 21 ++++++++++++++----- .../concert/fixtures/PricingStubs.java | 2 ++ .../fixtures/clients/ConcertHttpClient.java | 13 +++++++----- .../promoter/fixtures/FakePricingClient.java | 10 ++++++--- .../app/PricingService_liveCoding_Test.java | 7 ++++++- 7 files changed, 49 insertions(+), 17 deletions(-) diff --git a/services/Promoter/src/main/java/com/bottega/promoter/concert/Price.java b/services/Promoter/src/main/java/com/bottega/promoter/concert/Price.java index f3144a2a..effd75ff 100644 --- a/services/Promoter/src/main/java/com/bottega/promoter/concert/Price.java +++ b/services/Promoter/src/main/java/com/bottega/promoter/concert/Price.java @@ -14,6 +14,8 @@ @Getter public class Price { + private String id; + private String itemId; private Money price; private List factors; @@ -22,4 +24,5 @@ public Price applyFactor(PriceFactor factor) { this.factors.add(factor); return this; } + } diff --git a/services/Promoter/src/main/java/com/bottega/promoter/infra/client/pricing/PriceResponseDto.java b/services/Promoter/src/main/java/com/bottega/promoter/infra/client/pricing/PriceResponseDto.java index 44c03c0d..ca765602 100644 --- a/services/Promoter/src/main/java/com/bottega/promoter/infra/client/pricing/PriceResponseDto.java +++ b/services/Promoter/src/main/java/com/bottega/promoter/infra/client/pricing/PriceResponseDto.java @@ -1,16 +1,20 @@ package com.bottega.promoter.infra.client.pricing; -import java.util.*; - -import com.bottega.promoter.concert.*; +import com.bottega.promoter.concert.Price; +import com.bottega.promoter.concert.PriceFactor; import com.bottega.sharedlib.vo.Money; +import java.util.Arrays; +import java.util.Map; + public record PriceResponseDto( int price, PriceFactorResponseDto[] factors) { public Price toPrice() { return new Price( + "fake-id", + "item-id", new Money(price), Arrays.stream(factors) .map(PriceFactorResponseDto::toPriceFactor) diff --git a/services/Promoter/src/main/java/com/bottega/promoter/pricing/infra/PriceRepo.java b/services/Promoter/src/main/java/com/bottega/promoter/pricing/infra/PriceRepo.java index f0bc9e7f..27377e98 100644 --- a/services/Promoter/src/main/java/com/bottega/promoter/pricing/infra/PriceRepo.java +++ b/services/Promoter/src/main/java/com/bottega/promoter/pricing/infra/PriceRepo.java @@ -4,15 +4,26 @@ import com.bottega.promoter.concert.domain.ConcertId; import com.bottega.sharedlib.vo.Money; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class PriceRepo { + + Map db = new HashMap<>(); + public List findByItemId(ConcertId concertId) { - return List.of(new Price(new Money(100_00), new ArrayList<>())); + return db.values().stream() + .filter(price -> price.getItemId().equals(concertId.asString())) + .toList(); + } + + public Price savePriceFor(String itemId, int priceValue) { + Price price = new Price(UUID.randomUUID().toString(), itemId, new Money(priceValue), new ArrayList<>()); + db.put(price.getId(), price); + return price; } - public void save(Price price) { - //who cares + public Price save(Price price) { + db.put(price.getId(), price); + return price; } } diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java index 3c4bea3c..6521762b 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/PricingStubs.java @@ -79,6 +79,8 @@ public void stubApplyPercentageDiscount(PricingService pricingServiceMock) { given(pricingServiceMock.applyPercentageDiscount(new ConcertId("123"), 10)) .willReturn(Either.right( of(new Price( + "stubId", + "stubItemId", new Money(90_00), of(new PriceFactor( "PERCENTAGE", diff --git a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/clients/ConcertHttpClient.java b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/clients/ConcertHttpClient.java index e6cfe1e1..53b91da3 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/clients/ConcertHttpClient.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/concert/fixtures/clients/ConcertHttpClient.java @@ -1,14 +1,17 @@ package com.bottega.promoter.concert.fixtures.clients; -import java.time.*; - import com.bottega.promoter.concert.domain.ConcertId; import com.bottega.promoter.fixtures.TestBuilders; import com.bottega.sharedlib.config.TestClockConfig; import io.restassured.response.ValidatableResponse; -import lombok.*; +import lombok.Builder; +import lombok.RequiredArgsConstructor; import org.apache.groovy.util.Maps; import org.springframework.stereotype.Component; + +import java.time.Instant; +import java.time.LocalDate; + import static java.time.ZoneOffset.UTC; @Component @@ -32,11 +35,11 @@ public static class ConcertRequest { public ValidatableResponse createConcert(ConcertRequest concertRequest) { return builders.aRequestSpec() .body(Maps.of( - "title", concertRequest.title, + "titleString", concertRequest.title, "date", LocalDate.ofInstant(concertRequest.date, UTC).atStartOfDay().toLocalDate().toString(), "promoterId", concertRequest.promoterId )) - .post("/concert") + .post("/v2/concert") .then(); } diff --git a/services/Promoter/src/test/java/com/bottega/promoter/fixtures/FakePricingClient.java b/services/Promoter/src/test/java/com/bottega/promoter/fixtures/FakePricingClient.java index ca9643a6..ebe05b4a 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/fixtures/FakePricingClient.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/fixtures/FakePricingClient.java @@ -1,13 +1,15 @@ package com.bottega.promoter.fixtures; -import java.util.List; - -import com.bottega.promoter.concert.*; +import com.bottega.promoter.concert.Price; +import com.bottega.promoter.concert.PriceFactor; import com.bottega.promoter.concert.domain.ConcertId; import com.bottega.promoter.infra.client.pricing.PricingClient; import com.bottega.sharedlib.vo.Money; import com.bottega.sharedlib.vo.error.ErrorResult; import io.vavr.control.Either; + +import java.util.List; + import static java.util.List.of; public class FakePricingClient implements PricingClient { @@ -16,6 +18,8 @@ public class FakePricingClient implements PricingClient { public Either> applyPercentageDiscount(ConcertId itemId, int percentage) { return Either.right( of(new Price( + "fakeId", + "fakeItemId", new Money(90_00), of(new PriceFactor( "PERCENTAGE", diff --git a/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingService_liveCoding_Test.java b/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingService_liveCoding_Test.java index 3c132b62..a6337794 100644 --- a/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingService_liveCoding_Test.java +++ b/services/Promoter/src/test/java/com/bottega/promoter/pricing/api/app/PricingService_liveCoding_Test.java @@ -11,16 +11,21 @@ class PricingService_liveCoding_Test extends ConcertLogicTestBase { private PricingService pricingService; + private PriceRepo priceRepo; @Override @BeforeEach protected void setUp() { super.setUp(); - pricingService = new PricingService(new PriceRepo()); + priceRepo = new PriceRepo(); + pricingService = new PricingService(priceRepo); } @Test void applyPercentageDiscount_returnsDiscountedPrice() { + //given + priceRepo.savePriceFor("123", 100_00); + //when var result = pricingService.applyPercentageDiscount(new ConcertId("123"), 10);