package gov.samhsa.consent2share.web.controller; import static org.hamcrest.Matchers.notNullValue; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; import gov.samhsa.consent2share.domain.account.TroubleType; import gov.samhsa.consent2share.infrastructure.security.EmailAddressNotExistException; import gov.samhsa.consent2share.infrastructure.security.TokenExpiredException; import gov.samhsa.consent2share.infrastructure.security.TokenNotExistException; import gov.samhsa.consent2share.infrastructure.security.UsernameNotExistException; import gov.samhsa.consent2share.service.account.AccountService; import gov.samhsa.consent2share.service.account.PasswordResetService; import gov.samhsa.consent2share.service.dto.LoginTroubleDto; import gov.samhsa.consent2share.service.dto.PasswordResetDto; import gov.samhsa.consent2share.service.validator.FieldValidatorChangePassword; import gov.samhsa.consent2share.service.validator.FieldValidatorLoginTroubleCreateNewPassword; import gov.samhsa.consent2share.service.validator.FieldValidatorLoginTroublePassword; import gov.samhsa.consent2share.service.validator.FieldValidatorLoginTroubleSelection; import gov.samhsa.consent2share.service.validator.FieldValidatorLoginTroubleUsername; import gov.samhsa.consent2share.web.controller.AccountController; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.result.MockMvcResultHandlers; import org.springframework.util.StringUtils; public class AccountControllerTest { private AccountController sut; private FieldValidatorLoginTroublePassword fieldValidatorPassword; private FieldValidatorLoginTroubleUsername fieldValidatorUsername; private FieldValidatorLoginTroubleSelection fieldValidatorTroubleSelection; private FieldValidatorLoginTroubleCreateNewPassword fieldValidatorLoginTroubleCreateNewPassword; private PasswordResetService passwordResetService; private AccountService accountService; private FieldValidatorChangePassword fieldValidatorChangePassword; private MockMvc mockMvc; @Before public void setUp() { // Mock dependencies and create sut // Just to save a few lines of code for each individual test // But independency, clarity of the unit tests are much more important // than code reuse passwordResetService = mock(PasswordResetService.class); accountService = mock(AccountService.class); fieldValidatorPassword = new FieldValidatorLoginTroublePassword(); fieldValidatorUsername = new FieldValidatorLoginTroubleUsername(); fieldValidatorTroubleSelection = new FieldValidatorLoginTroubleSelection(); fieldValidatorLoginTroubleCreateNewPassword = new FieldValidatorLoginTroubleCreateNewPassword(); sut = new AccountController(fieldValidatorPassword, fieldValidatorLoginTroubleCreateNewPassword, fieldValidatorTroubleSelection, fieldValidatorChangePassword, fieldValidatorUsername, passwordResetService, accountService); mockMvc = standaloneSetup(this.sut).build(); } @Test public void testLoginTrouble_When_HttpGet() throws Exception { Matcher<LoginTroubleDto> loginTroubleDtoMatcher = notNullValue(LoginTroubleDto.class); mockMvc.perform(get("/loginTrouble.html")) .andExpect(status().isOk()) .andExpect( model().attributeExists( StringUtils.uncapitalize(LoginTroubleDto.class .getSimpleName()))) .andExpect( model().attribute( StringUtils.uncapitalize(LoginTroubleDto.class .getSimpleName()), loginTroubleDtoMatcher)) .andExpect(model().hasNoErrors()) .andExpect(view().name("views/loginTrouble")) .andDo(MockMvcResultHandlers.print()); } @Test public void testLoginTrouble_When_HttpPost_With_No_Value_For_Param_TroubleTypeId() throws Exception { mockMvc.perform(post("/loginTrouble.html").param("troubleTypeId", "")) .andExpect(status().isOk()).andExpect(model().hasErrors()) .andExpect(view().name("views/loginTrouble")); } @Test public void testLoginTrouble_When_HttpPost_With_0_Value_For_Param_TroubleTypeId() throws Exception { mockMvc.perform(post("/loginTrouble.html").param("troubleTypeId", "0")) .andExpect(status().isOk()).andExpect(model().hasErrors()) .andExpect(view().name("views/loginTrouble")); } @Test public void testLoginTrouble_When_HttpPost_With_4_Value_For_Param_TroubleTypeId() throws Exception { mockMvc.perform(post("/loginTrouble.html").param("troubleTypeId", "4")) .andExpect(status().isOk()).andExpect(model().hasErrors()) .andExpect(view().name("views/loginTrouble")); } @Test public void testLoginTrouble_When_HttpPost_With_Value_1_For_Param_TroubleTypeId() throws Exception { mockMvc.perform(post("/loginTrouble.html").param("troubleTypeId", "1")) .andExpect(status().is(302)) .andExpect(view().name("redirect:/loginTroublePassword.html")); } @Test public void testLoginTrouble_When_HttpPost_With_Value_2_For_Param_TroubleTypeId() throws Exception { mockMvc.perform(post("/loginTrouble.html").param("troubleTypeId", "2")) .andExpect(status().is(302)) .andExpect(view().name("redirect:/loginTroubleUsername.html")); } @Test public void testLoginTrouble_When_HttpPost_With_Value_3_For_Param_TroubleTypeId() throws Exception { mockMvc.perform(post("/loginTrouble.html").param("troubleTypeId", "3")) .andExpect(status().is(302)) .andExpect(view().name("redirect:/loginTroubleOther.html")); } @Test public void testLoginTroublePassword_When_HttpGet() throws Exception { Matcher<LoginTroubleDto> loginTroubleDtoMatcher = new TypeSafeMatcher<LoginTroubleDto>() { @Override public void describeTo(Description arg0) { arg0.appendText(String.format( "TroubleType of %s is UNKNOWN_PASSWORD", LoginTroubleDto.class.getSimpleName())); } @Override protected boolean matchesSafely(LoginTroubleDto item) { if (item != null && item.getTroubleTypeId() == TroubleType.UNKNOWN_PASSWORD .getValue()) { return true; } return false; } }; final String loginTroubleDtoDtoObjectName = StringUtils .uncapitalize(LoginTroubleDto.class.getSimpleName()); mockMvc.perform(get("/loginTroublePassword.html")) .andExpect(status().isOk()) .andExpect( model().attributeExists(loginTroubleDtoDtoObjectName)) .andExpect( model().attribute(loginTroubleDtoDtoObjectName, loginTroubleDtoMatcher)) .andExpect(model().hasNoErrors()) .andExpect(view().name("views/loginTroublePassword")) .andDo(MockMvcResultHandlers.print()); } @Test public void testLoginTroublePassword_When_HttpPost_With_Value_WhiteSpace_For_Param_Username() throws Exception { mockMvc.perform( post("/loginTroublePassword.html").param("username", " ")) .andExpect(status().isOk()).andExpect(model().hasErrors()) .andExpect(view().name("views/loginTroublePassword")); } @Test public void testLoginTroublePassword_When_HttpPost_With_Invalid_Lenght_For_Param_Username() throws Exception { mockMvc.perform( post("/loginTroublePassword.html").param("username", "1")) .andExpect(status().isOk()).andExpect(model().hasErrors()) .andExpect(view().name("views/loginTroublePassword")); mockMvc.perform( post("/loginTroublePassword.html").param("username", "1234567890123456789012345678901")) .andExpect(status().isOk()).andExpect(model().hasErrors()) .andExpect(view().name("views/loginTroublePassword")); } @Test public void testLoginTroublePassword_When_HttpPost_With_Value_WhiteSpace_For_Param_Email() throws Exception { mockMvc.perform(post("/loginTroublePassword.html").param("email", " ")) .andExpect(status().isOk()).andExpect(model().hasErrors()) .andExpect(view().name("views/loginTroublePassword")); } @Test public void testLoginTroublePassword_When_HttpPost_With_Invalid_Value_For_Param_Email() throws Exception { mockMvc.perform( post("/loginTroublePassword.html").param("email", "blabal")) .andExpect(status().isOk()).andExpect(model().hasErrors()) .andExpect(view().name("views/loginTroublePassword")); } @Test public void testLoginTroublePassword_When_HttpPost_With_Valid_Values_For_Param_Username_And_Email() throws Exception { doNothing().when(passwordResetService).createPasswordResetToken( anyString(), anyString(), anyString()); mockMvc.perform( post("/loginTroublePassword.html").param("username", "blabal") .param("email", "test@test.com")) .andExpect(status().is(302)) .andExpect(model().hasNoErrors()) .andExpect( request().sessionAttribute("tokenMessage", "tokenSuccess")) .andExpect(view().name("redirect:/newPasswordRequested.html")); verify(passwordResetService, times(1)).createPasswordResetToken( anyString(), anyString(), anyString()); } @Test public void testLoginTroublePassword_When_HttpPost_With_Valid_Values_For_Param_Username_And_Email_And_When_With_UsernameNotExistException() throws Exception { doThrow(new UsernameNotExistException("")) .when(passwordResetService) .createPasswordResetToken(anyString(), anyString(), anyString()); final String loginTroubleDtoObjectName = StringUtils .uncapitalize(LoginTroubleDto.class.getSimpleName()); mockMvc.perform( post("/loginTroublePassword.html").param("username", "blabal") .param("email", "test@test.com")) .andExpect(status().isOk()) .andExpect( model().attributeHasFieldErrors( loginTroubleDtoObjectName, "username")) .andExpect(view().name("views/loginTroublePassword")); } @Test public void testLoginTroublePassword_When_HttpPost_With_Valid_Values_For_Param_Username_And_Email_And_When_With_EmailAddressNotExistException() throws Exception { doThrow(new EmailAddressNotExistException("")).when( passwordResetService).createPasswordResetToken(anyString(), anyString(), anyString()); final String loginTroubleDtoObjectName = StringUtils .uncapitalize(LoginTroubleDto.class.getSimpleName()); mockMvc.perform( post("/loginTroublePassword.html").param("username", "blabal") .param("email", "test@test.com")) .andExpect(status().isOk()) .andExpect( model().attributeHasFieldErrors( loginTroubleDtoObjectName, "email")) .andExpect(view().name("views/loginTroublePassword")); } @Test public void testNewPasswordRequested_When_HttpGet() throws Exception { final String tokenMessageValue = "bla"; mockMvc.perform( get("/newPasswordRequested.html").sessionAttr("tokenMessage", tokenMessageValue)) .andExpect(status().isOk()) .andExpect(model().attribute("tokenMessage", tokenMessageValue)) .andExpect(model().hasNoErrors()) .andExpect(view().name("views/newPasswordRequested")) .andDo(MockMvcResultHandlers.print()); } @Test public void testVerifyLink_Returns_Bad_Request_When_HttpGet_Without_Para_Token() throws Exception { mockMvc.perform(get("/resetPasswordLink.html")).andExpect( status().is(400)); } @Test public void testVerifyLink_When_HttpGet_With_Para_Token_And_When_Token_Expired() throws Exception { final String tokenVaule = "bla"; when(passwordResetService.isPasswordResetTokenExpired(tokenVaule)) .thenReturn(true); mockMvc.perform( get("/resetPasswordLink.html").param("token", tokenVaule)) .andExpect(status().is(302)) .andExpect( request().sessionAttribute("tokenMessage", "tokenExpired")) .andExpect(view().name("redirect:/newPasswordRequested.html")); } @Test public void testVerifyLink_When_HttpGet_With_Para_Token_And_When_Token_Not_Expired() throws Exception { final String tokenVaule = "bla"; when(passwordResetService.isPasswordResetTokenExpired(tokenVaule)) .thenReturn(false); mockMvc.perform( get("/resetPasswordLink.html").param("token", tokenVaule)) .andExpect(status().is(302)) .andExpect(request().sessionAttribute("token", tokenVaule)) .andExpect(view().name("redirect:/createPassword.html")); } @Test public void testVerifyLink_When_HttpGet_With_Para_Token_And_When_Token_Not_Exist() throws Exception { final String tokenVaule = "bla"; when(passwordResetService.isPasswordResetTokenExpired(tokenVaule)) .thenThrow(new TokenNotExistException("")); mockMvc.perform( get("/resetPasswordLink.html").param("token", tokenVaule)) .andExpect(status().is(302)) .andExpect( request().sessionAttribute("tokenMessage", "tokenNotExist")) .andExpect(view().name("redirect:/newPasswordRequested.html")); } @Test public void testCreatePassword_When_HttpGet() throws Exception { final String tokenValue = "Bla"; Matcher<PasswordResetDto> passwordResetDtoDtoMatcher = new TypeSafeMatcher<PasswordResetDto>() { @Override public void describeTo(Description arg0) { arg0.appendText(String.format("Token of %s is %s", PasswordResetDto.class.getSimpleName(), tokenValue)); } @Override protected boolean matchesSafely(PasswordResetDto item) { if (item != null && item.getToken().equals(tokenValue)) { return true; } return false; } }; final String passwordResetDtoObjectName = StringUtils .uncapitalize(PasswordResetDto.class.getSimpleName()); mockMvc.perform( get("/createPassword.html").sessionAttr("token", tokenValue)) .andExpect(status().isOk()) .andExpect(model().attributeExists(passwordResetDtoObjectName)) .andExpect( model().attribute(passwordResetDtoObjectName, passwordResetDtoDtoMatcher)) .andExpect(model().hasNoErrors()) .andExpect(view().name("views/createPassword")) .andDo(MockMvcResultHandlers.print()); } @Test public void tesCcreatePasswordk_When_HttpPost_With_Value_WhiteSpace_For_Param_Password() throws Exception { final String passwordResetDtoObjectName = StringUtils .uncapitalize(PasswordResetDto.class.getSimpleName()); mockMvc.perform(post("/createPassword.html").param("password", " ")) .andExpect(status().isOk()) .andExpect( model().attributeHasFieldErrors( passwordResetDtoObjectName, "password")) .andExpect(view().name("views/createPassword")); } @Test public void tesCcreatePasswordk_When_HttpPost_With_Invalid_Length_For_Param_Password() throws Exception { final String passwordResetDtoObjectName = StringUtils .uncapitalize(PasswordResetDto.class.getSimpleName()); mockMvc.perform( post("/createPassword.html").param("password", "1234567")) .andExpect(status().isOk()) .andExpect( model().attributeHasFieldErrors( passwordResetDtoObjectName, "password")) .andExpect(view().name("views/createPassword")); mockMvc.perform( post("/createPassword.html").param("password", "1234567890123456789012345678901")) .andExpect(status().isOk()) .andExpect( model().attributeHasFieldErrors( passwordResetDtoObjectName, "password")) .andExpect(view().name("views/createPassword")); } @Test public void tesCcreatePasswordk_When_HttpPost_With_Value_WhiteSpace_For_Param_RepeatPassword() throws Exception { final String passwordResetDtoObjectName = StringUtils .uncapitalize(PasswordResetDto.class.getSimpleName()); mockMvc.perform( post("/createPassword.html").param("password", "12345678") .param("repeatPassword", " ")) .andExpect(status().isOk()) .andExpect( model().attributeHasFieldErrors( passwordResetDtoObjectName, "repeatPassword")) .andExpect(view().name("views/createPassword")); } @Test public void tesCcreatePasswordk_When_HttpPost_With_Invalid_Length_For_Param_RepeatPassword() throws Exception { final String passwordResetDtoObjectName = StringUtils .uncapitalize(PasswordResetDto.class.getSimpleName()); mockMvc.perform( post("/createPassword.html").param("password", "12345678") .param("repeatPassword", "1234567")) .andExpect(status().isOk()) .andExpect( model().attributeHasFieldErrors( passwordResetDtoObjectName, "repeatPassword")) .andExpect(view().name("views/createPassword")); mockMvc.perform( post("/createPassword.html").param("password", "12345678") .param("repeatPassword", "1234567890123456789012345678901")) .andExpect(status().isOk()) .andExpect( model().attributeHasFieldErrors( passwordResetDtoObjectName, "repeatPassword")) .andExpect(view().name("views/createPassword")); } @Test public void tesCcreatePasswordk_When_HttpPost_With_Different_Param_Password_And_RepeatPassword() throws Exception { final String passwordResetDtoObjectName = StringUtils .uncapitalize(PasswordResetDto.class.getSimpleName()); mockMvc.perform( post("/createPassword.html").param("password", "12345678") .param("repeatPassword", "123456789")) .andExpect(status().isOk()) .andExpect( model().attributeHasFieldErrors( passwordResetDtoObjectName, "password")) .andExpect(view().name("views/createPassword")); } @Test public void tesCcreatePasswordk_When_HttpPost_With_Valid_Param_Password_And_RepeatPassword() throws Exception { final String password = "Aa2345678$"; mockMvc.perform( post("/createPassword.html").param("password", password).param( "repeatPassword", password)) .andExpect(status().is(302)) .andExpect(view().name("redirect:/accountUpdated.html")); } @Test public void tesCcreatePasswordk_When_HttpPost_With_Valid_Param_Password_And_RepeatPassword_And_Token_Expired() throws Exception { final String password = "Aa2345678$"; doThrow(new TokenExpiredException("")) .when(passwordResetService) .resetPassword(Mockito.any(PasswordResetDto.class), anyString()); mockMvc.perform( post("/createPassword.html").param("password", password).param( "repeatPassword", password)) .andExpect(status().is(302)) .andExpect( request().sessionAttribute("tokenMessage", "tokenExpired")) .andExpect(view().name("redirect:/newPasswordRequested.html")); } @Test public void testAccountUpdated_When_HttpGet() throws Exception { mockMvc.perform(get("/accountUpdated.html")).andExpect(status().isOk()) .andExpect(view().name("views/accountUpdated")); } @Test public void testAccount_Username_Found() throws Exception { when(accountService.recoverUsername(anyString(), anyString(), anyString(), anyString())).thenReturn("test"); mockMvc.perform(post("/loginTroubleUsername.html") .param("firstname", "Albert") .param("lastname", "Smith") .param("birthdate", "1983-02-29") .param("email", "email@email.com")) .andExpect(status().isOk()) .andExpect(model().hasNoErrors()) .andExpect(view().name("views/loginTroubleUsernameFound")) .andDo(MockMvcResultHandlers.print()); } @Test public void testAccount_Username_NotFound() throws Exception { when(accountService.recoverUsername(anyString(), anyString(), anyString(), anyString())).thenReturn(null); mockMvc.perform(post("/loginTroubleUsername.html") .param("firstname", "Fake") .param("lastname", "Smith") .param("birthdate", "1983-02-29") .param("email", "email@email.com")) .andExpect(status().isOk()) .andExpect(view().name("views/loginTroubleUsername")) .andExpect(model().hasErrors()) .andDo(MockMvcResultHandlers.print()); } @Test public void testAccount_Username_FirstNameError() throws Exception { when(accountService.recoverUsername(anyString(), anyString(), anyString(), anyString())).thenReturn("test"); mockMvc.perform(post("/loginTroubleUsername.html") .param("firstname", "a") .param("lastname", "Smith") .param("birthdate", "1983-02-29") .param("email", "email@email.com")) .andExpect(status().isOk()) .andExpect(view().name("views/loginTroubleUsername")) .andExpect(model().hasErrors()) .andDo(MockMvcResultHandlers.print()); } @Test public void testAccount_Username_LastNameError() throws Exception { when(accountService.recoverUsername(anyString(), anyString(), anyString(), anyString())).thenReturn("test"); mockMvc.perform(post("/loginTroubleUsername.html") .param("firstname", "Albert") .param("lastname", "a") .param("birthdate", "1983-02-29") .param("email", "email@email.com")) .andExpect(status().isOk()) .andExpect(view().name("views/loginTroubleUsername")) .andExpect(model().hasErrors()) .andDo(MockMvcResultHandlers.print()); } @Test public void testAccount_Username_BirthDateError() throws Exception { when(accountService.recoverUsername(anyString(), anyString(), anyString(), anyString())).thenReturn("test"); mockMvc.perform(post("/loginTroubleUsername.html") .param("firstname", "Albert") .param("lastname", "Smith") .param("birthdate", "") .param("email", "email@email.com")) .andExpect(status().isOk()) .andExpect(view().name("views/loginTroubleUsername")) .andExpect(model().hasErrors()) .andDo(MockMvcResultHandlers.print()); } @Test public void testAccount_Username_EmailError() throws Exception { when(accountService.recoverUsername(anyString(), anyString(), anyString(), anyString())).thenReturn("test"); mockMvc.perform(post("/loginTroubleUsername.html") .param("firstname", "Albert") .param("lastname", "Smith") .param("birthdate", "1983-02-29") .param("email", "wrongEmail")) .andExpect(status().isOk()) .andExpect(view().name("views/loginTroubleUsername")) .andExpect(model().hasErrors()) .andDo(MockMvcResultHandlers.print()); } }