diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/common/FeatureToggleProperties.java b/alfa-service/src/main/java/de/ozgcloud/alfa/common/FeatureToggleProperties.java index 1aaabfc98f32b49742f2f709b6a967f18799242d..f4f9ed3147666758a818a8e00a6ba3150b8d2263 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/common/FeatureToggleProperties.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/common/FeatureToggleProperties.java @@ -20,7 +20,7 @@ public class FeatureToggleProperties { private boolean vorgangExport = false; /** - * Enable/Disable Bescheid creation feature + * Enable/Disable Bescheid creation feature. */ private boolean createBescheid = false; } diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangProperties.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..b0413eb8dacc873c3cdeb3d98ba2ae1532b0302a --- /dev/null +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangProperties.java @@ -0,0 +1,36 @@ +package de.ozgcloud.alfa.vorgang; + +import java.util.Collections; +import java.util.List; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Configuration +@ConfigurationProperties(prefix = VorgangProperties.PREFIX) +class VorgangProperties { + + public static final String PREFIX = "ozgcloud.vorgang"; + + /** + * Konfiguriert für welche Art von Anträgen der Button zur Erstellung von Bescheiden angezeigt wird. Der Art eines Antrags wird basierend auf form + * id und form engine name bestimmt. + */ + private List<VorgangProperty> bescheid = Collections.emptyList(); + + @Builder + @Setter + @Getter + static class VorgangProperty { + + private String formId; + private String formEngineName; + + } +} diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProzessor.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProzessor.java index 4db632f692b5f54ac348753a93d1e85ba2e8ce30..763dadcc1fc104b2728193388416e3cc9d130a99 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProzessor.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProzessor.java @@ -23,12 +23,14 @@ */ package de.ozgcloud.alfa.vorgang; +import static java.util.Optional.*; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; import java.util.Objects; import java.util.Optional; import java.util.function.Predicate; +import org.apache.commons.lang3.ObjectUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; @@ -37,7 +39,9 @@ import org.springframework.hateoas.server.RepresentationModelProcessor; import org.springframework.stereotype.Component; import de.ozgcloud.alfa.attachment.AttachmentController; +import de.ozgcloud.alfa.common.FeatureToggleProperties; import de.ozgcloud.alfa.common.ModelBuilder; +import de.ozgcloud.alfa.common.command.CommandController.CommandByRelationController; import de.ozgcloud.alfa.common.user.CurrentUserService; import de.ozgcloud.alfa.common.user.UserManagerUrlProvider; import de.ozgcloud.alfa.common.user.UserRole; @@ -45,6 +49,7 @@ import de.ozgcloud.alfa.historie.HistorieController; import de.ozgcloud.alfa.kommentar.KommentarController.KommentarByVorgangController; import de.ozgcloud.alfa.postfach.PostfachMailController; import de.ozgcloud.alfa.representation.RepresentationController; +import de.ozgcloud.alfa.vorgang.VorgangProperties.VorgangProperty; import de.ozgcloud.alfa.vorgang.forwarding.ForwardingController; @Component @@ -56,11 +61,15 @@ class VorgangWithEingangProzessor implements RepresentationModelProcessor<Entity static final LinkRelation REL_POSTFACH_MAILS = LinkRelation.of("postfachMails"); static final LinkRelation REL_VORGANG_FORWARDING = LinkRelation.of("forwarding"); static final LinkRelation REL_HISTORIE = LinkRelation.of("historie"); + static final LinkRelation REL_BESCHEID = LinkRelation.of("createBescheid"); static final String REL_SEARCH_USER = "search-user-profiles"; static final String USER_PROFILE_SEARCH_DELETED_PARAM = "deleted"; static final String USER_PROFILE_SEARCH_ORGANISATIONS_EINHEIT_ID_PARAM = "organisationsEinheitId"; + private static final Predicate<EingangHeader> HAS_FORM_ID_WITH_ENGINE_NAME = + eingangHeader -> ObjectUtils.allNotNull(eingangHeader.getFormEngineName(), eingangHeader.getFormId()); + @Autowired private PostfachMailController postfachMailController; @Autowired @@ -68,6 +77,11 @@ class VorgangWithEingangProzessor implements RepresentationModelProcessor<Entity @Autowired private UserManagerUrlProvider userManagerUrlProvider; + @Autowired + private FeatureToggleProperties featureToggleProperties; + @Autowired + private VorgangProperties vorgangProperties; + private static final Predicate<VorgangWithEingang> HAS_ATTACHMENTS = vorgangWithEingang -> vorgangWithEingang.getEingang() .getNumberOfAttachments() > 0; @@ -98,6 +112,9 @@ class VorgangWithEingangProzessor implements RepresentationModelProcessor<Entity .addLink(linkTo(methodOn(HistorieController.class).getAll(vorgang.getId())).withRel(REL_HISTORIE)) .ifMatch(() -> userManagerUrlProvider.isConfiguredForSearchUserProfile() && hasOrganisationsEinheitId(vorgang)) .addLink(() -> buildSearchUserProfilesLink(vorgang)) + .ifMatch(() -> isCreateBescheidEnabled(vorgang)) + .addLink(linkTo(methodOn(CommandByRelationController.class).createCommand(vorgang.getId(), vorgang.getId(), vorgang.getVersion(), + null)).withRel(REL_BESCHEID)) .buildModel(); } @@ -123,4 +140,24 @@ class VorgangWithEingangProzessor implements RepresentationModelProcessor<Entity private String getOrganisationsEinheitId(VorgangWithEingang vorgang) { return vorgang.getEingang().getZustaendigeStelle().getOrganisationseinheitenId(); } + + boolean isCreateBescheidEnabled(VorgangWithEingang vorgang) { + return featureToggleProperties.isCreateBescheid() && hasVorgangCreateBescheidEnabled(vorgang); + } + + boolean hasVorgangCreateBescheidEnabled(VorgangWithEingang vorgang) { + return ofNullable(vorgang.getEingang()) + .map(Eingang::getHeader) + .filter(HAS_FORM_ID_WITH_ENGINE_NAME) + .map(this::isCreateBescheidEnabled) + .orElse(false); + } + + private boolean isCreateBescheidEnabled(EingangHeader eingangHeader) { + return vorgangProperties.getBescheid().stream().filter(prop -> isFormIdAndFormEngineNameMatching(eingangHeader, prop)).count() > 0; + } + + private boolean isFormIdAndFormEngineNameMatching(EingangHeader eingangHeader, VorgangProperty prop) { + return prop.getFormId().equals(eingangHeader.getFormId()) && prop.getFormEngineName().equals(eingangHeader.getFormEngineName()); + } } \ No newline at end of file diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/command/VorgangWithEingangCommandProzessor.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/command/VorgangWithEingangCommandProzessor.java index 8aac520aebada2edea43b529e228eb7a74e2aa4d..8e12c1ba7725f548a7bce67b1347786e7a7b0795 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/command/VorgangWithEingangCommandProzessor.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/command/VorgangWithEingangCommandProzessor.java @@ -33,7 +33,6 @@ import org.springframework.hateoas.LinkRelation; import org.springframework.hateoas.server.RepresentationModelProcessor; import org.springframework.stereotype.Component; -import de.ozgcloud.alfa.common.FeatureToggleProperties; import de.ozgcloud.alfa.common.ModelBuilder; import de.ozgcloud.alfa.common.command.CommandController; import de.ozgcloud.alfa.common.command.CommandController.CommandByRelationController; @@ -48,7 +47,6 @@ public class VorgangWithEingangCommandProzessor implements RepresentationModelPr static final LinkRelation REL_VORGANG_FORWARD = LinkRelation.of("forward"); static final LinkRelation REL_PENDING_COMMANDS = LinkRelation.of("pending-commands"); - static final LinkRelation REL_BESCHEID = LinkRelation.of("createBescheid"); @Autowired private CurrentUserService userService; @@ -57,9 +55,6 @@ public class VorgangWithEingangCommandProzessor implements RepresentationModelPr @Autowired private CommandController commandController; - @Autowired - private FeatureToggleProperties featureToggle; - @Override public EntityModel<VorgangWithEingang> process(EntityModel<VorgangWithEingang> model) { var vorgang = model.getContent(); @@ -73,17 +68,14 @@ public class VorgangWithEingangCommandProzessor implements RepresentationModelPr null)).withRel(REL_VORGANG_FORWARD)) .ifMatch(this::existsPendingCommands) .addLink(linkTo(methodOn(CommandController.class).getPendingCommands(true, vorgang.getId())).withRel(REL_PENDING_COMMANDS)) - .ifMatch(() -> featureToggle.isCreateBescheid()) - .addLink(linkTo(methodOn(CommandByRelationController.class).createCommand(vorgang.getId(), vorgang.getId(), vorgang.getVersion(), - null)).withRel(REL_BESCHEID)) .buildModel(); } boolean isForwardingAllowed(VorgangWithEingang vorgang) { return userService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER) && (vorgang.getStatus() == VorgangStatus.NEU - || (vorgang.getStatus() == VorgangStatus.IN_BEARBEITUNG - && hasForwardingFailed(vorgang))); + || (vorgang.getStatus() == VorgangStatus.IN_BEARBEITUNG + && hasForwardingFailed(vorgang))); } private boolean hasForwardingFailed(VorgangWithEingang vorgang) { diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/EingangHeaderTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/EingangHeaderTestFactory.java index cb7cde735df4f3d45b8615fb6dc17dfc53732ee2..12e4e885ceaaedd594d36bdbc5181e48bfe61fe6 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/EingangHeaderTestFactory.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/EingangHeaderTestFactory.java @@ -30,12 +30,13 @@ public class EingangHeaderTestFactory { public static final String CREATED_AT_STR = "2020-01-10T10:30:00Z"; public static final ZonedDateTime CREATED_AT = ZonedDateTime.parse(CREATED_AT_STR); public static final String FORM_ENGINE_NAME = "AFM"; + public static final String FORM_ID = "test-form-id"; public static EingangHeader create() { return createBuilder().build(); } public static EingangHeader.EingangHeaderBuilder createBuilder() { - return EingangHeader.builder().createdAt(CREATED_AT).formEngineName(FORM_ENGINE_NAME); + return EingangHeader.builder().createdAt(CREATED_AT).formEngineName(FORM_ENGINE_NAME).formId(FORM_ID); } } \ No newline at end of file diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangPropertyTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangPropertyTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..4886c79aceafd2b31cfc686644538322b85d50c7 --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangPropertyTestFactory.java @@ -0,0 +1,17 @@ +package de.ozgcloud.alfa.vorgang; + +import de.ozgcloud.alfa.vorgang.VorgangProperties.VorgangProperty; + +public class VorgangPropertyTestFactory { + + public static VorgangProperty create() { + return createBuilder().build(); + } + + public static VorgangProperty.VorgangPropertyBuilder createBuilder() { + return VorgangProperty.builder() + .formEngineName(EingangHeaderTestFactory.FORM_ENGINE_NAME) + .formId(EingangHeaderTestFactory.FORM_ID); + } + +} diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProzessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProzessorTest.java index 3e4f937b21114b15174a0b3381910d680279a84e..7ad30484e360a874bfe1e58853d93e975d0cbc25 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProzessorTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProzessorTest.java @@ -27,6 +27,9 @@ import static de.ozgcloud.alfa.common.UserProfileUrlProviderTestFactory.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import java.util.Collections; +import java.util.List; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -35,11 +38,13 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Spy; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; import org.springframework.hateoas.LinkRelation; import org.springframework.web.util.UriComponentsBuilder; +import de.ozgcloud.alfa.common.FeatureToggleProperties; import de.ozgcloud.alfa.common.UserProfileUrlProvider; import de.ozgcloud.alfa.common.user.CurrentUserService; import de.ozgcloud.alfa.common.user.UserManagerUrlProvider; @@ -49,6 +54,7 @@ import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus; class VorgangWithEingangProzessorTest { + @Spy @InjectMocks private VorgangWithEingangProzessor processor; @Mock @@ -58,12 +64,13 @@ class VorgangWithEingangProzessorTest { @Mock private UserManagerUrlProvider userManagerUrlProvider; - private UserProfileUrlProvider urlProvider = new UserProfileUrlProvider(); + @Mock + private FeatureToggleProperties featureToggleProperties; - @BeforeEach - void init() { - initUserProfileUrlProvider(urlProvider); - } + @Mock + private VorgangProperties vorgangProperties; + + private UserProfileUrlProvider urlProvider = new UserProfileUrlProvider(); @Nested class TestAttachmentsLink { @@ -213,6 +220,11 @@ class VorgangWithEingangProzessorTest { @Nested class TestSearchUserProfileLink { + @BeforeEach + void init() { + initUserProfileUrlProvider(urlProvider); + } + @DisplayName("on configured for search user profile") @Nested class TestIsConfigured { @@ -273,4 +285,218 @@ class VorgangWithEingangProzessorTest { return VorgangWithEingangTestFactory.createBuilder().eingang(eingang).build(); } } + + @Nested + class TestHasVorgangCreateBescheidEnabled { + + @Nested + class TestOnEmptyBescheidProperties { + + @BeforeEach + void setUp() { + when(vorgangProperties.getBescheid()).thenReturn(Collections.emptyList()); + } + + @Test + void shouldReturnFalse() { + var hasEnabled = callProcessor(VorgangWithEingangTestFactory.create()); + + assertThat(hasEnabled).isFalse(); + } + + } + + @Nested + class TestOnBescheidPropertiesSet { + + @BeforeEach + void setUp() { + when(vorgangProperties.getBescheid()).thenReturn(List.of(VorgangPropertyTestFactory.create())); + } + + @Test + void shouldReturnFalseIfFormEngineNameNotEquals() { + var vorgang = createVorgang(EingangTestFactory.createBuilder() + .header(EingangHeaderTestFactory.createBuilder() + .formEngineName("different").build()) + .build()); + + var hasEnabled = callProcessor(vorgang); + + assertThat(hasEnabled).isFalse(); + } + + @Test + void shouldReturnTrue() { + var hasEnabled = callProcessor(VorgangWithEingangTestFactory.create()); + + assertThat(hasEnabled).isTrue(); + } + } + + @Test + void shouldReturnFalseOnEmptyEingang() { + var vorgangWithEmptyEingang = createVorgang(null); + + var hasEnabled = callProcessor(vorgangWithEmptyEingang); + + assertThat(hasEnabled).isFalse(); + } + + @Test + void shouldReturnFalseOnEmptyEingangHeader() { + var vorgangWithEmptyEingangHeader = EingangTestFactory.createBuilder().header(null).build(); + + var hasEnabled = callProcessor(createVorgang(vorgangWithEmptyEingangHeader)); + + assertThat(hasEnabled).isFalse(); + } + + @Test + void shouldReturnFalseOnEmptyFormEngineName() { + var vorgangWithEmptyFormEngineName = createVorgang( + EingangTestFactory.createBuilder().header(EingangHeaderTestFactory.createBuilder().formEngineName(null).build()).build()); + + var hasEnabled = callProcessor(vorgangWithEmptyFormEngineName); + + assertThat(hasEnabled).isFalse(); + } + + @Test + void shouldReturnFalseOnEmptyFormId() { + var vorgangWithEmptyFormId = createVorgang( + EingangTestFactory.createBuilder().header(EingangHeaderTestFactory.createBuilder().formId(null).build()).build()); + + var hasEnabled = callProcessor(vorgangWithEmptyFormId); + + assertThat(hasEnabled).isFalse(); + } + + private boolean callProcessor(VorgangWithEingang vorgang) { + return processor.hasVorgangCreateBescheidEnabled(vorgang); + } + + private VorgangWithEingang createVorgang(Eingang eingang) { + return VorgangWithEingangTestFactory.createBuilder().eingang(eingang).build(); + } + + } + + @Nested + class TestIsCreateBescheidEnabled { + + @Nested + class TestFeatureToggleDisabled { + + @BeforeEach + void setUp() { + when(featureToggleProperties.isCreateBescheid()).thenReturn(false); + } + + @Test + void shouldCallFeatureToggleProperties() { + callProcessor(VorgangWithEingangTestFactory.create()); + + verify(featureToggleProperties).isCreateBescheid(); + } + + @Test + void shouldNotCallHasVorgangCreateBescheidEnabled() { + var vorgang = VorgangWithEingangTestFactory.create(); + + callProcessor(vorgang); + + verify(processor, never()).hasVorgangCreateBescheidEnabled(vorgang); + } + + @Test + void shouldReturnFalse() { + var isEnabled = callProcessor(VorgangWithEingangTestFactory.create()); + + assertThat(isEnabled).isFalse(); + } + } + + @Nested + class TestFeatureToggleEnabled { + + private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + + @BeforeEach + void setUp() { + when(featureToggleProperties.isCreateBescheid()).thenReturn(true); + } + + @Test + void shouldCallFeatureToggleProperties() { + callProcessor(vorgang); + + verify(featureToggleProperties).isCreateBescheid(); + } + + @Test + void shouldCallHasVorgangCreateBescheidEnabled() { + callProcessor(vorgang); + + verify(processor).hasVorgangCreateBescheidEnabled(vorgang); + } + + @Test + void shouldReturnTrue() { + doReturn(true).when(processor).hasVorgangCreateBescheidEnabled(vorgang); + + var isEnabled = callProcessor(vorgang); + + assertThat(isEnabled).isTrue(); + } + + @Test + void shouldReturnFalse() { + doReturn(false).when(processor).hasVorgangCreateBescheidEnabled(vorgang); + + var isEnabled = callProcessor(vorgang); + + assertThat(isEnabled).isFalse(); + } + } + + private boolean callProcessor(VorgangWithEingang vorgang) { + return processor.isCreateBescheidEnabled(vorgang); + } + + } + + @Nested + class TestCreateBescheidLink { + + private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + private final EntityModel<VorgangWithEingang> vorgangEntityModel = EntityModel.of(vorgang); + + @BeforeEach + void activateFeature() { + initUserProfileUrlProvider(urlProvider); + } + + @Test + void shouldHaveCreateBescheidLink() { + doReturn(true).when(processor).isCreateBescheidEnabled(vorgang); + + var processed = processor.process(vorgangEntityModel); + + assertThat(processed.getLink(VorgangWithEingangProzessor.REL_BESCHEID)).isPresent().get() + .extracting(Link::getHref) + .isEqualTo("/api/vorgangs/" + VorgangHeaderTestFactory.ID + "/relations/" + VorgangHeaderTestFactory.ID + "/" + + VorgangHeaderTestFactory.VERSION + "/commands"); + } + + @Test + void shouldHaveNoLinkIfDisabled() { + doReturn(false).when(processor).isCreateBescheidEnabled(vorgang); + + var processed = processor.process(vorgangEntityModel); + + assertThat(processed.getLink(VorgangWithEingangProzessor.REL_BESCHEID)).isEmpty(); + } + } + } \ No newline at end of file diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/command/VorgangWithEingangCommandProzessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/command/VorgangWithEingangCommandProzessorTest.java index 275e8d60146a9bcb1544578e79bf6ab44e80790d..a7eefd62cb52822bb2b3ce89906cbe4a059922f1 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/command/VorgangWithEingangCommandProzessorTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/command/VorgangWithEingangCommandProzessorTest.java @@ -44,7 +44,6 @@ import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; import org.springframework.hateoas.LinkRelation; -import de.ozgcloud.alfa.common.FeatureToggleProperties; import de.ozgcloud.alfa.common.UserProfileUrlProvider; import de.ozgcloud.alfa.common.command.CommandController; import de.ozgcloud.alfa.common.user.CurrentUserService; @@ -68,9 +67,6 @@ class VorgangWithEingangCommandProzessorTest { @Mock private ForwardingController forwardingController; - @Mock - private FeatureToggleProperties featureToggle; - private VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); private EntityModel<VorgangWithEingang> vorgangEntityModel = EntityModel.of(vorgang); @@ -227,33 +223,4 @@ class VorgangWithEingangCommandProzessorTest { .isEqualTo("/api/commands?pending=true&vorgangId=" + VorgangHeaderTestFactory.ID); } } - - @Nested - class TestCreateBescheidLink { - - @BeforeEach - void activateFeature() { - when(featureToggle.isCreateBescheid()).thenReturn(true); - initUserProfileUrlProvider(urlProvider); - } - - @Test - void shouldHaveCreateBescheidLink() { - var processed = processor.process(vorgangEntityModel); - - assertThat(processed.getLink(VorgangWithEingangCommandProzessor.REL_BESCHEID)).isPresent().get() - .extracting(Link::getHref) - .isEqualTo("/api/vorgangs/" + VorgangHeaderTestFactory.ID + "/relations/" + VorgangHeaderTestFactory.ID + "/" - + VorgangHeaderTestFactory.VERSION + "/commands"); - } - - @Test - void shouldHaveNoLinkIfDisabled() { - when(featureToggle.isCreateBescheid()).thenReturn(false); - - var processed = processor.process(vorgangEntityModel); - - assertThat(processed.getLink(VorgangWithEingangCommandProzessor.REL_BESCHEID)).isEmpty(); - } - } } \ No newline at end of file diff --git a/goofy-client/apps/goofy-e2e/cypress.config.ts b/goofy-client/apps/goofy-e2e/cypress.config.ts index 9a49dde39416be544323860b89f605015d8f615a..21b3aad9fb32db1ae98081e63a3facb256b3593a 100644 --- a/goofy-client/apps/goofy-e2e/cypress.config.ts +++ b/goofy-client/apps/goofy-e2e/cypress.config.ts @@ -12,4 +12,4 @@ export default defineConfig({ return cypressEvents(on, config); } }, -}); \ No newline at end of file +}); diff --git a/goofy-client/apps/goofy-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-exportieren.cy.ts b/goofy-client/apps/goofy-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-exportieren.cy.ts index f860a6d99217dd94c8d807dd4c4f33bf92c4ff84..0e5cc6e24d453b4b316ee55d17045984eb1161ed 100644 --- a/goofy-client/apps/goofy-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-exportieren.cy.ts +++ b/goofy-client/apps/goofy-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-exportieren.cy.ts @@ -29,10 +29,11 @@ import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-lis import { VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; -import { dropCollections } from '../../../support/cypress-helper'; -import { exist, notExist } from '../../../support/cypress.util'; +import { countDownloadFiles, deleteDownloadFolder, dropCollections } from '../../../support/cypress-helper'; +import { exist, haveValue, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgaenge } from '../../../support/vorgang-util'; +import * as fs from 'fs'; registerLocaleData(localeDe, 'de', localeDeExtra); @@ -83,11 +84,14 @@ describe('Vorgang exportieren', () => { exist(menuItem.getButton()); }) - it('should download', () => { + it('should have 1 file in download folder after download', () => { menuItem.getButton().click(); waitForSpinnerToDisappear(); - //TODO In Cypress 10+ implement something like https://docs.cypress.io/api/commands/task#Return-number-of-files-in-the-folder + countDownloadFiles().then((count) => { + expect(count).to.eq(1); + deleteDownloadFolder(); + }); }) it('should close menu after download', () => { diff --git a/goofy-client/apps/goofy-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.search.cy.ts b/goofy-client/apps/goofy-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.search.cy.ts index 1e7f6eb1e7c108eeb80bba03550c68078ed89a36..977ce30f2e623f7661b02f9ea3ad8ed672bfbfaf 100644 --- a/goofy-client/apps/goofy-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.search.cy.ts +++ b/goofy-client/apps/goofy-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.search.cy.ts @@ -54,15 +54,19 @@ describe('VorgangList Suche', () => { const vorgangToStay: VorgangE2E = { ...createVorgang(), name: 'VorgangToStay', eingangs: [eingang], assignedTo: getUserSabineInternalId() }; const vorgangToDisappear: VorgangE2E = { ...buildVorgang(objectIds[0], 'VorgangToDisappear'), status: VorgangStatusE2E.NEU }; + const vorgangHyphen: VorgangE2E = { ...buildVorgang(objectIds[1], 'Vorgang-mit-Bindestrich'), status: VorgangStatusE2E.NEU }; + const vorgangWOHyphen: VorgangE2E = { ...buildVorgang(objectIds[2], 'Vorgang mit Leerzeichen'), status: VorgangStatusE2E.NEU }; const vorgangStayInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangToStay.name); const vorgangDisappearInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangToDisappear.name); + const vorgangHyphenInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangHyphen.name); + const vorgangWOHyphenInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangWOHyphen.name); const userSabine: UserE2E = getUserSabine(); before(() => { - initVorgaenge([vorgangToStay, vorgangToDisappear]); - initSearchIndex([vorgangToStay, vorgangToDisappear]); + initVorgaenge([vorgangToStay, vorgangToDisappear, vorgangHyphen, vorgangWOHyphen]); + initSearchIndex([vorgangToStay, vorgangToDisappear, vorgangHyphen, vorgangWOHyphen]); initUsermanagerUsers([getUserManagerUserSabine()]); loginAsSabine(); @@ -84,6 +88,64 @@ describe('VorgangList Suche', () => { notExist(vorgangDisappearInList.getRoot()); }) + describe('Search for partial strings...', () => { + it ('should find partial string at the beginning', () => { + doSearchWith('VorgangToS'); + waitForSpinnerToDisappear(); + + exist(vorgangStayInList.getRoot()); + }) + + it ('should find partial string in the middle', () => { + doSearchWith('gangToSt'); + waitForSpinnerToDisappear(); + + exist(vorgangStayInList.getRoot()); + }) + + it ('should find partial string at the end, case insensitive', () => { + doSearchWith('toStay'); + waitForSpinnerToDisappear(); + + exist(vorgangStayInList.getRoot()); + }) + + }) + + describe ('Search with hyphen', () => { + it ('should find entry with hyphen', () => { + doSearchWith('Vorgang-mit'); + waitForSpinnerToDisappear(); + + exist(vorgangHyphenInList.getRoot()); + notExist(vorgangWOHyphenInList.getRoot()); + }) + + it ('should find entry without hyphen', () => { + doSearchWith('Vorgang mit'); + waitForSpinnerToDisappear(); + + notExist(vorgangHyphenInList.getRoot()); + exist(vorgangWOHyphenInList.getRoot()); + }) + }) + + describe ('Search using AND operator', () => { + it ('should find entry with all matches', () => { + doSearchWith('Vorgang mit Leerzeichen'); + waitForSpinnerToDisappear(); + + exist(vorgangWOHyphenInList.getRoot()); + }) + + it ('should not find entry when using additional words', () => { + doSearchWith('Vorgang mit als Leerzeichen'); + waitForSpinnerToDisappear(); + + notExist(vorgangWOHyphenInList.getRoot()); + }) + }) + describe('navigate with filtered list to vorgang detail', () => { beforeEach(() => { @@ -442,6 +504,7 @@ describe('VorgangList Suche', () => { }) + function doSearchWith(searchBy: string): void { enterWith(vorgangSearch.getInput(), searchBy); } diff --git a/goofy-client/apps/goofy-e2e/src/support/cypress-helper.ts b/goofy-client/apps/goofy-e2e/src/support/cypress-helper.ts index bde71f182f74051db676b6bf41da1e23ff93072c..62b64501d57ac8bfed9e3492f184b01eae723a5f 100644 --- a/goofy-client/apps/goofy-e2e/src/support/cypress-helper.ts +++ b/goofy-client/apps/goofy-e2e/src/support/cypress-helper.ts @@ -37,6 +37,8 @@ enum CypressTasks { INIT_VORGANG_DATA = 'initVorgangData', INIT_VORGANG_ATTACHED_ITEM_DATA = 'initVorgangAttachedItemData', INIT_USERMANAGER_DATA = 'initUsermanagerData', + COUNT_FILES = 'countFiles', + DELETE_FOLDER = 'deleteFolder' } enum MongoCollections { @@ -48,6 +50,8 @@ enum MongoCollections { USER = "User" } +const DOWNLOAD_FOLDER: string = 'cypress/downloads'; + export function login(userJsonPath: string): void { cy.fixture(userJsonPath).then(user => { cy.login(user.name, user.password); @@ -108,6 +112,14 @@ export function dropCollections() { cy.task(CypressTasks.DROP_USER_MANAGER_COLLECTIONS, [MongoCollections.USER]); } +export function countDownloadFiles(): Cypress.Chainable<number> { + return cy.task(CypressTasks.COUNT_FILES, DOWNLOAD_FOLDER); +} + +export function deleteDownloadFolder(): void { + cy.task(CypressTasks.DELETE_FOLDER, DOWNLOAD_FOLDER); +} + export function scrollToWindowBottom(): void { cy.window().scrollTo('bottom'); } @@ -143,7 +155,7 @@ export function reload(): void { } export function readFileFromDownloads(fileName: string) { - return cy.readFile(`cypress/downloads/${fileName}`); + return cy.readFile(`${DOWNLOAD_FOLDER}/${fileName}`); } export function pressTab(): void { diff --git a/goofy-client/apps/goofy-e2e/src/support/cypress-tasks.ts b/goofy-client/apps/goofy-e2e/src/support/cypress-tasks.ts index 6c6806b83b7e4cd4e2d8dbfcd48976a506dc6774..d92b9e80d3c05c57f3e62671449e84d4ecd40f5b 100644 --- a/goofy-client/apps/goofy-e2e/src/support/cypress-tasks.ts +++ b/goofy-client/apps/goofy-e2e/src/support/cypress-tasks.ts @@ -1,3 +1,4 @@ +import { rmdir } from 'fs'; import { Long, MongoClient, ObjectId } from 'mongodb'; const Binary = require('mongodb').Binary; @@ -43,7 +44,16 @@ module.exports = (on: any, config: any) => { console.log('dropUserManagerCollections: ', collections); dropUserManagerCollectionsFromDatabase(config, collections); return 0; - } + }, + countFiles(folderName:string) { + console.log('counting files in folder %s', folderName); + return countFiles(folderName); + }, + deleteFolder(folderName:string) { + console.log('deleting folder %s', folderName); + deleteFolder(folderName); + return 0; + }, }); // Workaround für Angular 13 und Cypress mit Webpack 4, @@ -295,4 +305,28 @@ function dropCollections(databaseUrl, databaseName, collections){ }); } }); +} + +function countFiles(folderName:string): Promise<number> { + return new Promise((resolve, reject) => { + fs.readdir(folderName, (err, files) => { + if (err) { + console.error(err) + return reject(err) + } + resolve(files.length) + }) + }) +} + +function deleteFolder(folderName:string): void { + new Promise((resolve, reject) => { + rmdir(folderName, { maxRetries: 10, recursive: true }, (err) => { + if (err) { + console.error(err) + return reject(err) + } + resolve(null) + }) + }) } \ No newline at end of file diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml index 696cc298187a3424fbfceed525c6f778c5af26c4..a8f02ec54ef44fa7b65ff6472f5184df667f2bef 100644 --- a/src/main/helm/templates/deployment.yaml +++ b/src/main/helm/templates/deployment.yaml @@ -88,6 +88,15 @@ spec: {{- with (.Values.env).customList }} {{ toYaml . | indent 8 }} {{- end }} + {{- if ((.Values.ozgcloud).vorgang).bescheid}} + {{- range $index, $bescheid := ((.Values.ozgcloud).vorgang).bescheid }} + - name: ozgcloud_vorgang_bescheid_{{ $index }}_formId + value: {{ $bescheid.formId }} + - name: ozgcloud_vorgang_bescheid_{{ $index }}_formEngineName + value: {{ $bescheid.formEngineName }} + {{- end }} + {{- end}} + image: "{{ .Values.image.repo }}/{{ .Values.image.name }}:{{ coalesce (.Values.image).tag "latest" }}" imagePullPolicy: Always name: goofy diff --git a/src/test/helm/deployment_defaults_env_test.yaml b/src/test/helm/deployment_defaults_env_test.yaml index 6c64212eb3409ab825aac12fc8841dd68645ca74..473341be65848b9ddef1c42b6992a27c3a357f6b 100644 --- a/src/test/helm/deployment_defaults_env_test.yaml +++ b/src/test/helm/deployment_defaults_env_test.yaml @@ -50,6 +50,7 @@ tests: content: name: spring_profiles_active value: oc, test + - it: should have service binding root set: usermanagerName: user-manager @@ -59,7 +60,8 @@ tests: content: name: SERVICE_BINDING_ROOT value: "/bindings" - - it: should have user assitance documentation url + + - it: should have user assistance documentation url templates: - templates/deployment.yaml set: @@ -69,4 +71,37 @@ tests: path: spec.template.spec.containers[0].env content: name: ozgcloud_user-assistance_documentation_url - value: http:// \ No newline at end of file + value: http:// + + - it: should have create Bescheid Konfiguration + templates: + - templates/deployment.yaml + set: + ozgcloud: + vorgang: + bescheid: + - formEngineName: AFM + formId: form_id_1 + - formEngineName: FormSolutions + formId: form_id_2 + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: ozgcloud_vorgang_bescheid_0_formId + value: form_id_1 + - contains: + path: spec.template.spec.containers[0].env + content: + name: ozgcloud_vorgang_bescheid_0_formEngineName + value: AFM + - contains: + path: spec.template.spec.containers[0].env + content: + name: ozgcloud_vorgang_bescheid_1_formId + value: form_id_2 + - contains: + path: spec.template.spec.containers[0].env + content: + name: ozgcloud_vorgang_bescheid_1_formEngineName + value: FormSolutions \ No newline at end of file