-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
System Tests Have Been Created for Admin User Auth Flows
- Loading branch information
1 parent
90d28c6
commit d1baf87
Showing
5 changed files
with
360 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package com.ays; | ||
|
||
import com.ays.admin_user.model.entity.AdminUserEntityBuilder; | ||
import com.ays.auth.config.AysTokenConfigurationParameter; | ||
import com.ays.auth.model.AysToken; | ||
import com.ays.auth.model.enums.AysTokenClaims; | ||
import com.ays.common.util.AysRandomUtil; | ||
import com.ays.parameter.model.AysParameter; | ||
import com.ays.parameter.model.AysParameterBuilder; | ||
import com.ays.parameter.service.AysParameterService; | ||
import com.ays.user.model.entity.UserEntityBuilder; | ||
import com.ays.util.AysTestData; | ||
import io.jsonwebtoken.JwtBuilder; | ||
import io.jsonwebtoken.Jwts; | ||
import io.jsonwebtoken.SignatureAlgorithm; | ||
import org.apache.commons.lang3.time.DateUtils; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.Mock; | ||
import org.mockito.Mockito; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||
import org.springframework.test.web.servlet.MockMvc; | ||
|
||
import java.util.Date; | ||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
@SpringBootTest | ||
@ExtendWith(MockitoExtension.class) | ||
@AutoConfigureMockMvc | ||
public abstract class AbstractSystemTest extends AbstractTestContainerConfiguration { | ||
|
||
@Autowired | ||
protected MockMvc mockMvc; | ||
protected AysToken mockAdminUserToken; | ||
protected AysToken mockUserToken; | ||
|
||
|
||
@Mock | ||
private AysTokenConfigurationParameter tokenConfiguration; | ||
@Mock | ||
private AysParameterService parameterService; | ||
|
||
@BeforeEach | ||
public void initializeAuth() { | ||
Set<AysParameter> parameters = AysParameterBuilder.getParameters(); | ||
Mockito.when(parameterService.getParameters(Mockito.anyString())) | ||
.thenReturn(parameters); | ||
this.tokenConfiguration = new AysTokenConfigurationParameter(parameterService); | ||
|
||
final Map<String, Object> claimsOfAdminUser = new AdminUserEntityBuilder() | ||
.withId(AysTestData.AdminUser.VALID_ID_ONE) | ||
.withUsername(AysTestData.AdminUser.VALID_USERNAME_ONE) | ||
.withEmail(AysTestData.AdminUser.VALID_EMAIL_ONE) | ||
.build() | ||
.getClaims(); | ||
this.mockAdminUserToken = this.generate(claimsOfAdminUser); | ||
this.mockUserToken = this.generate(new UserEntityBuilder().build().getClaims()); | ||
} | ||
|
||
private AysToken generate(Map<String, Object> claims) { | ||
final long currentTimeMillis = System.currentTimeMillis(); | ||
|
||
final Date tokenIssuedAt = new Date(currentTimeMillis); | ||
|
||
final Date accessTokenExpiresAt = DateUtils.addMinutes(new Date(currentTimeMillis), tokenConfiguration.getAccessTokenExpireMinute()); | ||
final String accessToken = Jwts.builder() | ||
.setId(AysRandomUtil.generateUUID()) | ||
.setIssuer(tokenConfiguration.getIssuer()) | ||
.setIssuedAt(tokenIssuedAt) | ||
.setExpiration(accessTokenExpiresAt) | ||
.signWith(tokenConfiguration.getPrivateKey(), SignatureAlgorithm.RS512) | ||
.setHeaderParam(AysTokenClaims.TYPE.getValue(), OAuth2AccessToken.TokenType.BEARER.getValue()) | ||
.addClaims(claims) | ||
.compact(); | ||
|
||
final Date refreshTokenExpiresAt = DateUtils.addDays(new Date(currentTimeMillis), tokenConfiguration.getRefreshTokenExpireDay()); | ||
final JwtBuilder refreshTokenBuilder = Jwts.builder(); | ||
final String refreshToken = refreshTokenBuilder | ||
.setId(AysRandomUtil.generateUUID()) | ||
.setIssuer(tokenConfiguration.getIssuer()) | ||
.setIssuedAt(tokenIssuedAt) | ||
.setExpiration(refreshTokenExpiresAt) | ||
.signWith(tokenConfiguration.getPrivateKey(), SignatureAlgorithm.RS512) | ||
.setHeaderParam(AysTokenClaims.TYPE.getValue(), OAuth2AccessToken.TokenType.BEARER.getValue()) | ||
.claim(AysTokenClaims.USER_ID.getValue(), claims.get(AysTokenClaims.USER_ID.getValue())) | ||
.claim(AysTokenClaims.USERNAME.getValue(), claims.get(AysTokenClaims.USERNAME.getValue())) | ||
.compact(); | ||
|
||
return AysToken.builder() | ||
.accessToken(accessToken) | ||
.accessTokenExpiresAt(accessTokenExpiresAt.toInstant().getEpochSecond()) | ||
.refreshToken(refreshToken) | ||
.build(); | ||
} | ||
|
||
} |
228 changes: 228 additions & 0 deletions
228
src/test/java/com/ays/admin_user/controller/AdminUserAuthSystemTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
package com.ays.admin_user.controller; | ||
|
||
import com.ays.AbstractSystemTest; | ||
import com.ays.admin_user.model.dto.request.AdminUserRegisterRequest; | ||
import com.ays.admin_user.model.dto.request.AdminUserRegisterRequestBuilder; | ||
import com.ays.auth.model.dto.request.AysLoginRequest; | ||
import com.ays.auth.model.dto.request.AysLoginRequestBuilder; | ||
import com.ays.auth.model.dto.request.AysTokenInvalidateRequest; | ||
import com.ays.auth.model.dto.request.AysTokenRefreshRequest; | ||
import com.ays.auth.model.dto.response.AysTokenResponse; | ||
import com.ays.auth.model.mapper.AysTokenToAysTokenResponseMapper; | ||
import com.ays.common.model.AysPhoneNumber; | ||
import com.ays.common.model.AysPhoneNumberBuilder; | ||
import com.ays.common.model.dto.response.AysResponse; | ||
import com.ays.common.model.dto.response.AysResponseBuilder; | ||
import com.ays.common.util.exception.model.AysError; | ||
import com.ays.common.util.exception.model.AysErrorBuilder; | ||
import com.ays.util.AysMockMvcRequestBuilders; | ||
import com.ays.util.AysMockResultMatchersBuilders; | ||
import com.ays.util.AysTestData; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; | ||
import org.springframework.test.web.servlet.result.MockMvcResultHandlers; | ||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers; | ||
|
||
class AdminUserAuthSystemTest extends AbstractSystemTest { | ||
|
||
private final AysTokenToAysTokenResponseMapper aysTokenToAysTokenResponseMapper = AysTokenToAysTokenResponseMapper.initialize(); | ||
|
||
private static final String BASE_PATH = "/api/v1/authentication/admin"; | ||
|
||
@Test | ||
void givenValidAdminUserRegisterRequest_whenAdminUserRegistered_thenReturnSuccessResponse() throws Exception { | ||
// Given | ||
AdminUserRegisterRequest mockRequest = new AdminUserRegisterRequestBuilder() | ||
.withValidFields() | ||
.withInstitutionId(AysTestData.VALID_INSTITUTION_ID_ONE) | ||
.withVerificationId(AysTestData.VALID_VERIFICATION_ID) | ||
.build(); | ||
|
||
// Then | ||
AysResponse<Void> mockResponse = AysResponseBuilder.SUCCESS; | ||
mockMvc.perform(AysMockMvcRequestBuilders | ||
.post(BASE_PATH.concat("/register"), mockRequest)) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(AysMockResultMatchersBuilders.status().isOk()) | ||
.andExpect(AysMockResultMatchersBuilders.time() | ||
.isNotEmpty()) | ||
.andExpect(AysMockResultMatchersBuilders.httpStatus() | ||
.value(mockResponse.getHttpStatus().name())) | ||
.andExpect(AysMockResultMatchersBuilders.isSuccess() | ||
.value(mockResponse.getIsSuccess())) | ||
.andExpect(AysMockResultMatchersBuilders.response() | ||
.doesNotExist()); | ||
} | ||
|
||
@Test | ||
void givenPhoneNumberWithAlphanumericCharacter_whenPhoneNumberIsNotValid_thenReturnValidationError() throws Exception { | ||
// Given | ||
AysPhoneNumber mockPhoneNumber = new AysPhoneNumberBuilder() | ||
.withCountryCode("ABC") | ||
.withLineNumber("ABC").build(); | ||
AdminUserRegisterRequest mockRequest = new AdminUserRegisterRequestBuilder() | ||
.withValidFields() | ||
.withPhoneNumber(mockPhoneNumber).build(); | ||
|
||
// Then | ||
AysError mockErrorResponse = AysErrorBuilder.VALIDATION_ERROR; | ||
mockMvc.perform(AysMockMvcRequestBuilders | ||
.post(BASE_PATH.concat("/register"), mockRequest)) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(AysMockResultMatchersBuilders.status().isBadRequest()) | ||
.andExpect(AysMockResultMatchersBuilders.time() | ||
.isNotEmpty()) | ||
.andExpect(AysMockResultMatchersBuilders.httpStatus() | ||
.value(mockErrorResponse.getHttpStatus().name())) | ||
.andExpect(AysMockResultMatchersBuilders.header() | ||
.value(mockErrorResponse.getHeader())) | ||
.andExpect(AysMockResultMatchersBuilders.isSuccess() | ||
.value(mockErrorResponse.getIsSuccess())) | ||
.andExpect(AysMockResultMatchersBuilders.response() | ||
.doesNotExist()) | ||
.andExpect(AysMockResultMatchersBuilders.subErrors() | ||
.isNotEmpty()); | ||
} | ||
|
||
@Test | ||
void givenPhoneNumberWithInvalidLength_whenPhoneNumberIsNotValid_thenReturnValidationError() throws Exception { | ||
// Given | ||
AysPhoneNumber mockPhoneNumber = new AysPhoneNumberBuilder() | ||
.withCountryCode("456786745645") | ||
.withLineNumber("6546467456435548676845321346656654").build(); | ||
AdminUserRegisterRequest mockRequest = new AdminUserRegisterRequestBuilder() | ||
.withValidFields() | ||
.withPhoneNumber(mockPhoneNumber).build(); | ||
|
||
// Then | ||
AysError mockErrorResponse = AysErrorBuilder.VALIDATION_ERROR; | ||
mockMvc.perform(AysMockMvcRequestBuilders | ||
.post(BASE_PATH.concat("/register"), mockRequest)) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(AysMockResultMatchersBuilders.status().isBadRequest()) | ||
.andExpect(AysMockResultMatchersBuilders.time() | ||
.isNotEmpty()) | ||
.andExpect(AysMockResultMatchersBuilders.httpStatus() | ||
.value(mockErrorResponse.getHttpStatus().name())) | ||
.andExpect(AysMockResultMatchersBuilders.header() | ||
.value(mockErrorResponse.getHeader())) | ||
.andExpect(AysMockResultMatchersBuilders.isSuccess() | ||
.value(mockErrorResponse.getIsSuccess())) | ||
.andExpect(AysMockResultMatchersBuilders.response() | ||
.doesNotExist()) | ||
.andExpect(AysMockResultMatchersBuilders.subErrors() | ||
.isNotEmpty()); | ||
} | ||
|
||
@Test | ||
void givenValidLoginRequest_whenTokensGeneratedSuccessfully_thenReturnTokenResponse() throws Exception { | ||
// Given | ||
AysLoginRequest mockRequest = new AysLoginRequestBuilder() | ||
.withUsername(AysTestData.AdminUser.VALID_USERNAME_ONE) | ||
.withPassword(AysTestData.AdminUser.VALID_PASSWORD_ONE).build(); | ||
|
||
// Then | ||
AysTokenResponse mockResponse = aysTokenToAysTokenResponseMapper.map(mockAdminUserToken); | ||
AysResponse<AysTokenResponse> mockAysResponse = AysResponseBuilder.successOf(mockResponse); | ||
mockMvc.perform(AysMockMvcRequestBuilders | ||
.post(BASE_PATH.concat("/token"), mockRequest)) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(AysMockResultMatchersBuilders.status().isOk()) | ||
.andExpect(AysMockResultMatchersBuilders.time() | ||
.isNotEmpty()) | ||
.andExpect(AysMockResultMatchersBuilders.httpStatus() | ||
.value(mockAysResponse.getHttpStatus().getReasonPhrase())) | ||
.andExpect(AysMockResultMatchersBuilders.isSuccess() | ||
.value(mockAysResponse.getIsSuccess())) | ||
.andExpect(AysMockResultMatchersBuilders.response() | ||
.isNotEmpty()) | ||
.andExpect(MockMvcResultMatchers.jsonPath("$.response.accessToken") | ||
.isNotEmpty()) | ||
.andExpect(MockMvcResultMatchers.jsonPath("$.response.accessTokenExpiresAt") | ||
.isNotEmpty()) | ||
.andExpect(MockMvcResultMatchers.jsonPath("$.response.refreshToken") | ||
.isNotEmpty()); | ||
|
||
} | ||
|
||
@Test | ||
void givenValidTokenRefreshRequest_whenAccessTokenGeneratedSuccessfully_thenReturnTokenResponse() throws Exception { | ||
// Given | ||
AysTokenRefreshRequest mockRequest = AysTokenRefreshRequest.builder() | ||
.refreshToken(mockAdminUserToken.getRefreshToken()) | ||
.build(); | ||
|
||
// Then | ||
AysTokenResponse mockResponse = aysTokenToAysTokenResponseMapper.map(mockAdminUserToken); | ||
AysResponse<AysTokenResponse> mockAysResponse = AysResponseBuilder.successOf(mockResponse); | ||
mockMvc.perform(AysMockMvcRequestBuilders | ||
.post(BASE_PATH.concat("/token/refresh"), mockRequest)) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(AysMockResultMatchersBuilders.status().isOk()) | ||
.andExpect(AysMockResultMatchersBuilders.time() | ||
.isNotEmpty()) | ||
.andExpect(AysMockResultMatchersBuilders.httpStatus() | ||
.value(mockAysResponse.getHttpStatus().getReasonPhrase())) | ||
.andExpect(AysMockResultMatchersBuilders.isSuccess() | ||
.value(mockAysResponse.getIsSuccess())) | ||
.andExpect(AysMockResultMatchersBuilders.response() | ||
.isNotEmpty()) | ||
.andExpect(MockMvcResultMatchers.jsonPath("$.response.accessToken") | ||
.isNotEmpty()) | ||
.andExpect(MockMvcResultMatchers.jsonPath("$.response.accessTokenExpiresAt") | ||
.isNotEmpty()) | ||
.andExpect(MockMvcResultMatchers.jsonPath("$.response.refreshToken") | ||
.isNotEmpty()); | ||
} | ||
|
||
@Test | ||
void givenValidAysTokenInvalidateRequest_whenTokensInvalidated_thenReturnSuccessResponse() throws Exception { | ||
// Given | ||
AysTokenInvalidateRequest mockRequest = AysTokenInvalidateRequest.builder() | ||
.refreshToken(mockAdminUserToken.getRefreshToken()) | ||
.build(); | ||
|
||
// Then | ||
String endpoint = BASE_PATH.concat("/token/invalidate"); | ||
AysResponse<Void> mockResponse = AysResponseBuilder.SUCCESS; | ||
mockMvc.perform(AysMockMvcRequestBuilders | ||
.post(endpoint, mockAdminUserToken.getAccessToken(), mockRequest)) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(AysMockResultMatchersBuilders.status().isOk()) | ||
.andExpect(AysMockResultMatchersBuilders.time() | ||
.isNotEmpty()) | ||
.andExpect(AysMockResultMatchersBuilders.httpStatus() | ||
.value(mockResponse.getHttpStatus().name())) | ||
.andExpect(AysMockResultMatchersBuilders.isSuccess() | ||
.value(mockResponse.getIsSuccess())) | ||
.andExpect(AysMockResultMatchersBuilders.response() | ||
.doesNotExist()); | ||
} | ||
|
||
@Test | ||
void givenValidAysTokenInvalidateRequest_whenUserUnauthorizedForTokensInvalidating_thenReturnAccessDeniedException() throws Exception { | ||
// Given | ||
AysTokenInvalidateRequest mockRequest = AysTokenInvalidateRequest.builder() | ||
.refreshToken(mockAdminUserToken.getRefreshToken()) | ||
.build(); | ||
|
||
// Then | ||
String endpoint = BASE_PATH.concat("/token/invalidate"); | ||
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders | ||
.post(endpoint, mockUserToken.getAccessToken(), mockRequest); | ||
|
||
AysResponse<AysError> mockResponse = AysResponseBuilder.FORBIDDEN; | ||
mockMvc.perform(mockHttpServletRequestBuilder) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(AysMockResultMatchersBuilders.status().isForbidden()) | ||
.andExpect(AysMockResultMatchersBuilders.time() | ||
.isNotEmpty()) | ||
.andExpect(AysMockResultMatchersBuilders.httpStatus() | ||
.value(mockResponse.getHttpStatus().name())) | ||
.andExpect(AysMockResultMatchersBuilders.isSuccess() | ||
.value(mockResponse.getIsSuccess())) | ||
.andExpect(AysMockResultMatchersBuilders.response() | ||
.doesNotExist()); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,5 +6,21 @@ | |
public class AysTestData { | ||
|
||
public static final String VALID_EMAIL = "[email protected]"; | ||
public static final String VALID_VERIFICATION_ID = "3cfeb994-88f4-48d0-b105-309f42f91412"; | ||
public static final String VALID_INSTITUTION_ID_ONE = "77ece256-bf0e-4bbe-801d-173083f8bdcf"; | ||
public static final String VALID_INSTITUTION_ID_TWO = "91df7ae9-d5b9-44ae-b54f-d5d55359c4a4"; | ||
|
||
public static class AdminUser { | ||
public static final String VALID_ID_ONE = "9262f0fc-93db-4f7e-81c6-aaad85c2b206"; | ||
public static final String VALID_USERNAME_ONE = "ays-admin-1"; | ||
public static final String VALID_PASSWORD_ONE = "A123y456S."; | ||
public static final String VALID_EMAIL_ONE = "[email protected]"; | ||
|
||
|
||
public static final String VALID_ID_TWO = "87ab173b-1b7d-4264-abd7-438e5ed2c1fa"; | ||
public static final String VALID_USERNAME_TWO = "ays-admin-2"; | ||
public static final String VALID_PASSWORD_TWO = "A123y456S."; | ||
public static final String VALID_EMAIL_TWO = "[email protected]"; | ||
} | ||
|
||
} |