From bad7d146fa1740454e647307d0f9150e08960bcf Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Wed, 14 Sep 2022 17:51:04 +0200 Subject: [PATCH] implements HsOfficePartnerController.patch --- .../partner/HsOfficePartnerController.java | 15 +- .../partner/HsOfficePartnerEntityPatch.java | 45 +++ .../hs-office/api-mappings.yaml | 2 +- .../hs-office/hs-office-partner-schemas.yaml | 109 ++++--- .../hs-office-partners-with-uuid.yaml | 3 +- ...OfficePartnerControllerAcceptanceTest.java | 120 ++++++- .../HsOfficePartnerEntityPatchUnitTest.java | 307 ++++++++++++++++++ .../net/hostsharing/test/JsonMatcher.java | 1 - 8 files changed, 544 insertions(+), 58 deletions(-) create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatch.java create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatchUnitTest.java diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java index a31d785f..c56199c5 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerController.java @@ -1,6 +1,7 @@ package net.hostsharing.hsadminng.hs.office.partner; import net.hostsharing.hsadminng.Mapper; +import net.hostsharing.hsadminng.OptionalFromJson; import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRepository; import net.hostsharing.hsadminng.hs.office.generated.api.v1.api.HsOfficePartnersApi; @@ -114,14 +115,24 @@ public class HsOfficePartnerController implements HsOfficePartnersApi { @Override @Transactional - public ResponseEntity updatePartner( + public ResponseEntity patchPartner( final String currentUser, final String assumedRoles, final UUID partnerUuid, final HsOfficePartnerPatchResource body) { - return null; + + context.define(currentUser, assumedRoles); + + final var current = partnerRepo.findByUuid(partnerUuid).orElseThrow(); + + new HsOfficePartnerEntityPatch(current, contactRepo::findByUuid, personRepo::findByUuid).apply(body); + + final var saved = partnerRepo.save(current); + final var mapped = map(saved, HsOfficePartnerResource.class); + return ResponseEntity.ok(mapped); } + final BiConsumer PARTNER_ENTITY_TO_RESOURCE_POSTMAPPER = (entity, resource) -> { resource.setPerson(map(entity.getPerson(), HsOfficePersonResource.class)); resource.setContact(map(entity.getContact(), HsOfficeContactResource.class)); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatch.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatch.java new file mode 100644 index 00000000..90053ff5 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatch.java @@ -0,0 +1,45 @@ +package net.hostsharing.hsadminng.hs.office.partner; + +import net.hostsharing.hsadminng.OptionalFromJson; +import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; +import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource; +import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; + +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.UUID; +import java.util.function.Function; + +class HsOfficePartnerEntityPatch { + + private final HsOfficePartnerEntity entity; + private final Function> fetchContact; + private final Function> fetchPerson; + + HsOfficePartnerEntityPatch( + final HsOfficePartnerEntity entity, + final Function> fetchContact, + final Function> fetchPerson) { + this.entity = entity; + this.fetchContact = fetchContact; + this.fetchPerson = fetchPerson; + } + + void apply(final HsOfficePartnerPatchResource resource) { + OptionalFromJson.of(resource.getContactUuid()).ifPresent(newValue -> { + entity.setContact(fetchContact.apply(newValue).orElseThrow( + () -> new NoSuchElementException("cannot find contact uuid " + newValue) + )); + }); + OptionalFromJson.of(resource.getPersonUuid()).ifPresent(newValue -> { + entity.setPerson(fetchPerson.apply(newValue).orElseThrow( + () -> new NoSuchElementException("cannot find person uuid " + newValue) + )); + }); + OptionalFromJson.of(resource.getRegistrationOffice()).ifPresent(entity::setRegistrationOffice); + OptionalFromJson.of(resource.getRegistrationNumber()).ifPresent(entity::setRegistrationNumber); + OptionalFromJson.of(resource.getBirthday()).ifPresent(entity::setBirthday); + OptionalFromJson.of(resource.getBirthName()).ifPresent(entity::setBirthName); + OptionalFromJson.of(resource.getDateOfDeath()).ifPresent(entity::setDateOfDeath); + } +} diff --git a/src/main/resources/api-definition/hs-office/api-mappings.yaml b/src/main/resources/api-definition/hs-office/api-mappings.yaml index 467b9b78..14309def 100644 --- a/src/main/resources/api-definition/hs-office/api-mappings.yaml +++ b/src/main/resources/api-definition/hs-office/api-mappings.yaml @@ -12,5 +12,5 @@ map: - type: string:uuid => java.util.UUID paths: - /api/hs/office/partners/{packageUUID}: + /api/hs/office/partners/{partnerUUID}: null: org.openapitools.jackson.nullable.JsonNullable diff --git a/src/main/resources/api-definition/hs-office/hs-office-partner-schemas.yaml b/src/main/resources/api-definition/hs-office/hs-office-partner-schemas.yaml index bf567274..cd79d96f 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-partner-schemas.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-partner-schemas.yaml @@ -3,58 +3,89 @@ components: schemas: - HsOfficePartnerBase: + HsOfficePartner: type: object properties: + uuid: + type: string + format: uuid + person: + $ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson' + contact: + $ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact' + registrationOffice: + type: string + registrationNumber: + type: string + birthName: + type: string + birthday: + type: string + format: date + dateOfDeath: + type: string + format: date + + HsOfficePartnerPatch: + type: object + properties: + personUuid: + type: string + format: uuid + nullable: true + contactUuid: + type: string + format: uuid + nullable: true registrationOffice: type: string + nullable: true registrationNumber: type: string + nullable: true birthName: type: string + nullable: true birthday: type: string format: date + nullable: true dateOfDeath: type: string format: date - - HsOfficePartner: - allOf: - - type: object - properties: - uuid: - type: string - format: uuid - person: - $ref: './hs-office-person-schemas.yaml#/components/schemas/HsOfficePerson' - contact: - $ref: './hs-office-contact-schemas.yaml#/components/schemas/HsOfficeContact' - - $ref: '#/components/schemas/HsOfficePartnerBase' - - HsOfficePartnerPatch: - allOf: - - type: object - properties: - personUuid: - type: string - format: uuid - contactUuid: - type: string - format: uuid - - $ref: '#/components/schemas/HsOfficePartnerBase' + nullable: true HsOfficePartnerInsert: - allOf: - - type: object - properties: - personUuid: - type: string - format: uuid - contactUuid: - type: string - format: uuid - - required: - - personUuid - - contactUuid - - $ref: '#/components/schemas/HsOfficePartnerBase' + type: object + properties: + personUuid: + type: string + format: uuid + contactUuid: + type: string + format: uuid + registrationOffice: + type: string + nullable: true + registrationNumber: + type: string + nullable: true + birthName: + type: string + nullable: true + birthday: + type: string + format: date + nullable: true + dateOfDeath: + type: string + format: date + nullable: true + required: + - personUuid + - contactUuid + - registrationOffice + - registrationNumber + - birthName + - birthday + - dateOfDeath diff --git a/src/main/resources/api-definition/hs-office/hs-office-partners-with-uuid.yaml b/src/main/resources/api-definition/hs-office/hs-office-partners-with-uuid.yaml index 63562bb2..bc9927f3 100644 --- a/src/main/resources/api-definition/hs-office/hs-office-partners-with-uuid.yaml +++ b/src/main/resources/api-definition/hs-office/hs-office-partners-with-uuid.yaml @@ -29,7 +29,8 @@ get: patch: tags: - hs-office-partners - operationId: updatePartner + description: 'Updates a single business partner by its uuid, if permitted for the current subject.' + operationId: patchPartner parameters: - $ref: './auth.yaml#/components/parameters/currentUser' - $ref: './auth.yaml#/components/parameters/assumedRoles' diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java index 892d7b0b..31efb062 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerControllerAcceptanceTest.java @@ -99,7 +99,7 @@ class HsOfficePartnerControllerAcceptanceTest { class AddPartner { @Test - void globalAdmin_withoutAssumedRole_canAddPartner_withGeneratedUuid() { + void globalAdmin_withoutAssumedRole_canAddPartner() { context.define("superuser-alex@hostsharing.net"); final var givenPerson = personRepo.findPersonByOptionalNameLike("Ostfriesische").get(0); @@ -114,10 +114,7 @@ class HsOfficePartnerControllerAcceptanceTest { "contactUuid": "%s", "personUuid": "%s", "registrationOffice": "Registergericht Hamburg", - "registrationNumber": "123456", - "birthName": null, - "birthday": null, - "dateOfDeath": null + "registrationNumber": "123456" } """.formatted(givenContact.getUuid(), givenPerson.getUuid())) .port(port) @@ -153,12 +150,7 @@ class HsOfficePartnerControllerAcceptanceTest { .body(""" { "contactUuid": "%s", - "personUuid": "%s", - "registrationOffice": "Registergericht Hamburg", - "registrationNumber": "123456", - "birthName": null, - "birthday": null, - "dateOfDeath": null + "personUuid": "%s" } """.formatted(givenContactUuid, givenPerson.getUuid())) .port(port) @@ -268,6 +260,104 @@ class HsOfficePartnerControllerAcceptanceTest { } } + @Nested + @Accepts({ "Partner:U(Update)" }) + class PatchPartner { + + @Test + void globalAdmin_withoutAssumedRole_canPatchAllPropertiesOfArbitraryPartner() { + + context.define("superuser-alex@hostsharing.net"); + final var givenPartner = givenSomeTemporaryPartnerBessler(); + final var givenPerson = personRepo.findPersonByOptionalNameLike("Ostfriesische").get(0); + final var givenContact = contactRepo.findContactByOptionalLabelLike("forth").get(0); + + final var location = RestAssured // @formatter:off + .given() + .header("current-user", "superuser-alex@hostsharing.net") + .contentType(ContentType.JSON) + .body(""" + { + "contactUuid": "%s", + "personUuid": "%s", + "registrationOffice": "Registergericht Hamburg", + "registrationNumber": "222222", + "birthName": "Maja Schmidt", + "birthday": "1938-04-08", + "dateOfDeath": "2022-01-12" + } + """.formatted(givenContact.getUuid(), givenPerson.getUuid())) + .port(port) + .when() + .patch("http://localhost/api/hs/office/partners/" + givenPartner.getUuid()) + .then().assertThat() + .statusCode(200) + .contentType(ContentType.JSON) + .body("uuid", isUuidValid()) + .body("registrationNumber", is("222222")) + .body("contact.label", is(givenContact.getLabel())) + .body("person.tradeName", is(givenPerson.getTradeName())); + // @formatter:on + + // finally, the partner is actually updated + assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent().get() + .matches(person -> { + assertThat(person.getPerson().getTradeName()).isEqualTo("Ostfriesische Kuhhandel OHG"); + assertThat(person.getContact().getLabel()).isEqualTo("forth contact"); + assertThat(person.getRegistrationOffice()).isEqualTo("Registergericht Hamburg"); + assertThat(person.getRegistrationNumber()).isEqualTo("222222"); + assertThat(person.getBirthName()).isEqualTo("Maja Schmidt"); + assertThat(person.getBirthday()).isEqualTo("1938-04-08"); + assertThat(person.getDateOfDeath()).isEqualTo("2022-01-12"); + return true; + }); + } + + @Test + void globalAdmin_withoutAssumedRole_canPatchPartialPropertiesOfArbitraryPartner() { + + context.define("superuser-alex@hostsharing.net"); + final var givenPartner = givenSomeTemporaryPartnerBessler(); + + final var location = RestAssured // @formatter:off + .given() + .header("current-user", "superuser-alex@hostsharing.net") + .contentType(ContentType.JSON) + .body(""" + { + "birthName": "Maja Schmidt", + "birthday": "1938-04-08", + "dateOfDeath": "2022-01-12" + } + """) + .port(port) + .when() + .patch("http://localhost/api/hs/office/partners/" + givenPartner.getUuid()) + .then().assertThat() + .statusCode(200) + .contentType(ContentType.JSON) + .body("uuid", isUuidValid()) + .body("birthName", is("Maja Schmidt")) + .body("contact.label", is(givenPartner.getContact().getLabel())) + .body("person.tradeName", is(givenPartner.getPerson().getTradeName())); + // @formatter:on + + // finally, the partner is actually updated + assertThat(partnerRepo.findByUuid(givenPartner.getUuid())).isPresent().get() + .matches(person -> { + assertThat(person.getPerson().getTradeName()).isEqualTo(givenPartner.getPerson().getTradeName()); + assertThat(person.getContact().getLabel()).isEqualTo(givenPartner.getContact().getLabel()); + assertThat(person.getRegistrationOffice()).isEqualTo(null); + assertThat(person.getRegistrationNumber()).isEqualTo(null); + assertThat(person.getBirthName()).isEqualTo("Maja Schmidt"); + assertThat(person.getBirthday()).isEqualTo("1938-04-08"); + assertThat(person.getDateOfDeath()).isEqualTo("2022-01-12"); + return true; + }); + } + + } + @Nested @Accepts({ "Partner:D(Delete)" }) class DeletePartner { @@ -282,7 +372,7 @@ class HsOfficePartnerControllerAcceptanceTest { .header("current-user", "superuser-alex@hostsharing.net") .port(port) .when() - .delete("http://localhost/api/hs/office/partners/" + toCleanup(givenPartner.getUuid())) + .delete("http://localhost/api/hs/office/partners/" + givenPartner.getUuid()) .then().log().body().assertThat() .statusCode(204); // @formatter:on @@ -302,7 +392,7 @@ class HsOfficePartnerControllerAcceptanceTest { .header("current-user", "customer-admin@forthcontact.example.com") .port(port) .when() - .delete("http://localhost/api/hs/office/partners/" + toCleanup(givenPartner.getUuid())) + .delete("http://localhost/api/hs/office/partners/" + givenPartner.getUuid()) .then().log().body().assertThat() .statusCode(403); // @formatter:on @@ -322,7 +412,7 @@ class HsOfficePartnerControllerAcceptanceTest { .header("current-user", "selfregistered-user-drew@hostsharing.org") .port(port) .when() - .delete("http://localhost/api/hs/office/partners/" + toCleanup(givenPartner.getUuid())) + .delete("http://localhost/api/hs/office/partners/" + givenPartner.getUuid()) .then().log().body().assertThat() .statusCode(404); // @formatter:on @@ -347,6 +437,8 @@ class HsOfficePartnerControllerAcceptanceTest { .contact(givenContact) .build(); + toCleanup(newPartner.getUuid()); + return partnerRepo.save(newPartner); }).assertSuccessful().returnedValue(); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatchUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatchUnitTest.java new file mode 100644 index 00000000..7c103dd4 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntityPatchUnitTest.java @@ -0,0 +1,307 @@ +package net.hostsharing.hsadminng.hs.office.partner; + +import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactEntity; +import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficePartnerPatchResource; +import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.openapitools.jackson.nullable.JsonNullable; + +import java.time.LocalDate; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowableOfType; + +// TODO: there must be an easier way to test such patch classes +class HsOfficePartnerEntityPatchUnitTest { + + private static final UUID INITIAL_PARTNER_UUID = UUID.randomUUID(); + private static final UUID INITIAL_CONTACT_UUID = UUID.randomUUID(); + private static final UUID INITIAL_PERSON_UUID = UUID.randomUUID(); + private static final UUID PATCHED_CONTACT_UUID = UUID.randomUUID(); + private static final UUID PATCHED_PERSON_UUID = UUID.randomUUID(); + + private static final LocalDate INITIAL_BIRTHDAY = LocalDate.parse("1900-01-01"); + private static final LocalDate PATCHED_BIRTHDAY = LocalDate.parse("1990-12-31"); + + private static final LocalDate INITIAL_DAY_OF_DEATH = LocalDate.parse("2000-01-01"); + private static final LocalDate PATCHED_DAY_OF_DEATH = LocalDate.parse("2022-08-31"); + + final HsOfficePartnerEntity givenPartner = new HsOfficePartnerEntity(); + private final HsOfficePersonEntity givenInitialPerson = new HsOfficePersonEntity(); + private final HsOfficeContactEntity givenInitialContact = new HsOfficeContactEntity(); + + final HsOfficePartnerPatchResource patchResource = new HsOfficePartnerPatchResource(); + + private final HsOfficePartnerEntityPatch hsOfficePartnerEntityPatch = new HsOfficePartnerEntityPatch( + givenPartner, + uuid -> uuid == PATCHED_CONTACT_UUID + ? Optional.of(newContact(uuid)) + : Optional.empty(), + uuid -> uuid == PATCHED_PERSON_UUID + ? Optional.of(newPerson(uuid)) + : Optional.empty()); + + { + givenInitialPerson.setUuid(INITIAL_PERSON_UUID); + givenInitialContact.setUuid(INITIAL_CONTACT_UUID); + + givenPartner.setUuid(INITIAL_PARTNER_UUID); + givenPartner.setPerson(givenInitialPerson); + givenPartner.setContact(givenInitialContact); + givenPartner.setRegistrationOffice("initial Reg-Office"); + givenPartner.setRegistrationNumber("initial Reg-Number"); + givenPartner.setBirthday(INITIAL_BIRTHDAY); + givenPartner.setBirthName("initial birth name"); + givenPartner.setDateOfDeath(INITIAL_DAY_OF_DEATH); + } + + @Test + void willPatchAllProperties() { + // given + patchResource.setContactUuid(JsonNullable.of(PATCHED_CONTACT_UUID)); + patchResource.setPersonUuid(JsonNullable.of(PATCHED_PERSON_UUID)); + patchResource.setRegistrationNumber(JsonNullable.of("patched Reg-Number")); + patchResource.setRegistrationOffice(JsonNullable.of("patched Reg-Office")); + patchResource.setBirthday(JsonNullable.of(PATCHED_BIRTHDAY)); + patchResource.setBirthName(JsonNullable.of("patched birth name")); + patchResource.setDateOfDeath(JsonNullable.of(PATCHED_DAY_OF_DEATH)); + + // when + hsOfficePartnerEntityPatch.apply(patchResource); + + // then + new HsOfficePartnerEntityMatcher() + .withPatchedContactUuid(PATCHED_CONTACT_UUID) + .withPatchedPersonUuid(PATCHED_PERSON_UUID) + .withPatchedRegistrationOffice("patched Reg-Office") + .withPatchedRegistrationNumber("patched Reg-Number") + .withPatchedBirthday(PATCHED_BIRTHDAY) + .withPatchedBirthName("patched birth name") + .withPatchedDateOfDeath(PATCHED_DAY_OF_DEATH) + .matches(givenPartner); + } + + @Test + void willThrowIfNoContactFound() { + // given + patchResource.setContactUuid(JsonNullable.of(null)); + + // when + final var exception = catchThrowableOfType(() -> { + hsOfficePartnerEntityPatch.apply(patchResource); + }, NoSuchElementException.class); + + // then + assertThat(exception.getMessage()).isEqualTo("cannot find contact uuid null"); + } + + @Test + void willThrowIfNoPersonFound() { + // given + patchResource.setPersonUuid(JsonNullable.of(null)); + + // when + final var exception = catchThrowableOfType(() -> { + hsOfficePartnerEntityPatch.apply(patchResource); + }, NoSuchElementException.class); + + // then + assertThat(exception.getMessage()).isEqualTo("cannot find person uuid null"); + } + + @Test + void willPatchOnlyContactProperty() { + // given + patchResource.setContactUuid(JsonNullable.of(PATCHED_CONTACT_UUID)); + + // when + hsOfficePartnerEntityPatch.apply(patchResource); + + // then + new HsOfficePartnerEntityMatcher() + .withPatchedContactUuid(PATCHED_CONTACT_UUID) + .matches(givenPartner); + } + + @Test + void willPatchOnlyPersonProperty() { + // given + patchResource.setPersonUuid(JsonNullable.of(PATCHED_PERSON_UUID)); + + // when + hsOfficePartnerEntityPatch.apply(patchResource); + + // then + new HsOfficePartnerEntityMatcher() + .withPatchedPersonUuid(PATCHED_PERSON_UUID) + .matches(givenPartner); + } + + @ParameterizedTest + @ValueSource(strings = { "patched Reg-Office" }) + @NullSource + void willPatchOnlyRegOfficeProperty(final String patchedValue) { + // given + patchResource.setRegistrationOffice(JsonNullable.of(patchedValue)); + + // when + hsOfficePartnerEntityPatch.apply(patchResource); + + // then + new HsOfficePartnerEntityMatcher() + .withPatchedRegistrationOffice(patchedValue) + .matches(givenPartner); + } + + @ParameterizedTest + @ValueSource(strings = { "patched birth name" }) + @NullSource + void willPatchOnlyRegNumberProperty(final String patchedValue) { + // given + patchResource.setRegistrationNumber(JsonNullable.of(patchedValue)); + + // when + hsOfficePartnerEntityPatch.apply(patchResource); + + // then + new HsOfficePartnerEntityMatcher() + .withPatchedRegistrationNumber(patchedValue) + .matches(givenPartner); + } + + @ParameterizedTest + @EnumSource(LocalDatePatches.class) + void willPatchOnlyBirthdayProperty(final LocalDatePatches patch) { + // given + patchResource.setBirthday(JsonNullable.of(patch.value)); + + // when + hsOfficePartnerEntityPatch.apply(patchResource); + + // then + new HsOfficePartnerEntityMatcher() + .withPatchedBirthday(patch.value) + .matches(givenPartner); + } + + @ParameterizedTest + @ValueSource(strings = { "patched birth name" }) + @NullSource + void willPatchOnlyBirthNameProperty(final String patchedValue) { + // given + patchResource.setBirthName(JsonNullable.of(patchedValue)); + + // when + hsOfficePartnerEntityPatch.apply(patchResource); + + // then + new HsOfficePartnerEntityMatcher() + .withPatchedBirthName(patchedValue) + .matches(givenPartner); + } + + @ParameterizedTest + @EnumSource(LocalDatePatches.class) + void willPatchOnlyDateOfDeathProperty(final LocalDatePatches patch) { + // given + patchResource.setDateOfDeath(JsonNullable.of(patch.value)); + + // when + hsOfficePartnerEntityPatch.apply(patchResource); + + // then + new HsOfficePartnerEntityMatcher() + .withPatchedDateOfDeath(patch.value) + .matches(givenPartner); + } + + private HsOfficeContactEntity newContact(final UUID uuid) { + final var newContact = new HsOfficeContactEntity(); + newContact.setUuid(uuid); + return newContact; + } + + private HsOfficePersonEntity newPerson(final UUID uuid) { + final var newPerson = new HsOfficePersonEntity(); + newPerson.setUuid(uuid); + return newPerson; + } + + private static class HsOfficePartnerEntityMatcher { + + private UUID expectedContactUuid = INITIAL_CONTACT_UUID; + private UUID expectedPersonUuid = INITIAL_PERSON_UUID; + private String expectedRegOffice = "initial Reg-Office"; + private String expectedRegNumber = "initial Reg-Number"; + private LocalDate expectedBirthday = INITIAL_BIRTHDAY; + private String expectedBirthName = "initial birth name"; + private LocalDate expectedDateOfDeath = INITIAL_DAY_OF_DEATH; + + HsOfficePartnerEntityMatcher withPatchedContactUuid(final UUID patchedContactUuid) { + expectedContactUuid = patchedContactUuid; + return this; + } + + HsOfficePartnerEntityMatcher withPatchedPersonUuid(final UUID patchedPersonUuid) { + expectedPersonUuid = patchedPersonUuid; + return this; + } + + HsOfficePartnerEntityMatcher withPatchedRegistrationOffice(final String patchedRegOffice) { + expectedRegOffice = patchedRegOffice; + return this; + } + + HsOfficePartnerEntityMatcher withPatchedRegistrationNumber(final String patchedRegNumber) { + expectedRegNumber = patchedRegNumber; + return this; + } + + HsOfficePartnerEntityMatcher withPatchedBirthday(final LocalDate patchedBirthday) { + expectedBirthday = patchedBirthday; + return this; + } + + HsOfficePartnerEntityMatcher withPatchedBirthName(final String patchedBirthName) { + expectedBirthName = patchedBirthName; + return this; + } + + HsOfficePartnerEntityMatcher withPatchedDateOfDeath(final LocalDate patchedDayOfDeath) { + expectedDateOfDeath = patchedDayOfDeath; + return this; + } + + void matches(final HsOfficePartnerEntity givenPartner) { + + assertThat(givenPartner.getContact().getUuid()).isEqualTo(expectedContactUuid); + assertThat(givenPartner.getPerson().getUuid()).isEqualTo(expectedPersonUuid); + assertThat(givenPartner.getRegistrationOffice()).isEqualTo(expectedRegOffice); + assertThat(givenPartner.getRegistrationNumber()).isEqualTo(expectedRegNumber); + assertThat(givenPartner.getBirthday()).isEqualTo(expectedBirthday); + assertThat(givenPartner.getBirthName()).isEqualTo(expectedBirthName); + assertThat(givenPartner.getDateOfDeath()).isEqualTo(expectedDateOfDeath); + + } + + } + + enum LocalDatePatches { + REAL_VALUE(LocalDate.now()), + NULL_VALUE(null); + + final LocalDate value; + + LocalDatePatches(final LocalDate patchedBirthday) { + value = patchedBirthday; + } + } + +} diff --git a/src/test/java/net/hostsharing/test/JsonMatcher.java b/src/test/java/net/hostsharing/test/JsonMatcher.java index f29a0857..3f5457c2 100644 --- a/src/test/java/net/hostsharing/test/JsonMatcher.java +++ b/src/test/java/net/hostsharing/test/JsonMatcher.java @@ -48,7 +48,6 @@ public class JsonMatcher extends BaseMatcher { } try { final var actualJson = new ObjectMapper().writeValueAsString(actual); - compareMode = JSONCompareMode.LENIENT; JSONAssert.assertEquals(expected, actualJson, compareMode); return true; } catch (final JSONException | JsonProcessingException e) {