Skip to content
Snippets Groups Projects
RootViewLinkHandlerTest.java 23.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • package de.ozgcloud.alfa;
    
    import static org.assertj.core.api.Assertions.*;
    import static org.mockito.ArgumentMatchers.*;
    import static org.mockito.Mockito.*;
    
    import java.util.Optional;
    
    
    OZGCloud's avatar
    OZGCloud committed
    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.junit.jupiter.params.ParameterizedTest;
    import org.junit.jupiter.params.provider.EnumSource;
    import org.junit.jupiter.params.provider.EnumSource.Mode;
    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    import org.mockito.Spy;
    import org.springframework.hateoas.Link;
    import org.springframework.hateoas.LinkRelation;
    
    
    OZGCloud's avatar
    OZGCloud committed
    import com.thedeanda.lorem.LoremIpsum;
    
    
    import de.ozgcloud.alfa.common.ModelBuilder;
    import de.ozgcloud.alfa.common.user.CurrentUserService;
    import de.ozgcloud.alfa.common.user.UserId;
    import de.ozgcloud.alfa.common.user.UserProfileTestFactory;
    import de.ozgcloud.alfa.common.user.UserRole;
    import de.ozgcloud.alfa.system.SystemStatusService;
    import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus;
    
    class RootViewLinkHandlerTest {
    
    	@Spy
    	@InjectMocks
    	private RootViewLinkHandler viewLinkHandler;
    	@Mock
    	private CurrentUserService currentUserService;
    	@Mock
    	private SystemStatusService systemStatusService;
    
    	@DisplayName("Add view links")
    	@Nested
    	class TestAddViewLinks {
    
    		@Mock
    		private Root rootResource;
    
    		private Optional<UserId> emptyUserId = Optional.empty();
    
    		@Test
    		void shouldAddVorgaengeAllLink() {
    			var modelBuilder = ModelBuilder.fromEntity(rootResource);
    			viewLinkHandler.addViewLinks(modelBuilder, emptyUserId);
    
    			assertThat(modelBuilder.buildModel().getLink(RootViewLinkHandler.ALL_VORGAENGE_REL))
    					.get().extracting(Link::getHref).isEqualTo("/api/vorgangs?page=0&limit=100");
    		}
    
    		@Test
    		void shouldCallAddSearchAllVorgaengeLink() {
    			var modelBuilder = ModelBuilder.fromEntity(rootResource);
    			viewLinkHandler.addViewLinks(modelBuilder, emptyUserId);
    
    			verify(viewLinkHandler).addSearchAllVorgaengeLink(modelBuilder);
    		}
    
    		@Test
    		void shouldAddLinksForVerwaltungPoststelle() {
    			when(currentUserService.hasRole(UserRole.VERWALTUNG_POSTSTELLE)).thenReturn(true);
    
    			var modelBuilder = ModelBuilder.fromEntity(rootResource);
    			viewLinkHandler.addViewLinks(modelBuilder, emptyUserId);
    
    			verify(viewLinkHandler).addViewLinksForVerwaltungPoststelle(modelBuilder, emptyUserId);
    		}
    
    		@Test
    		void shouldAddLinksForVerwaltungUser() {
    			when(currentUserService.hasRole(UserRole.VERWALTUNG_POSTSTELLE)).thenReturn(false);
    			when(currentUserService.hasRole(UserRole.VERWALTUNG_USER)).thenReturn(true);
    
    			var modelBuilder = ModelBuilder.fromEntity(rootResource);
    			viewLinkHandler.addViewLinks(modelBuilder, emptyUserId);
    
    			verify(viewLinkHandler).addViewLinksForVerwaltungUser(modelBuilder, emptyUserId);
    		}
    
    		@DisplayName("for " + UserRole.VERWALTUNG_POSTSTELLE)
    		@Nested
    		class TestVerwaltungPoststelle {
    
    			private final ModelBuilder<Root> modelBuilder = ModelBuilder.fromEntity(rootResource);
    
    			@Test
    			void shouldCallBuildMyVorgaengeLink() {
    				viewLinkHandler.addViewLinksForVerwaltungPoststelle(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    				verify(viewLinkHandler).buildMyVorgaengeLink(UserProfileTestFactory.ID);
    			}
    
    			@DisplayName("search my vorgaenge")
    			@Nested
    			class TestSearchMyVorgaenge {
    
    				@DisplayName("on configured search server")
    				@Nested
    				class TestOnConfiguredSearchServer {
    
    					@Test
    					void shouldCallBuildSearchMyVorgaengeLink() {
    						when(systemStatusService.isSearchServerAvailable()).thenReturn(true);
    
    						viewLinkHandler.addViewLinksForVerwaltungPoststelle(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    						verify(viewLinkHandler).buildSearchMyVorgaengeLink(UserProfileTestFactory.ID);
    					}
    				}
    
    				@DisplayName("on not configured search server")
    				@Nested
    				class TestOnNotConfiguredSearchServer {
    
    					@Test
    					void shouldNotCallBuildSearchMyVorgaengeLink() {
    						when(systemStatusService.isSearchServerAvailable()).thenReturn(false);
    
    						viewLinkHandler.addViewLinksForVerwaltungPoststelle(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    						verify(viewLinkHandler, never()).buildSearchMyVorgaengeLink(any());
    					}
    				}
    			}
    		}
    
    		@DisplayName("for " + UserRole.VERWALTUNG_USER)
    		@Nested
    		class TestVerwaltungUser {
    
    			private final ModelBuilder<Root> modelBuilder = ModelBuilder.fromEntity(rootResource);
    
    			@Test
    			void shouldCallAddUnassignedVorgaengeLink() {
    				viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    				verify(viewLinkHandler).buildGetAllUnassignedVorgaengeLink();
    			}
    
    			@Test
    			void shouldCallAddMyVorgaengeLink() {
    				viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    				verify(viewLinkHandler).buildMyVorgaengeLink(UserProfileTestFactory.ID);
    			}
    
    			@DisplayName("search my vorgaenge")
    			@Nested
    			class TestSearchMy {
    
    				@DisplayName("on configured search server")
    				@Nested
    				class TestOnConfiguredSearchServer {
    
    					@Test
    					void shouldCallBuildSearchMyVorgaengeLink() {
    						when(systemStatusService.isSearchServerAvailable()).thenReturn(true);
    
    						viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    						verify(viewLinkHandler).buildSearchMyVorgaengeLink(UserProfileTestFactory.ID);
    					}
    				}
    
    				@DisplayName("on not configured search server")
    				@Nested
    				class TestOnNotConfiguredSearchServer {
    
    					@Test
    					void shouldNotCallBuildSearchMyVorgaengeLink() {
    						when(systemStatusService.isSearchServerAvailable()).thenReturn(false);
    
    						viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    						verify(viewLinkHandler, never()).buildSearchMyVorgaengeLink(any());
    					}
    				}
    			}
    
    			@Test
    			void shouldCallAddVorgangStatusLinks() {
    				viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    				verify(viewLinkHandler).addAllVorgangStatusLinks(modelBuilder);
    			}
    
    			@Test
    			void shouldCallAddMyVorgaengeStatusLinks() {
    				viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    				verify(viewLinkHandler).buildMyVorgaengeStatusLinks(UserProfileTestFactory.ID);
    			}
    
    			@Test
    			void shouldCallAddUnassignedVorgaengeStatusLinks() {
    				viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    				verify(viewLinkHandler).buildUnassignedVorgaengeStatusLinks();
    			}
    
    			@DisplayName("search unassigned vorgaenge")
    			@Nested
    			class TestSearchUnassignedVorgaengeLink {
    
    				@DisplayName("with configured search server")
    				@Nested
    				class TestWithConfiguredSearchServer {
    
    					@Test
    					void shouldCallBuildSearchUnassignedVorgaengeLink() {
    						when(systemStatusService.isSearchServerAvailable()).thenReturn(true);
    
    						viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    						verify(viewLinkHandler).buildSearchUnassignedVorgaengeLink();
    					}
    				}
    
    				@DisplayName("with not configured search server")
    				@Nested
    				class TestWithNotConfiguredSearchServer {
    
    					@Test
    					void shouldNotCallBuildSearchUnassignedVorgaengeLink() {
    						when(systemStatusService.isSearchServerAvailable()).thenReturn(false);
    
    						viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    						verify(viewLinkHandler, never()).buildSearchUnassignedVorgaengeLink();
    					}
    				}
    			}
    
    			@DisplayName("vorgaenge with open wiedervorlagen")
    			@Nested
    			class TestVorgaengeWithOpenWiedervorlagen {
    
    				@Test
    				void shouldAddAllLink() {
    					var modelBuilder = ModelBuilder.fromEntity(rootResource);
    					viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    					assertThat(modelBuilder.buildModel().getLink(RootViewLinkHandler.ALL_WIEDERVORLAGEN_REL))
    							.get().extracting(Link::getHref).isEqualTo("/api/vorgangs?page=0&limit=100&nextFrist=exists");
    				}
    
    				@DisplayName("considering user")
    				@Nested
    				class TestConsideringUser {
    
    					@Test
    					void shouldAddAssignedLinkIfExists() {
    						var modelBuilder = ModelBuilder.fromEntity(rootResource);
    						viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    						assertThat(modelBuilder.buildModel().getLink(RootViewLinkHandler.MY_WIEDERVORLAGEN_REL))
    								.get().extracting(Link::getHref)
    								.isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=" + UserProfileTestFactory.ID + "&nextFrist=exists");
    					}
    
    					@Test
    					void shoulNotAddAssignedLinkIfNotExists() {
    						var modelBuilder = ModelBuilder.fromEntity(rootResource);
    						viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.empty());
    
    						assertThat(modelBuilder.buildModel().getLink(RootViewLinkHandler.MY_WIEDERVORLAGEN_REL)).isNotPresent();
    					}
    				}
    
    				@Test
    				void shouldAddUnassignedLink() {
    					var modelBuilder = ModelBuilder.fromEntity(rootResource);
    					viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    					assertThat(modelBuilder.buildModel().getLink(RootViewLinkHandler.UNASSIGNED_WIEDERVORLAGEN_REL))
    							.get().extracting(Link::getHref).isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=&nextFrist=exists");
    				}
    			}
    
    OZGCloud's avatar
    OZGCloud committed
    
    			@Test
    			void shouldAddLinksForUngeleseneNachrichten() {
    				viewLinkHandler.addViewLinksForVerwaltungUser(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    				verify(viewLinkHandler).addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    			}
    
    		}
    
    		@DisplayName("search all vorgaenge")
    		@Nested
    		class TestSearchAllVorgaenge {
    
    			@Test
    			void shouldBeAddedIfSearchServerIsAvailable() {
    				when(systemStatusService.isSearchServerAvailable()).thenReturn(true);
    
    				var modelBuilder = ModelBuilder.fromEntity(rootResource);
    				viewLinkHandler.addSearchAllVorgaengeLink(modelBuilder);
    
    				assertThat(modelBuilder.buildModel().getLink(RootViewLinkHandler.SEARCH_ALL_REL))
    						.get().extracting(Link::getHref).isEqualTo("/api/vorgangs?page=0&limit=100&searchBy={searchBy}");
    			}
    
    			@Test
    			void shouldNotBeAddedIfSearchServerIsUnavailable() {
    				when(systemStatusService.isSearchServerAvailable()).thenReturn(false);
    
    				var modelBuilder = spy(ModelBuilder.fromEntity(rootResource));
    				viewLinkHandler.addSearchAllVorgaengeLink(modelBuilder);
    
    				verify(modelBuilder, never()).addLink(any(Link.class));
    			}
    		}
    
    		@DisplayName("my vorgaenge")
    		@Nested
    		class TestAddMyLink {
    
    			@Test
    			void shouldBeAddedIfUserIsPresent() {
    				var link = viewLinkHandler.buildMyVorgaengeLink(UserProfileTestFactory.ID);
    
    
    OZGCloud's avatar
    OZGCloud committed
    				assertThat(link.getHref()).isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=" + UserProfileTestFactory.ID);
    
    			}
    		}
    
    		@DisplayName("search my vorgaenge")
    		@Nested
    		class TestSearchMyVorgaengeLink {
    
    			@Test
    			void shouldCallBuild() {
    				viewLinkHandler.buildSearchMyVorgaengeLink(UserProfileTestFactory.ID);
    
    				verify(viewLinkHandler).buildGetAllVorgaengeByAssignedToAndSearchByLink(UserProfileTestFactory.ID);
    			}
    
    			@Test
    			void shouldBuildLinkWithMyVorgaengeRel() {
    				var link = viewLinkHandler.buildSearchMyVorgaengeLink(UserProfileTestFactory.ID);
    
    				assertThat(link.getRel()).extracting(LinkRelation::value).isEqualTo(RootViewLinkHandler.SEARCH_MY_VORGEANGE_REL);
    			}
    		}
    
    		@DisplayName("search unassigned vorgaenge")
    		@Nested
    		class TestSearchUnassignedVorgaenge {
    
    			@Test
    			void shouldBuildLink() {
    				var link = viewLinkHandler.buildSearchUnassignedVorgaengeLink();
    
    				assertThat(link.getHref()).isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=&searchBy={searchBy}");
    				assertThat(link.getRel().value()).isEqualTo(RootViewLinkHandler.SEARCH_UNASSIGNED_VORGEANGE_REL);
    			}
    		}
    
    		@DisplayName("search all vorgaenge by assignedTo")
    		@Nested
    		class TestBuildGetAllVorgaengeByAssigendToAndSearchLink {
    
    			@Test
    			void shouldBuildLink() {
    				var link = viewLinkHandler.buildGetAllVorgaengeByAssignedToAndSearchByLink(UserProfileTestFactory.ID).withSelfRel();
    
    				assertThat(link).extracting(Link::getHref)
    						.isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=" + UserProfileTestFactory.ID.toString() + "&searchBy={searchBy}");
    			}
    		}
    
    		@DisplayName("all vorgang status")
    		@Nested
    		class TestAddAllVorgangStatusLinks {
    
    			private final ModelBuilder<Root> modelBuilder = ModelBuilder.fromEntity(rootResource);
    
    			@Test
    			void shouldCallAddVorgangStatusLinks() {
    				viewLinkHandler.addAllVorgangStatusLinks(modelBuilder);
    
    				verify(viewLinkHandler).addVorgangStatusLinks(modelBuilder, RootViewLinkHandler.VORGAENGE_ALL_REL_TEMPLATE);
    			}
    		}
    
    		@DisplayName("my vorgang status")
    		@Nested
    		class TestAddMyVorgangStatusLinks {
    
    			@Test
    			void shouldCallAddVorgangStatusLink() {
    				viewLinkHandler.buildMyVorgaengeStatusLinks(UserProfileTestFactory.ID);
    
    				verify(viewLinkHandler).buildVorgangStatusLinks(RootViewLinkHandler.VORGAENGE_MY_REL_TEMPLATE, UserProfileTestFactory.ID);
    			}
    
    		}
    
    		@DisplayName("vorgang status")
    		@Nested
    		class TestBuildVorgangStatusLinks {
    
    			private final UserId userId = UserProfileTestFactory.ID;
    
    			@Test
    			void shouldCallBuildVorgangListByPageLink() {
    				viewLinkHandler.buildVorgangStatusLinks(RootViewLinkHandler.VORGAENGE_ALL_REL_TEMPLATE, UserProfileTestFactory.ID);
    
    				verify(viewLinkHandler, times(7)).buildGetAllVorgaengeByAssignedToAndStatus(
    						any(VorgangStatus.class),
    						eq(RootViewLinkHandler.VORGAENGE_ALL_REL_TEMPLATE),
    						eq(userId));
    			}
    
    			@Test
    			void shouldCallFormatLinkRelTemplate() {
    				viewLinkHandler.buildVorgangStatusLinks(RootViewLinkHandler.VORGAENGE_ALL_REL_TEMPLATE, UserProfileTestFactory.ID);
    
    				verify(viewLinkHandler, times(7)).formatLinkRelTemplate(eq(RootViewLinkHandler.VORGAENGE_ALL_REL_TEMPLATE), any(VorgangStatus.class));
    			}
    
    			@Test
    			void shouldBuildLinks() {
    				var links = viewLinkHandler.buildVorgangStatusLinks(RootViewLinkHandler.VORGAENGE_ALL_REL_TEMPLATE, UserProfileTestFactory.ID);
    
    				assertThat(links).hasSize(7);
    			}
    		}
    
    		@DisplayName("format linkrel template")
    		@Nested
    		class TestFormatLinkRelTemplate {
    
    			@ParameterizedTest
    			@EnumSource(mode = Mode.INCLUDE, names = { "NEU", "ANGENOMMEN", "IN_BEARBEITUNG", "BESCHIEDEN", "ABGESCHLOSSEN", "VERWORFEN",
    					"ZU_LOESCHEN" })
    			void shouldCallFormatLinkRelTemplateWithAllVorgaengeTemplate(VorgangStatus status) {
    				var linkRel = viewLinkHandler.formatLinkRelTemplate(RootViewLinkHandler.VORGAENGE_ALL_REL_TEMPLATE, status);
    
    				assertThat(linkRel).isEqualTo("vorgaenge_" + status.toString().toLowerCase() + "_all");
    			}
    
    			@ParameterizedTest
    			@EnumSource(mode = Mode.INCLUDE, names = { "NEU", "ANGENOMMEN", "IN_BEARBEITUNG", "BESCHIEDEN", "ABGESCHLOSSEN", "VERWORFEN",
    					"ZU_LOESCHEN" })
    			void shouldCallFormatLinkRelTemplateWithMyVorgaengeTemplate(VorgangStatus status) {
    				var linkRel = viewLinkHandler.formatLinkRelTemplate(RootViewLinkHandler.VORGAENGE_MY_REL_TEMPLATE, status);
    
    				assertThat(linkRel).isEqualTo("vorgaenge_" + status.toString().toLowerCase() + "_my");
    			}
    
    			@ParameterizedTest
    			@EnumSource(mode = Mode.INCLUDE, names = { "NEU", "ANGENOMMEN", "IN_BEARBEITUNG", "BESCHIEDEN", "ABGESCHLOSSEN", "VERWORFEN",
    					"ZU_LOESCHEN" })
    			void shouldCallFormatLinkRelTemplateWithUnassignedVorgaengeTemplate(VorgangStatus status) {
    				var linkRel = viewLinkHandler.formatLinkRelTemplate(RootViewLinkHandler.VORGAENGE_UNASSIGNED_REL_TEMPLATE, status);
    
    				assertThat(linkRel).isEqualTo("vorgaenge_" + status.toString().toLowerCase() + "_unassigned");
    			}
    		}
    
    		@DisplayName("build get all vorgaenge by status")
    		@Nested
    		class TestBuildGetAllByStatus {
    
    			@ParameterizedTest
    			@EnumSource(mode = Mode.INCLUDE, names = { "NEU", "ANGENOMMEN", "IN_BEARBEITUNG", "BESCHIEDEN", "ABGESCHLOSSEN", "VERWORFEN",
    					"ZU_LOESCHEN" })
    			void shouldAddByStatus(VorgangStatus status) {
    				var link = viewLinkHandler.buildGetAllVorgaengeByStatus(status, RootViewLinkHandler.VORGAENGE_MY_REL_TEMPLATE);
    
    				assertThat(link.getHref()).isEqualTo("/api/vorgangs?page=0&limit=100&status=" + status.toString());
    			}
    
    		}
    
    		@DisplayName("build get all vorgaenge by assignedTo and status")
    		@Nested
    		class TestBuildGetAllVorgaengeByAssignedToAndStatus {
    
    			@ParameterizedTest
    			@EnumSource(mode = Mode.INCLUDE, names = { "NEU", "ANGENOMMEN", "IN_BEARBEITUNG", "BESCHIEDEN", "ABGESCHLOSSEN", "VERWORFEN",
    					"ZU_LOESCHEN" })
    			void shouldAddByAssignedToAndStatus(VorgangStatus status) {
    				var link = viewLinkHandler.buildGetAllVorgaengeByAssignedToAndStatus(status, RootViewLinkHandler.VORGAENGE_MY_REL_TEMPLATE,
    						UserProfileTestFactory.ID);
    
    				assertThat(link.getHref()).isEqualTo(
    						"/api/vorgangs?page=0&limit=100&assignedTo=" + UserProfileTestFactory.ID.toString() + "&status=" + status.toString());
    			}
    		}
    
    		@DisplayName("build get all unassigned vorgaenge by status")
    		@Nested
    		class TestBuildGetAllUnassignedVorgaengeByStatus {
    
    			@ParameterizedTest
    			@EnumSource(mode = Mode.INCLUDE, names = { "NEU", "ANGENOMMEN", "IN_BEARBEITUNG", "BESCHIEDEN", "ABGESCHLOSSEN", "VERWORFEN",
    					"ZU_LOESCHEN" })
    			void shouldAddByUnassignedToAndStatus(VorgangStatus status) {
    				var link = viewLinkHandler.buildGetAllVorgaengeByAssignedToAndStatus(status, RootViewLinkHandler.VORGAENGE_MY_REL_TEMPLATE,
    						UserId.empty());
    
    				assertThat(link.getHref()).isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=&status=" + status.toString());
    			}
    		}
    	}
    
    
    OZGCloud's avatar
    OZGCloud committed
    	@Nested
    	class TestBuildGelAllByUngeleseneNachrichtenLink {
    
    		@Test
    		void shouldHaveLinkHref() {
    			var link = viewLinkHandler.buildGelAllByUngeleseneNachrichtenLink();
    
    			assertThat(link)
    					.extracting(Link::getHref)
    					.isEqualTo("/api/vorgangs?page=0&limit=100&nachrichten=ungelesene");
    		}
    
    		@Test
    		void shouldHaveLinkRel() {
    			var link = viewLinkHandler.buildGelAllByUngeleseneNachrichtenLink();
    
    			assertThat(link)
    					.extracting(Link::getRel)
    					.extracting(LinkRelation::value)
    					.isEqualTo(RootViewLinkHandler.ALL_UNGELESENE_NACHRICHTEN_REL);
    		}
    	}
    
    	@Nested
    	class TestBuildGetAllByAssignedToAndUngeleseneNachrichten {
    
    		@Nested
    		class AssignTo {
    
    			@Test
    			void shouldHaveLink() {
    				var link = viewLinkHandler.buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID,
    						RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL);
    
    				assertThat(link)
    						.extracting(Link::getHref)
    						.isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=" + UserProfileTestFactory.ID + "&nachrichten=ungelesene");
    			}
    
    			@Test
    			void shouldHaveLinkRel() {
    				var link = viewLinkHandler.buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID,
    						RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL);
    
    				assertThat(link)
    						.extracting(Link::getRel)
    						.extracting(LinkRelation::value)
    						.isEqualTo(RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL);
    			}
    		}
    
    		@Nested
    		class Unassigned {
    
    			@Test
    			void shouldHaveLink() {
    				var link = viewLinkHandler.buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(),
    						RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL);
    
    				assertThat(link)
    						.extracting(Link::getHref)
    						.isEqualTo("/api/vorgangs?page=0&limit=100&assignedTo=&nachrichten=ungelesene");
    			}
    
    			@Test
    			void shouldHaveLinkRel() {
    				var link = viewLinkHandler.buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(),
    						RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL);
    
    				assertThat(link)
    						.extracting(Link::getRel)
    						.extracting(LinkRelation::value)
    						.isEqualTo(RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL);
    			}
    
    		}
    
    	}
    
    	@Nested
    	class TestAddGetByUngeleseneNachrichtenLinks {
    
    		@Mock
    		private Root rootResource;
    		private final ModelBuilder<Root> modelBuilder = ModelBuilder.fromEntity(rootResource);
    		private final Link linkAllUngeleseneNachrichten = Link.of(LoremIpsum.getInstance().getUrl());
    		private final Link linkMyUngeleseneNachrichten = Link.of(LoremIpsum.getInstance().getUrl());
    		private final Link linkUnassignedUngeleseneNachrichten = Link.of(LoremIpsum.getInstance().getUrl());
    
    		@BeforeEach
    		void setUp() {
    			doReturn(linkAllUngeleseneNachrichten).when(viewLinkHandler).buildGelAllByUngeleseneNachrichtenLink();
    			doReturn(linkUnassignedUngeleseneNachrichten).when(viewLinkHandler)
    					.buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(), RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL);
    		}
    
    		@Test
    		void shouldBuildLinkForUngeleseneNachrichten() {
    			viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    			verify(viewLinkHandler).buildGelAllByUngeleseneNachrichtenLink();
    		}
    
    		@Test
    		void shouldAddLinkForUngeleseneNachrichten() {
    			var modelBuilder = ModelBuilder.fromEntity(rootResource);
    
    			viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    			assertThat(modelBuilder.buildModel().getLinks()).contains(linkAllUngeleseneNachrichten);
    		}
    
    		@Test
    		void shouldBuildLinkForUnassignedUngeleseneNachrichten() {
    			viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.empty());
    
    			verify(viewLinkHandler).buildGetAllByAssignedToAndUngeleseneNachrichten(UserId.empty(),
    					RootViewLinkHandler.UNASSIGNED_UNGELESENE_NACHRICHTEN_REL);
    		}
    
    		@Test
    		void shouldAddLinkForUnassignedUngeleseneNachrichten() {
    			var modelBuilder = ModelBuilder.fromEntity(rootResource);
    
    			viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.empty());
    
    			assertThat(modelBuilder.buildModel().getLinks()).contains(linkUnassignedUngeleseneNachrichten);
    		}
    
    		@Nested
    		class UsedIdExists {
    
    			@BeforeEach
    			void setUp() {
    				doReturn(linkMyUngeleseneNachrichten).when(viewLinkHandler).buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID,
    						RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL);
    			}
    
    			@Test
    			void shouldBuildLinkForMyUngeleseneNachrichten() {
    				viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    				verify(viewLinkHandler).buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID,
    						RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL);
    			}
    
    			@Test
    			void shouldAddLinkForMyUngeleseneNachrichten() {
    				var modelBuilder = ModelBuilder.fromEntity(rootResource);
    
    				viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.of(UserProfileTestFactory.ID));
    
    				assertThat(modelBuilder.buildModel().getLinks()).contains(linkMyUngeleseneNachrichten);
    			}
    		}
    
    		@Nested
    		class UserIdEmpty {
    
    			@Test
    			void shouldNotBuildLinkForMyUngeleseneNachrichten() {
    				viewLinkHandler.addGetByUngeleseneNachrichtenLinks(modelBuilder, Optional.empty());
    
    				verify(viewLinkHandler, never()).buildGetAllByAssignedToAndUngeleseneNachrichten(UserProfileTestFactory.ID,
    						RootViewLinkHandler.MY_UNGELESENE_NACHRICHTEN_REL);
    			}
    		}
    
    	}
    
    
    	//	@DisplayName("Test user assistance documentation link")
    	//	@Nested
    	//	class TestDocumentationLink {
    	//
    	//		private static final String DOCUMENTATION_URL = "http://alfa-docs";
    	//
    	//		@Test
    	//		void shouldNotHaveLinkForUndefinedUrl() {
    	//			var link = viewLinkHandler.toModel(root);
    	//
    	//			assertThat(link.getLink(RootViewLinkHandler.REL_DOCUMENTATIONS)).isEmpty();
    	//		}
    	//
    	//		@Test
    	//		void shouldHaveLinkForDefinedUrl() {
    	//			ReflectionTestUtils.setField(viewLinkHandler, "documentationUrl", DOCUMENTATION_URL);
    	//
    	//			var link = viewLinkHandler.toModel(root);
    	//
    	//			assertThat(link.getLink(RootViewLinkHandler.REL_DOCUMENTATIONS))
    	//					.isPresent()
    	//					.map(Link::getHref)
    	//					.hasValue(DOCUMENTATION_URL);
    	//		}
    	//
    	//		@Test
    	//		void shouldNotHaveLinkForEmptyStringUrl() {
    	//			ReflectionTestUtils.setField(viewLinkHandler, "documentationUrl", "");
    	//
    	//			var link = viewLinkHandler.toModel(root);
    	//
    	//			assertThat(link.getLink(RootViewLinkHandler.REL_DOCUMENTATIONS)).isEmpty();
    	//		}
    	//
    	//	}