add DomainSetup-HostingAssets for new BookingItem via created-event #111
@ -3,6 +3,7 @@ package net.hostsharing.hsadminng.hs.booking.item;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
import net.hostsharing.hsadminng.rbac.object.BaseEntity;
|
import net.hostsharing.hsadminng.rbac.object.BaseEntity;
|
||||||
|
|
||||||
@ -23,6 +24,7 @@ import java.util.UUID;
|
|||||||
@Table(schema = "hs_booking", name = "item_created_event")
|
@Table(schema = "hs_booking", name = "item_created_event")
|
||||||
@SuperBuilder(toBuilder = true)
|
@SuperBuilder(toBuilder = true)
|
||||||
@Getter
|
@Getter
|
||||||
|
@ToString
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class BookingItemCreatedEventEntity implements BaseEntity {
|
public class BookingItemCreatedEventEntity implements BaseEntity {
|
||||||
@Id
|
@Id
|
||||||
|
@ -89,10 +89,9 @@ public abstract class HsHostingAsset implements Stringifyable, BaseEntity<HsHost
|
|||||||
@JoinColumn(name = "alarmcontactuuid")
|
@JoinColumn(name = "alarmcontactuuid")
|
||||||
private HsOfficeContactRealEntity alarmContact;
|
private HsOfficeContactRealEntity alarmContact;
|
||||||
|
|
||||||
@Builder.Default
|
|
||||||
@OneToMany(cascade = CascadeType.REFRESH, orphanRemoval = true, fetch = FetchType.LAZY)
|
@OneToMany(cascade = CascadeType.REFRESH, orphanRemoval = true, fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "parentassetuuid", referencedColumnName = "uuid")
|
@JoinColumn(name = "parentassetuuid", referencedColumnName = "uuid")
|
||||||
private List<HsHostingAssetRealEntity> subHostingAssets = new ArrayList<>();
|
private List<HsHostingAssetRealEntity> subHostingAssets;
|
||||||
|
|
||||||
@Column(name = "identifier")
|
@Column(name = "identifier")
|
||||||
private String identifier; // e.g. vm1234, xyz00, example.org, xyz00_abc
|
private String identifier; // e.g. vm1234, xyz00, example.org, xyz00_abc
|
||||||
@ -125,6 +124,13 @@ public abstract class HsHostingAsset implements Stringifyable, BaseEntity<HsHost
|
|||||||
PatchableMapWrapper.of(configWrapper, (newWrapper) -> {configWrapper = newWrapper;}, config).assign(newConfig);
|
PatchableMapWrapper.of(configWrapper, (newWrapper) -> {configWrapper = newWrapper;}, config).assign(newConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<HsHostingAssetRealEntity> getSubHostingAssets() {
|
||||||
|
if (subHostingAssets == null) {
|
||||||
|
subHostingAssets = new ArrayList<>();
|
||||||
|
}
|
||||||
|
return subHostingAssets;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PatchableMapWrapper<Object> directProps() {
|
public PatchableMapWrapper<Object> directProps() {
|
||||||
return getConfig();
|
return getConfig();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.hostsharing.hsadminng.hs.hosting.asset.factories;
|
package net.hostsharing.hsadminng.hs.hosting.asset.factories;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsHostingAssetAutoInsertResource;
|
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsHostingAssetAutoInsertResource;
|
||||||
@ -10,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class HsBookingItemCreatedListener implements ApplicationListener<BookingItemCreatedAppEvent> {
|
public class HsBookingItemCreatedListener implements ApplicationListener<BookingItemCreatedAppEvent> {
|
||||||
|
|
||||||
@ -24,12 +26,22 @@ public class HsBookingItemCreatedListener implements ApplicationListener<Booking
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void onApplicationEvent(final BookingItemCreatedAppEvent event) {
|
public void onApplicationEvent(final BookingItemCreatedAppEvent bookingItemCreatedAppEvent) {
|
||||||
|
if (containsAssetJson(bookingItemCreatedAppEvent)) {
|
||||||
|
createRelatedHostingAsset(bookingItemCreatedAppEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean containsAssetJson(final BookingItemCreatedAppEvent bookingItemCreatedAppEvent) {
|
||||||
|
return bookingItemCreatedAppEvent.getEntity().getAssetJson() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createRelatedHostingAsset(final BookingItemCreatedAppEvent event) throws JsonProcessingException {
|
||||||
final var newBookingItemRealEntity = event.getEntity().getBookingItem();
|
final var newBookingItemRealEntity = event.getEntity().getBookingItem();
|
||||||
final var asset = jsonMapper.readValue(event.getEntity().getAssetJson(), HsHostingAssetAutoInsertResource.class);
|
final var asset = jsonMapper.readValue(event.getEntity().getAssetJson(), HsHostingAssetAutoInsertResource.class);
|
||||||
final var factory = switch (newBookingItemRealEntity.getType()) {
|
final var factory = switch (newBookingItemRealEntity.getType()) {
|
||||||
case PRIVATE_CLOUD, CLOUD_SERVER, MANAGED_SERVER -> null; // for now, no automatic HostingAsset possible
|
case PRIVATE_CLOUD, CLOUD_SERVER, MANAGED_SERVER -> null; // for now, no automatic HostingAsset possible
|
||||||
case MANAGED_WEBSPACE -> null; // FIXME: implement ManagedWebspace HostingAsset creation, where possible
|
case MANAGED_WEBSPACE -> new ManagedWebspaceHostingAssetFactory(emw, newBookingItemRealEntity, asset, standardMapper);
|
||||||
case DOMAIN_SETUP -> new DomainSetupHostingAssetFactory(emw, newBookingItemRealEntity, asset, standardMapper);
|
case DOMAIN_SETUP -> new DomainSetupHostingAssetFactory(emw, newBookingItemRealEntity, asset, standardMapper);
|
||||||
};
|
};
|
||||||
if (factory != null) {
|
if (factory != null) {
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.hosting.asset.factories;
|
||||||
|
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsHostingAssetAutoInsertResource;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsHostingAssetTypeResource;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRealEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAsset;
|
||||||
|
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRealEntity;
|
||||||
|
import net.hostsharing.hsadminng.mapper.StandardMapper;
|
||||||
|
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
|
||||||
|
|
||||||
|
import jakarta.validation.ValidationException;
|
||||||
|
|
||||||
|
import static java.util.Optional.ofNullable;
|
||||||
|
|
||||||
|
public class ManagedWebspaceHostingAssetFactory extends HostingAssetFactory {
|
||||||
|
|
||||||
|
public ManagedWebspaceHostingAssetFactory(
|
||||||
|
final EntityManagerWrapper emw,
|
||||||
|
final HsBookingItemRealEntity newBookingItemRealEntity,
|
||||||
|
final HsHostingAssetAutoInsertResource asset,
|
||||||
|
final StandardMapper standardMapper) {
|
||||||
|
super(emw, newBookingItemRealEntity, asset, standardMapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HsHostingAsset create() {
|
||||||
|
if (asset.getType() != HsHostingAssetTypeResource.MANAGED_WEBSPACE) {
|
||||||
|
throw new ValidationException("requires MANAGED_WEBSPACE hosting asset, but got " +
|
||||||
|
ofNullable(asset)
|
||||||
|
.map(HsHostingAssetAutoInsertResource::getType)
|
||||||
|
.map(Enum::name)
|
||||||
|
.orElse(null));
|
||||||
|
}
|
||||||
|
final var managedWebspaceHostingAsset = standardMapper.map(asset, HsHostingAssetRealEntity.class);
|
||||||
|
managedWebspaceHostingAsset.setBookingItem(fromBookingItem);
|
||||||
|
|
||||||
|
return managedWebspaceHostingAsset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void persist(final HsHostingAsset newManagedWebspaceHostingAsset) {
|
||||||
|
super.persist(newManagedWebspaceHostingAsset);
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
package net.hostsharing.hsadminng.mapper;
|
package net.hostsharing.hsadminng.mapper;
|
||||||
|
|
||||||
|
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
|
||||||
import org.modelmapper.ModelMapper;
|
import org.modelmapper.ModelMapper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import jakarta.validation.ValidationException;
|
import jakarta.validation.ValidationException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -21,10 +21,10 @@ import static net.hostsharing.hsadminng.errors.DisplayAs.DisplayName;
|
|||||||
*/
|
*/
|
||||||
abstract class Mapper extends ModelMapper {
|
abstract class Mapper extends ModelMapper {
|
||||||
|
|
||||||
@PersistenceContext
|
EntityManagerWrapper em;
|
||||||
EntityManager em;
|
|
||||||
|
|
||||||
Mapper() {
|
Mapper(@Autowired final EntityManagerWrapper em) {
|
||||||
|
this.em = em;
|
||||||
getConfiguration().setAmbiguityIgnored(true);
|
getConfiguration().setAmbiguityIgnored(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.hostsharing.hsadminng.mapper;
|
package net.hostsharing.hsadminng.mapper;
|
||||||
|
|
||||||
|
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8,7 +10,8 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
public class StandardMapper extends Mapper {
|
public class StandardMapper extends Mapper {
|
||||||
|
|
||||||
public StandardMapper() {
|
public StandardMapper(@Autowired final EntityManagerWrapper em) {
|
||||||
|
super(em);
|
||||||
getConfiguration().setAmbiguityIgnored(true);
|
getConfiguration().setAmbiguityIgnored(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package net.hostsharing.hsadminng.mapper;
|
package net.hostsharing.hsadminng.mapper;
|
||||||
|
|
||||||
|
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import static org.modelmapper.convention.MatchingStrategies.STRICT;
|
import static org.modelmapper.convention.MatchingStrategies.STRICT;
|
||||||
@ -13,7 +15,8 @@ import static org.modelmapper.convention.MatchingStrategies.STRICT;
|
|||||||
@Component
|
@Component
|
||||||
public class StrictMapper extends Mapper {
|
public class StrictMapper extends Mapper {
|
||||||
|
|
||||||
public StrictMapper() {
|
public StrictMapper(@Autowired final EntityManagerWrapper em) {
|
||||||
|
super(em);
|
||||||
getConfiguration().setMatchingStrategy(STRICT);
|
getConfiguration().setMatchingStrategy(STRICT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,69 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void projectAgent_canAddBookingItemWithHostingAsset() {
|
void projectAgent_canAddManagedWebspaceBookingItemWithHostingAsset() {
|
||||||
|
|
||||||
|
context.define("superuser-alex@hostsharing.net", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT");
|
||||||
|
final var givenProject = findDefaultProjectOfDebitorNumber(1000111);
|
||||||
|
|
||||||
|
final var location = RestAssured // @formatter:off
|
||||||
|
.given()
|
||||||
|
.header("current-subject", "superuser-alex@hostsharing.net")
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body("""
|
||||||
|
{
|
||||||
|
"projectUuid": "{projectUuid}",
|
||||||
|
"type": "MANAGED_WEBSPACE",
|
||||||
|
"caption": "some managed webspace",
|
||||||
|
"resources": {
|
||||||
|
"SSD": 25,
|
||||||
|
"Traffic": 250
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"type": "MANAGED_WEBSPACE",
|
||||||
|
"identifier": "fir00"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
.replace("{projectUuid}", givenProject.getUuid().toString())
|
||||||
|
)
|
||||||
|
.port(port)
|
||||||
|
.when()
|
||||||
|
.post("http://localhost/api/hs/booking/items")
|
||||||
|
.then().log().all().assertThat()
|
||||||
|
.statusCode(201)
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body("", lenientlyEquals("""
|
||||||
|
{
|
||||||
|
"type": "MANAGED_WEBSPACE",
|
||||||
|
"caption": "some managed webspace",
|
||||||
|
"validFrom": "{today}",
|
||||||
|
"validTo": null
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
.replace("{today}", LocalDate.now().toString())
|
||||||
|
.replace("{todayPlus1Month}", LocalDate.now().plusMonths(1).toString()))
|
||||||
|
)
|
||||||
|
.header("Location", matchesRegex("http://localhost:[1-9][0-9]*/api/hs/booking/items/[^/]*"))
|
||||||
|
.extract().header("Location"); // @formatter:on
|
||||||
|
|
||||||
|
// then, the new BookingItem can be accessed under the generated UUID
|
||||||
|
final var newBookingItem = fetchRealBookingItemFromURI(location);
|
||||||
|
assertThat(newBookingItem)
|
||||||
|
.extracting(HsBookingItem::getCaption)
|
||||||
|
.isEqualTo("some managed webspace");
|
||||||
|
|
||||||
|
// and the related HostingAssets are also got created
|
||||||
|
final var domainSetupHostingAsset = realHostingAssetRepo.findByIdentifier("fir00");
|
||||||
|
assertThat(domainSetupHostingAsset).isNotEmpty()
|
||||||
|
.map(HsHostingAsset::getBookingItem)
|
||||||
|
.contains(newBookingItem);
|
||||||
|
final var event = bookingItemCreationEventRepo.findByBookingItem(newBookingItem);
|
||||||
|
assertThat(event).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void projectAgent_canAddDomainSetupBookingItemWithHostingAsset() {
|
||||||
|
|
||||||
context.define("superuser-alex@hostsharing.net", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT");
|
context.define("superuser-alex@hostsharing.net", "hs_booking.project#D-1000111-D-1000111defaultproject:AGENT");
|
||||||
final var givenProject = findDefaultProjectOfDebitorNumber(1000111);
|
final var givenProject = findDefaultProjectOfDebitorNumber(1000111);
|
||||||
|
@ -59,7 +59,7 @@ class DomainSetupHostingAssetFactoryUnitTest {
|
|||||||
private ObjectMapper jsonMapper = new JsonObjectMapperConfiguration().customObjectMapper().build();
|
private ObjectMapper jsonMapper = new JsonObjectMapperConfiguration().customObjectMapper().build();
|
||||||
|
|
||||||
@Spy
|
@Spy
|
||||||
private StandardMapper standardMapper = new StandardMapper();
|
private StandardMapper standardMapper = new StandardMapper(emw);
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private HsBookingItemCreatedListener listener;
|
private HsBookingItemCreatedListener listener;
|
||||||
@ -107,8 +107,9 @@ class DomainSetupHostingAssetFactoryUnitTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(emwFake.stream(BookingItemCreatedEventEntity.class).findAny().isEmpty())
|
assertThat(emwFake.stream(BookingItemCreatedEventEntity.class))
|
||||||
.as("the event should not have been persisted, but got persisted").isTrue();
|
.as("the event should not have been persisted, but got persisted")
|
||||||
|
.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -0,0 +1,137 @@
|
|||||||
|
package net.hostsharing.hsadminng.hs.hosting.asset.factories;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import net.hostsharing.hsadminng.config.JsonObjectMapperConfiguration;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.debitor.HsBookingDebitorEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.item.BookingItemCreatedAppEvent;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.item.BookingItemCreatedEventEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRealEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
|
||||||
|
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRealEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRealEntity;
|
||||||
|
import net.hostsharing.hsadminng.hs.hosting.asset.validators.Dns;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContact;
|
||||||
|
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealEntity;
|
||||||
|
import net.hostsharing.hsadminng.lambda.Reducer;
|
||||||
|
import net.hostsharing.hsadminng.mapper.StandardMapper;
|
||||||
|
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
|
||||||
|
import net.hostsharing.hsadminng.persistence.EntityManagerWrapperFake;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Spy;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static net.hostsharing.hsadminng.mapper.PatchableMapWrapper.entry;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
// Tests the DomainSetupHostingAssetFactory through a HsBookingItemCreatedListener instance.
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class ManagedWebspaceHostingAssetFactoryUnitTest {
|
||||||
|
|
||||||
|
final HsBookingDebitorEntity debitor = HsBookingDebitorEntity.builder()
|
||||||
|
.debitorNumber(12345)
|
||||||
|
.defaultPrefix("xyz")
|
||||||
|
.build();
|
||||||
|
final HsBookingProjectRealEntity project = HsBookingProjectRealEntity.builder()
|
||||||
|
.debitor(debitor)
|
||||||
|
.caption("Test-Project")
|
||||||
|
.build();
|
||||||
|
final HsOfficeContact alarmContact = HsOfficeContactRealEntity.builder()
|
||||||
|
.uuid(UUID.randomUUID())
|
||||||
|
.caption("Alarm Contact xyz")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private EntityManagerWrapperFake emwFake = new EntityManagerWrapperFake();
|
||||||
|
|
||||||
|
@Spy
|
||||||
|
private EntityManagerWrapper emw = emwFake;
|
||||||
|
|
||||||
|
@Spy
|
||||||
|
private ObjectMapper jsonMapper = new JsonObjectMapperConfiguration().customObjectMapper().build();
|
||||||
|
|
||||||
|
@Spy
|
||||||
|
private StandardMapper standardMapper = new StandardMapper(emw);
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
private HsBookingItemCreatedListener listener;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void initMocks() {
|
||||||
|
emwFake.persist(alarmContact);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void doesNotPersistAnyEntityWithoutHostingAssetWithoutValidationErrors() {
|
||||||
|
// given
|
||||||
|
final var givenBookingItem = HsBookingItemRealEntity.builder()
|
||||||
|
.type(HsBookingItemType.MANAGED_WEBSPACE)
|
||||||
|
.project(project)
|
||||||
|
.caption("Test Managed-Webspace")
|
||||||
|
.resources(Map.ofEntries(
|
||||||
|
Map.entry("RAM", 25),
|
||||||
|
Map.entry("Traffic", 250)
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// when
|
||||||
|
listener.onApplicationEvent(
|
||||||
|
new BookingItemCreatedAppEvent(this, givenBookingItem, null)
|
||||||
|
);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(emwFake.stream(BookingItemCreatedEventEntity.class).findAny().isEmpty())
|
||||||
|
.as("the event should not have been persisted, but got persisted").isTrue();
|
||||||
|
assertThat(emwFake.stream(HsHostingAssetRealEntity.class).findAny().isEmpty())
|
||||||
|
.as("the hosting asset should not have been persisted, but got persisted").isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void persistsEventEntityIfDomainSetupVerificationFails() {
|
||||||
|
// given
|
||||||
|
final var givenBookingItem = createBookingItemFromResources(
|
||||||
|
entry("domainName", "example.org")
|
||||||
|
);
|
||||||
|
final var givenAssetJson = """
|
||||||
|
{
|
||||||
|
"identifier": "xyz00"
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
Dns.fakeResultForDomain("example.org", Dns.Result.fromRecords()); // without valid verificationCode
|
||||||
|
|
||||||
|
// when
|
||||||
|
listener.onApplicationEvent(
|
||||||
|
new BookingItemCreatedAppEvent(this, givenBookingItem, givenAssetJson)
|
||||||
|
);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEventStatus(givenBookingItem, givenAssetJson,
|
||||||
|
"requires MANAGED_WEBSPACE hosting asset, but got null");
|
||||||
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
private static HsBookingItemRealEntity createBookingItemFromResources(final Map.Entry<String, String>... givenResources) {
|
||||||
|
return HsBookingItemRealEntity.builder()
|
||||||
|
.type(HsBookingItemType.MANAGED_WEBSPACE)
|
||||||
|
.resources(Map.ofEntries(givenResources))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertEventStatus(
|
||||||
|
final HsBookingItemRealEntity givenBookingItem,
|
||||||
|
final String givenAssetJson,
|
||||||
|
final String expectedErrorMessage) {
|
||||||
|
emwFake.stream(BookingItemCreatedEventEntity.class)
|
||||||
|
.reduce(Reducer::toSingleElement)
|
||||||
|
.map(eventEntity -> {
|
||||||
|
assertThat(eventEntity.getBookingItem()).isSameAs(givenBookingItem);
|
||||||
|
assertThat(eventEntity.getAssetJson()).isEqualTo(givenAssetJson);
|
||||||
|
assertThat(eventEntity.getStatusMessage()).isEqualTo(expectedErrorMessage);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorEntity;
|
|||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipPatchResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipPatchResource;
|
||||||
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipStatusResource;
|
import net.hostsharing.hsadminng.hs.office.generated.api.v1.model.HsOfficeMembershipStatusResource;
|
||||||
import net.hostsharing.hsadminng.mapper.StandardMapper;
|
import net.hostsharing.hsadminng.mapper.StandardMapper;
|
||||||
|
import net.hostsharing.hsadminng.persistence.EntityManagerWrapper;
|
||||||
import net.hostsharing.hsadminng.rbac.test.PatchUnitTestBase;
|
import net.hostsharing.hsadminng.rbac.test.PatchUnitTestBase;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.TestInstance;
|
import org.junit.jupiter.api.TestInstance;
|
||||||
@ -12,7 +13,6 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@ -38,9 +38,9 @@ class HsOfficeMembershipEntityPatcherUnitTest extends PatchUnitTestBase<
|
|||||||
private static final Boolean PATCHED_MEMBERSHIP_FEE_BILLABLE = false;
|
private static final Boolean PATCHED_MEMBERSHIP_FEE_BILLABLE = false;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private EntityManager em;
|
private EntityManagerWrapper em;
|
||||||
|
|
||||||
private StandardMapper mapper = new StandardMapper();
|
private StandardMapper mapper = new StandardMapper(em);
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void initMocks() {
|
void initMocks() {
|
||||||
|
@ -21,9 +21,13 @@ public class EntityManagerWrapperFake extends EntityManagerWrapper {
|
|||||||
return find(entity.getClass(), id) != null;
|
return find(entity.getClass(), id) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T getReference(final Class<T> entityClass, final Object primaryKey) {
|
||||||
|
return find(entityClass, primaryKey);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T find(final Class<T> entityClass, final Object primaryKey) {
|
public <T> T find(final Class<T> entityClass, final Object primaryKey) {
|
||||||
final var self = this;
|
|
||||||
if (entityClasses.containsKey(entityClass)) {
|
if (entityClasses.containsKey(entityClass)) {
|
||||||
final var entities = entityClasses.get(entityClass);
|
final var entities = entityClasses.get(entityClass);
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
@ -87,5 +91,4 @@ public class EntityManagerWrapperFake extends EntityManagerWrapper {
|
|||||||
}
|
}
|
||||||
throw new IllegalArgumentException("No @Id field found in entity class: " + entity.getClass().getName());
|
throw new IllegalArgumentException("No @Id field found in entity class: " + entity.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user