content: package org.ays.auth.controller;
  
  import org.ays.AysRestControllerTest;
  import org.ays.auth.model.enums.AysSourcePage;
  import org.ays.auth.model.mapper.AysTokenToResponseMapper;
  import org.ays.auth.model.request.AysForgotPasswordRequestBuilder;
  import org.ays.auth.model.request.AysLoginRequest;
  import org.ays.auth.model.request.AysLoginRequestBuilder;
  import org.ays.auth.model.request.AysPasswordCreateRequest;
  import org.ays.auth.model.request.AysPasswordCreateRequestBuilder;
  import org.ays.auth.model.request.AysPasswordForgotRequest;
  import org.ays.auth.model.request.AysTokenInvalidateRequest;
  import org.ays.auth.model.request.AysTokenInvalidateRequestBuilder;
  import org.ays.auth.model.request.AysTokenRefreshRequest;
  import org.ays.auth.model.request.AysTokenRefreshRequestBuilder;
  import org.ays.auth.model.response.AysTokenResponse;
  import org.ays.auth.service.AysAuthService;
  import org.ays.auth.service.AysUserPasswordService;
  import org.ays.common.model.response.AysErrorResponse;
  import org.ays.common.model.response.AysErrorResponseBuilder;
  import org.ays.common.model.response.AysResponse;
  import org.ays.common.model.response.AysResponseBuilder;
  import org.ays.util.AysMockMvcRequestBuilders;
  import org.ays.util.AysMockResultMatchersBuilders;
  import org.ays.util.AysValidTestData;
  import org.junit.jupiter.api.Test;
  import org.junit.jupiter.params.ParameterizedTest;
  import org.junit.jupiter.params.provider.ValueSource;
  import org.mockito.Mockito;
  import org.springframework.test.context.bean.override.mockito.MockitoBean;
  import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
  import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
  
  class AysAuthControllerTest extends AysRestControllerTest {
  
      @MockitoBean
      private AysAuthService authService;
  
      @MockitoBean
      private AysUserPasswordService userPasswordService;
  
  
      private final AysTokenToResponseMapper tokenToResponseMapper = AysTokenToResponseMapper.initialize();
  
  
      private static final String BASE_PATH = "/api/v1/authentication";
  
  
      @ParameterizedTest
      @ValueSource(strings = {
              "a@b.co",
              "abcdef@mail.com",
              "abc+def@archive.com",
              "john.doe123@example.co.uk",
              "admin_123@example.org",
              "admin-test@ays.com",
              "johndoe@gmail.com",
              "janedoe123@yahoo.com",
              "michael.jordan@nba.com",
              "alice.smith@company.co.uk",
              "info@mywebsite.org",
              "support@helpdesk.net",
              "rajeshmehmetjosephanastasiyahamidjianguonalalitachunoscarmanojfelixmichaelhugoaslambeatrizsergeyemmaricardohenrymunnigaryrobertorosehungabdullahramaisaaclijunxinchonadiaqiangyuliyabrendapauljeanlyubovpablogiuseppexuanchaosimakevinminlongperez@aystest.org"
      })
      void givenValidLoginRequestWithValidEmailAddress_whenTokensGeneratedSuccessfully_thenReturnTokenResponse(String mockEmailAddress) throws Exception {
          // Given
          AysLoginRequest mockLoginRequest = new AysLoginRequestBuilder()
                  .withEmailAddress(mockEmailAddress)
                  .withPassword(AysValidTestData.PASSWORD)
                  .withSourcePage(AysSourcePage.INSTITUTION)
                  .build();
  
          // When
          Mockito.when(authService.authenticate(Mockito.any()))
                  .thenReturn(mockUserToken);
  
          // Then
          String endpoint = BASE_PATH.concat("/token");
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .post(endpoint, mockLoginRequest);
  
          AysTokenResponse mockTokenResponse = tokenToResponseMapper.map(mockUserToken);
          AysResponse<AysTokenResponse> mockResponse = AysResponseBuilder.successOf(mockTokenResponse);
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isOk())
                  .andExpect(AysMockResultMatchersBuilders.response()
                          .isNotEmpty())
                  .andExpect(MockMvcResultMatchers.jsonPath("$.response.accessToken")
                          .value(mockResponse.getResponse().getAccessToken()))
                  .andExpect(MockMvcResultMatchers.jsonPath("$.response.accessTokenExpiresAt")
                          .doesNotHaveJsonPath())
                  .andExpect(MockMvcResultMatchers.jsonPath("$.response.refreshToken")
                          .value(mockResponse.getResponse().getRefreshToken()));
  
          // Verify
          Mockito.verify(authService, Mockito.times(1))
                  .authenticate(Mockito.any());
      }
  
      @ParameterizedTest
      @ValueSource(strings = {
              "a@b.c",
              "plainaddress",
              "@missingusername.com",
              "username@.com",
              "username@gmail",
              "username@gmail..com",
              "username@gmail.c",
              "username@-gmail.com",
              "username@gmail-.com",
              "username@gmail.com.",
              "username@.gmail.com",
              "username@gmail@gmail.com",
              "username(john.doe)@gmail.com",
              "user@domain(comment).com",
              "usernamegmail.com",
              "username@gmail,com",
              "username@gmail space.co",
              "username@gmail..co.uk",
              "user#gmail.com",
              "bekeleandreaevelynirenealexandrascottmirasoniamustafahuivladimirmarcoyolandaraymondakhtermichaeldennistatianayuliyagangmargaretthomassumanjeanamymostafasaidrubenchenedithjumasitimeilucasgaryghulamminaxiaohongmarcosrafaelamyantoniamohamadfatmaahmed@aystest.org"
      })
      void givenInvalidLoginRequestWithInvalidEmailAddress_whenEmailsAreNotValid_thenReturnValidationError(String mockEmailAddress) throws Exception {
          // Given
          AysLoginRequest mockLoginRequest = new AysLoginRequestBuilder()
                  .withEmailAddress(mockEmailAddress)
                  .withPassword(AysValidTestData.PASSWORD)
                  .withSourcePage(AysSourcePage.INSTITUTION)
                  .build();
  
          // Then
          String endpoint = BASE_PATH.concat("/token");
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .post(endpoint, mockLoginRequest);
  
          AysErrorResponse mockErrorResponse = AysErrorResponseBuilder.VALIDATION_ERROR;
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockErrorResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isBadRequest())
                  .andExpect(AysMockResultMatchersBuilders.subErrors()
                          .isNotEmpty());
  
          // Verify
          Mockito.verify(authService, Mockito.never())
                  .authenticate(Mockito.any());
      }
  
      @ParameterizedTest
      @ValueSource(strings = {
              "g",
              "g.h2j5L",
              "uqTY6zlNlPgQZtyaRIVNPEAaLAPdOxEhmLWcoCcR4TbkLWedAcaHa96ZYXdrvor7qhN8B5ccms06NfbzVG2gzq0DWkHLxQupzmmbH3W9UhrnLS0LjuBVgOjQEoyaXesrJ"
      })
      void givenInvalidLoginRequestWithInvalidPassword_whenPasswordDoesNotValid_thenReturnValidationError(String mockPassword) throws Exception {
          // Given
          AysLoginRequest mockLoginRequest = new AysLoginRequestBuilder()
                  .withEmailAddress(AysValidTestData.User.EMAIL_ADDRESS)
                  .withPassword(mockPassword)
                  .withSourcePage(AysSourcePage.INSTITUTION)
                  .build();
  
          // Then
          String endpoint = BASE_PATH.concat("/token");
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .post(endpoint, mockLoginRequest);
  
          AysErrorResponse mockErrorResponse = AysErrorResponseBuilder.VALIDATION_ERROR;
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockErrorResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isBadRequest())
                  .andExpect(AysMockResultMatchersBuilders.subErrors()
                          .isNotEmpty());
  
          // Verify
          Mockito.verify(authService, Mockito.never())
                  .authenticate(Mockito.any());
      }
  
  
      @Test
      void givenValidTokenRefreshRequest_whenAccessTokenGeneratedSuccessfully_thenReturnTokenResponse() throws Exception {
          // Given
          AysTokenRefreshRequest mockTokenRefreshRequest = AysTokenRefreshRequestBuilder.VALID_FOR_USER;
  
          // When
          Mockito.when(authService.refreshAccessToken(Mockito.anyString()))
                  .thenReturn(mockUserToken);
  
          // Then
          String endpoint = BASE_PATH.concat("/token/refresh");
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .post(endpoint, mockTokenRefreshRequest);
  
          AysTokenResponse mockTokenResponse = tokenToResponseMapper.map(mockUserToken);
          AysResponse<AysTokenResponse> mockResponse = AysResponseBuilder.successOf(mockTokenResponse);
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isOk())
                  .andExpect(AysMockResultMatchersBuilders.response()
                          .isNotEmpty())
                  .andExpect(MockMvcResultMatchers.jsonPath("$.response.accessToken")
                          .value(mockResponse.getResponse().getAccessToken()))
                  .andExpect(MockMvcResultMatchers.jsonPath("$.response.accessTokenExpiresAt")
                          .doesNotHaveJsonPath())
                  .andExpect(MockMvcResultMatchers.jsonPath("$.response.refreshToken")
                          .value(mockResponse.getResponse().getRefreshToken()));
  
          // Verify
          Mockito.verify(authService, Mockito.times(1))
                  .refreshAccessToken(Mockito.anyString());
      }
  
      @Test
      void givenValidAysTokenInvalidateRequest_whenTokensInvalidated_thenReturnSuccessResponse() throws Exception {
          // Given
          AysTokenInvalidateRequest mockTokenInvalidateRequest = AysTokenInvalidateRequestBuilder.VALID_FOR_USER;
  
          // When
          Mockito.doNothing()
                  .when(authService)
                  .invalidateTokens(Mockito.any());
  
          // Then
          String endpoint = BASE_PATH.concat("/token/invalidate");
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .post(endpoint, mockUserToken.getAccessToken(), mockTokenInvalidateRequest);
  
          AysResponse<Void> mockResponse = AysResponseBuilder.success();
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isOk())
                  .andExpect(AysMockResultMatchersBuilders.response()
                          .doesNotExist());
  
          // Verify
          Mockito.verify(authService, Mockito.times(1))
                  .invalidateTokens(Mockito.any());
      }
  
  
      @ParameterizedTest
      @ValueSource(strings = {
              "a@b.co",
              "abcdef@mail.com",
              "abc+def@archive.com",
              "john.doe123@example.co.uk",
              "admin_123@example.org",
              "admin-test@ays.com",
              "johndoe@gmail.com",
              "janedoe123@yahoo.com",
              "michael.jordan@nba.com",
              "alice.smith@company.co.uk",
              "info@mywebsite.org",
              "support@helpdesk.net",
              "rajeshmehmetjosephanastasiyahamidjianguonalalitachunoscarmanojfelixmichaelhugoaslambeatrizsergeyemmaricardohenrymunnigaryrobertorosehungabdullahramaisaaclijunxinchonadiaqiangyuliyabrendapauljeanlyubovpablogiuseppexuanchaosimakevinminlongperez@aystest.org"
      })
      void givenValidForgotPasswordRequest_whenSendPasswordCreateMail_thenReturnSuccessResponse(String mockEmailAddress) throws Exception {
          // Given
          AysPasswordForgotRequest mockForgotPasswordRequest = new AysForgotPasswordRequestBuilder()
                  .withEmailAddress(mockEmailAddress)
                  .build();
  
          // When
          Mockito.doNothing()
                  .when(userPasswordService)
                  .forgotPassword(Mockito.any(AysPasswordForgotRequest.class));
  
          // Then
          String endpoint = BASE_PATH.concat("/password/forgot");
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .post(endpoint, mockForgotPasswordRequest);
  
          AysResponse<Void> mockResponse = AysResponseBuilder.success();
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isOk())
                  .andExpect(AysMockResultMatchersBuilders.response()
                          .doesNotExist());
  
          // Verify
          Mockito.verify(userPasswordService, Mockito.times(1))
                  .forgotPassword(Mockito.any(AysPasswordForgotRequest.class));
      }
  
      @ParameterizedTest
      @ValueSource(strings = {
              "a@b.c",
              "plainaddress",
              "@missingusername.com",
              "username@.com",
              "username@gmail",
              "username@gmail..com",
              "username@gmail.c",
              "username@-gmail.com",
              "username@gmail-.com",
              "username@gmail.com.",
              "username@.gmail.com",
              "username@gmail@gmail.com",
              "username(john.doe)@gmail.com",
              "user@domain(comment).com",
              "usernamegmail.com",
              "username@gmail,com",
              "username@gmail space.co",
              "username@gmail..co.uk",
              "user#gmail.com",
              "bekeleandreaevelynirenealexandrascottmirasoniamustafahuivladimirmarcoyolandaraymondakhtermichaeldennistatianayuliyagangmargaretthomassumanjeanamymostafasaidrubenchenedithjumasitimeilucasgaryghulamminaxiaohongmarcosrafaelamyantoniamohamadfatmaahmed@aystest.org"
      })
      void givenForgotPasswordRequestWithInvalidEmailAddress_whenEmailDoesNotValid_thenReturnValidationError(String mockEmailAddress) throws Exception {
  
          // Given
          AysPasswordForgotRequest mockForgotPasswordRequest = new AysForgotPasswordRequestBuilder()
                  .withEmailAddress(mockEmailAddress)
                  .build();
  
          // Then
          String endpoint = BASE_PATH.concat("/password/forgot");
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .post(endpoint, mockForgotPasswordRequest);
  
          AysErrorResponse mockErrorResponse = AysErrorResponseBuilder.VALIDATION_ERROR;
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockErrorResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isBadRequest())
                  .andExpect(AysMockResultMatchersBuilders.subErrors()
                          .isNotEmpty());
  
          // Verify
          Mockito.verify(userPasswordService, Mockito.never())
                  .forgotPassword(Mockito.any(AysPasswordForgotRequest.class));
      }
  
      @Test
      void givenForgotPasswordRequestWithoutEmailAddress_whenEmailIsNull_thenReturnValidationError() throws Exception {
  
          // Given
          AysPasswordForgotRequest mockForgotPasswordRequest = new AysForgotPasswordRequestBuilder()
                  .withEmailAddress(null)
                  .build();
  
          // Then
          String endpoint = BASE_PATH.concat("/password/forgot");
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .post(endpoint, mockForgotPasswordRequest);
  
          AysErrorResponse mockErrorResponse = AysErrorResponseBuilder.VALIDATION_ERROR;
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockErrorResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isBadRequest())
                  .andExpect(AysMockResultMatchersBuilders.subErrors()
                          .isNotEmpty());
  
          // Verify
          Mockito.verify(userPasswordService, Mockito.never())
                  .forgotPassword(Mockito.any(AysPasswordForgotRequest.class));
      }
  
  
      @Test
      void givenValidId_whenCheckPasswordIdSuccessfully_thenReturnSuccessResponse() throws Exception {
          // Given
          String mockId = "40fb7a46-40bd-46cb-b44f-1f47162133b1";
  
          // When
          Mockito.doNothing()
                  .when(userPasswordService)
                  .checkPasswordChangingValidity(Mockito.anyString());
  
          // Then
          String endpoint = BASE_PATH.concat("/password/").concat(mockId).concat("/validity");
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .get(endpoint);
  
          AysResponse<Void> mockResponse = AysResponseBuilder.success();
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isOk())
                  .andExpect(AysMockResultMatchersBuilders.response()
                          .doesNotExist());
  
          // Verify
          Mockito.verify(userPasswordService, Mockito.times(1))
                  .checkPasswordChangingValidity(Mockito.anyString());
      }
  
      @ParameterizedTest
      @ValueSource(strings = {
              "A",
              "493268349068342"
      })
      void givenId_whenIdDoesNotValid_thenReturnValidationError(String invalidId) throws Exception {
  
          // Then
          String endpoint = BASE_PATH.concat("/password/").concat(invalidId).concat("/validity");
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .get(endpoint);
  
          AysErrorResponse mockErrorResponse = AysErrorResponseBuilder.VALIDATION_ERROR;
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockErrorResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isBadRequest())
                  .andExpect(AysMockResultMatchersBuilders.subErrors()
                          .isNotEmpty());
  
          // Verify
          Mockito.verify(userPasswordService, Mockito.never())
                  .checkPasswordChangingValidity(Mockito.anyString());
      }
  
  
      @Test
      void givenValidPasswordCreateRequest_whenPasswordCreated_thenReturnSuccessResponse() throws Exception {
          // Given
          String mockId = "1fa43c75-7a7a-4041-8cef-03be8429dd30";
          AysPasswordCreateRequest mockPasswordCreateRequest = new AysPasswordCreateRequestBuilder()
                  .withValidValues()
                  .build();
  
          // When
          Mockito.doNothing()
                  .when(userPasswordService)
                  .createPassword(Mockito.anyString(), Mockito.any(AysPasswordCreateRequest.class));
  
          // Then
          String endpoint = BASE_PATH.concat("/password/").concat(mockId);
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .post(endpoint, mockPasswordCreateRequest);
  
          AysResponse<Void> mockResponse = AysResponseBuilder.success();
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isOk())
                  .andExpect(AysMockResultMatchersBuilders.response()
                          .doesNotExist());
  
          // Verify
          Mockito.verify(userPasswordService, Mockito.times(1))
                  .createPassword(Mockito.anyString(), Mockito.any(AysPasswordCreateRequest.class));
      }
  
      @Test
      void givenPasswordCreateRequest_whenPasswordsNotEqual_thenReturnValidationError() throws Exception {
  
          // Given
          String mockId = "1fa43c75-7a7a-4041-8cef-03be8429dd30";
          AysPasswordCreateRequest mockPasswordCreateRequest = new AysPasswordCreateRequestBuilder()
                  .withPassword("password")
                  .withPasswordRepeat("password1")
                  .build();
  
          // Then
          String endpoint = BASE_PATH.concat("/password/").concat(mockId);
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .post(endpoint, mockPasswordCreateRequest);
  
          AysErrorResponse mockErrorResponse = AysErrorResponseBuilder.VALIDATION_ERROR;
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockErrorResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isBadRequest())
                  .andExpect(AysMockResultMatchersBuilders.subErrors()
                          .isNotEmpty());
  
          // Verify
          Mockito.verify(userPasswordService, Mockito.never())
                  .createPassword(Mockito.anyString(), Mockito.any(AysPasswordCreateRequest.class));
      }
  
  
      @ParameterizedTest
      @ValueSource(strings = {
              "g",
              "g.h2j5L",
              "uqTY6zlNlPgQZtyaRIVNPEAaLAPdOxEhmLWcoCcR4TbkLWedAcaHa96ZYXdrvor7qhN8B5ccms06NfbzVG2gzq0DWkHLxQupzmmbH3W9UhrnLS0LjuBVgOjQEoyaXesrJ"
      })
      void givenPasswordCreateRequest_whenPasswordDoesNotValid_thenReturnValidationError(String mockPassword) throws Exception {
  
          // Given
          String mockId = "1fa43c75-7a7a-4041-8cef-03be8429dd30";
          AysPasswordCreateRequest mockPasswordCreateRequest = new AysPasswordCreateRequestBuilder()
                  .withPassword(mockPassword)
                  .withPasswordRepeat(mockPassword)
                  .build();
  
          // Then
          String endpoint = BASE_PATH.concat("/password/").concat(mockId);
          MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders
                  .post(endpoint, mockPasswordCreateRequest);
  
          AysErrorResponse mockErrorResponse = AysErrorResponseBuilder.VALIDATION_ERROR;
  
          aysMockMvc.perform(mockHttpServletRequestBuilder, mockErrorResponse)
                  .andExpect(AysMockResultMatchersBuilders.status()
                          .isBadRequest())
                  .andExpect(AysMockResultMatchersBuilders.subErrors()
                          .isNotEmpty());
  
          // Verify
          Mockito.verify(userPasswordService, Mockito.never())
                  .createPassword(Mockito.anyString(), Mockito.any(AysPasswordCreateRequest.class));
      }
  
  }
  