diff --git a/Jenkinsfile b/Jenkinsfile index b494923b65ddf758299ed0c7412cd278ab4840ab..caeb98bd4c0bd9b352aa6cbcf77d0bee2b00af34 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,8 +1,3 @@ -def FAILED_STAGE -def IMAGE_TAG -def VERSION -def E2E_FAILED - pipeline { agent { node { @@ -14,6 +9,10 @@ pipeline { BLUE_OCEAN_URL = "https://jenkins.ozg-sh.de/blue/organizations/jenkins/goofy/detail/${env.BRANCH_NAME}/${env.BUILD_NUMBER}/pipeline" RELEASE_REGEX = /\d+.\d+.\d+/ SNAPSHOT_REGEX = /\d+.\d+.\d+-SNAPSHOT/ + FAILED_STAGE = "" + IMAGE_TAG = "" + VERSION = "" + E2E_FAILED = "" } options { @@ -295,8 +294,8 @@ pipeline { post { failure { script { - if (env.BRANCH_NAME == 'master') { - slackSend(color: "danger", message: "Goofy: Build Failed. Stage: ${FAILED_STAGE} Build-ID: <${BLUE_OCEAN_URL}|${env.BUILD_NUMBER}>") + if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME == 'release') { + sendFailureMessage() } } } @@ -555,4 +554,27 @@ Void waitForKeycloakClientCreation(realm) { while(sh(script: shScript, returnStatus: true)) { sh 'sleep 5' } +} + +Void sendFailureMessage() { + def room = '' + def data = """{"msgtype":"m.text", \ + "body":"Goofy: Build Failed. Stage: ${FAILED_STAGE} Build-ID: ${env.BUILD_NUMBER} Link: ${BLUE_OCEAN_URL}", \ + "format": "org.matrix.custom.html", \ + "formatted_body":"Goofy: Build Failed. Stage: ${FAILED_STAGE} Build-ID: <a href='${BLUE_OCEAN_URL}'>${env.BUILD_NUMBER}</a>"}""" + + if (env.BRANCH_NAME == 'master') { + room = "!iQPAvQIiRwRpNOszjw:matrix.ozg-sh.de" + } + else if (env.BRANCH_NAME == 'release') { + room = "!oWZpUGTFsxkJIYNfYg:matrix.ozg-sh.de" + } + + sh "curl -XPOST -H 'authorization: Bearer ${getElementAccessToken()}' -d '${data}' https://matrix.ozg-sh.de/_matrix/client/v3/rooms/$room/send/m.room.message" +} + +String getElementAccessToken() { + withCredentials([string(credentialsId: 'element-login-json', variable: 'LOGIN_JSON')]) { + return readJSON ( text: sh (script: '''curl -XPOST -d \"$LOGIN_JSON\" https://matrix.ozg-sh.de/_matrix/client/v3/login''', returnStdout: true)).access_token + } } \ No newline at end of file diff --git a/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/navigation/navigation.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/navigation/navigation.e2e-spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..c0fcd0535bd473b973157f8a0d997b311fcc572c --- /dev/null +++ b/goofy-client/apps/goofy-e2e/src/integration/einheitlicher-ansprechpartner/navigation/navigation.e2e-spec.ts @@ -0,0 +1,38 @@ +import { NavigationE2EComponent } from 'apps/goofy-e2e/src/components/navigation/navigation.e2e.component'; +import { VorgangListE2EComponent } from 'apps/goofy-e2e/src/components/vorgang/vorgang-list.e2e.component'; +import { MainPage, waitForSpinnerToDisappear } from 'apps/goofy-e2e/src/page-objects/main.po'; +import { dropCollections } from 'apps/goofy-e2e/src/support/cypress-helper'; +import { exist, notExist } from 'apps/goofy-e2e/src/support/cypress.util'; +import { loginAsEmil } from 'apps/goofy-e2e/src/support/user-util'; + +describe('Navigation', () => { + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const navigation: NavigationE2EComponent = mainPage.getNavigation(); + + before(() => { + loginAsEmil(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }) + + after(() => { + dropCollections(); + }) + + describe('navigation item myVorgaenge', () => { + + it('should not exists', () => { + notExist(navigation.getMyVorgaengeItem()); + }) + }) + + describe('navigation item allVorgaenge', () => { + + it('should exists', () => { + exist(navigation.getAllVorgaengeItem()); + }) + }) +}) \ No newline at end of file diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/navigation/navigation.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/navigation/navigation.e2e-spec.ts index 8f5b997336681229f082ca75e91d259aac2ff6f5..ea0f9b68a56773b16844691ab359166c59cd0ab3 100644 --- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/navigation/navigation.e2e-spec.ts +++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/navigation/navigation.e2e-spec.ts @@ -36,6 +36,20 @@ describe('Navigation', () => { dropCollections(); }) + describe('navigation item myVorgaenge', () => { + + it('should exists', () => { + exist(navigation.getMyVorgaengeItem()); + }) + }) + + describe('navigation item allVorgaenge', () => { + + it('should exists', () => { + exist(navigation.getAllVorgaengeItem()); + }) + }) + describe('click on my vorgaenge', () => { it('should hide not to user assigned vorgaenge', () => { diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts index 04c011a405433385a98d2539c52698ddf192bcd7..0db5f5c30dcf4202691e4baf5576b27a26020e78 100644 --- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts +++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts @@ -98,7 +98,7 @@ describe('Vorgang-detailansicht filtered by organisationseinheit', () => { }) }) - describe('on user zonk', () => { + describe.skip('on user zonk', () => { const authorizedUrl: string = vorgangUrlVisibleToKOrdner; const forbiddenUrl: string = vorgangUrlVisibleToKFinder; diff --git a/goofy-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts b/goofy-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts index e348fc3066c57679a84f5def9ef4bfc30db95e96..da289d23b08b39fc784ab6f47c0b1f9752a2b35e 100644 --- a/goofy-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts +++ b/goofy-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts @@ -8,7 +8,8 @@ import { Observable } from "rxjs"; export class KommentarFormService extends AbstractFormService { static readonly TEXT = 'text'; - static readonly FIELD_PATH_PREFIX = 'command.body'; + + static readonly FIELD_PATH_PREFIX = 'kommentar'; constructor(formBuilder: FormBuilder, private kommentarService: KommentarService) { super(formBuilder); diff --git a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts index 57ab3de2f31a77602503da3fcf7d9b7412890279..5ab808bee6238f93a364ee6ed49803d0cc9b1de3 100644 --- a/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts +++ b/goofy-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts @@ -12,7 +12,7 @@ export class WiedervorlageFormService extends AbstractFormService { static readonly FIELD_FRIST = 'frist'; static readonly FIELD_ATTACHMENTS = 'attachments'; - static readonly FIELD_PATH_PREFIX = 'command.body'; + static readonly FIELD_PATH_PREFIX = 'wiedervorlage'; constructor( formBuilder: FormBuilder, diff --git a/goofy-client/pom.xml b/goofy-client/pom.xml index d15e3eeb0414f326b8c9706fae66c062a8599b56..faad162ec16c487a9fbecefeff21c89a4683b9fa 100644 --- a/goofy-client/pom.xml +++ b/goofy-client/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>de.itvsh.ozg</groupId> <artifactId>goofy</artifactId> - <version>0.26.0-SNAPSHOT</version> + <version>0.27.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> diff --git a/goofy-server/pom.xml b/goofy-server/pom.xml index df7eac60260003e0a8035c7a0d4d09cf33e850cd..00c500a456dd955aad006695ea5f4d62b6e2f2b5 100644 --- a/goofy-server/pom.xml +++ b/goofy-server/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>de.itvsh.ozg</groupId> <artifactId>goofy</artifactId> - <version>0.26.0-SNAPSHOT</version> + <version>0.27.0-SNAPSHOT</version> </parent> <artifactId>goofy-server</artifactId> diff --git a/goofy-server/src/main/java/de/itvsh/goofy/RootController.java b/goofy-server/src/main/java/de/itvsh/goofy/RootController.java index f394e86ca7234a76fca635adbb013a6558f16aed..97b2c40373c78b5024cc55eb7c6b5d917240e935 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/RootController.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/RootController.java @@ -45,16 +45,20 @@ public class RootController { linkTo(VorgangController.class).withRel(REL_VORGAENGE), linkTo(methodOn(UserProfileController.class).findUsers(null)).withRel(REL_SEARCH_USER), linkTo(DownloadTokenController.class).withRel(REL_DOWNLOAD_TOKEN), - buildVorgangListByPageLink(REL_SEARCH, Optional.empty()), + buildVorgangListByPageLink(REL_SEARCH, Optional.empty())) + .ifMatch(this::hasVerwaltungRole).addLinks( buildVorgangListByPageLink(REL_MY_VORGAENGE, Optional.of(currentUserService.getUserId())), buildVorgangListByPageLink(REL_SEARCH_MY_VORGAENGE, Optional.of(currentUserService.getUserId()))) .buildModel(); } - private boolean hasRole() { + boolean hasRole() { + return hasVerwaltungRole() || currentUserService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER); + } + + boolean hasVerwaltungRole() { return currentUserService.hasRole(UserRole.VERWALTUNG_USER) - || currentUserService.hasRole(UserRole.VERWALTUNG_POSTSTELLE) - || currentUserService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER); + || currentUserService.hasRole(UserRole.VERWALTUNG_POSTSTELLE); } private Link buildVorgangListByPageLink(String linkRel, Optional<UserId> assignedTo) { diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItem.java b/goofy-server/src/main/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItem.java new file mode 100644 index 0000000000000000000000000000000000000000..68f99ec311c1e56478cd9bed891c5f4dd2b55955 --- /dev/null +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItem.java @@ -0,0 +1,21 @@ +package de.itvsh.goofy.common.attacheditem; + +import java.util.Map; + +import de.itvsh.goofy.common.command.CommandBody; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class VorgangAttachedItem implements CommandBody { + + private String id; + private long version; + + private String client; + private String vorgangId; + private String itemName; + + private Map<String, Object> item; +} \ No newline at end of file diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemService.java b/goofy-server/src/main/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemService.java new file mode 100644 index 0000000000000000000000000000000000000000..de236d619f152683cf74c467abb009421d8f143d --- /dev/null +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemService.java @@ -0,0 +1,76 @@ +package de.itvsh.goofy.common.attacheditem; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import de.itvsh.goofy.common.command.Command; +import de.itvsh.goofy.common.command.CommandBody; +import de.itvsh.goofy.common.command.CommandBodyMapper; +import de.itvsh.goofy.common.command.CommandOrder; +import de.itvsh.goofy.common.command.CommandService; +import de.itvsh.goofy.common.command.CreateCommand; +import de.itvsh.goofy.kommentar.Kommentar; +import de.itvsh.goofy.wiedervorlage.Wiedervorlage; + +@Service +public class VorgangAttachedItemService { + + @Autowired + private CommandBodyMapper commandBodyMapper; + @Autowired + private CommandService commandService; + + static final String WIEDERVORLAGE_ITEM_NAME = "Wiedervorlage"; + static final String KOMMENTAR_ITEM_NAME = "Kommentar"; + + public Command createNewWiedervorlage(Wiedervorlage wiedervorlage, String vorgangId) { + var vorgangAttachedItem = buildVorgangAttachedItem(wiedervorlage, vorgangId, WIEDERVORLAGE_ITEM_NAME); + + return commandService.createCommand(buildCreateCommand(vorgangId, vorgangAttachedItem)); + } + + public Command createNewKommentar(Kommentar kommentar, String vorgangId) { + var vorgangAttachedItem = buildVorgangAttachedItem(kommentar, vorgangId, KOMMENTAR_ITEM_NAME); + + return commandService.createCommand(buildCreateCommand(vorgangId, vorgangAttachedItem)); + } + + CreateCommand buildCreateCommand(String vorgangId, CommandBody body) { + return CreateCommand.builder() + .vorgangId(vorgangId) + .relationId(vorgangId) + .order(CommandOrder.CREATE_ATTACHED_ITEM) + .body(body) + .build(); + } + + public Command editKommentar(Kommentar kommentar, String kommentarId, long kommentarVersion) { + var vorgangAttachedItem = buildVorgangAttachedItem(kommentar, kommentar.getVorgangId(), KOMMENTAR_ITEM_NAME); + + return commandService.createCommand(buildUpdateCommand(kommentar.getVorgangId(), kommentarId, vorgangAttachedItem), kommentarVersion); + } + + public Command editWiedervorlage(Wiedervorlage wiedervorlage, String wiedervorlageId, long wiedervorlageVersion) { + var vorgangAttachedItem = buildVorgangAttachedItem(wiedervorlage, wiedervorlage.getVorgangId(), WIEDERVORLAGE_ITEM_NAME); + + return commandService.createCommand(buildUpdateCommand(wiedervorlage.getVorgangId(), wiedervorlageId, vorgangAttachedItem), + wiedervorlageVersion); + } + + VorgangAttachedItem buildVorgangAttachedItem(CommandBody body, String vorgangId, String itemName) { + return VorgangAttachedItem.builder() + .vorgangId(vorgangId) + .itemName(itemName) + .item(commandBodyMapper.fromObjectToMap(body)) + .build(); + } + + CreateCommand buildUpdateCommand(String vorgangId, String kommentarId, CommandBody body) { + return CreateCommand.builder() + .vorgangId(vorgangId) + .relationId(kommentarId) + .order(CommandOrder.UPDATE_ATTACHED_ITEM) + .body(body) + .build(); + } +} \ No newline at end of file diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandBodyMapper.java b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandBodyMapper.java index 703a17d43d415bfcd5d39da8b002796399825f44..094c88df95e860744c2764df2e87820823ca155d 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandBodyMapper.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandBodyMapper.java @@ -1,10 +1,12 @@ package de.itvsh.goofy.common.command; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.Optional; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -18,27 +20,13 @@ import de.itvsh.ozg.pluto.grpc.command.GrpcCommandBodyField; @Mapper public interface CommandBodyMapper { - final Predicate<Entry<Object, Object>> HAS_NOT_NULL_VALUE = entry -> Objects.nonNull(entry.getValue()); final Predicate<Entry<Object, Object>> IS_NOT_CLASS_VALUE = entry -> !StringUtils.equals("class", entry.getKey().toString()); + final Predicate<Entry<Object, Object>> IS_NOT_VERSION_VALUE = entry -> !StringUtils.equals("version", entry.getKey().toString()); static final String VORGANG_ID_PROPERTY = "vorgangId"; static final String ITEM_NAME_PROPERTY = "itemName"; static final String ITEM_PROPERTY = "item"; - default Map<String, Object> fromObjectToMap(Object object) { - return new BeanMap(object).entrySet().stream() - .filter(HAS_NOT_NULL_VALUE) - .filter(IS_NOT_CLASS_VALUE) - .collect(Collectors.toMap(entry -> entry.getKey().toString(), this::checkEnumValue)); - } - - private Object checkEnumValue(Entry<Object, Object> entry) { - if (entry.getValue() instanceof Enum<?> enumValue) { - return enumValue.name(); - } - return entry.getValue(); - } - default GrpcCommandBody mapToBody(Map<String, String> bodyMap) { if (Objects.isNull(bodyMap)) { return GrpcCommandBody.getDefaultInstance(); @@ -68,12 +56,24 @@ public interface CommandBodyMapper { } return bodyMap.entrySet().stream() - .filter(HAS_NOT_NULL_VALUE) .filter(IS_NOT_CLASS_VALUE) - .map(entry -> GrpcCommandBodyField.newBuilder().setName(entry.getKey().toString()).setValue(entry.getValue().toString()).build()) + .map(this::buildBodyField) .collect(Collectors.toList()); } + default GrpcCommandBodyField buildBodyField(Entry<Object, Object> entry) { + var bodyFieldMapper = GrpcCommandBodyField.newBuilder().setName(entry.getKey().toString()); + + if (Objects.nonNull(entry.getValue())) { + bodyFieldMapper.setValue(getNullableStringValue(entry.getValue())); + } + return bodyFieldMapper.build(); + } + + default String getNullableStringValue(Object entryValue) { + return Optional.ofNullable(entryValue).map(Object::toString).orElse(null); + } + default Map<String, String> map(GrpcCommandBody body) { return body.getFieldList().stream().collect(Collectors.toMap(GrpcCommandBodyField::getName, GrpcCommandBodyField::getValue)); } @@ -82,6 +82,20 @@ public interface CommandBodyMapper { return Map.of( VORGANG_ID_PROPERTY, command.getVorgangId(), ITEM_NAME_PROPERTY, itemName, - ITEM_PROPERTY, new BeanMap(command.getBody())); + ITEM_PROPERTY, fromObjectToMap(command.getBody())); + } + + default Map<String, Object> fromObjectToMap(Object object) { + return new BeanMap(object).entrySet().stream() + .filter(IS_NOT_CLASS_VALUE) + .filter(IS_NOT_VERSION_VALUE) + .collect(HashMap::new, (map, entry) -> map.put(entry.getKey().toString(), checkEnumValue(entry.getValue())), Map::putAll); + } + + private Object checkEnumValue(Object entryValue) { + if (entryValue instanceof Enum<?> enumValue) { + return enumValue.name(); + } + return entryValue; } } \ No newline at end of file diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandController.java b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandController.java index d6c45c11a6021bddc0cb4cbb7ac6b89189c6200f..ad32f9c4794525c36f50f6d5ab79d82d3de45e99 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandController.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandController.java @@ -78,13 +78,16 @@ public class CommandController { @PostMapping public ResponseEntity<Void> createCommand(@PathVariable String vorgangId, @PathVariable String relationId, @PathVariable long relationVersion, @RequestBody CreateCommand command) { - command = command.toBuilder().vorgangId(vorgangId).relationId(relationId).build(); + command = command.toBuilder() + .vorgangId(vorgangId) + .relationId(relationId) + .build(); if (isSendPostfachMailOrder(command)) { command = prepareCommandForPostfachNachricht(command, vorgangId); } - var created = createCommand(command, relationVersion); + var created = service.createCommand(command, relationVersion); return ResponseEntity.created(linkTo(CommandController.class).slash(created.getId()).toUri()).build(); } @@ -115,16 +118,12 @@ public class CommandController { return vorgangController.getVorgang(vorgangId); } - public Command createCommand(CreateCommand command, long version) { - return service.createCommand(command, version); - } - - public Command createCommand(CreateCommand command, String itemName) { - return service.createCommand(command, itemName); + public Command createCommandWithoutRelation(CreateCommand command) { + return service.createCommandWithoutRelation(command); } - public Command createCommandWithoutValidation(CreateCommand command, String itemName) { - return service.createCommandWithoutValidation(command, itemName); + public Command createCommandWithoutValidation(CreateCommand command, String itemName, long relationVersion) { + return service.createCommandWithoutValidation(command, itemName, relationVersion); } } } \ No newline at end of file diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandRemoteService.java b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandRemoteService.java index bc35a6d14771b3822737b95cf2efa5d5b2677cf1..2e23b23ba4ac35cea37447aa882ce3d52b3f7f1c 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandRemoteService.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandRemoteService.java @@ -32,8 +32,8 @@ public class CommandRemoteService { @Autowired private GrpcObjectMapper objectMapper; - public Command createCommand(CreateCommand command, long version) { - return doCreateCommand(buildCreateCommandRequest(command, version)); + public Command createCommand(CreateCommand command) { + return doCreateCommand(buildCreateCommandRequest(command)); } public Command createCommand(CreateCommand command, String itemName) { @@ -46,30 +46,30 @@ public class CommandRemoteService { return mapper.toCommand(response.getCommand()); } - GrpcCreateCommandRequest buildCreateCommandRequest(CreateCommand command, long version) { + GrpcCreateCommandRequest buildCreateCommandRequest(CreateCommand command) { + return buildCreateRequestBuilder(command) + .setBodyObj(objectMapper.fromMap(bodyMapper.fromObjectToMap(command.getBody()))) + .build(); + } + + GrpcCreateCommandRequest buildCreateAttachedItemCommandRequest(CreateCommand command, String itemName) { + return buildCreateRequestBuilder(command) + .setBodyObj(objectMapper.fromMap(bodyMapper.mapToBodyMap(command, itemName))) + .build(); + } + + GrpcCreateCommandRequest.Builder buildCreateRequestBuilder(CreateCommand command) { var requestBuilder = GrpcCreateCommandRequest.newBuilder() .setCallContext(contextService.createCallContext()) .setVorgangId(command.getVorgangId()) .setRelationId(command.getRelationId()) - .setRelationVersion(version) - .addAllBody(bodyMapper.mapToBodyFields(command.getBody())) - .setBodyObj(objectMapper.fromMap(bodyMapper.fromObjectToMap(command.getBody()))) - .setOrderString(command.getOrder().name()); + .setRelationVersion(command.getRelationVersion()) + .setOrderString(command.getOrder().name()) + .addAllBody(bodyMapper.mapToBodyFields(command.getBody())); Optional.ofNullable(command.getRedirectRequest()).map(mapper::toGrpcRedirectRequest).ifPresent(requestBuilder::setRedirectRequest); - return requestBuilder.build(); - } - - GrpcCreateCommandRequest buildCreateAttachedItemCommandRequest(CreateCommand command, String itemName) { - return GrpcCreateCommandRequest.newBuilder() - .setCallContext(contextService.createCallContext()) - .setRelationId(command.getVorgangId()) - .setRelationVersion(-1) - .setVorgangId(command.getVorgangId()) - .setOrder(GrpcOrder.valueOf(command.getOrder().name())) - .setBodyObj(objectMapper.fromMap(bodyMapper.mapToBodyMap(command, itemName))) - .build(); + return requestBuilder; } public Command revokeCommand(String commandId) { diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandService.java b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandService.java index 5d27b7f6d9e16955e61eefbe3ffbfce0272e7740..a70772101744018f0ec92d7669ae7b1334fe2ffd 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandService.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CommandService.java @@ -11,22 +11,36 @@ import org.springframework.validation.annotation.Validated; import lombok.NonNull; -@Service @Validated -class CommandService { +@Service +public class CommandService { + + static final long NO_RELATION_VERSION = -1; @Autowired private CommandRemoteService remoteService; - public Command createCommand(@Valid CreateCommand command, long version) { - return remoteService.createCommand(command, version); + public Command createCommand(CreateCommand command) { + command = command.toBuilder().relationVersion(NO_RELATION_VERSION).build(); + + return remoteService.createCommand(command); } - public Command createCommand(@Valid CreateCommand command, String itemName) { - return remoteService.createCommand(command, itemName); + public Command createCommand(@Valid CreateCommand command, long relationVersion) { + command = command.toBuilder().relationVersion(relationVersion).build(); + + return remoteService.createCommand(command); } - public Command createCommandWithoutValidation(CreateCommand command, String itemName) { + public Command createCommandWithoutRelation(CreateCommand command) { + command = command.toBuilder().relationVersion(NO_RELATION_VERSION).build(); + + return remoteService.createCommand(command); + } + + public Command createCommandWithoutValidation(CreateCommand command, String itemName, long relationVersion) { + command = command.toBuilder().relationVersion(relationVersion).build(); + return remoteService.createCommand(command, itemName); } diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CreateCommand.java b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CreateCommand.java index ce4bec48e195335fabb156ac73d405dfa437d6ec..c63125db8f2dc0cd58fb283d688e550ce8cf99ef 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/common/command/CreateCommand.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/command/CreateCommand.java @@ -28,6 +28,7 @@ public class CreateCommand { private String vorgangId; private String relationId; + private long relationVersion; private CommandOrder order; @Valid diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/Kommentar.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/Kommentar.java index 89eb1615fb6c468455689c949429c01e664907e6..9937eb74be669db72fbade1341a720cdeab908e7 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/Kommentar.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/Kommentar.java @@ -30,6 +30,8 @@ public class Kommentar implements CommandBody { @JsonIgnore private String id; + @JsonIgnore + private long version; @JsonIgnore private String vorgangId; diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarCommandController.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarCommandController.java index b9040667714e68b01695b0ee0290d02d29e6b3cf..394259041336c6de405cf1a332948404d25922ad 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarCommandController.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarCommandController.java @@ -2,8 +2,6 @@ package de.itvsh.goofy.kommentar; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; -import java.time.ZonedDateTime; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; @@ -14,48 +12,28 @@ import org.springframework.web.bind.annotation.RestController; import de.itvsh.goofy.common.command.Command; import de.itvsh.goofy.common.command.CommandController; -import de.itvsh.goofy.common.command.CommandController.CommandByRelationController; -import de.itvsh.goofy.common.command.CommandOrder; -import de.itvsh.goofy.common.command.CreateCommand; -import de.itvsh.goofy.common.user.CurrentUserService; @RestController @RequestMapping(KommentarCommandController.KOMMENTAR_COMMANDS) public class KommentarCommandController { - static final String KOMMENTAR_COMMANDS = "/api/kommentars/{kommentarId}/commands"; - static final String NOT_SET = "-1"; + static final String KOMMENTAR_COMMANDS = "/api/kommentars/{kommentarId}/{kommentarVersion}/commands"; @Autowired private KommentarService service; - @Autowired - private CommandByRelationController commandByRelationController; - @PostMapping - public ResponseEntity<Void> createCommand(@RequestBody KommentarCommand kommentarCommand, @PathVariable String kommentarId) { - var command = commandByRelationController.createCommand(buildCommand(service.getById(kommentarId), kommentarCommand), - KommentarRemoteService.ITEM_NAME); - return buildResponseLink(command); + public ResponseEntity<Void> editKommentar(@RequestBody KommentarCommand kommentarCommand, @PathVariable String kommentarId, + @PathVariable long kommentarVersion) { + var createdCommand = service.editKommentar(kommentarCommand.getKommentar(), kommentarId, kommentarVersion); + + return buildResponseLink(createdCommand); } private ResponseEntity<Void> buildResponseLink(Command createdKommentarCommand) { return ResponseEntity.created(linkTo(CommandController.class).slash(createdKommentarCommand.getId()).toUri()).build(); } - CreateCommand buildCommand(Kommentar kommentar, KommentarCommand command) { - var commandBuilder = CreateCommand.builder() - .order(CommandOrder.UPDATE_ATTACHED_ITEM) - .relationId(NOT_SET) - .vorgangId(kommentar.getVorgangId()); - - return commandBuilder.body(updateKommandByCommand(kommentar, command)).build(); - } - - private Kommentar updateKommandByCommand(Kommentar kommentar, KommentarCommand command) { - return kommentar.toBuilder().text(command.getKommentar().getText()).build(); - } - @RestController @RequestMapping(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG) public static class KommentarCommandByVorgangController { @@ -63,33 +41,13 @@ public class KommentarCommandController { static final String KOMMENTAR_COMMANDS_BY_VORGANG = "/api/vorgangs/{vorgangId}/kommentarCommands"; @Autowired - private CommandByRelationController commandByRelationController; - - @Autowired - private CurrentUserService userService; + private KommentarService service; - @PostMapping() - public ResponseEntity<Void> createCommand(@RequestBody KommentarCommand command, @PathVariable String vorgangId) { - var createdCommand = commandByRelationController.createCommand(buildCommand(vorgangId, command), KommentarRemoteService.ITEM_NAME); + @PostMapping + public ResponseEntity<Void> createKommentar(@RequestBody KommentarCommand command, @PathVariable String vorgangId) { + var createdCommand = service.createKommentar(command.getKommentar(), vorgangId); return ResponseEntity.created(linkTo(CommandController.class).slash(createdCommand.getId()).toUri()).build(); } - - CreateCommand buildCommand(String vorgangId, KommentarCommand command) { - return CreateCommand.builder() - .vorgangId(vorgangId) - .order(CommandOrder.CREATE_ATTACHED_ITEM) - .relationId(NOT_SET) - .body(buildBody(command.getKommentar())) - .build(); - } - - Kommentar buildBody(Kommentar kommentar) { - return kommentar.toBuilder() - .createdAt(ZonedDateTime.now().withNano(0)) - .createdBy(userService.getUserId().toString()) - .build(); - } - } -} +} \ No newline at end of file diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarMapper.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarMapper.java index c36561d38afa4080e10c69b1782aa37e57095400..395c02868b9a1a1cf6c3f9656c6a19b50366af43 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarMapper.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarMapper.java @@ -9,25 +9,36 @@ import org.mapstruct.MappingConstants; import org.mapstruct.NullValueCheckStrategy; import org.mapstruct.ReportingPolicy; import org.mapstruct.ValueMapping; +import org.springframework.beans.factory.annotation.Autowired; +import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper; import de.itvsh.ozg.pluto.grpc.command.GrpcCommand; +import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItem; @Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) -public interface KommentarMapper { +abstract class KommentarMapper { static final String ID = "id"; static final String TEXT = "text"; static final String CREATED_BY = "createdBy"; static final String CREATED_AT = "createdAt"; + @Autowired + private GrpcObjectMapper grpcObjectMapper; + @Mapping(target = "kommentar", ignore = true) @ValueMapping(source = "UNRECOGNIZED", target = MappingConstants.NULL) @ValueMapping(source = "UNDEFINED", target = MappingConstants.NULL) - KommentarCommand toKommentarCommand(GrpcCommand command); + abstract KommentarCommand toKommentarCommand(GrpcCommand command); + + public Kommentar fromItem(GrpcVorgangAttachedItem vorgangAttachedItem) { + return fromItemMap(grpcObjectMapper.mapFromGrpc(vorgangAttachedItem.getItem()), vorgangAttachedItem.getVersion()); + } - default Kommentar fromItemMap(Map<String, Object> map) { + Kommentar fromItemMap(Map<String, Object> map, long version) { return Kommentar.builder() .id((String) map.get(ID)) + .version(version) .createdAt(ZonedDateTime.parse((String) map.get(CREATED_AT))) .createdBy((String) map.get(CREATED_BY)) .text((String) map.get(TEXT)) diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarModelAssembler.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarModelAssembler.java index fda3d28ec5f38a9055c7ab517cf284cc5d52bfe3..f1fda7f7fe86d4ef4e4e257c96e08b69a7dc5759 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarModelAssembler.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarModelAssembler.java @@ -22,7 +22,7 @@ class KommentarModelAssembler implements RepresentationModelAssembler<Kommentar, @Override public EntityModel<Kommentar> toModel(Kommentar kommentar) { var selfLink = linkTo(KommentarController.class).slash(kommentar.getId()); - var commandLink = linkTo(methodOn(KommentarCommandController.class).createCommand(null, kommentar.getId())); + var commandLink = linkTo(methodOn(KommentarCommandController.class).editKommentar(null, kommentar.getId(), kommentar.getVersion())); return ModelBuilder.fromEntity(kommentar).addLink(selfLink.withSelfRel()) .addLink(commandLink.withRel(REL_EDIT)) @@ -32,6 +32,7 @@ class KommentarModelAssembler implements RepresentationModelAssembler<Kommentar, public CollectionModel<EntityModel<Kommentar>> toCollectionModel(Stream<Kommentar> entities, String vorgangId) { return CollectionModel.of(entities.map(this::toModel).collect(Collectors.toList()), linkTo(KommentarController.class).withSelfRel(), - linkTo(methodOn(KommentarCommandByVorgangController.class).createCommand(null, vorgangId)).withRel(REL_CREATE)); + linkTo(methodOn(KommentarCommandByVorgangController.class).createKommentar(null, vorgangId)) + .withRel(REL_CREATE)); } } \ No newline at end of file diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarRemoteService.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarRemoteService.java index 2e2d6c6cb0ce3dab68978db6e72f06bafcb51ef7..c6873ea395c1988420c1bef8057ae5f95b125276 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarRemoteService.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarRemoteService.java @@ -6,31 +6,25 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import de.itvsh.goofy.GoofyServerApplication; -import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper; import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest; -import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemResponse; import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemRequest; import de.itvsh.ozg.pluto.vorgangAttachedItem.VorgangAttachedItemServiceGrpc.VorgangAttachedItemServiceBlockingStub; import net.devh.boot.grpc.client.inject.GrpcClient; @Service class KommentarRemoteService { + static final String ITEM_NAME = "Kommentar"; @GrpcClient(GoofyServerApplication.GRPC_CLIENT) private VorgangAttachedItemServiceBlockingStub vorgangAttachedItemServiceStub; @Autowired private KommentarMapper mapper; - @Autowired - private GrpcObjectMapper grpcObjectMapper; public Stream<Kommentar> findByVorgangId(String vorgangId) { - GrpcFindVorgangAttachedItemResponse response = vorgangAttachedItemServiceStub - .find(buildFindRequest(vorgangId)); + var response = vorgangAttachedItemServiceStub.find(buildFindRequest(vorgangId)); - return response.getVorgangAttachedItemsList().stream() - .map(item -> grpcObjectMapper.mapFromGrpc(item.getItem())) - .map(mapper::fromItemMap); + return response.getVorgangAttachedItemsList().stream().map(mapper::fromItem); } GrpcFindVorgangAttachedItemRequest buildFindRequest(String vorgangId) { @@ -42,8 +36,8 @@ class KommentarRemoteService { public Kommentar getById(String kommentarId) { var response = vorgangAttachedItemServiceStub.getById(buildRequest(kommentarId)); - var kommentar = mapper.fromItemMap(grpcObjectMapper.mapFromGrpc(response.getVorgangAttachedItem().getItem())); - return kommentar.toBuilder().vorgangId(response.getVorgangAttachedItem().getVorgangId()).build(); + + return mapper.fromItem(response.getVorgangAttachedItem()).toBuilder().vorgangId(response.getVorgangAttachedItem().getVorgangId()).build(); } private GrpcVorgangAttachedItemRequest buildRequest(String kommentarId) { diff --git a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarService.java b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarService.java index 8b14e5f2262ef7a7628d9c2526f3704fa9654707..1a6627031e2d66b5b420705f339c10c0ece767c4 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarService.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/kommentar/KommentarService.java @@ -1,17 +1,46 @@ package de.itvsh.goofy.kommentar; +import java.time.ZonedDateTime; import java.util.stream.Stream; +import javax.validation.Valid; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -@Service +import de.itvsh.goofy.common.attacheditem.VorgangAttachedItemService; +import de.itvsh.goofy.common.command.Command; +import de.itvsh.goofy.common.user.CurrentUserService; + @Validated +@Service class KommentarService { @Autowired private KommentarRemoteService remoteService; + @Autowired + private CurrentUserService currentUserService; + @Autowired + private VorgangAttachedItemService vorgangAttachedItemService; + + public Command createKommentar(@Valid Kommentar kommentar, String vorgangId) { + return vorgangAttachedItemService.createNewKommentar(addCreated(kommentar), vorgangId); + } + + Kommentar addCreated(Kommentar kommentar) { + return kommentar.toBuilder() + .createdAt(ZonedDateTime.now().withNano(0)) + .createdBy(currentUserService.getUserId().toString()) + .build(); + } + + public Command editKommentar(@Valid Kommentar kommentar, String kommentarId, long kommentarVersion) { + var loadedKommentar = getById(kommentarId); + var preparedKommentar = loadedKommentar.toBuilder().text(kommentar.getText()).build(); + + return vorgangAttachedItemService.editKommentar(preparedKommentar, kommentarId, kommentarVersion); + } public Stream<Kommentar> findByVorgangId(String vorgangId) { return remoteService.findByVorgangId(vorgangId); @@ -20,4 +49,4 @@ class KommentarService { public Kommentar getById(String kommentarId) { return remoteService.getById(kommentarId); } -} +} \ No newline at end of file diff --git a/goofy-server/src/main/java/de/itvsh/goofy/postfach/PostfachMailController.java b/goofy-server/src/main/java/de/itvsh/goofy/postfach/PostfachMailController.java index 4bd0a32d73aa3817555633bbc1b936d2a80c6952..aba1528f495b685b32fababbaeff557f283b4eae 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/postfach/PostfachMailController.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/postfach/PostfachMailController.java @@ -19,7 +19,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import de.itvsh.goofy.common.binaryfile.BinaryFileController; -import de.itvsh.goofy.common.command.Command; import de.itvsh.goofy.common.command.CommandController; import de.itvsh.goofy.common.command.CommandController.CommandByRelationController; import de.itvsh.goofy.common.command.CreateCommand; @@ -90,16 +89,15 @@ public class PostfachMailController { @PostMapping public ResponseEntity<Void> createCommand(@PathVariable String vorgangId, @PathVariable String postfachMailId, @RequestBody CreateCommand command) { - command = command.toBuilder().vorgangId(vorgangId).relationId(postfachMailId).build(); - var created = createCommand(command); + command = command.toBuilder() + .vorgangId(vorgangId) + .relationId(postfachMailId) + .build(); + var created = commandByRelationController.createCommandWithoutRelation(command); service.resendPostfachMail(created.getId(), postfachMailId); return ResponseEntity.created(linkTo(CommandController.class).slash(created.getId()).toUri()).build(); } - - Command createCommand(CreateCommand command) { - return commandByRelationController.createCommand(command, -1); - } } } \ No newline at end of file diff --git a/goofy-server/src/main/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessor.java b/goofy-server/src/main/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessor.java index 89b9dee2f56e78d599b55ac73c0ece2cedc2e803..072324a882b2bbbecb773f88723ab3f0a4cf8b01 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessor.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessor.java @@ -18,14 +18,12 @@ import de.itvsh.goofy.common.user.UserRole; import de.itvsh.goofy.vorgang.Vorgang.VorgangStatus; import de.itvsh.goofy.vorgang.VorgangWithEingang; import de.itvsh.goofy.vorgang.forwarding.ForwardingController; -import de.itvsh.goofy.wiedervorlage.WiedervorlageCommandController.WiedervorlageCommandByVorgangController; @Component public class VorgangWithEingangCommandProzessor implements RepresentationModelProcessor<EntityModel<VorgangWithEingang>> { static final LinkRelation REL_VORGANG_FORWARD = LinkRelation.of("forward"); static final LinkRelation REL_PENDING_COMMANDS = LinkRelation.of("pending-commands"); - static final LinkRelation REL_CREATE_WIEDERVORLAGE = LinkRelation.of("create-wiedervorlage"); @Autowired private CurrentUserService userService; @@ -45,9 +43,6 @@ public class VorgangWithEingangCommandProzessor implements RepresentationModelPr .addLink(linkTo( methodOn(CommandByRelationController.class).createCommand(vorgang.getId(), vorgang.getId(), vorgang.getVersion(), null)).withRel(REL_VORGANG_FORWARD)) - .ifMatch(() -> userService.hasRole(UserRole.VERWALTUNG_USER)) - .addLink(linkTo(methodOn(WiedervorlageCommandByVorgangController.class).createCommand(null, vorgang.getId())) - .withRel(REL_CREATE_WIEDERVORLAGE)) .ifMatch(this::existsPendingCommands) .addLink(linkTo(methodOn(CommandController.class).getPendingCommands(true, vorgang.getId())).withRel(REL_PENDING_COMMANDS)) .buildModel(); diff --git a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/Wiedervorlage.java b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/Wiedervorlage.java index f842842587530ad75cabe1c5246ec2bfdc2d6f08..950343c58851a274800b7b848f384f9241df6864 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/Wiedervorlage.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/Wiedervorlage.java @@ -42,6 +42,8 @@ public class Wiedervorlage implements CommandBody { @JsonIgnore private String vorgangId; + @JsonIgnore + private long version; @JsonProperty(access = Access.READ_ONLY) private boolean done; diff --git a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandController.java b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandController.java index e6270b5ad8ab05eeee8c8729d03aaa4e223102b2..95eee8f6422f37e547f8f059b22196c28b1d855b 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandController.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandController.java @@ -2,7 +2,6 @@ package de.itvsh.goofy.wiedervorlage; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; -import java.time.ZonedDateTime; import java.util.Objects; import org.springframework.beans.factory.annotation.Autowired; @@ -19,14 +18,12 @@ import de.itvsh.goofy.common.command.CommandController; import de.itvsh.goofy.common.command.CommandController.CommandByRelationController; import de.itvsh.goofy.common.command.CommandOrder; import de.itvsh.goofy.common.command.CreateCommand; -import de.itvsh.goofy.common.user.CurrentUserService; @RestController @RequestMapping(WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS) public class WiedervorlageCommandController { - static final String WIEDERVORLAGE_COMMANDS = "/api/wiedervorlages/{wiedervorlageId}/commands"; - static final String NOT_SET = "-1"; + static final String WIEDERVORLAGE_COMMANDS = "/api/wiedervorlages/{wiedervorlageId}/{wiedervorlageVersion}/commands"; @Autowired private CommandByRelationController commandByRelationController; @@ -35,8 +32,9 @@ public class WiedervorlageCommandController { private WiedervorlageService service; @PostMapping - public ResponseEntity<Void> createCommand(@RequestBody WiedervorlageCommand command, @PathVariable String wiedervorlageId) { - var commandWithUpdatedWiedervorlage = buildCommand(service.getById(wiedervorlageId), command); + public ResponseEntity<Void> updateWiedervorlage(@RequestBody WiedervorlageCommand command, @PathVariable String wiedervorlageId, + @PathVariable long wiedervorlageVersion) { + var commandWithUpdatedWiedervorlage = buildCommand(service.getById(wiedervorlageId), command, wiedervorlageVersion); var createdCommand = createByOrder(commandWithUpdatedWiedervorlage, command.getOrder()); @@ -45,10 +43,11 @@ public class WiedervorlageCommandController { return ResponseEntity.created(linkTo(CommandController.class).slash(createdCommand.getId()).toUri()).build(); } - CreateCommand buildCommand(Wiedervorlage wiedervorlage, WiedervorlageCommand command) { + CreateCommand buildCommand(Wiedervorlage wiedervorlage, WiedervorlageCommand command, long wiedervorlageVersion) { var commandBuilder = CreateCommand.builder() .order(CommandOrder.UPDATE_ATTACHED_ITEM) - .relationId(NOT_SET) + .relationId(wiedervorlage.getId()) + .relationVersion(wiedervorlageVersion) .vorgangId(wiedervorlage.getVorgangId()); switch (command.getOrder()) { @@ -65,9 +64,10 @@ public class WiedervorlageCommandController { Command createByOrder(CreateCommand command, CommandOrder commandOrder) { if (shouldBeValidated(commandOrder)) { - return commandByRelationController.createCommand(command, WiedervorlageRemoteService.ITEM_NAME); + return service.editWiedervorlage((Wiedervorlage) command.getBody(), command.getRelationId(), command.getRelationVersion()); } else { - return commandByRelationController.createCommandWithoutValidation(command, WiedervorlageRemoteService.ITEM_NAME); + return commandByRelationController.createCommandWithoutValidation(command, WiedervorlageRemoteService.ITEM_NAME, + command.getRelationVersion()); } } @@ -89,39 +89,18 @@ public class WiedervorlageCommandController { static final String WIEDERVORLAGE_COMMANDS_BY_VORGANG = "/api/vorgangs/{vorgangId}/wiedervorlageCommands"; - @Autowired - private CommandByRelationController commandByRelationController; - - @Autowired - private CurrentUserService userService; - @Autowired private WiedervorlageService service; @PostMapping - public ResponseEntity<Void> createCommand(@RequestBody WiedervorlageCommand command, @PathVariable String vorgangId) { - var createdCommand = commandByRelationController.createCommand(buildCommand(vorgangId, command), WiedervorlageRemoteService.ITEM_NAME); + public ResponseEntity<Void> createWiedervorlage(@RequestBody WiedervorlageCommand command, @PathVariable String vorgangId) { + var preparedWiedervorlage = stripAttachmentFileUriToId(command.getWiedervorlage()); + var createdCommand = service.createWiedervorlage(preparedWiedervorlage, vorgangId); - service.updateNextFrist(command.getWiedervorlage(), vorgangId); + service.updateNextFrist(preparedWiedervorlage, vorgangId); return ResponseEntity.created(linkTo(CommandController.class).slash(createdCommand.getId()).toUri()).build(); } - - CreateCommand buildCommand(String vorgangId, WiedervorlageCommand command) { - return CreateCommand.builder() - .vorgangId(vorgangId) - .order(CommandOrder.CREATE_ATTACHED_ITEM) - .body(buildBody(command.getWiedervorlage())) - .build(); - } - - Wiedervorlage buildBody(Wiedervorlage wiedervorlage) { - wiedervorlage = wiedervorlage.toBuilder() - .createdAt(ZonedDateTime.now().withNano(0)) - .createdBy(userService.getUserId().toString()) - .build(); - return stripAttachmentFileUriToId(wiedervorlage); - } } // TODO Durch LinkedResource am attachment Attribute ersetzen diff --git a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapper.java b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapper.java index 6213f6439493801330c7546683e2ffc6cb9a8a9b..3dd222c011ec78ab460a2911d869fc364cc09ca6 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapper.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapper.java @@ -11,15 +11,21 @@ import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.NullValueCheckStrategy; import org.mapstruct.ReportingPolicy; +import org.springframework.beans.factory.annotation.Autowired; import de.itvsh.goofy.common.binaryfile.FileId; import de.itvsh.goofy.common.binaryfile.FileIdMapper; +import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper; +import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItem; @Mapper(uses = { FileIdMapper.class }, unmappedTargetPolicy = ReportingPolicy.WARN, // unmappedSourcePolicy = ReportingPolicy.WARN, // nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, // collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED) -public interface WiedervorlageMapper { +abstract class WiedervorlageMapper { + + @Autowired + private GrpcObjectMapper grpcObjectMapper; static final String ID = "id"; static final String DONE = "done"; @@ -31,9 +37,14 @@ public interface WiedervorlageMapper { static final String FRIST = "frist"; static final String ATTACHMENTS = "attachments"; - default Wiedervorlage fromItemMap(Map<String, Object> itemMap) { + public Wiedervorlage fromItem(GrpcVorgangAttachedItem item) { + return fromItemMap(grpcObjectMapper.mapFromGrpc(item.getItem()), item.getVersion()); + } + + Wiedervorlage fromItemMap(Map<String, Object> itemMap, long version) { return Wiedervorlage.builder() .id((String) itemMap.get(ID)) + .version(version) .done(Boolean.valueOf((String) itemMap.get(DONE))) .createdBy((String) itemMap.get(CREATED_BY)) .createdAt(ZonedDateTime.parse((String) itemMap.get(CREATED_AT))) diff --git a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssembler.java b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssembler.java index 7743f050749d885035e39b3db23aa75d0c88ef6c..6bbdd7c7eca4940433d2149f7a6632e8d9d4da1e 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssembler.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssembler.java @@ -34,7 +34,8 @@ class WiedervorlageModelAssembler implements RepresentationModelAssembler<Wieder @Override public EntityModel<Wiedervorlage> toModel(Wiedervorlage wiedervorlage) { var selfLink = linkTo(WiedervorlageController.class).slash(wiedervorlage.getId()); - var commandLink = linkTo(methodOn(WiedervorlageCommandController.class).createCommand(null, wiedervorlage.getId())); + var commandLink = linkTo( + methodOn(WiedervorlageCommandController.class).updateWiedervorlage(null, wiedervorlage.getId(), wiedervorlage.getVersion())); return ModelBuilder.fromEntity(wiedervorlage).addLink(selfLink.withSelfRel()) .addLink(commandLink.withRel(REL_EDIT)) @@ -48,7 +49,8 @@ class WiedervorlageModelAssembler implements RepresentationModelAssembler<Wieder public CollectionModel<EntityModel<Wiedervorlage>> toCollectionModel(Stream<Wiedervorlage> entities, String vorgangId) { return CollectionModel.of(entities.map(this::toModel).collect(Collectors.toList()), linkTo(WiedervorlageController.class).withSelfRel(), - linkTo(methodOn(WiedervorlageCommandByVorgangController.class).createCommand(null, vorgangId)).withRel(REL_CREATE), + linkTo(methodOn(WiedervorlageCommandByVorgangController.class).createWiedervorlage(null, vorgangId)) + .withRel(REL_CREATE), linkTo(BinaryFileController.class).slash(vorgangId).slash("wiedervorlageAttachment").slash("file") .withRel(REL_UPLOAD_FILE)); } diff --git a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteService.java b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteService.java index b39b3f0d9ef9efe82cb1f3a43d0fa15d84ab2a4c..73bc379fdacc8d16bd19750017c5ed90c35abae8 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteService.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteService.java @@ -10,7 +10,6 @@ import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; import de.itvsh.goofy.GoofyServerApplication; -import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper; import de.itvsh.ozg.pluto.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceBlockingStub; import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcAccessPermission; import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcClientAttribute; @@ -37,16 +36,12 @@ public class WiedervorlageRemoteService { @Autowired private WiedervorlageMapper mapper; @Autowired - private GrpcObjectMapper grpcObjectMapper; - @Autowired private ApplicationContext context; public Stream<Wiedervorlage> findByVorgangId(String vorgangId) { var response = vorgangAttachedItemServiceStub.find(buildFindRequest(vorgangId)); - return response.getVorgangAttachedItemsList().stream() - .map(item -> grpcObjectMapper.mapFromGrpc(item.getItem())) - .map(mapper::fromItemMap); + return response.getVorgangAttachedItemsList().stream().map(mapper::fromItem); } GrpcFindVorgangAttachedItemRequest buildFindRequest(String vorgangId) { @@ -58,8 +53,8 @@ public class WiedervorlageRemoteService { public Wiedervorlage getById(String wiedervorlageId) { var response = vorgangAttachedItemServiceStub.getById(GrpcVorgangAttachedItemRequest.newBuilder().setId(wiedervorlageId).build()); - var wiedervorlage = mapper.fromItemMap(grpcObjectMapper.mapFromGrpc(response.getVorgangAttachedItem().getItem())); - return wiedervorlage.toBuilder().vorgangId(response.getVorgangAttachedItem().getVorgangId()).build(); + + return mapper.fromItem(response.getVorgangAttachedItem()).toBuilder().vorgangId(response.getVorgangAttachedItem().getVorgangId()).build(); } public void updateNextFrist(String vorgangId, Optional<LocalDate> nextFrist) { diff --git a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageService.java b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageService.java index 4d6961375b53686657df8aa323f17c06f8eddd96..e508c813a169c3ed9570239ff1add9df2491c2ae 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageService.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/wiedervorlage/WiedervorlageService.java @@ -1,15 +1,24 @@ package de.itvsh.goofy.wiedervorlage; import java.time.LocalDate; +import java.time.ZonedDateTime; import java.util.Comparator; import java.util.Optional; import java.util.function.Predicate; import java.util.stream.Stream; +import javax.validation.Valid; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import de.itvsh.goofy.common.attacheditem.VorgangAttachedItemService; +import de.itvsh.goofy.common.command.Command; +import de.itvsh.goofy.common.user.CurrentUserService; +@Validated @Service class WiedervorlageService { @@ -17,6 +26,25 @@ class WiedervorlageService { @Autowired private WiedervorlageRemoteService remoteService; + @Autowired + private VorgangAttachedItemService vorgangAttachedItemService; + @Autowired + private CurrentUserService currentUserService; + + public Command createWiedervorlage(@Valid Wiedervorlage wiedervorlage, String vorgangId) { + return vorgangAttachedItemService.createNewWiedervorlage(addCreated(wiedervorlage), vorgangId); + } + + Wiedervorlage addCreated(Wiedervorlage wiedervorlage) { + return wiedervorlage.toBuilder() + .createdAt(ZonedDateTime.now().withNano(0)) + .createdBy(currentUserService.getUserId().toString()) + .build(); + } + + public Command editWiedervorlage(@Valid Wiedervorlage wiedervorlage, String wiedervorlageId, long wiedervorlageVersion) { + return vorgangAttachedItemService.editWiedervorlage(wiedervorlage, wiedervorlageId, wiedervorlageVersion); + } public Wiedervorlage getById(String wiedervorlageId) { return remoteService.getById(wiedervorlageId); diff --git a/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java index 778e0dc261ca83baefff24df794e4e346fb7c403..bd32012c381f870f397df66abc0485a793c5c0db 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java @@ -14,6 +14,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Spy; import org.springframework.boot.info.BuildProperties; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; @@ -24,12 +25,14 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import static org.assertj.core.api.Assertions.*; import de.itvsh.goofy.common.user.CurrentUserService; +import de.itvsh.goofy.common.user.UserRole; import de.itvsh.goofy.common.user.UserTestFactory; class RootControllerTest { private final String PATH = "/api"; + @Spy @InjectMocks // NOSONAR private RootController controller; @Mock @@ -50,13 +53,13 @@ class RootControllerTest { @Nested class TestLinks { - @DisplayName("with any role") + @DisplayName("with any verwaltung role") @Nested - class TestWithAnyRole { + class TestWithVerwaltungRole { @BeforeEach void mockCurrentUserService() { - when(currentUserService.hasRole(anyString())).thenReturn(true); + doReturn(true).when(controller).hasVerwaltungRole(); } @Test @@ -115,6 +118,32 @@ class RootControllerTest { } } + @DisplayName("with role " + UserRole.EINHEITLICHER_ANSPRECHPARTNER) + @Nested + class TestWithEinheitlicherAnsprechpartnerRole { + + @BeforeEach + void mock() { + when(currentUserService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER)).thenReturn(true); + + doReturn(false).when(controller).hasVerwaltungRole(); + } + + @Test + void shoulNotHaveMyVorgaengeLink() { + var model = controller.getRootResource(); + + assertThat(model.getLink(RootController.REL_MY_VORGAENGE)).isNotPresent(); + } + + @Test + void shoulNotHaveSearchMyVorgaengeLink() { + var model = controller.getRootResource(); + + assertThat(model.getLink(RootController.REL_SEARCH_MY_VORGAENGE)).isNotPresent(); + } + } + @DisplayName("with no role") @Nested class TestWithNoRole { diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..119c69476263cf2451c055d215dfefcb07ce74cb --- /dev/null +++ b/goofy-server/src/test/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemServiceTest.java @@ -0,0 +1,275 @@ +package de.itvsh.goofy.common.attacheditem; + +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import static org.assertj.core.api.Assertions.*; + +import de.itvsh.goofy.common.attacheditem.VorgangAttachedItem; +import de.itvsh.goofy.common.attacheditem.VorgangAttachedItemService; +import de.itvsh.goofy.common.command.Command; +import de.itvsh.goofy.common.command.CommandBodyMapper; +import de.itvsh.goofy.common.command.CommandOrder; +import de.itvsh.goofy.common.command.CommandService; +import de.itvsh.goofy.common.command.CommandTestFactory; +import de.itvsh.goofy.common.command.CreateCommand; +import de.itvsh.goofy.kommentar.Kommentar; +import de.itvsh.goofy.kommentar.KommentarTestFactory; +import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; +import de.itvsh.goofy.wiedervorlage.Wiedervorlage; +import de.itvsh.goofy.wiedervorlage.WiedervorlageTestFactory; + +class VorgangAttachedItemServiceTest { + + @Spy + @InjectMocks + private VorgangAttachedItemService service; + @Mock + private CommandBodyMapper commandBodyMapper; + @Mock + private CommandService commandService; + + @DisplayName("Create new wiedervorlage") + @Nested + class TestCreateNewWiedervorlage { + + private Wiedervorlage wiedervorlage = WiedervorlageTestFactory.create(); + + @BeforeEach + void mockServices() { + doReturn(VorgangAttachedItemTestFactory.create()).when(service).buildVorgangAttachedItem(any(), any(), any()); + doReturn(CommandTestFactory.createCreateCommand()).when(service).buildCreateCommand(any(), any()); + } + + @Test + void shouldBuildVorgangAttachedItem() { + callCreateNewWiedervorlage(); + + verify(service).buildVorgangAttachedItem(wiedervorlage, VorgangHeaderTestFactory.ID, VorgangAttachedItemService.WIEDERVORLAGE_ITEM_NAME); + } + + @Test + void shouldBuildCreateCommand() { + callCreateNewWiedervorlage(); + + verify(service).buildCreateCommand(eq(VorgangHeaderTestFactory.ID), any(VorgangAttachedItem.class)); + } + + @Test + void shouldCallCommandService() { + callCreateNewWiedervorlage(); + + verify(commandService).createCommand(any(CreateCommand.class)); + } + + private Command callCreateNewWiedervorlage() { + return service.createNewWiedervorlage(wiedervorlage, VorgangHeaderTestFactory.ID); + } + } + + @DisplayName("Edit wiedervorlage") + @Nested + class TestEditWiedervorlage { + + private Wiedervorlage wiedervorlage = WiedervorlageTestFactory.create(); + + @BeforeEach + void mockService() { + doReturn(VorgangAttachedItemTestFactory.create()).when(service).buildVorgangAttachedItem(any(), any(), any()); + doReturn(CommandTestFactory.createCreateCommand()).when(service).buildUpdateCommand(any(), any(), any()); + } + + @Test + void shouldBuildVorgangAttachedItem() { + callEditWiedervorlage(); + + verify(service).buildVorgangAttachedItem(wiedervorlage, VorgangHeaderTestFactory.ID, VorgangAttachedItemService.WIEDERVORLAGE_ITEM_NAME); + } + + @Test + void shouldBuildCreateCommand() { + callEditWiedervorlage(); + + verify(service).buildUpdateCommand(eq(VorgangHeaderTestFactory.ID), eq(WiedervorlageTestFactory.ID), any(VorgangAttachedItem.class)); + } + + @Test + void shouldCallCommandService() { + callEditWiedervorlage(); + + verify(commandService).createCommand(any(CreateCommand.class), eq(WiedervorlageTestFactory.VERSION)); + } + + private Command callEditWiedervorlage() { + return service.editWiedervorlage(wiedervorlage, WiedervorlageTestFactory.ID, WiedervorlageTestFactory.VERSION); + } + + } + + @DisplayName("Create new kommentar") + @Nested + class TestCreateNewKommentar { + + private Kommentar kommentar = KommentarTestFactory.create(); + + @BeforeEach + void mockServices() { + doReturn(VorgangAttachedItemTestFactory.create()).when(service).buildVorgangAttachedItem(any(), any(), any()); + doReturn(CommandTestFactory.createCreateCommand()).when(service).buildCreateCommand(any(), any()); + } + + @Test + void shouldBuildVorgangAttachedItem() { + callCreateNewKommentar(); + + verify(service).buildVorgangAttachedItem(kommentar, VorgangHeaderTestFactory.ID, VorgangAttachedItemService.KOMMENTAR_ITEM_NAME); + } + + @Test + void shouldBuildCreateCommand() { + callCreateNewKommentar(); + + verify(service).buildCreateCommand(eq(VorgangHeaderTestFactory.ID), any(VorgangAttachedItem.class)); + } + + @Test + void shouldCallCommandService() { + callCreateNewKommentar(); + + verify(commandService).createCommand(any(CreateCommand.class)); + } + + private Command callCreateNewKommentar() { + return service.createNewKommentar(kommentar, VorgangHeaderTestFactory.ID); + } + } + + @DisplayName("Edit kommentar") + @Nested + class TestEditKommentar { + + private Kommentar kommentar = KommentarTestFactory.create(); + + @BeforeEach + void mockService() { + doReturn(VorgangAttachedItemTestFactory.create()).when(service).buildVorgangAttachedItem(any(), any(), any()); + doReturn(CommandTestFactory.createCreateCommand()).when(service).buildUpdateCommand(any(), any(), any()); + } + + @Test + void shouldBuildVorgangAttachedItem() { + callEditKommentar(); + + verify(service).buildVorgangAttachedItem(kommentar, VorgangHeaderTestFactory.ID, VorgangAttachedItemService.KOMMENTAR_ITEM_NAME); + } + + @Test + void shouldBuildCreateCommand() { + callEditKommentar(); + + verify(service).buildUpdateCommand(eq(VorgangHeaderTestFactory.ID), eq(KommentarTestFactory.ID), any(VorgangAttachedItem.class)); + } + + @Test + void shouldCallCommandService() { + callEditKommentar(); + + verify(commandService).createCommand(any(CreateCommand.class), eq(KommentarTestFactory.VERSION)); + } + + private Command callEditKommentar() { + return service.editKommentar(kommentar, KommentarTestFactory.ID, KommentarTestFactory.VERSION); + } + } + + @DisplayName("build vorgang attached item") + @Nested + class TestBuildVorgangAttachedItem { + + private static final Wiedervorlage BODY = WiedervorlageTestFactory.create(); + + @BeforeEach + void mockServices() { + when(commandBodyMapper.fromObjectToMap(any())).thenReturn(VorgangAttachedItemTestFactory.ITEM); + } + + @Test + void shouldCallCommandBodyMapper() { + buildVorgangAttachedItem(); + + verify(commandBodyMapper).fromObjectToMap(BODY); + } + + @Test + void shouldContainsVorgangId() { + var vorgangAttachedItem = buildVorgangAttachedItem(); + + assertThat(vorgangAttachedItem.getVorgangId()).isEqualTo(VorgangHeaderTestFactory.ID); + } + + @Test + void shouldContainsItemName() { + var vorgangAttachedItem = buildVorgangAttachedItem(); + + assertThat(vorgangAttachedItem.getItemName()).isEqualTo(VorgangAttachedItemService.WIEDERVORLAGE_ITEM_NAME); + } + + @Test + void shouldContainsItem() { + var vorgangAttachedItem = buildVorgangAttachedItem(); + + assertThat(vorgangAttachedItem.getItem()).isEqualTo(VorgangAttachedItemTestFactory.ITEM); + } + + private VorgangAttachedItem buildVorgangAttachedItem() { + return service.buildVorgangAttachedItem(BODY, VorgangHeaderTestFactory.ID, + VorgangAttachedItemService.WIEDERVORLAGE_ITEM_NAME); + } + } + + @DisplayName("build createCommand") + @Nested + class TestBuildCreateCommand { + + @Test + void shouldContainsVorgangId() throws Exception { + var createCommand = buildCommand(); + + assertThat(createCommand.getVorgangId()).isEqualTo(VorgangHeaderTestFactory.ID); + } + + @Test + void shouldContainsRelationId() throws Exception { + var createCommand = buildCommand(); + + assertThat(createCommand.getRelationId()).isEqualTo(VorgangHeaderTestFactory.ID); + } + + @Test + void shouldContainsOrder() throws Exception { + var createCommand = buildCommand(); + + assertThat(createCommand.getOrder()).isEqualTo(CommandOrder.CREATE_ATTACHED_ITEM); + } + + @Test + void shouldContainsBody() throws Exception { + var createCommand = buildCommand(); + + assertThat(((VorgangAttachedItem) createCommand.getBody())).usingRecursiveComparison() + .isEqualTo(VorgangAttachedItemTestFactory.create()); + } + + private CreateCommand buildCommand() { + return service.buildCreateCommand(VorgangHeaderTestFactory.ID, VorgangAttachedItemTestFactory.create()); + } + } +} \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..4ea3c9250428a4fb96f62434c21b8abebecb4416 --- /dev/null +++ b/goofy-server/src/test/java/de/itvsh/goofy/common/attacheditem/VorgangAttachedItemTestFactory.java @@ -0,0 +1,28 @@ +package de.itvsh.goofy.common.attacheditem; + +import java.util.Map; +import java.util.UUID; + +import de.itvsh.goofy.common.attacheditem.VorgangAttachedItem; + +public class VorgangAttachedItemTestFactory { + + public static final String ID = UUID.randomUUID().toString(); + public static final long VERSION = 42; + public static final String CLIENT = "Goofy"; + public static final String ITEM_NAME = "ItemName"; + public static final Map<String, Object> ITEM = Map.of("oneKey", "oneValue"); + + public static VorgangAttachedItem create() { + return createBuilder().build(); + } + + public static VorgangAttachedItem.VorgangAttachedItemBuilder createBuilder() { + return VorgangAttachedItem.builder() + .id(ID) + .version(VERSION) + .client(CLIENT) + .itemName(ITEM_NAME) + .item(ITEM); + } +} \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandBodyMapperTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandBodyMapperTest.java index 13d0d22456f477f570a97c73bc50e1991d947272..6f1e3eeeedae9ce2bdd44d2089de4bd7132a81fc 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandBodyMapperTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandBodyMapperTest.java @@ -35,40 +35,44 @@ class CommandBodyMapperTest { class TestFromObjectToMap { @Test - void shouldMapAllFieldsExceptClass() { + void shouldMapAllValues() { + var commandAsObject = CommandTestFactory.create(); + + var mappedMap = mapper.fromObjectToMap(commandAsObject); + + assertThat(mappedMap).hasSize(12) + .containsEntry("id", CommandTestFactory.ID) + .containsEntry("status", CommandTestFactory.STATUS.name()) + .containsEntry("order", CommandTestFactory.ORDER.name()) + .containsEntry("relationId", CommandTestFactory.RELATION_ID) + .containsEntry("vorgangId", CommandTestFactory.VORGANG_ID); + } + + @Test + void shouldNotMapClass() { var commandAsObject = CommandTestFactory.create(); var mappedMap = mapper.fromObjectToMap(commandAsObject); - assertThat(mappedMap).hasSize(5).doesNotContainKey("class"); + assertThat(mappedMap).doesNotContainKey("class"); } @Test - void shouldNotMapNullValue() { + void shouldMapNullValue() { var commandAsObject = CommandTestFactory.createBuilder().status(null).build(); var mappedMap = mapper.fromObjectToMap(commandAsObject); - assertThat(mappedMap) - .hasSize(4) - .doesNotContainKey("status") - .containsEntry("order", CommandTestFactory.ORDER.name()) - .containsEntry("relationId", CommandTestFactory.RELATION_ID) - .containsEntry("vorgangId", CommandTestFactory.VORGANG_ID); + assertThat(mappedMap).containsEntry("status", null); } @Test - void shouldMapAllValues() { - var commandAsObject = CommandTestFactory.create(); + void shouldNotMapVersion() { + var commandAsObject = WiedervorlageTestFactory.create(); var mappedMap = mapper.fromObjectToMap(commandAsObject); - assertThat(mappedMap) - .hasSize(5) - .containsEntry("status", CommandTestFactory.STATUS.name()) - .containsEntry("order", CommandTestFactory.ORDER.name()) - .containsEntry("relationId", CommandTestFactory.RELATION_ID) - .containsEntry("vorgangId", CommandTestFactory.VORGANG_ID); + assertThat(mappedMap).doesNotContainKey("version"); } } @@ -150,10 +154,11 @@ class CommandBodyMapperTest { } @Test - void shouldFilterEntriesWithNullValue() { + void shouldMapNullAsEmptyValue() { var result = mapper.mapToBodyFields(buildBodyMapWithNullValue()); - assertThat(result).isEmpty(); + assertThat(result).hasSize(1); + assertThat(result.get(0).getValue()).isEmpty(); } private Map<Object, Object> buildBodyMapWithNullValue() { diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandControllerTest.java index 1d701b2269b468c4d63d4a3f13309c47d7e930af..a920b70120ac24cb3e397292a8ea963d49200f03 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandControllerTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandControllerTest.java @@ -160,8 +160,11 @@ class CommandControllerTest { void callService() throws Exception { doRequest(); - verify(service).createCommand(createCommandCaptor.capture(), eq(VorgangHeaderTestFactory.VERSION)); + verify(service).createCommand(createCommandCaptor.capture(), eq(CommandTestFactory.RELATION_VERSION)); assertThat(createCommandCaptor.getValue().getOrder()).isEqualTo(CommandTestFactory.ORDER); + assertThat(createCommandCaptor.getValue().getVorgangId()).isEqualTo(CommandTestFactory.VORGANG_ID); + assertThat(createCommandCaptor.getValue().getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID); + assertThat(createCommandCaptor.getValue().getRelationVersion()).isZero(); } @DisplayName("should have location header") @@ -248,33 +251,35 @@ class CommandControllerTest { } } + @DisplayName("Create by vorgang with relation id") @Nested - class CreateByVorgangAndItemName { + class TestCreateByVorgangWithoutRelationId { - private static final String ITEM_NAME = "Wiedervorlage"; private final CreateCommand command = CommandTestFactory.createCreateCommand(); - @Nested - class WithValidation { - - @Test - void shouldCallService() { - controller.createCommand(command, ITEM_NAME); + @Test + void shouldCallSerice() { + controller.createCommandWithoutRelation(command); - verify(service).createCommand(command, ITEM_NAME); - } + verify(service).createCommandWithoutRelation(command); } + } + + @Nested + class CreateByVorgangAndItemName { + + private static final String ITEM_NAME = "Wiedervorlage"; + private final CreateCommand command = CommandTestFactory.createCreateCommand(); @Nested class WithoutValidation { @Test void shouldCallService() { - controller.createCommandWithoutValidation(command, ITEM_NAME); + controller.createCommandWithoutValidation(command, ITEM_NAME, CommandTestFactory.RELATION_VERSION); - verify(service).createCommandWithoutValidation(command, ITEM_NAME); + verify(service).createCommandWithoutValidation(command, ITEM_NAME, CommandTestFactory.RELATION_VERSION); } - } } } diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandITCase.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandITCase.java index ca0b874eddb7bf5fd8c6e99427081766af79a5f8..0aff0b1a2396b22a28acae4957f99cb21cc7ca37 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandITCase.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandITCase.java @@ -1,6 +1,5 @@ package de.itvsh.goofy.common.command; -import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @@ -22,6 +21,8 @@ import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; +import static org.assertj.core.api.Assertions.*; + import de.itvsh.goofy.common.ValidationMessageCodes; import de.itvsh.goofy.common.user.UserTestFactory; import de.itvsh.goofy.postfach.PostfachMailTestFactory; @@ -52,14 +53,14 @@ public class CommandITCase { @BeforeEach void initTests() { - when(commandRemoteService.createCommand(any(), anyLong())).thenReturn(CommandTestFactory.create()); + when(commandRemoteService.createCommand(any())).thenReturn(CommandTestFactory.create()); } @Test void shouldExtractUserId() throws Exception { createCommand(); - verify(commandRemoteService).createCommand(commandCaptor.capture(), anyLong()); + verify(commandRemoteService).createCommand(commandCaptor.capture()); assertThat(commandCaptor.getValue().getBody()).hasFieldOrPropertyWithValue("assignedTo", UserTestFactory.ID); } @@ -180,7 +181,7 @@ public class CommandITCase { @BeforeEach void initMockCommand() { - when(commandRemoteService.createCommand(any(CreateCommand.class), anyLong())).thenReturn(CommandTestFactory.create()); + when(commandRemoteService.createCommand(any(CreateCommand.class))).thenReturn(CommandTestFactory.create()); } @Test @@ -232,7 +233,7 @@ public class CommandITCase { @Test void shouldProceedOnValidInput() throws Exception { - when(commandRemoteService.createCommand(any(CreateCommand.class), anyLong())).thenReturn(CommandTestFactory.create()); + when(commandRemoteService.createCommand(any(CreateCommand.class))).thenReturn(CommandTestFactory.create()); var content = PostfachMailTestFactory.buildSendPostfachMailContent(); @@ -243,7 +244,7 @@ public class CommandITCase { ResultActions doRequest(String content) throws Exception { return mockMvc.perform(post("/api/vorgangs/" + CommandTestFactory.VORGANG_ID + "/relations/" + CommandTestFactory.RELATION_ID + "/" - + CommandTestFactory.VERSION + "/commands") + + CommandTestFactory.RELATION_VERSION + "/commands") .contentType(MediaType.APPLICATION_JSON) .content(content)); } diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandRemoteServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandRemoteServiceTest.java index 3b9794b4c12d1a7d2d96c35e805e0c758b02c2b6..3e687d3a2c49b701a06b0547d922a4e57cb4a2fe 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandRemoteServiceTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandRemoteServiceTest.java @@ -78,28 +78,28 @@ class CommandRemoteServiceTest { @BeforeEach void initTest() { - doReturn(request).when(service).buildCreateCommandRequest(any(), anyLong()); + doReturn(request).when(service).buildCreateCommandRequest(any()); when(commandServiceStub.createCommand(any())).thenReturn(GrpcCommandResponse.newBuilder().build()); when(mapper.toCommand(any())).thenReturn(resultCommand); } @Test void shouldCreateRequest() { - service.createCommand(createCommand, CommandTestFactory.VERSION); + service.createCommand(createCommand); - verify(service).buildCreateCommandRequest(createCommand, CommandTestFactory.VERSION); + verify(service).buildCreateCommandRequest(createCommand); } @Test void shouldCallServiceStub() { - service.createCommand(createCommand, CommandTestFactory.VERSION); + service.createCommand(createCommand); verify(commandServiceStub).createCommand(request); } @Test void shouldReturnResultCommand() { - var result = service.createCommand(createCommand, CommandTestFactory.VERSION); + var result = service.createCommand(createCommand); assertThat(result).isSameAs(resultCommand); } @@ -177,7 +177,7 @@ class CommandRemoteServiceTest { when(mapper.toGrpcRedirectRequest(any())).thenReturn(grpcRedirectRequest); var command = CommandTestFactory.createCreateCommandBuilder().redirectRequest(RedirectRequestTestFactory.create()).build(); - var request = service.buildCreateCommandRequest(command, CommandTestFactory.VERSION); + var request = service.buildCreateCommandRequest(command); assertThat(request.getRedirectRequest()).isNotNull().isSameAs(grpcRedirectRequest); } @@ -185,16 +185,14 @@ class CommandRemoteServiceTest { @ParameterizedTest @EnumSource void shouldHaveOrder(CommandOrder order) { - var request = service.buildCreateCommandRequest(CommandTestFactory.createCreateCommandBuilder().order(order).build(), - CommandTestFactory.VERSION); + var request = service.buildCreateCommandRequest(CommandTestFactory.createCreateCommandBuilder().order(order).build()); assertThat(request.getOrderString()).isEqualTo(order.name()); } private GrpcCreateCommandRequest buildRequest() { return service.buildCreateCommandRequest( - CommandTestFactory.createCreateCommandBuilder().body(RedirectRequestTestFactory.create()).build(), - CommandTestFactory.VERSION); + CommandTestFactory.createCreateCommandBuilder().body(RedirectRequestTestFactory.create()).build()); } } } @@ -262,17 +260,17 @@ class CommandRemoteServiceTest { } @Test - void shouldContainsVorgangIdAsRelationId() { + void shouldContainsRelationId() { var request = buildRequest(); - assertThat(request.getRelationId()).isEqualTo(CommandTestFactory.VORGANG_ID); + assertThat(request.getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID); } @Test void shouldContainsRelationVersion() { var request = buildRequest(); - assertThat(request.getRelationVersion()).isEqualTo(-1); + assertThat(request.getRelationVersion()).isEqualTo(CommandTestFactory.RELATION_VERSION); } @Test @@ -283,10 +281,10 @@ class CommandRemoteServiceTest { } @Test - void shouldContainsOrder() { + void shouldContainsOrderString() { var request = buildRequest(); - assertThat(request.getOrder()).isEqualTo(GrpcOrder.VORGANG_ANNEHMEN); + assertThat(request.getOrderString()).isEqualTo(GrpcOrder.VORGANG_ANNEHMEN.name()); } private GrpcCreateCommandRequest buildRequest() { diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandServiceTest.java index acd0c9ad4631dfe38a8eddc7a2f293dd66e2b706..4c49293df735c22d7bb628daa17870c1285aa927 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandServiceTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandServiceTest.java @@ -1,6 +1,5 @@ package de.itvsh.goofy.common.command; -import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @@ -11,6 +10,8 @@ import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; +import static org.assertj.core.api.Assertions.*; + import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; class CommandServiceTest { @@ -28,27 +29,61 @@ class CommandServiceTest { private final CreateCommand command = CommandTestFactory.createCreateCommand(); - @Test - void shouldCallRemoteServiceWithVersion() { - service.createCommand(command, CommandTestFactory.VERSION); + @Nested + class TestWithCreateCommandOnly { + + @Test + void shouldCallRemoteService() { + service.createCommand(command); + + verify(remoteService).createCommand(any(CreateCommand.class)); + } - verify(remoteService).createCommand(command, CommandTestFactory.VERSION); + @Test + void shouldHaveSetRelationVersion() { + service.createCommand(command); + + verify(remoteService).createCommand(createCommandCaptor.capture()); + assertThat(createCommandCaptor.getValue().getRelationVersion()).isEqualTo(CommandService.NO_RELATION_VERSION); + } } - @Test - void shouldHaveVorgangId() { - service.createCommand(command, CommandTestFactory.VERSION); + @Nested + class TestWithRelationVersion { + + @Test + void shouldCallRemoteService() { + service.createCommand(command, CommandTestFactory.RELATION_VERSION); + + verify(remoteService).createCommand(any(CreateCommand.class)); + } - verify(remoteService).createCommand(createCommandCaptor.capture(), anyLong()); - assertThat(createCommandCaptor.getValue().getVorgangId()).isEqualTo(CommandTestFactory.VORGANG_ID); + @Test + void shouldHaveSetRelationVersion() { + service.createCommand(command, CommandTestFactory.RELATION_VERSION); + + verify(remoteService).createCommand(createCommandCaptor.capture()); + assertThat(createCommandCaptor.getValue().getRelationVersion()).isEqualTo(CommandTestFactory.RELATION_VERSION); + } } - @Test - void shouldHaveRelationId() { - service.createCommand(command, CommandTestFactory.VERSION); + @Nested + class TestWithoutRelationVersion { + + @Test + void shouldCallRemoteService() { + service.createCommandWithoutRelation(command); + + verify(remoteService).createCommand(any(CreateCommand.class)); + } - verify(remoteService).createCommand(createCommandCaptor.capture(), anyLong()); - assertThat(createCommandCaptor.getValue().getRelationId()).isEqualTo(CommandTestFactory.RELATION_ID); + @Test + void shouldHaveSetRelationVersion() { + service.createCommandWithoutRelation(command); + + verify(remoteService).createCommand(createCommandCaptor.capture()); + assertThat(createCommandCaptor.getValue().getRelationVersion()).isEqualTo(CommandService.NO_RELATION_VERSION); + } } } @@ -59,24 +94,21 @@ class CommandServiceTest { private final CreateCommand command = CommandTestFactory.createCreateCommand(); @Nested - class WithValidation { + class WithoutValidation { @Test void shouldCallRemoteService() { - service.createCommand(command, ITEM_NAME); + service.createCommandWithoutValidation(command, ITEM_NAME, CommandTestFactory.RELATION_VERSION); - verify(remoteService).createCommand(command, ITEM_NAME); + verify(remoteService).createCommand(any(CreateCommand.class), eq(ITEM_NAME)); } - } - - @Nested - class WithoutValidation { @Test - void shouldCallRemoteService() { - service.createCommandWithoutValidation(command, ITEM_NAME); + void shouldHaveSetRelationVersion() { + service.createCommandWithoutValidation(command, ITEM_NAME, CommandTestFactory.RELATION_VERSION); - verify(remoteService).createCommand(command, ITEM_NAME); + verify(remoteService).createCommand(createCommandCaptor.capture(), eq(ITEM_NAME)); + assertThat(createCommandCaptor.getValue().getRelationVersion()).isEqualTo(CommandTestFactory.RELATION_VERSION); } } } diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandTestFactory.java index 0cebc6cf3ae6aa0cc843a73ded18ab21614c22e0..84072f84de42653a03d1f050b6c20c2dd2f46d74 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandTestFactory.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/common/command/CommandTestFactory.java @@ -13,7 +13,7 @@ public class CommandTestFactory { public static final CommandOrder ORDER = CommandOrder.VORGANG_ANNEHMEN; public static final String RELATION_ID = ForwardingTestFactory.ID; - public static final long VERSION = VorgangHeaderTestFactory.VERSION; + public static final long RELATION_VERSION = VorgangHeaderTestFactory.VERSION; public static Command create() { return createBuilder().build(); @@ -36,6 +36,7 @@ public class CommandTestFactory { return CreateCommand.builder() .vorgangId(VORGANG_ID) .relationId(RELATION_ID) + .relationVersion(RELATION_VERSION) .order(ORDER); } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/user/GoofyUserTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/common/user/GoofyUserTestFactory.java index dd713bdae5e65d6ada50b375071cc6adefb25c4c..fb8a5c667c83e35d0b986946b6a2c45cb59116ff 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/common/user/GoofyUserTestFactory.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/common/user/GoofyUserTestFactory.java @@ -1,15 +1,20 @@ package de.itvsh.goofy.common.user; +import java.util.UUID; + import de.itvsh.goofy.vorgang.ZustaendigeStelleTestFactory; public class GoofyUserTestFactory { + public static final UserId ID = UserId.from(UUID.randomUUID().toString()); + public static GoofyUser create() { return createBuilder().build(); } public static GoofyUser.GoofyUserBuilder createBuilder() { return GoofyUser.builder() + .id(ID) .organisationseinheitId(ZustaendigeStelleTestFactory.ORGANISATIONSEINHEITEN_ID); } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandControllerTest.java index 3eb84c3ec6ae60f487ba067875086369004b81bc..f9332017ddd6264e6dd06c77e9d5f6126fd40282 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandControllerTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandControllerTest.java @@ -1,14 +1,11 @@ package de.itvsh.goofy.kommentar; import static de.itvsh.goofy.kommentar.KommentarCommandTestFactory.*; -import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -import java.util.UUID; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -16,17 +13,14 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Spy; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import de.itvsh.goofy.common.command.CommandController.CommandByRelationController; -import de.itvsh.goofy.common.command.CommandOrder; import de.itvsh.goofy.common.command.CommandTestFactory; import de.itvsh.goofy.common.command.CreateCommand; -import de.itvsh.goofy.common.user.CurrentUserService; -import de.itvsh.goofy.common.user.UserId; import de.itvsh.goofy.kommentar.KommentarCommandController.KommentarCommandByVorgangController; import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; @@ -38,53 +32,37 @@ class KommentarCommandControllerTest { @Nested class TestCreateKommentarCommandByVorgang { + @Spy @InjectMocks private KommentarCommandByVorgangController controller; @Mock private KommentarService service; - @Mock - private CommandByRelationController commandByRelationController; - @Mock - private CurrentUserService userService; private MockMvc mockMvc; @BeforeEach void init() { mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); - when(userService.getUserId()).thenReturn(UserId.from(UUID.randomUUID())); - when(commandByRelationController.createCommand(any(), anyString())).thenReturn(CommandTestFactory.create()); - } - @Test - void shouldReturnCreated() throws Exception { - doRequest().andExpect(status().isCreated()); + when(service.createKommentar(any(), any())).thenReturn(CommandTestFactory.create()); } @Test void shouldCallService() throws Exception { doRequest(); - verify(commandByRelationController).createCommand(any(), eq(KommentarRemoteService.ITEM_NAME)); + verify(service).createKommentar(any(Kommentar.class), eq(VorgangHeaderTestFactory.ID)); } @Test - void shouldGiveCommandToService() throws Exception { - doRequest(); - - verify(commandByRelationController).createCommand(commandCaptor.capture(), anyString()); - var command = commandCaptor.getValue(); - - assertThat(command).usingRecursiveComparison() - .ignoringFields("body", "status") - .isEqualTo(CommandTestFactory.createBuilder().order(CommandOrder.CREATE_ATTACHED_ITEM) - .relationId(KommentarCommandController.NOT_SET) - .id(null).build()); + void shouldReturnCreated() throws Exception { + doRequest().andExpect(status().isCreated()); } private ResultActions doRequest() throws Exception { - return mockMvc.perform(post(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID) - .content(createValidRequestContent()).contentType(MediaType.APPLICATION_JSON)) + return mockMvc.perform( + post(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID) + .content(createValidRequestContent()).contentType(MediaType.APPLICATION_JSON)) .andExpect(status().is2xxSuccessful()); } } @@ -92,13 +70,12 @@ class KommentarCommandControllerTest { @Nested class TestCreateEditKommentarCommand { - final String REPONSE_HEADER = "http://localhost/api/commands/" + KommentarCommandTestFactory.ID; + private final static String REPONSE_HEADER = "http://localhost/api/commands/" + KommentarCommandTestFactory.ID; + @Spy @InjectMocks private KommentarCommandController controller; @Mock - private CommandByRelationController commandByRelationController; - @Mock private KommentarService service; private MockMvc mockMvc; @@ -106,34 +83,20 @@ class KommentarCommandControllerTest { @BeforeEach void init() { mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); - when(commandByRelationController.createCommand(any(), anyString())).thenReturn(CommandTestFactory.create()); - when(service.getById(any())).thenReturn(KommentarTestFactory.createBuilder().vorgangId(VorgangHeaderTestFactory.ID).build()); - } - @Test - void shouldReturnCreated() throws Exception { - doRequest().andExpect(status().isCreated()); + when(service.editKommentar(any(), any(), anyLong())).thenReturn(CommandTestFactory.create()); } @Test void shouldCallService() throws Exception { doRequest(); - verify(service).getById(any()); + verify(service).editKommentar(any(Kommentar.class), eq(KommentarTestFactory.ID), eq(KommentarTestFactory.VERSION)); } @Test - void shouldGiveCommandToService() throws Exception { - doRequest(); - - verify(commandByRelationController).createCommand(commandCaptor.capture(), anyString()); - var command = commandCaptor.getValue(); - - assertThat(command).usingRecursiveComparison() - .ignoringFields("body", "status") - .isEqualTo(CommandTestFactory.createBuilder().order(CommandOrder.UPDATE_ATTACHED_ITEM) - .relationId(KommentarCommandController.NOT_SET).id(null) - .build()); + void shouldReturnCreated() throws Exception { + doRequest().andExpect(status().isCreated()); } @Test @@ -143,7 +106,7 @@ class KommentarCommandControllerTest { ResultActions doRequest() throws Exception { String content = createValidRequestContent(); - return mockMvc.perform(post(KommentarCommandController.KOMMENTAR_COMMANDS, KommentarTestFactory.ID) + return mockMvc.perform(post(KommentarCommandController.KOMMENTAR_COMMANDS, KommentarTestFactory.ID, KommentarTestFactory.VERSION) .content(content).contentType(MediaType.APPLICATION_JSON)) .andExpect(status().is2xxSuccessful()); } diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandITCase.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandITCase.java index 37c96c2c937358f455fab7fcc967503267cf42ab..ef360511deca6b6b066d4e30a18be240a536be03 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandITCase.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarCommandITCase.java @@ -46,14 +46,14 @@ class KommentarCommandITCase { @BeforeEach void initTest() { when(remoteService.getById(any())).thenReturn(KommentarTestFactory.create()); - when(commandRemoteService.createCommand(any(), anyString())).thenReturn(CommandTestFactory.create()); + when(commandRemoteService.createCommand(any())).thenReturn(CommandTestFactory.create()); } @Test void shouldCreateCommand() throws Exception { doRequestByKommentarId(createValidRequestContent()).andExpect(status().isCreated()); - verify(commandRemoteService).createCommand(any(), eq(KommentarRemoteService.ITEM_NAME)); + verify(commandRemoteService).createCommand(any()); } @WithMockUser @@ -68,7 +68,7 @@ class KommentarCommandITCase { doRequestByKommentarId(content).andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.issues.length()").value(1)) - .andExpect(jsonPath("$.issues.[0].field").value("command.body.text")) + .andExpect(jsonPath("$.issues.[0].field").value("kommentar.text")) .andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY)); } @@ -78,7 +78,7 @@ class KommentarCommandITCase { String content = buildContentWithText(StringUtils.EMPTY); doRequestByKommentarId(content).andExpect(status().isUnprocessableEntity()) - .andExpect(jsonPath("$.issues.[0].field").value("command.body.text")); + .andExpect(jsonPath("$.issues.[0].field").value("kommentar.text")); } @@ -100,7 +100,7 @@ class KommentarCommandITCase { } private ResultActions doRequestByKommentarId(String content) throws Exception { - return mockMvc.perform(post(KommentarCommandController.KOMMENTAR_COMMANDS, KommentarTestFactory.ID) + return mockMvc.perform(post(KommentarCommandController.KOMMENTAR_COMMANDS, KommentarTestFactory.ID, KommentarTestFactory.VERSION) .contentType(MediaType.APPLICATION_JSON) .content(content)); } @@ -110,17 +110,19 @@ class KommentarCommandITCase { @Nested class TestCreateCommandByVorgangId { + private static final long RELATION_ID_ON_CREATE = -1; + @BeforeEach void initTest() { when(remoteService.getById(any())).thenReturn(KommentarTestFactory.create()); - when(commandRemoteService.createCommand(any(), anyString())).thenReturn(CommandTestFactory.create()); + when(commandRemoteService.createCommand(any())).thenReturn(CommandTestFactory.create()); } @Test void shouldCreateCommand() throws Exception { doRequestByVorgangId(createValidRequestContent()).andExpect(status().isCreated()); - verify(commandRemoteService).createCommand(any(), eq(KommentarRemoteService.ITEM_NAME)); + verify(commandRemoteService).createCommand(any()); } @WithMockUser @@ -135,7 +137,7 @@ class KommentarCommandITCase { doRequestByVorgangId(content).andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.issues.length()").value(1)) - .andExpect(jsonPath("$.issues.[0].field").value("command.body.text")) + .andExpect(jsonPath("$.issues.[0].field").value("kommentar.text")) .andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY)); } @@ -145,7 +147,7 @@ class KommentarCommandITCase { String content = buildContentWithText(StringUtils.EMPTY); doRequestByVorgangId(content).andExpect(status().isUnprocessableEntity()) - .andExpect(jsonPath("$.issues.[0].field").value("command.body.text")); + .andExpect(jsonPath("$.issues.[0].field").value("kommentar.text")); } @@ -167,9 +169,10 @@ class KommentarCommandITCase { } private ResultActions doRequestByVorgangId(String content) throws Exception { - return mockMvc.perform(post(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID) - .contentType(MediaType.APPLICATION_JSON) - .content(content)); + return mockMvc.perform(post(KommentarCommandByVorgangController.KOMMENTAR_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID, + RELATION_ID_ON_CREATE) + .contentType(MediaType.APPLICATION_JSON) + .content(content)); } } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarMapperTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarMapperTest.java index 74380e47bbbb5e6315f72c9cac7853d6aaf961a2..b059c5ec3dd1177dfd22673b6aa73594abf671e5 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarMapperTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarMapperTest.java @@ -1,17 +1,58 @@ package de.itvsh.goofy.kommentar; -import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mapstruct.factory.Mappers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import static org.assertj.core.api.Assertions.*; + +import de.itvsh.goofy.vorgang.GrpcVorgangAttachedItemTestFactory; +import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper; class KommentarMapperTest { + @Spy + @InjectMocks private KommentarMapper mapper = Mappers.getMapper(KommentarMapper.class); + @Mock + private GrpcObjectMapper grpcObjectMapper; + @DisplayName("Map from item") + @Nested + class TestFromItem { + + @BeforeEach + void mockMapper() { + when(grpcObjectMapper.mapFromGrpc(any())).thenReturn(KommentarTestFactory.createAsMap()); + } + + @Test + void shouldCallGrpcObjectMapper() { + mapper.fromItem(GrpcVorgangAttachedItemTestFactory.create()); + + verify(grpcObjectMapper).mapFromGrpc(GrpcVorgangAttachedItemTestFactory.ITEM); + } + + @Test + void shouldCallMapperFromItemMap() { + mapper.fromItem(GrpcVorgangAttachedItemTestFactory.create()); + + verify(mapper).fromItemMap(KommentarTestFactory.createAsMap(), KommentarTestFactory.VERSION); + } + } + + @DisplayName("Map from item map") @Nested class TestFromItemMap { + @Test void shouldMapId() { var kommentar = map(); @@ -19,6 +60,13 @@ class KommentarMapperTest { assertThat(kommentar.getId()).isEqualTo(KommentarTestFactory.ID); } + @Test + void shouldMapVersion() { + var kommentar = map(); + + assertThat(kommentar.getVersion()).isEqualTo(KommentarTestFactory.VERSION); + } + @Test void shouldMapCreatedBy() { var kommentar = map(); @@ -42,6 +90,6 @@ class KommentarMapperTest { } private Kommentar map() { - return mapper.fromItemMap(KommentarTestFactory.createAsMap()); + return mapper.fromItemMap(KommentarTestFactory.createAsMap(), KommentarTestFactory.VERSION); } } diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarModelAssemblerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarModelAssemblerTest.java index 250e85a35dc78caf6645cf7119933390e194a127..9e605466c1e115ca671e7152d75376ba46ada19d 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarModelAssemblerTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarModelAssemblerTest.java @@ -1,7 +1,5 @@ package de.itvsh.goofy.kommentar; -import static org.assertj.core.api.Assertions.*; - import java.util.Collections; import org.junit.jupiter.api.Nested; @@ -13,6 +11,8 @@ import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; import org.springframework.hateoas.server.EntityLinks; +import static org.assertj.core.api.Assertions.*; + import de.itvsh.goofy.common.user.UserProfileTestFactory; import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; @@ -31,7 +31,9 @@ class KommentarModelAssemblerTest { class TestLinksOnModel { final String COMMAND_BY_KOMMENTAR_PATH = // - KommentarCommandController.KOMMENTAR_COMMANDS.replace("{kommentarId}", KommentarTestFactory.ID); + KommentarCommandController.KOMMENTAR_COMMANDS + .replace("{kommentarId}", KommentarTestFactory.ID) + .replace("{kommentarVersion}", String.valueOf(KommentarTestFactory.VERSION)); @Test void shouldHaveSelfLink() { @@ -73,7 +75,8 @@ class KommentarModelAssemblerTest { var link = collectionModel.getLink(KommentarModelAssembler.REL_CREATE); assertThat(link).isPresent(); - assertThat(link.get().getHref()).isEqualTo("/api/vorgangs/" + VorgangHeaderTestFactory.ID + "/kommentarCommands"); + assertThat(link.get().getHref()).isEqualTo( + "/api/vorgangs/" + VorgangHeaderTestFactory.ID + "/kommentarCommands"); } } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarRemoteServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarRemoteServiceTest.java index 6b8c32c2b10a75d57a416b112e405f229cc339cd..364b8af57e85a8873ad4f58d55988c094d21b392 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarRemoteServiceTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarRemoteServiceTest.java @@ -6,6 +6,7 @@ import static org.mockito.Mockito.*; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; @@ -14,7 +15,6 @@ import org.mockito.Spy; import de.itvsh.goofy.vorgang.GrpcVorgangAttachedItemTestFactory; import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; -import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper; import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest; import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemResponse; import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItem; @@ -27,24 +27,23 @@ class KommentarRemoteServiceTest { @Spy @InjectMocks private KommentarRemoteService service; - @Mock private VorgangAttachedItemServiceBlockingStub vorgangAttachedItemServiceStub; @Mock private KommentarMapper mapper; - @Mock - private GrpcObjectMapper grpcObjectMapper; private GrpcVorgangAttachedItem kommentar = GrpcVorgangAttachedItemTestFactory.create(); + @DisplayName("Find by vorgangId") @Nested class TestFindByVorgangId { private GrpcFindVorgangAttachedItemRequest request = GrpcFindVorgangAttachedItemRequest.newBuilder() - .setVorgangId(VorgangHeaderTestFactory.ID).setItemName(KommentarRemoteService.ITEM_NAME).build(); + .setVorgangId(VorgangHeaderTestFactory.ID) + .setItemName(KommentarRemoteService.ITEM_NAME) + .build(); private GrpcFindVorgangAttachedItemResponse response = GrpcFindVorgangAttachedItemResponse.newBuilder() .clearVorgangAttachedItems() - .addVorgangAttachedItems(kommentar) .addVorgangAttachedItems(kommentar).build(); @BeforeEach @@ -61,10 +60,10 @@ class KommentarRemoteServiceTest { @Test void shouldCallMapper() { - Stream<Kommentar> result = service.findByVorgangId(VorgangHeaderTestFactory.ID); + var result = service.findByVorgangId(VorgangHeaderTestFactory.ID); collectStreamElementsToTriggerLazyStream(result); - verify(mapper, times(2)).fromItemMap(any()); + verify(mapper).fromItem(any()); } private void collectStreamElementsToTriggerLazyStream(Stream<Kommentar> stream) { @@ -72,17 +71,20 @@ class KommentarRemoteServiceTest { } } + @DisplayName("Find by id") @Nested class TestGetById { - GrpcVorgangAttachedItemResponse response = GrpcVorgangAttachedItemResponse.newBuilder() - .setVorgangAttachedItem(GrpcVorgangAttachedItemTestFactory.create()).build(); - GrpcVorgangAttachedItemRequest request = GrpcVorgangAttachedItemRequest.newBuilder().setId(KommentarTestFactory.ID).build(); + private GrpcVorgangAttachedItemResponse response = GrpcVorgangAttachedItemResponse.newBuilder() + .setVorgangAttachedItem(GrpcVorgangAttachedItemTestFactory.create()) + .build(); + private GrpcVorgangAttachedItemRequest request = GrpcVorgangAttachedItemRequest.newBuilder() + .setId(KommentarTestFactory.ID) + .build(); @BeforeEach void mockStub() { when(vorgangAttachedItemServiceStub.getById(any())).thenReturn(response); - when(grpcObjectMapper.mapFromGrpc(any())).thenReturn(KommentarTestFactory.createAsMap()); - when(mapper.fromItemMap(any())).thenReturn(KommentarTestFactory.create()); + when(mapper.fromItem(any())).thenReturn(KommentarTestFactory.create()); } @Test @@ -96,7 +98,7 @@ class KommentarRemoteServiceTest { void shouldCallMapper() { service.getById(KommentarTestFactory.ID); - verify(mapper).fromItemMap(any()); + verify(mapper).fromItem(any()); } } } diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarServiceTest.java index d7193d38b9d8ba7ae8385d7e2414f0e42a2d45e8..ab903893f2acdc5e4566c6606bf40c432388a609 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarServiceTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarServiceTest.java @@ -1,21 +1,145 @@ package de.itvsh.goofy.kommentar; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Spy; + +import static org.assertj.core.api.Assertions.*; +import de.itvsh.goofy.common.attacheditem.VorgangAttachedItemService; +import de.itvsh.goofy.common.command.Command; +import de.itvsh.goofy.common.command.CommandTestFactory; +import de.itvsh.goofy.common.user.CurrentUserService; +import de.itvsh.goofy.common.user.GoofyUserTestFactory; import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; class KommentarServiceTest { + @Spy @InjectMocks private KommentarService service; - @Mock private KommentarRemoteService remoteService; + @Mock + private VorgangAttachedItemService vorgangAttachedItemService; + @Mock + private CurrentUserService currentUserService; + + @DisplayName("Create kommentar") + @Nested + class TestCreateKommentar { + + @DisplayName("should") + @Nested + class TestCalls { + + @BeforeEach + void mockServices() { + doReturn(KommentarTestFactory.create()).when(service).addCreated(any()); + when(vorgangAttachedItemService.createNewKommentar(any(), any())).thenReturn(CommandTestFactory.create()); + } + + @DisplayName("add created") + @Test + void shouldAddCreated() { + callCreateKommentar(); + + verify(service).addCreated(any(Kommentar.class)); + } + + @DisplayName("call vorgangattacheditem service") + @Test + void shouldCallVorgangAttachedItemService() { + callCreateKommentar(); + + verify(vorgangAttachedItemService).createNewKommentar(any(Kommentar.class), eq(VorgangHeaderTestFactory.ID)); + } + } + + @DisplayName("Add created") + @Nested + class TestAddCreated { + + @BeforeEach + void mockServices() { + when(currentUserService.getUserId()).thenReturn(GoofyUserTestFactory.ID); + } + + @Test + void shouldSetCreatedAt() throws Exception { + var kommentar = callAddCreated(); + + assertThat(kommentar.getCreatedAt()).isNotNull().isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS)); + } + + @Test + void shouldSetCreatedBy() throws Exception { + var kommentar = callAddCreated(); + + assertThat(kommentar.getCreatedBy()).isEqualTo(GoofyUserTestFactory.ID.toString()); + } + + private Kommentar callAddCreated() { + return service.addCreated(KommentarTestFactory.createBuilder().createdAt(null).createdBy(null).build()); + } + } + + private Command callCreateKommentar() { + return service.createKommentar(KommentarTestFactory.create(), VorgangHeaderTestFactory.ID); + } + } + + @DisplayName("Edit kommentar") + @Nested + class TestEditKommentar { + + @Captor + private ArgumentCaptor<Kommentar> kommentarCaptor; + + @BeforeEach + void mockKommentarService() { + when(remoteService.getById(anyString())).thenReturn(KommentarTestFactory.createBuilder().text("text needs to be override").build()); + } + + @Test + void shouldCallGetById() { + callEditKommentar(); + + verify(service).getById(KommentarTestFactory.ID); + } + + @Test + void shouldReplaceText() { + callEditKommentar(); + + verify(vorgangAttachedItemService).editKommentar(kommentarCaptor.capture(), eq(KommentarTestFactory.ID), + eq(KommentarTestFactory.VERSION)); + assertThat(kommentarCaptor.getValue().getText()).isEqualTo(KommentarTestFactory.TEXT); + } + + @Test + void shouldCallVorgangAttachedItemService() { + callEditKommentar(); + + verify(vorgangAttachedItemService).editKommentar(any(Kommentar.class), eq(KommentarTestFactory.ID), eq(KommentarTestFactory.VERSION)); + } + + private Command callEditKommentar() { + return service.editKommentar(KommentarTestFactory.create(), KommentarTestFactory.ID, KommentarTestFactory.VERSION); + } + } @Nested class TestGetById { diff --git a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarTestFactory.java index 99abb0b24b22ca5ab6743ae4de507409dfdf0995..aee4801acc0698a5b90c1e4994552608fae227b5 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarTestFactory.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/kommentar/KommentarTestFactory.java @@ -8,12 +8,14 @@ import com.thedeanda.lorem.Lorem; import com.thedeanda.lorem.LoremIpsum; import de.itvsh.goofy.common.user.UserProfileTestFactory; +import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; public class KommentarTestFactory { private static Lorem lorem = LoremIpsum.getInstance(); public static final String ID = UUID.randomUUID().toString(); + public static final long VERSION = 73; public static final String CREATED_BY = UserProfileTestFactory.ID.toString(); public static final String CREATED_AT_STR = "2021-01-10T10:30:00Z"; @@ -28,6 +30,8 @@ public class KommentarTestFactory { public static Kommentar.KommentarBuilder createBuilder() { return Kommentar.builder() .id(ID) + .vorgangId(VorgangHeaderTestFactory.ID) + .version(VERSION) .text(TEXT) .createdBy(CREATED_BY) .createdAt(CREATED_AT); diff --git a/goofy-server/src/test/java/de/itvsh/goofy/postfach/PostfachMailCommandControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/postfach/PostfachMailCommandControllerTest.java index dc3c4932db2382e4713c473d9fbcdb2980fd1ed7..77f85fb625a2744ebe45085cd8731efaf93104c1 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/postfach/PostfachMailCommandControllerTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/postfach/PostfachMailCommandControllerTest.java @@ -8,6 +8,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.springframework.http.MediaType; @@ -40,9 +42,19 @@ class PostfachMailCommandControllerTest { @Nested class TestCreateCommand { + @Captor + private ArgumentCaptor<CreateCommand> createCommandCaptor; + @BeforeEach void mockController() { - when(commandByRelationController.createCommand(any(CreateCommand.class), anyLong())).thenReturn(CommandTestFactory.create()); + when(commandByRelationController.createCommandWithoutRelation(any(CreateCommand.class))).thenReturn(CommandTestFactory.create()); + } + + @Test + void shouldCallCommandByRelationController() throws Exception { + doRequest(); + + verify(commandByRelationController).createCommandWithoutRelation(createCommandCaptor.capture()); } @Test @@ -63,13 +75,4 @@ class PostfachMailCommandControllerTest { .content(PostfachMailTestFactory.buildResendPostfachMailContent())); } } - - @Test - void shouldCallCommandByRelationController() { - var createCommand = CommandTestFactory.createCreateCommand(); - - controller.createCommand(createCommand); - - verify(commandByRelationController).createCommand(createCommand, -1); - } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/vorgang/GrpcVorgangAttachedItemTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/vorgang/GrpcVorgangAttachedItemTestFactory.java index 78b56c924b1bd1f4991f47d5bfc40cb3c5b0704a..216ba59a1db199deb47cbdf31d9f6b8189c50ce7 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/vorgang/GrpcVorgangAttachedItemTestFactory.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/vorgang/GrpcVorgangAttachedItemTestFactory.java @@ -15,6 +15,7 @@ public class GrpcVorgangAttachedItemTestFactory { public final static String ITEM_NAME = LoremIpsum.getInstance().getWords(1); public final static String ITEM_KEY = LoremIpsum.getInstance().getWords(1); public final static String ITEM_VALUE = LoremIpsum.getInstance().getWords(1); + public final static long VERSION = 73; public static final GrpcObject ITEM = GrpcObject.newBuilder() .addProperty(GrpcProperty.newBuilder() @@ -33,6 +34,7 @@ public class GrpcVorgangAttachedItemTestFactory { .setClient(CLIENT) .setVorgangId(VorgangHeaderTestFactory.ID) .setItemName(ITEM_NAME) - .setItem(ITEM); + .setItem(ITEM) + .setVersion(VERSION); } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessorTest.java b/goofy-server/src/test/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessorTest.java index 2c34ae5ee0a1ae740a3510031d6427eac5a2ffeb..54a15a5328b13dfe251e5a7afe6ca9935655978c 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessorTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/vorgang/command/VorgangWithEingangCommandProzessorTest.java @@ -1,11 +1,9 @@ package de.itvsh.goofy.vorgang.command; -import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.util.Collections; -import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -22,6 +20,8 @@ import org.springframework.hateoas.Link; import org.springframework.hateoas.LinkRelation; import org.springframework.security.test.context.support.WithMockUser; +import static org.assertj.core.api.Assertions.*; + import de.itvsh.goofy.common.command.CommandController; import de.itvsh.goofy.common.user.CurrentUserService; import de.itvsh.goofy.common.user.UserRole; @@ -187,31 +187,4 @@ class VorgangWithEingangCommandProzessorTest { .isEqualTo("/api/commands?pending=true&vorgangId=" + VorgangHeaderTestFactory.ID); } } - - @Nested - class TestCreateWiedervorlageLink { - - @Test - void shouldHaveCreateWiedervorlageLink() { - when(userService.hasRole(UserRole.VERWALTUNG_USER)).thenReturn(true); - when(userService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER)).thenReturn(false); - - EntityModel<VorgangWithEingang> model = processor.process(EntityModel.of(VorgangWithEingangTestFactory.create())); - var link = model.getLink(VorgangWithEingangCommandProzessor.REL_CREATE_WIEDERVORLAGE); - - assertThat(link).isPresent().get().extracting(Link::getHref) - .isEqualTo("/api/vorgangs/" + VorgangHeaderTestFactory.ID + "/wiedervorlageCommands"); - } - - @Test - void shouldNotHaveCreateWiedervorlageLink() { - when(userService.hasRole(UserRole.VERWALTUNG_USER)).thenReturn(false); - when(userService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER)).thenReturn(false); - - Optional<Link> model = processor.process(EntityModel.of(VorgangWithEingangTestFactory.create())) - .getLink(VorgangWithEingangCommandProzessor.REL_CREATE_WIEDERVORLAGE); - - assertThat(model).isNotPresent(); - } - } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandByVorgangControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandByVorgangControllerTest.java index 1bfc0085bc36578ff105d9ecac9a2b788f3b39fc..d15a8312ffff46ba61638a047f00a14df3768072 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandByVorgangControllerTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandByVorgangControllerTest.java @@ -1,14 +1,10 @@ package de.itvsh.goofy.wiedervorlage; -import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -import java.time.ZonedDateTime; -import java.time.temporal.ChronoUnit; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -23,14 +19,10 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import de.itvsh.goofy.common.binaryfile.BinaryFileTestFactory; -import de.itvsh.goofy.common.binaryfile.FileId; import de.itvsh.goofy.common.command.CommandController.CommandByRelationController; -import de.itvsh.goofy.common.command.CommandOrder; import de.itvsh.goofy.common.command.CommandTestFactory; import de.itvsh.goofy.common.command.CreateCommand; import de.itvsh.goofy.common.user.CurrentUserService; -import de.itvsh.goofy.common.user.UserTestFactory; import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; import de.itvsh.goofy.wiedervorlage.WiedervorlageCommandController.WiedervorlageCommandByVorgangController; @@ -61,23 +53,17 @@ class WiedervorlageCommandByVorgangControllerTest { @BeforeEach void mockUserService() { - when(userService.getUserId()).thenReturn(UserTestFactory.ID); + when(service.createWiedervorlage(any(), any())).thenReturn(CommandTestFactory.create()); } @Nested class ServiceMethod { - @BeforeEach - void initMocks() { - when(commandByRelationController.createCommand(any(), any())).thenReturn(CommandTestFactory.create()); - } - @Test - void shouldCallCommandByRelationController() throws Exception { + void shouldCallService() throws Exception { doRequest(); - verify(commandByRelationController).createCommand(any(CreateCommand.class), - eq(WiedervorlageRemoteService.ITEM_NAME)); + verify(service).createWiedervorlage(any(Wiedervorlage.class), eq(VorgangHeaderTestFactory.ID)); } @Test @@ -92,75 +78,6 @@ class WiedervorlageCommandByVorgangControllerTest { doRequest().andExpect(status().isCreated()); } } - - @Nested - class BuildCreateCommand { - - @Test - void shouldContainsOrder() throws Exception { - var createCommand = buildCommand(); - - assertThat(createCommand.getOrder()).isEqualTo(CommandOrder.CREATE_ATTACHED_ITEM); - } - - @Test - void shouldContainsVorgangId() throws Exception { - var createCommand = buildCommand(); - - assertThat(createCommand.getVorgangId()).isEqualTo(VorgangHeaderTestFactory.ID); - } - - @Test - void shouldContainsBody() throws Exception { - var createCommand = buildCommand(); - - assertThat(((Wiedervorlage) createCommand.getBody())).usingRecursiveComparison().ignoringFields("createdAt", "createdBy") - .isEqualTo(WiedervorlageTestFactory.create()); - } - - private CreateCommand buildCommand() { - return controller.buildCommand(VorgangHeaderTestFactory.ID, WiedervorlageCommandTestFactory.create()); - } - } - - @Nested - class BuildBody { - - private final Wiedervorlage wiedervorlage = WiedervorlageTestFactory.create(); - - @Test - void shouldSetCreatedAt() { - var enrichedWiedervorlage = buildBody(wiedervorlage.toBuilder().createdAt(null).build()); - - assertThat(enrichedWiedervorlage.getCreatedAt()).isCloseTo(ZonedDateTime.now().withNano(0), - within(2, ChronoUnit.SECONDS)); - } - - @Test - void shouldSetCreatedBy() { - var enrichedWiedervorlage = buildBody(wiedervorlage.toBuilder().createdBy(null).build()); - - assertThat(enrichedWiedervorlage.getCreatedBy()).isEqualTo(UserTestFactory.ID.toString()); - } - - @Nested - class StripAttachmentFileUriToId { - - @Test - void shouldStripFileUriToFileId() { - var fileIdAsUri = FileId.from("api/irgendwas/dazwischen/" + BinaryFileTestFactory.ID); - var wiedervorlageWithAttachmentAsFileUri = WiedervorlageTestFactory.createBuilder().attachment(fileIdAsUri).build(); - - var wiedervorlage = buildBody(wiedervorlageWithAttachmentAsFileUri); - - assertThat(wiedervorlage.getAttachments().get(0)).isEqualTo(BinaryFileTestFactory.FILE_ID); - } - } - - private Wiedervorlage buildBody(Wiedervorlage wiedervorlage) { - return controller.buildBody(wiedervorlage); - } - } } private ResultActions doRequest() throws Exception { diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandControllerTest.java index 3e1834ad47c6dc23488c91e236b0717e2305228e..892c2c68b614fa0c57f8b1b17645a2310e1645ea 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandControllerTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandControllerTest.java @@ -1,6 +1,5 @@ package de.itvsh.goofy.wiedervorlage; -import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @@ -20,7 +19,10 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import static org.assertj.core.api.Assertions.*; + import de.itvsh.goofy.common.binaryfile.BinaryFileTestFactory; +import de.itvsh.goofy.common.binaryfile.FileId; import de.itvsh.goofy.common.command.Command; import de.itvsh.goofy.common.command.CommandController.CommandByRelationController; import de.itvsh.goofy.common.command.CommandOrder; @@ -95,9 +97,17 @@ class WiedervorlageCommandControllerTest { doRequest().andExpect(header().string("Location", RESPONSE_HEADER)); } + @Test + void shouldBuildCommand() throws Exception { + doRequest(); + + verify(controller).buildCommand(any(Wiedervorlage.class), any(WiedervorlageCommand.class), eq(WiedervorlageTestFactory.VERSION)); + } + private ResultActions doRequest() throws Exception { - return mockMvc.perform(post(WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS, WiedervorlageTestFactory.ID) - .content(WiedervorlageCommandTestFactory.createValidRequestContent()).contentType(MediaType.APPLICATION_JSON)) + return mockMvc.perform( + post(WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS, WiedervorlageTestFactory.ID, WiedervorlageTestFactory.VERSION) + .content(WiedervorlageCommandTestFactory.createValidRequestContent()).contentType(MediaType.APPLICATION_JSON)) .andExpect(status().is2xxSuccessful()); } } @@ -116,7 +126,14 @@ class WiedervorlageCommandControllerTest { void shouldHaveRelationId() { var command = callBuildCommand(); - assertThat(command.getRelationId()).isEqualTo(WiedervorlageCommandController.NOT_SET); + assertThat(command.getRelationId()).isEqualTo(WiedervorlageTestFactory.ID); + } + + @Test + void shouldHaveRelationVersion() { + var command = callBuildCommand(); + + assertThat(command.getRelationVersion()).isEqualTo(WiedervorlageTestFactory.VERSION); } @Test @@ -216,7 +233,7 @@ class WiedervorlageCommandControllerTest { } CreateCommand callBuildCommand(WiedervorlageCommand command) { - return controller.buildCommand(WiedervorlageTestFactory.create(), command); + return controller.buildCommand(WiedervorlageTestFactory.create(), command, WiedervorlageTestFactory.VERSION); } } @@ -230,7 +247,8 @@ class WiedervorlageCommandControllerTest { void shouldCallCreateCommand() { createCommandByOrder(CommandOrder.EDIT_WIEDERVORLAGE); - verify(commandByRelationController).createCommand(any(), eq(WiedervorlageRemoteService.ITEM_NAME)); + verify(service).editWiedervorlage(any(Wiedervorlage.class), eq(CommandTestFactory.RELATION_ID), + eq(CommandTestFactory.RELATION_VERSION)); } } @@ -241,7 +259,8 @@ class WiedervorlageCommandControllerTest { void shouldCallCreateCommandWithoutValidation() { createCommandByOrder(CommandOrder.WIEDERVORLAGE_ERLEDIGEN); - verify(commandByRelationController).createCommandWithoutValidation(any(), eq(WiedervorlageRemoteService.ITEM_NAME)); + verify(commandByRelationController).createCommandWithoutValidation(any(), eq(WiedervorlageRemoteService.ITEM_NAME), + eq(CommandTestFactory.RELATION_VERSION)); } } @@ -252,13 +271,29 @@ class WiedervorlageCommandControllerTest { void shouldCallCreateCommandWithoutValidation() { createCommandByOrder(CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN); - verify(commandByRelationController).createCommandWithoutValidation(any(), eq(WiedervorlageRemoteService.ITEM_NAME)); + verify(commandByRelationController).createCommandWithoutValidation(any(), eq(WiedervorlageRemoteService.ITEM_NAME), + eq(CommandTestFactory.RELATION_VERSION)); } } private Command createCommandByOrder(CommandOrder order) { - return controller.createByOrder(CommandTestFactory.createCreateCommand(), order); + return controller.createByOrder( + CommandTestFactory.createCreateCommandBuilder().body(WiedervorlageTestFactory.create()).build(), order); } } } + + @Nested + class StripAttachmentFileUriToId { + + @Test + void shouldStripFileUriToFileId() { + var fileIdAsUri = FileId.from("api/irgendwas/dazwischen/" + BinaryFileTestFactory.ID); + var wiedervorlageWithAttachmentAsFileUri = WiedervorlageTestFactory.createBuilder().attachment(fileIdAsUri).build(); + + var wiedervorlage = WiedervorlageCommandController.stripAttachmentFileUriToId(wiedervorlageWithAttachmentAsFileUri); + + assertThat(wiedervorlage.getAttachments().get(0)).isEqualTo(BinaryFileTestFactory.FILE_ID); + } + } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandITCase.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandITCase.java index 145aa620085692c67cf8f5a5739e69ed4e9b5c16..b4271cc9c0001e0b8046a0ba66186097fa46025d 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandITCase.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageCommandITCase.java @@ -71,7 +71,7 @@ class WiedervorlageCommandITCase { doRequest(content).andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.issues.length()").value(1)) - .andExpect(jsonPath("$.issues.[0].field").value("command.body.betreff")) + .andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.betreff")) .andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY)); } @@ -81,7 +81,7 @@ class WiedervorlageCommandITCase { String content = buildContentWithBetreff("a"); doRequest(content).andExpect(status().isUnprocessableEntity()) - .andExpect(jsonPath("$.issues.[0].field").value("command.body.betreff")); + .andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.betreff")); } @@ -112,7 +112,7 @@ class WiedervorlageCommandITCase { doRequest(content).andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.issues.length()").value(1)) - .andExpect(jsonPath("$.issues.[0].field").value("command.body.frist")) + .andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.frist")) .andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_DATE_PAST)); } @@ -123,7 +123,7 @@ class WiedervorlageCommandITCase { doRequest(content).andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.issues.length()").value(1)) - .andExpect(jsonPath("$.issues.[0].field").value("command.body.frist")) + .andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.frist")) .andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY)); } @@ -134,9 +134,10 @@ class WiedervorlageCommandITCase { } private ResultActions doRequest(String content) throws Exception { - return mockMvc.perform(post(WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS, WiedervorlageTestFactory.ID) - .contentType(MediaType.APPLICATION_JSON) - .content(content)); + return mockMvc.perform( + post(WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS, WiedervorlageTestFactory.ID, WiedervorlageTestFactory.VERSION) + .contentType(MediaType.APPLICATION_JSON) + .content(content)); } } @@ -145,9 +146,11 @@ class WiedervorlageCommandITCase { @Nested class TestCreateCreateCommand { + private static final long RELATION_ID_ON_CREATE = -1; + @BeforeEach void initTest() { - when(commandRemoteService.createCommand(any(), anyString())).thenReturn(CommandTestFactory.create()); + when(commandRemoteService.createCommand(any())).thenReturn(CommandTestFactory.create()); when(wiedervorlageRemoteService.getById(anyString())).thenReturn(WiedervorlageTestFactory.create()); } @@ -155,7 +158,7 @@ class WiedervorlageCommandITCase { void shouldCreateCommand() throws Exception { doRequest(createValidRequestContent()).andExpect(status().isCreated()); - verify(commandRemoteService).createCommand(any(), anyString()); + verify(commandRemoteService).createCommand(any()); } @WithMockUser @@ -170,7 +173,7 @@ class WiedervorlageCommandITCase { doRequest(content).andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.issues.length()").value(1)) - .andExpect(jsonPath("$.issues.[0].field").value("command.body.betreff")) + .andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.betreff")) .andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY)); } @@ -180,7 +183,7 @@ class WiedervorlageCommandITCase { String content = buildContentWithBetreff("a"); doRequest(content).andExpect(status().isUnprocessableEntity()) - .andExpect(jsonPath("$.issues.[0].field").value("command.body.betreff")); + .andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.betreff")); } @@ -212,7 +215,7 @@ class WiedervorlageCommandITCase { doRequest(content).andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.issues.length()").value(1)) - .andExpect(jsonPath("$.issues.[0].field").value("command.body.frist")) + .andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.frist")) .andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_DATE_PAST)); } @@ -224,16 +227,17 @@ class WiedervorlageCommandITCase { doRequest(content).andExpect(status().isUnprocessableEntity()) .andExpect(jsonPath("$.issues.length()").value(1)) - .andExpect(jsonPath("$.issues.[0].field").value("command.body.frist")) + .andExpect(jsonPath("$.issues.[0].field").value("wiedervorlage.frist")) .andExpect(jsonPath("$.issues.[0].messageCode").value(ValidationMessageCodes.FIELD_IS_EMPTY)); } } private ResultActions doRequest(String content) throws Exception { - return mockMvc.perform(post(WiedervorlageCommandByVorgangController.WIEDERVORLAGE_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID) - .contentType(MediaType.APPLICATION_JSON) - .content(content)); + return mockMvc.perform(post(WiedervorlageCommandByVorgangController.WIEDERVORLAGE_COMMANDS_BY_VORGANG, VorgangHeaderTestFactory.ID, + RELATION_ID_ON_CREATE) + .contentType(MediaType.APPLICATION_JSON) + .content(content)); } } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapperTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapperTest.java index c01ecfd503854baedb44893b6fd49692f3deb5cc..3b21f24d6a98eb7c2808706afdc8dcd35648ca81 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapperTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageMapperTest.java @@ -1,26 +1,62 @@ package de.itvsh.goofy.wiedervorlage; -import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; import java.util.HashMap; import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mapstruct.factory.Mappers; import org.mockito.InjectMocks; +import org.mockito.Mock; import org.mockito.Spy; +import static org.assertj.core.api.Assertions.*; + import de.itvsh.goofy.common.binaryfile.BinaryFileTestFactory; import de.itvsh.goofy.common.binaryfile.FileIdMapper; +import de.itvsh.goofy.vorgang.GrpcVorgangAttachedItemTestFactory; +import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper; class WiedervorlageMapperTest { + @Spy @InjectMocks private WiedervorlageMapper mapper = Mappers.getMapper(WiedervorlageMapper.class); @Spy private FileIdMapper fileIdMapper = Mappers.getMapper(FileIdMapper.class); + @Mock + private GrpcObjectMapper grpcObjectMapper; + + @DisplayName("Map from item") + @Nested + class TestFromItem { + + @BeforeEach + void mockMapper() { + when(grpcObjectMapper.mapFromGrpc(any())).thenReturn(WiedervorlageTestFactory.createAsMap()); + } + + @Test + void shouldCallGrpcObjectMapper() { + mapper.fromItem(GrpcVorgangAttachedItemTestFactory.create()); + + verify(grpcObjectMapper).mapFromGrpc(GrpcVorgangAttachedItemTestFactory.ITEM); + } + + @Test + void shouldCallMapperFromItemMap() { + mapper.fromItem(GrpcVorgangAttachedItemTestFactory.create()); + + verify(mapper).fromItemMap(WiedervorlageTestFactory.createAsMap(), GrpcVorgangAttachedItemTestFactory.VERSION); + } + } + @DisplayName("Map from item map") @Nested class TestFromItemMap { @@ -31,6 +67,13 @@ class WiedervorlageMapperTest { assertThat(wiedervorlage.getId()).isEqualTo(WiedervorlageTestFactory.ID); } + @Test + void shouldMapVersion() { + var wiedervorlage = map(); + + assertThat(wiedervorlage.getVersion()).isEqualTo(WiedervorlageTestFactory.VERSION); + } + @Test void shouldMapDone() { var wiedervorlage = map(); @@ -82,7 +125,7 @@ class WiedervorlageMapperTest { wiedervorlageWithoutAttachments.putAll(WiedervorlageTestFactory.createAsMap()); wiedervorlageWithoutAttachments.remove(WiedervorlageMapper.ATTACHMENTS); - var wiedervorlage = mapper.fromItemMap(wiedervorlageWithoutAttachments); + var wiedervorlage = mapper.fromItemMap(wiedervorlageWithoutAttachments, WiedervorlageTestFactory.VERSION); assertThat(wiedervorlage.getAttachments()).isEmpty(); } @@ -96,7 +139,7 @@ class WiedervorlageMapperTest { @Test void shouldMapAttachmentList() { - var wiedervorlage = mapper.fromItemMap(createWiedervorlageAsMapWithMultipleAttachments()); + var wiedervorlage = mapper.fromItemMap(createWiedervorlageAsMapWithMultipleAttachments(), WiedervorlageTestFactory.VERSION); assertThat(wiedervorlage.getAttachments()).hasSize(2); assertThat(wiedervorlage.getAttachments().get(0)).isEqualTo(BinaryFileTestFactory.FILE_ID); @@ -112,7 +155,7 @@ class WiedervorlageMapperTest { } private Wiedervorlage map() { - return mapper.fromItemMap(WiedervorlageTestFactory.createAsMap()); + return mapper.fromItemMap(WiedervorlageTestFactory.createAsMap(), WiedervorlageTestFactory.VERSION); } } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssemblerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssemblerTest.java index 7aeb26900300ecbf2698e4b0b60000839e685274..9106cf6495d827777b93143782f93cdc6d52dd1e 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssemblerTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageModelAssemblerTest.java @@ -1,7 +1,5 @@ package de.itvsh.goofy.wiedervorlage; -import static org.assertj.core.api.Assertions.*; - import java.util.Collections; import org.junit.jupiter.api.Nested; @@ -12,6 +10,8 @@ import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.server.EntityLinks; +import static org.assertj.core.api.Assertions.*; + import de.itvsh.goofy.common.file.OzgFileTestFactory; import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; @@ -28,8 +28,9 @@ class WiedervorlageModelAssemblerTest { @Nested class TestLinksOnModel { - private final String COMMAND_BY_WIEDERVORLAGE_PATH = WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS.replace("{wiedervorlageId}", - WiedervorlageTestFactory.ID); + private static final String COMMAND_BY_WIEDERVORLAGE_PATH = WiedervorlageCommandController.WIEDERVORLAGE_COMMANDS + .replace("{wiedervorlageId}", WiedervorlageTestFactory.ID) + .replace("{wiedervorlageVersion}", String.valueOf(WiedervorlageTestFactory.VERSION)); @Test void shouldHaveSelfLink() { diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteServiceTest.java index ab6761aaee84a45d2ca86ffdf0051715abb25ea4..307fa72a02e549754a8dac1940e5bb4f38c5bd45 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteServiceTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageRemoteServiceTest.java @@ -1,6 +1,5 @@ package de.itvsh.goofy.wiedervorlage; -import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; @@ -20,10 +19,11 @@ import org.mockito.Mock; import org.mockito.Spy; import org.springframework.context.ApplicationContext; +import static org.assertj.core.api.Assertions.*; + import de.itvsh.goofy.ApplicationTestFactory; import de.itvsh.goofy.vorgang.GrpcVorgangAttachedItemTestFactory; import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; -import de.itvsh.kop.pluto.common.grpc.GrpcObjectMapper; import de.itvsh.ozg.pluto.grpc.clientAttribute.ClientAttributeServiceGrpc.ClientAttributeServiceBlockingStub; import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcAccessPermission; import de.itvsh.ozg.pluto.grpc.clientAttribute.GrpcDeleteClientAttributeRequest; @@ -47,8 +47,6 @@ class WiedervorlageRemoteServiceTest { @Mock private WiedervorlageMapper mapper; @Mock - private GrpcObjectMapper grpcObjectMapper; - @Mock private ApplicationContext applicationContext; @Nested @@ -78,21 +76,14 @@ class WiedervorlageRemoteServiceTest { @BeforeEach void mockGrpcMapper() { - when(grpcObjectMapper.mapFromGrpc(any())).thenReturn(WiedervorlageTestFactory.createAsMap()); - } - - @Test - void shouldCallForGrpcObject() { - callFindById(); - - verify(grpcObjectMapper).mapFromGrpc(GrpcVorgangAttachedItemTestFactory.ITEM); + when(mapper.fromItem(any())).thenReturn(WiedervorlageTestFactory.create()); } @Test void shouldCallForWiedervorlage() { callFindById(); - verify(mapper).fromItemMap(WiedervorlageTestFactory.createAsMap()); + verify(mapper).fromItem(GrpcVorgangAttachedItemTestFactory.create()); } private void callFindById() { @@ -141,8 +132,7 @@ class WiedervorlageRemoteServiceTest { @BeforeEach void initMocks() { when(vorgangAttachedItemServiceStub.getById(any())).thenReturn(response); - when(grpcObjectMapper.mapFromGrpc(any())).thenReturn(WiedervorlageTestFactory.createAsMap()); - when(mapper.fromItemMap(any())).thenReturn(WiedervorlageTestFactory.create()); + when(mapper.fromItem(any())).thenReturn(WiedervorlageTestFactory.create()); } @Test @@ -152,18 +142,11 @@ class WiedervorlageRemoteServiceTest { verify(vorgangAttachedItemServiceStub).getById(request); } - @Test - void shouldCallGrpcObjectMapper() { - service.getById(WiedervorlageTestFactory.ID); - - verify(grpcObjectMapper).mapFromGrpc(GrpcVorgangAttachedItemTestFactory.ITEM); - } - @Test void shouldCallWiedervorlageMapper() { service.getById(WiedervorlageTestFactory.ID); - verify(mapper).fromItemMap(WiedervorlageTestFactory.createAsMap()); + verify(mapper).fromItem(GrpcVorgangAttachedItemTestFactory.create()); } @Test diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageServiceTest.java index 1609042fd1f5e58458f8dffa0dd91f1970e9c338..a3621a9d1f74a6170e124c36ad487de1520e733f 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageServiceTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageServiceTest.java @@ -1,22 +1,33 @@ package de.itvsh.goofy.wiedervorlage; -import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.time.LocalDate; +import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.util.Optional; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatchers; +import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; +import static org.assertj.core.api.Assertions.*; + +import de.itvsh.goofy.common.attacheditem.VorgangAttachedItemService; +import de.itvsh.goofy.common.command.Command; +import de.itvsh.goofy.common.command.CommandService; +import de.itvsh.goofy.common.command.CommandTestFactory; +import de.itvsh.goofy.common.user.CurrentUserService; +import de.itvsh.goofy.common.user.GoofyUserTestFactory; import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; class WiedervorlageServiceTest { @@ -24,9 +35,98 @@ class WiedervorlageServiceTest { @Spy @InjectMocks private WiedervorlageService service; - @Mock private WiedervorlageRemoteService remoteService; + @Mock + private VorgangAttachedItemService vorgangAttachedItemService; + @Mock + private CommandService commandService; + @Mock + private CurrentUserService currentUserService; + + @DisplayName("Create wiedervorlage") + @Nested + class TestCreateWiedervorlage { + + @DisplayName("should") + @Nested + class TestCalls { + + @BeforeEach + void mockServices() { + doReturn(WiedervorlageTestFactory.create()).when(service).addCreated(any()); + when(vorgangAttachedItemService.createNewWiedervorlage(any(), any())).thenReturn(CommandTestFactory.create()); + } + + @DisplayName("add created") + @Test + void shouldAddCreated() { + callCreateWiedervorlage(); + + verify(service).addCreated(any(Wiedervorlage.class)); + } + + @DisplayName("call vorgangattacheditem service") + @Test + void shouldCallVorgangAttachedItemService() { + callCreateWiedervorlage(); + + verify(vorgangAttachedItemService).createNewWiedervorlage(any(Wiedervorlage.class), eq(VorgangHeaderTestFactory.ID)); + } + } + + @DisplayName("Add created") + @Nested + class TestAddCreated { + + @BeforeEach + void mockServices() { + when(currentUserService.getUserId()).thenReturn(GoofyUserTestFactory.ID); + } + + @Test + void shouldSetCreatedAt() throws Exception { + var wiedervorlage = callAddCreated(); + + assertThat(wiedervorlage.getCreatedAt()).isNotNull().isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS)); + } + + @Test + void shouldSetCreatedBy() throws Exception { + var wiedervorlage = callAddCreated(); + + assertThat(wiedervorlage.getCreatedBy()).isEqualTo(GoofyUserTestFactory.ID.toString()); + } + + private Wiedervorlage callAddCreated() { + return service.addCreated(WiedervorlageTestFactory.createBuilder().createdAt(null).createdBy(null).build()); + } + } + + private Command callCreateWiedervorlage() { + return service.createWiedervorlage(WiedervorlageTestFactory.create(), VorgangHeaderTestFactory.ID); + } + } + + @DisplayName("Edit wiedervorlage") + @Nested + class TestEditWiedervorlage { + + @Captor + private ArgumentCaptor<Wiedervorlage> wiedervorlageCaptor; + + @Test + void shouldCallVorgangAttachedItemService() { + callEditWiedervorlage(); + + verify(vorgangAttachedItemService).editWiedervorlage(any(Wiedervorlage.class), eq(WiedervorlageTestFactory.ID), + eq(WiedervorlageTestFactory.VERSION)); + } + + private Command callEditWiedervorlage() { + return service.editWiedervorlage(WiedervorlageTestFactory.create(), WiedervorlageTestFactory.ID, WiedervorlageTestFactory.VERSION); + } + } @Nested class TestGetById { diff --git a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageTestFactory.java b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageTestFactory.java index 70efe8c69be101ce3dceeb1fbd71e92a34630067..60a2d19554191e09fbab178d699cec4e078a2cfd 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageTestFactory.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/wiedervorlage/WiedervorlageTestFactory.java @@ -13,7 +13,7 @@ import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; public class WiedervorlageTestFactory { public static final String ID = UUID.randomUUID().toString(); - + public static final long VERSION = 73; public static final boolean DONE = false; public static final String CREATED_BY = UUID.randomUUID().toString(); public static final String CREATED_BY_NAME = LoremIpsum.getInstance().getName(); @@ -32,6 +32,7 @@ public class WiedervorlageTestFactory { public static Wiedervorlage.WiedervorlageBuilder createBuilder() { return Wiedervorlage.builder() .id(ID) + .version(VERSION) .done(DONE) .betreff(BETREFF) .beschreibung(BESCHREIBUNG) diff --git a/pom.xml b/pom.xml index d777589e440e5c9b114b123c98bd5de9706b6a01..c1ef0b7be4e8c3bcca6e7bf3c32d8fb63af4bb04 100644 --- a/pom.xml +++ b/pom.xml @@ -5,14 +5,14 @@ <groupId>de.itvsh.ozg</groupId> <artifactId>goofy</artifactId> - <version>0.26.0-SNAPSHOT</version> + <version>0.27.0-SNAPSHOT</version> <name>Goofy Parent</name> <packaging>pom</packaging> <parent> <groupId>de.itvsh.kop.common</groupId> <artifactId>kop-common-parent</artifactId> - <version>1.1.3-SNAPSHOT</version> + <version>1.1.3</version> </parent> <modules> @@ -24,7 +24,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> - <pluto.version>0.26.0-SNAPSHOT</pluto.version> + <pluto.version>0.27.0-SNAPSHOT</pluto.version> </properties> <dependencyManagement>