OfficeScenarioTests CoopShares+Assets #121
@ -46,6 +46,7 @@ public class CustomErrorResponse {
|
|||||||
this.path = path;
|
this.path = path;
|
||||||
this.statusCode = status.value();
|
this.statusCode = status.value();
|
||||||
this.statusPhrase = status.getReasonPhrase();
|
this.statusPhrase = status.getReasonPhrase();
|
||||||
|
// HOWTO: debug serverside error response - set a breakpoint here
|
||||||
this.message = message.startsWith("ERROR: [") ? message : "ERROR: [" + statusCode + "] " + message;
|
this.message = message.startsWith("ERROR: [") ? message : "ERROR: [" + statusCode + "] " + message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ import java.util.List;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
import static java.util.Optional.ofNullable;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
|
||||||
public class HsOfficeMembershipController implements HsOfficeMembershipsApi {
|
public class HsOfficeMembershipController implements HsOfficeMembershipsApi {
|
||||||
@ -39,7 +41,8 @@ public class HsOfficeMembershipController implements HsOfficeMembershipsApi {
|
|||||||
context.define(currentSubject, assumedRoles);
|
context.define(currentSubject, assumedRoles);
|
||||||
|
|
||||||
final var entities = ( memberNumber != null)
|
final var entities = ( memberNumber != null)
|
||||||
? List.of(membershipRepo.findMembershipByMemberNumber(memberNumber))
|
// FIXME: RestTest for the case that findMembershipByMemberNumber returns null
|
||||||
|
? ofNullable(membershipRepo.findMembershipByMemberNumber(memberNumber)).stream().toList()
|
||||||
: membershipRepo.findMembershipsByOptionalPartnerUuid(partnerUuid);
|
: membershipRepo.findMembershipsByOptionalPartnerUuid(partnerUuid);
|
||||||
|
|
||||||
final var resources = mapper.mapList(entities, HsOfficeMembershipResource.class,
|
final var resources = mapper.mapList(entities, HsOfficeMembershipResource.class,
|
||||||
|
@ -12,6 +12,7 @@ import net.hostsharing.hsadminng.hs.office.scenarios.debitor.FinallyDeleteSepaMa
|
|||||||
import net.hostsharing.hsadminng.hs.office.scenarios.debitor.DontDeleteDefaultDebitor;
|
import net.hostsharing.hsadminng.hs.office.scenarios.debitor.DontDeleteDefaultDebitor;
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.debitor.InvalidateSepaMandateForDebitor;
|
import net.hostsharing.hsadminng.hs.office.scenarios.debitor.InvalidateSepaMandateForDebitor;
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.membership.CancelMembership;
|
import net.hostsharing.hsadminng.hs.office.scenarios.membership.CancelMembership;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.membership.CoopSharesTransactionUseCase;
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.membership.CreateMembership;
|
import net.hostsharing.hsadminng.hs.office.scenarios.membership.CreateMembership;
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.partner.AddOperationsContactToPartner;
|
import net.hostsharing.hsadminng.hs.office.scenarios.partner.AddOperationsContactToPartner;
|
||||||
import net.hostsharing.hsadminng.hs.office.scenarios.partner.CreatePartner;
|
import net.hostsharing.hsadminng.hs.office.scenarios.partner.CreatePartner;
|
||||||
@ -49,7 +50,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1010)
|
@Order(1010)
|
||||||
@Produces(explicitly = "Partner: Test AG", implicitly = {"Person: Test AG", "Contact: Test AG - Hamburg"})
|
@Produces(explicitly = "Partner: P-31010 - Test AG", implicitly = {"Person: Test AG", "Contact: Test AG - Hamburg"})
|
||||||
void shouldCreateLegalPersonAsPartner() {
|
void shouldCreateLegalPersonAsPartner() {
|
||||||
new CreatePartner(this)
|
new CreatePartner(this)
|
||||||
.given("partnerNumber", 31010)
|
.given("partnerNumber", 31010)
|
||||||
@ -71,7 +72,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1011)
|
@Order(1011)
|
||||||
@Produces(explicitly = "Partner: Michelle Matthieu", implicitly = {"Person: Michelle Matthieu", "Contact: Michelle Matthieu"})
|
@Produces(explicitly = "Partner: P-31011 - Michelle Matthieu", implicitly = {"Person: Michelle Matthieu", "Contact: Michelle Matthieu"})
|
||||||
void shouldCreateNaturalPersonAsPartner() {
|
void shouldCreateNaturalPersonAsPartner() {
|
||||||
new CreatePartner(this)
|
new CreatePartner(this)
|
||||||
.given("partnerNumber", 31011)
|
.given("partnerNumber", 31011)
|
||||||
@ -148,7 +149,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1100)
|
@Order(1100)
|
||||||
@Requires("Partner: Michelle Matthieu")
|
@Requires("Partner: P-31011 - Michelle Matthieu")
|
||||||
void shouldAmendContactData() {
|
void shouldAmendContactData() {
|
||||||
new AmendContactData(this)
|
new AmendContactData(this)
|
||||||
.given("partnerName", "Matthieu")
|
.given("partnerName", "Matthieu")
|
||||||
@ -158,7 +159,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1101)
|
@Order(1101)
|
||||||
@Requires("Partner: Michelle Matthieu")
|
@Requires("Partner: P-31011 - Michelle Matthieu")
|
||||||
void shouldAddPhoneNumberToContactData() {
|
void shouldAddPhoneNumberToContactData() {
|
||||||
new AddPhoneNumberToContactData(this)
|
new AddPhoneNumberToContactData(this)
|
||||||
.given("partnerName", "Matthieu")
|
.given("partnerName", "Matthieu")
|
||||||
@ -169,7 +170,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1102)
|
@Order(1102)
|
||||||
@Requires("Partner: Michelle Matthieu")
|
@Requires("Partner: P-31011 - Michelle Matthieu")
|
||||||
void shouldRemovePhoneNumberFromContactData() {
|
void shouldRemovePhoneNumberFromContactData() {
|
||||||
new RemovePhoneNumberFromContactData(this)
|
new RemovePhoneNumberFromContactData(this)
|
||||||
.given("partnerName", "Matthieu")
|
.given("partnerName", "Matthieu")
|
||||||
@ -179,7 +180,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1103)
|
@Order(1103)
|
||||||
@Requires("Partner: Test AG")
|
@Requires("Partner: P-31010 - Test AG")
|
||||||
void shouldReplaceContactData() {
|
void shouldReplaceContactData() {
|
||||||
new ReplaceContactData(this)
|
new ReplaceContactData(this)
|
||||||
.given("partnerName", "Test AG")
|
.given("partnerName", "Test AG")
|
||||||
@ -201,7 +202,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(1201)
|
@Order(1201)
|
||||||
@Requires("Partner: Michelle Matthieu")
|
@Requires("Partner: P-31011 - Michelle Matthieu")
|
||||||
void shouldUpdatePersonData() {
|
void shouldUpdatePersonData() {
|
||||||
new ShouldUpdatePersonData(this)
|
new ShouldUpdatePersonData(this)
|
||||||
.given("oldFamilyName", "Matthieu")
|
.given("oldFamilyName", "Matthieu")
|
||||||
@ -211,7 +212,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(2010)
|
@Order(2010)
|
||||||
@Requires("Partner: Test AG")
|
@Requires("Partner: P-31010 - Test AG")
|
||||||
@Produces("Debitor: Test AG - main debitor")
|
@Produces("Debitor: Test AG - main debitor")
|
||||||
void shouldCreateSelfDebitorForPartner() {
|
void shouldCreateSelfDebitorForPartner() {
|
||||||
new CreateSelfDebitorForPartner(this, "Debitor: Test AG - main debitor")
|
new CreateSelfDebitorForPartner(this, "Debitor: Test AG - main debitor")
|
||||||
@ -313,7 +314,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(4000)
|
@Order(4000)
|
||||||
@Requires("Partner: Test AG")
|
@Requires("Partner: P-31010 - Test AG")
|
||||||
@Produces("Membership: Test AG 00")
|
@Produces("Membership: Test AG 00")
|
||||||
void shouldCreateMembershipForPartner() {
|
void shouldCreateMembershipForPartner() {
|
||||||
new CreateMembership(this)
|
new CreateMembership(this)
|
||||||
@ -326,6 +327,51 @@ class HsOfficeScenarioTests extends ScenarioTest {
|
|||||||
.keep();
|
.keep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(4200)
|
||||||
|
@Requires("Membership: Test AG 00")
|
||||||
|
@Produces("Coop-Shares SUBSCRIPTION Transaction")
|
||||||
|
void testCoopSharesSubscriptionTransaction() {
|
||||||
|
new CoopSharesTransactionUseCase(this)
|
||||||
|
.given("memberNumber", "3101000")
|
||||||
|
.given("transactionType", "SUBSCRIPTION")
|
||||||
|
.given("reference", "sign 2024-01-15")
|
||||||
|
.given("shareCount", "100")
|
||||||
|
.given("comment", "Signing the Membership")
|
||||||
|
.given("transactionDate", "2024-01-15")
|
||||||
|
.doRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(4201)
|
||||||
|
@Requires("Coop-Shares SUBSCRIPTION Transaction")
|
||||||
|
@Produces("Coop-Shares ADJUSTMENT Transaction")
|
||||||
|
void testCoopSharesAdjustmentTransaction() {
|
||||||
|
new CoopSharesTransactionUseCase(this)
|
||||||
|
.given("memberNumber", "3102000")
|
||||||
|
.given("transactionType", "ADJUSTMENT")
|
||||||
|
.given("reference", "adjust 2024-01-16")
|
||||||
|
.given("shareCount", "-90")
|
||||||
|
.given("comment", "Cancelling 90 Shares, correcting wrong number of digits in subscription")
|
||||||
|
.given("transactionDate", "2024-01-16")
|
||||||
|
.doRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(4202)
|
||||||
|
@Requires("Coop-Shares SUBSCRIPTION Transaction")
|
||||||
|
@Produces("Coop-Shares CANCELLATION Transaction")
|
||||||
|
void testCoopSharesCancellationTransaction() {
|
||||||
|
new CoopSharesTransactionUseCase(this)
|
||||||
|
.given("memberNumber", "3102000")
|
||||||
|
.given("transactionType", "CANCELLATION")
|
||||||
|
.given("reference", "cancel 2024-01-15")
|
||||||
|
.given("shareCount", "8")
|
||||||
|
.given("comment", "Cancelling 8 Shares")
|
||||||
|
.given("transactionDate", "2024-02-15")
|
||||||
|
.doRun();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Order(4900)
|
@Order(4900)
|
||||||
@Requires("Membership: Test AG 00")
|
@Requires("Membership: Test AG 00")
|
||||||
|
@ -4,6 +4,8 @@ import net.hostsharing.hsadminng.hs.office.scenarios.UseCase.HttpResponse;
|
|||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
public class PathAssertion {
|
public class PathAssertion {
|
||||||
|
|
||||||
private final String path;
|
private final String path;
|
||||||
@ -14,10 +16,25 @@ public class PathAssertion {
|
|||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public Consumer<UseCase.HttpResponse> contains(final String resolvableValue) {
|
public Consumer<UseCase.HttpResponse> contains(final String resolvableValue) {
|
||||||
return response -> response.path(path).contains(ScenarioTest.resolve(resolvableValue));
|
return response -> {
|
||||||
|
try {
|
||||||
|
// FIXME: typed check instead of .map(Object::toString) possible?
|
||||||
|
response.path(path).map(Object::toString).contains(ScenarioTest.resolve(resolvableValue));
|
||||||
|
} catch (final AssertionError e) {
|
||||||
|
// without this, the error message is often lacking important context
|
||||||
|
fail(e.getMessage() + " in `path(\"" + path + "\").contains(\"" + resolvableValue + "\")`" );
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public Consumer<HttpResponse> doesNotExist() {
|
public Consumer<HttpResponse> doesNotExist() {
|
||||||
return response -> response.path(path).isNull(); // here, null Optional means key not found in JSON
|
return response -> {
|
||||||
|
try {
|
||||||
|
response.path(path).isNull(); // here, null Optional means key not found in JSON
|
||||||
|
} catch (final AssertionError e) {
|
||||||
|
// without this, the error message is often lacking important context
|
||||||
|
fail(e.getMessage() + " in `path(\"" + path + "\").doesNotExist()`" );
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,16 +302,17 @@ public abstract class UseCase<T extends UseCase<?>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public Optional<String> getFromBodyAsOptional(final String path) {
|
public <T> Optional<T> getFromBodyAsOptional(final String path) {
|
||||||
try {
|
try {
|
||||||
return Optional.ofNullable(JsonPath.parse(response.body()).read(ScenarioTest.resolve(path)));
|
return Optional.ofNullable(JsonPath.parse(response.body()).read(ScenarioTest.resolve(path)));
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
|
// FIXME: catch more precise exception class
|
||||||
return null; // means the property did not exist at all, not that it was there with value null
|
return null; // means the property did not exist at all, not that it was there with value null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public OptionalAssert<String> path(final String path) {
|
public <T> OptionalAssert<T> path(final String path) {
|
||||||
return assertThat(getFromBodyAsOptional(path));
|
return assertThat(getFromBodyAsOptional(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.office.scenarios.membership;
|
||||||
|
|
||||||
|
import io.restassured.http.ContentType;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.UseCase;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.scenarios.ScenarioTest;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
import static io.restassured.http.ContentType.JSON;
|
||||||
|
import static org.springframework.http.HttpStatus.OK;
|
||||||
|
|
||||||
|
public class CoopSharesTransactionUseCase extends UseCase<CoopSharesTransactionUseCase> {
|
||||||
|
|
||||||
|
public CoopSharesTransactionUseCase(final ScenarioTest testSuite) {
|
||||||
|
super(testSuite);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HttpResponse run() {
|
||||||
|
|
||||||
|
obtain("membershipUuid", () ->
|
||||||
|
httpGet("/api/hs/office/memberships?memberNumber=&{memberNumber}")
|
||||||
|
.expecting(OK).expecting(JSON).expectArrayElements(1),
|
||||||
|
response -> response.getFromBody("$[0].uuid")
|
||||||
|
);
|
||||||
|
|
||||||
|
return httpPost("/api/hs/office/coopsharestransactions", usingJsonBody("""
|
||||||
|
{
|
||||||
|
"membership.uuid": ${membershipUuid},
|
||||||
|
"transactionType": ${transactionType},
|
||||||
|
"reference": ${reference},
|
||||||
|
"shareCount": ${shareCount},
|
||||||
|
"comment": ${comment},
|
||||||
|
"valueDate": ${transactionDate}
|
||||||
|
}
|
||||||
|
"""))
|
||||||
|
.expecting(HttpStatus.CREATED).expecting(ContentType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void verify(final HttpResponse response) {
|
||||||
|
verify("Verify Coop-Shares %{transactionType}-Transaction",
|
||||||
|
() -> httpGet("/api/hs/office/coopsharestransactions/" + response.getLocationUuid())
|
||||||
|
.expecting(HttpStatus.OK).expecting(ContentType.JSON),
|
||||||
|
// path("transactionType").contains("%{transactionType}"),
|
||||||
|
// path("memberNumber").contains("%{memberNumber}"),
|
||||||
|
path("shareCount").contains("%{shareCount}"),
|
||||||
|
path("comment").contains("%{comment}"),
|
||||||
|
path("valueDate").contains("%{transactionDate}")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -16,9 +16,11 @@ public class CreateMembership extends UseCase<CreateMembership> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HttpResponse run() {
|
protected HttpResponse run() {
|
||||||
|
// FIXME: httpGet "partner.uuid": ${Partner: Test AG}
|
||||||
|
|
||||||
return httpPost("/api/hs/office/memberships", usingJsonBody("""
|
return httpPost("/api/hs/office/memberships", usingJsonBody("""
|
||||||
{
|
{
|
||||||
"partner.uuid": ${Partner: Test AG},
|
"partner.uuid": ${Partner: P-31010 - Test AG},
|
||||||
"memberNumberSuffix": ${memberNumberSuffix},
|
"memberNumberSuffix": ${memberNumberSuffix},
|
||||||
"status": "ACTIVE",
|
"status": "ACTIVE",
|
||||||
"validFrom": ${validFrom},
|
"validFrom": ${validFrom},
|
||||||
|
Loading…
Reference in New Issue
Block a user