package uk.ac.ox.zoo.seeg.abraid.mp.publicsite.web.user.account; import org.junit.Test; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.ui.Model; import org.springframework.ui.ModelMap; import uk.ac.ox.zoo.seeg.abraid.mp.common.domain.Expert; import uk.ac.ox.zoo.seeg.abraid.mp.common.domain.ValidatorDiseaseGroup; import uk.ac.ox.zoo.seeg.abraid.mp.common.dto.json.AbraidJsonObjectMapper; import uk.ac.ox.zoo.seeg.abraid.mp.common.service.core.DiseaseService; import uk.ac.ox.zoo.seeg.abraid.mp.common.service.core.ExpertService; import uk.ac.ox.zoo.seeg.abraid.mp.publicsite.domain.JsonExpertDetails; import uk.ac.ox.zoo.seeg.abraid.mp.publicsite.security.CurrentUserService; import uk.ac.ox.zoo.seeg.abraid.mp.publicsite.validator.ValidationException; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.*; /** * Tests for AccountController. * Copyright (c) 2014 University of Oxford */ public class AccountControllerTest { private static AccountController createTarget(int userId, ExpertService expertServiceIn, DiseaseService diseaseService, AccountControllerValidator adminControllerValidator, AccountControllerHelper accountControllerTransactionHelper, CurrentUserService currentUserService) { CurrentUserService userService; if (currentUserService == null) { userService = getCurrentUserService(); when(userService.getCurrentUserId()).thenReturn(userId); } else { userService = currentUserService; } ExpertService expertService = expertServiceIn; if (expertService == null) { expertService = mock(ExpertService.class); when(expertService.getExpertById(userId)).thenReturn(mock(Expert.class)); } return new AccountController( userService, expertService, diseaseService == null ? mock(DiseaseService.class) : diseaseService, new AbraidJsonObjectMapper(), adminControllerValidator == null ? mock(AccountControllerValidator.class) : adminControllerValidator, accountControllerTransactionHelper == null ? mock(AccountControllerHelper.class) : accountControllerTransactionHelper); } @Test public void getAccountEditPageReturnsCorrectTemplate() throws Exception { // Arrange AccountController target = createTarget(1, null, null, null, null, null); // Act String result = target.getAccountEditPage(mock(ModelMap.class)); // Assert assertThat(result).isEqualTo("account/edit"); } @Test public void getAccountEditPageAssignsCorrectModelData() throws Exception { // Arrange ExpertService expertService = mock(ExpertService.class); Expert expert = mock(Expert.class); when(expertService.getExpertById(anyInt())).thenReturn(expert); when(expert.getName()).thenReturn("name"); when(expert.getJobTitle()).thenReturn("job"); when(expert.getInstitution()).thenReturn("institute"); when(expert.getVisibilityRequested()).thenReturn(true); when(expert.getValidatorDiseaseGroups()).thenReturn(createMockValidatorDiseaseGroups()); DiseaseService diseaseService = mock(DiseaseService.class); when(diseaseService.getAllValidatorDiseaseGroups()).thenReturn(createMockValidatorDiseaseGroups()); AccountController target = createTarget(1, expertService, diseaseService, null, null, null); // Act ModelMap model = mock(ModelMap.class); target.getAccountEditPage(model); // Assert verify(model).addAttribute("diseases", "[{\"id\":1,\"name\":\"1\"},{\"id\":2,\"name\":\"2\"},{\"id\":3,\"name\":\"3\"}]"); verify(model).addAttribute("jsonExpert", "{\"name\":\"name\",\"visibilityRequested\":true,\"diseaseInterests\":[1,2,3],\"jobTitle\":\"job\",\"institution\":\"institute\"}"); } @Test public void submitAccountEditPageReturnsBadRequestIfValidationFails() throws Exception { // Arrange AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountController target = createTarget(1, null, null, validator, null, null); when(validator.validate(any(JsonExpertDetails.class))).thenReturn(Arrays.asList("FAIL1", "FAIL2")); // Act ResponseEntity<Collection<String>> result = target.submitAccountEditPage(mock(JsonExpertDetails.class)); // Assert assertThat(result.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); assertThat(result.getBody()).containsOnly("FAIL1", "FAIL2"); } @Test public void submitAccountEditPageReturnsBadRequestIfSaveFails() throws Exception { // Arrange AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); AccountController target = createTarget(1, null, null, validator, helper, null); doThrow(new ValidationException(Arrays.asList("FAIL3"))) .when(helper).processExpertProfileUpdateAsTransaction(anyInt(), any(JsonExpertDetails.class)); // Act ResponseEntity<Collection<String>> result = target.submitAccountEditPage(mock(JsonExpertDetails.class)); // Assert assertThat(result.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); assertThat(result.getBody()).containsOnly("FAIL3"); } @Test public void submitAccountEditPageSavesExpertAndReturnsNoContentForValidRequest() throws Exception { AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); int userId = 99; AccountController target = createTarget(userId, null, null, validator, helper, null); // Act JsonExpertDetails expert = mock(JsonExpertDetails.class); ResponseEntity<Collection<String>> result = target.submitAccountEditPage(expert); // Assert verify(helper).processExpertProfileUpdateAsTransaction(userId, expert); assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); } @Test public void getChangeEmailPageReturnsCorrectTemplate() throws Exception { // Arrange ExpertService expertService = mock(ExpertService.class); when(expertService.getExpertById(1)).thenReturn(mock(Expert.class)); when(expertService.getExpertById(1).getEmail()).thenReturn("expectedEmail"); AccountController target = createTarget(1, expertService, null, null, null, null); ModelMap model = mock(ModelMap.class); // Act String result = target.getChangeEmailPage(model); // Assert verify(model).addAttribute("email", "expectedEmail"); assertThat(result).isEqualTo("account/email"); } @Test public void submitChangeEmailPageReturnsBadRequestIfValidationFails() throws Exception { // Arrange AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); AccountController target = createTarget(1, null, null, validator, helper, null); when(validator.validateEmailChange(anyString(), anyString(), anyInt())).thenReturn(Arrays.asList("FAIL1", "FAIL2")); // Act ResponseEntity<Collection<String>> result = target.submitChangeEmailPage("email", "password"); // Assert assertThat(result.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); assertThat(result.getBody()).containsOnly("FAIL1", "FAIL2"); } @Test public void submitChangeEmailPageReturnsBadRequestIfSaveFails() throws Exception { // Arrange AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); AccountController target = createTarget(1, null, null, validator, helper, null); doThrow(new ValidationException(Arrays.asList("FAIL3"))) .when(helper).processExpertEmailChangeAsTransaction(anyInt(), anyString()); // Act ResponseEntity<Collection<String>> result = target.submitChangeEmailPage("email", "password"); // Assert assertThat(result.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); assertThat(result.getBody()).containsOnly("FAIL3"); } @Test public void submitChangeEmailPageSavesPasswordAndReturnsNoContentForValidRequest() throws Exception { AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); int userId = 99; AccountController target = createTarget(userId, null, null, validator, helper, null); // Act ResponseEntity<Collection<String>> result = target.submitChangeEmailPage("email", "password"); // Assert verify(helper).processExpertEmailChangeAsTransaction(userId, "email"); assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); } @Test public void getChangePasswordPageReturnsCorrectTemplate() throws Exception { // Arrange AccountController target = createTarget(1, null, null, null, null, null); // Act String result = target.getChangePasswordPage(); // Assert assertThat(result).isEqualTo("account/password"); } @Test public void submitChangePasswordPageReturnsBadRequestIfValidationFails() throws Exception { // Arrange AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); AccountController target = createTarget(1, null, null, validator, helper, null); when(validator.validatePasswordChange(anyString(), anyString(), anyString(), anyInt())).thenReturn(Arrays.asList("FAIL1", "FAIL2")); // Act ResponseEntity<Collection<String>> result = target.submitChangePasswordPage("oldPassword", "newPassword", "confirmPassword"); // Assert assertThat(result.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); assertThat(result.getBody()).containsOnly("FAIL1", "FAIL2"); } @Test public void submitChangePasswordPageReturnsBadRequestIfSaveFails() throws Exception { // Arrange AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); AccountController target = createTarget(1, null, null, validator, helper, null); doThrow(new ValidationException(Arrays.asList("FAIL3"))) .when(helper).processExpertPasswordChangeAsTransaction(anyInt(), anyString()); // Act ResponseEntity<Collection<String>> result = target.submitChangePasswordPage("oldPassword", "newPassword", "confirmPassword"); // Assert assertThat(result.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); assertThat(result.getBody()).containsOnly("FAIL3"); } @Test public void submitChangePasswordPageSavesPasswordAndReturnsNoContentForValidRequest() throws Exception { AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); int userId = 99; AccountController target = createTarget(userId, null, null, validator, helper, null); // Act ResponseEntity<Collection<String>> result = target.submitChangePasswordPage("oldPassword", "newPassword", "confirmPassword"); // Assert verify(helper).processExpertPasswordChangeAsTransaction(userId, "newPassword"); assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); } @Test public void getPasswordResetRequestPageReturnsCorrectTemplate() throws Exception { // Arrange AccountController target = createTarget(1, null, null, null, null, getCurrentUserService()); // Act String result = target.getPasswordResetRequestPage(); // Assert assertThat(result).isEqualTo("account/reset/request"); } @Test public void getPasswordResetRequestPageRedirectsLoggedInUsers() throws Exception { // Arrange CurrentUserService userService = getCurrentUserService(); when(userService.getCurrentUserId()).thenReturn(1); AccountController target = createTarget(1, null, null, null, null, userService); // Act String result = target.getPasswordResetRequestPage(); // Assert assertThat(result).isEqualTo("redirect:/"); } @Test public void submitPasswordResetRequestPageReturnsBadRequestIfValidationFails() throws Exception { // Arrange AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); AccountController target = createTarget(1, null, null, validator, helper, null); when(validator.validateNewPasswordResetRequest(anyString())).thenReturn(Arrays.asList("FAIL1", "FAIL2")); // Act ResponseEntity<Collection<String>> result = target.submitPasswordResetRequestPage("email", mock(HttpServletRequest.class)); // Assert assertThat(result.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); assertThat(result.getBody()).containsOnly("FAIL1", "FAIL2"); } @Test public void submitPasswordResetRequestPageReturnsBadRequestIfHelperFails() throws Exception { // Arrange AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); AccountController target = createTarget(1, null, null, validator, helper, null); doThrow(new ValidationException(Arrays.asList("FAIL3"))) .when(helper).processExpertPasswordResetRequestAsTransaction(eq("email"), anyString()); // Act HttpServletRequest httpServletRequest = createHttpServletRequest("https", "abraid.domain", 443, "/", true); ResponseEntity<Collection<String>> result = target.submitPasswordResetRequestPage("email", httpServletRequest); // Assert assertThat(result.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); assertThat(result.getBody()).containsOnly("FAIL3"); } @Test public void submitPasswordResetRequestPageIssuesNewResetKeyForValidRequest() throws Exception { AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); AccountController target = createTarget(99, null, null, validator, helper, null); HttpServletRequest httpServletRequest = createHttpServletRequest("https", "abraid.domain", 443, "/", true); // Act ResponseEntity<Collection<String>> result = target.submitPasswordResetRequestPage("email", httpServletRequest); // Assert verify(helper).processExpertPasswordResetRequestAsTransaction("email", "https://abraid.domain/"); assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); } @Test public void getPasswordResetProcessingPageReturnsCorrectTemplateForValidParameters() throws Exception { // Arrange AccountControllerValidator adminControllerValidator = mock(AccountControllerValidator.class); AccountController target = createTarget(1, null, null, adminControllerValidator, null, getCurrentUserService()); when(adminControllerValidator.validatePasswordResetRequest(7, "key")).thenReturn(new ArrayList<String>()); Model model = mock(Model.class); // Act String result = target.getPasswordResetProcessingPage(7, "key", model); // Assert verify(model).addAttribute("id", 7); verify(model).addAttribute("key", "key"); assertThat(result).isEqualTo("account/reset/process"); } @Test public void getPasswordResetProcessingPageReturnsCorrectTemplateForInvalidParameters() throws Exception { // Arrange AccountControllerValidator adminControllerValidator = mock(AccountControllerValidator.class); AccountController target = createTarget(1, null, null, adminControllerValidator, null, getCurrentUserService()); List<String> failures = Arrays.asList("Failure"); when(adminControllerValidator.validatePasswordResetRequest(7, "key")).thenReturn(failures); Model model = mock(Model.class); // Act String result = target.getPasswordResetProcessingPage(7, "key", model); // Assert verify(model).addAttribute("failures", failures); assertThat(result).isEqualTo("account/reset/invalid"); } @Test public void getPasswordResetProcessingPageRedirectsLoggedInUsers() throws Exception { // Arrange CurrentUserService userService = getCurrentUserService(); when(userService.getCurrentUserId()).thenReturn(1); AccountController target = createTarget(1, null, null, null, null, userService); // Act String result = target.getPasswordResetProcessingPage(7, "key", mock(Model.class)); // Assert assertThat(result).isEqualTo("redirect:/"); } @Test public void submitPasswordResetProcessingPageReturnsBadRequestIfValidationFails() throws Exception { // Arrange AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); AccountController target = createTarget(1, null, null, validator, helper, null); when(validator.validatePasswordResetProcessing("password", "confirm", 7, "key")).thenReturn(Arrays.asList("FAIL1", "FAIL2")); // Act ResponseEntity<Collection<String>> result = target.submitPasswordResetProcessingPage(7, "password", "confirm", "key"); // Assert assertThat(result.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); assertThat(result.getBody()).containsOnly("FAIL1", "FAIL2"); } @Test public void submitPasswordResetProcessingPageReturnsBadRequestIfHelperFails() throws Exception { // Arrange AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); AccountController target = createTarget(1, null, null, validator, helper, null); doThrow(new ValidationException(Arrays.asList("FAIL3"))) .when(helper).processExpertPasswordResetAsTransaction("password", 7); // Act ResponseEntity<Collection<String>> result = target.submitPasswordResetProcessingPage(7, "password", "confirm", "key"); // Assert assertThat(result.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); assertThat(result.getBody()).containsOnly("FAIL3"); } @Test public void submitPasswordResetProcessingPageUpdatesPasswordForValidRequest() throws Exception { AccountControllerValidator validator = mock(AccountControllerValidator.class); AccountControllerHelper helper = mock(AccountControllerHelper.class); AccountController target = createTarget(99, null, null, validator, helper, null); // Act ResponseEntity<Collection<String>> result = target.submitPasswordResetProcessingPage(7, "password", "confirm", "key"); // Assert verify(helper).processExpertPasswordResetAsTransaction("password", 7); assertThat(result.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); } private List<ValidatorDiseaseGroup> createMockValidatorDiseaseGroups() { ArrayList<ValidatorDiseaseGroup> groups = new ArrayList<>(); groups.add(createMockValidatorDiseaseGroup(1, "1")); groups.add(createMockValidatorDiseaseGroup(2, "2")); groups.add(createMockValidatorDiseaseGroup(3, "3")); return groups; } private ValidatorDiseaseGroup createMockValidatorDiseaseGroup(int id, String name) { ValidatorDiseaseGroup mock = new ValidatorDiseaseGroup(id, name); return mock; } private HttpServletRequest createHttpServletRequest(String schema, String host, int port, String context, boolean useXFowarded) { HttpServletRequest httpServletRequest = mock(HttpServletRequest.class); if (useXFowarded) { when(httpServletRequest.getScheme()).thenReturn("http"); when(httpServletRequest.getServerName()).thenReturn("localhost"); when(httpServletRequest.getServerPort()).thenReturn(8080); when(httpServletRequest.getHeader("X-Forwarded-Host")).thenReturn(host + ":" + port); when(httpServletRequest.getHeader("X-Forwarded-Proto")).thenReturn(schema); } else { when(httpServletRequest.getScheme()).thenReturn(schema); when(httpServletRequest.getServerName()).thenReturn(host); when(httpServletRequest.getServerPort()).thenReturn(port); } when(httpServletRequest.getContextPath()).thenReturn(context); return httpServletRequest; } private static CurrentUserService getCurrentUserService() { CurrentUserService mock = mock(CurrentUserService.class); when(mock.getCurrentUserId()).thenReturn(null); return mock; } }