Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add integration tests for GET /v1/skills/requests route #169

Merged
merged 9 commits into from
Nov 27, 2024
5 changes: 5 additions & 0 deletions skill-tree/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>

<!--Start io.jsonwebtoken: todo: remove the below block when rolling back to new version -->
<dependency>
Expand Down
6 changes: 5 additions & 1 deletion skill-tree/src/main/resources/application-test.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ cookieName=rds-session-v2-development
spring.datasource.url=jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/skilltreetestdb
spring.datasource.username=${MYSQL_DB_USERNAME}
spring.datasource.password=${MYSQL_DB_PASSWORD}

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=create-drop

spring.flyway.enabled=true
spring.flyway.locations=classpath:db/migrations

spring.jpa.show-sql=true
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
package com.RDS.skilltree.skills;

import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.RDS.skilltree.dtos.RdsGetUserDetailsResDto;
import com.RDS.skilltree.enums.SkillTypeEnum;
import com.RDS.skilltree.enums.UserSkillStatusEnum;
import com.RDS.skilltree.models.Endorsement;
import com.RDS.skilltree.models.Skill;
import com.RDS.skilltree.models.UserSkills;
import com.RDS.skilltree.repositories.EndorsementRepository;
import com.RDS.skilltree.repositories.SkillRepository;
import com.RDS.skilltree.repositories.UserSkillRepository;
import com.RDS.skilltree.services.external.RdsService;
import com.RDS.skilltree.utils.JWTUtils;
import com.RDS.skilltree.viewmodels.RdsUserViewModel;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.Cookie;
import org.junit.jupiter.api.*;
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.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import utils.CustomResultMatchers;
import utils.WithCustomMockUser;

@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
public class GetAllSkillRequestIntegrationTest {
@Autowired private MockMvc mockMvc;

@Autowired private UserSkillRepository userSkillRepository;

@Autowired private EndorsementRepository endorsementRepository;

@MockBean private RdsService rdsService;

@Autowired private SkillRepository skillRepository;

@MockBean private JWTUtils jwtUtils;

private final String route = "/v1/skills/requests";

@BeforeEach
void setUp() {
// Clean up repositories
skillRepository.deleteAll();
endorsementRepository.deleteAll();
userSkillRepository.deleteAll();

// Setup super-user detail
RdsUserViewModel superUser = new RdsUserViewModel();
superUser.setId("super-user-id");
RdsUserViewModel.Roles roles = new RdsUserViewModel.Roles();
roles.setSuper_user(true);
superUser.setRoles(roles);

RdsGetUserDetailsResDto superUserDetails = new RdsGetUserDetailsResDto();
superUserDetails.setUser(superUser);

// Setup normal-users detail
RdsUserViewModel normalUser = new RdsUserViewModel();
normalUser.setId("user-id");
RdsUserViewModel.Roles normalUserRoles = new RdsUserViewModel.Roles();
normalUserRoles.setSuper_user(false);
normalUser.setRoles(normalUserRoles);

RdsGetUserDetailsResDto normalUserDetails = new RdsGetUserDetailsResDto();
normalUserDetails.setUser(normalUser);

RdsUserViewModel normalUser2 = new RdsUserViewModel();
normalUser2.setId("user-id-2");
normalUser2.setRoles(normalUserRoles);
RdsGetUserDetailsResDto normalUser2Details = new RdsGetUserDetailsResDto();
normalUser2Details.setUser(normalUser2);

// Setup mock skills
Skill skill1 = new Skill();
skill1.setName("Java");
skill1.setType(SkillTypeEnum.ATOMIC);
skill1.setCreatedBy("super-user-id");

Skill skill2 = new Skill();
skill2.setName("Springboot");
skill2.setType(SkillTypeEnum.ATOMIC);
skill2.setCreatedBy("super-user-id");

skillRepository.save(skill1);
skillRepository.save(skill2);

// Setup mock user-skills
UserSkills userSkills1 = new UserSkills();
userSkills1.setSkill(skill1);
userSkills1.setUserId("user-id");
userSkills1.setStatus(UserSkillStatusEnum.PENDING);

UserSkills userSkills2 = new UserSkills();
userSkills2.setSkill(skill2);
userSkills2.setUserId("user-id");
userSkills2.setStatus(UserSkillStatusEnum.APPROVED);

UserSkills userSkills3 = new UserSkills();
userSkills3.setSkill(skill2);
userSkills3.setUserId("user-id-2");
userSkills3.setStatus(UserSkillStatusEnum.PENDING);

userSkillRepository.save(userSkills1);
userSkillRepository.save(userSkills2);
userSkillRepository.save(userSkills3);

// Setup mock endorsements
Endorsement endorsement1 = new Endorsement();
endorsement1.setId(1);
endorsement1.setEndorserId("super-user-id");
endorsement1.setEndorseId("user-id");
endorsement1.setSkill(skill1);
endorsement1.setMessage("endorsement message");

Endorsement endorsement2 = new Endorsement();
endorsement2.setId(3);
endorsement2.setEndorserId("user-id-2");
endorsement2.setEndorseId("user-id");
endorsement2.setSkill(skill2);
endorsement2.setMessage("skill2 for user-id");

Endorsement endorsement3 = new Endorsement();
endorsement3.setId(4);
endorsement3.setEndorserId("super-user-id");
endorsement3.setEndorseId("user-id-2");
endorsement3.setSkill(skill2);
endorsement3.setMessage("skill2 for user-id-2");

endorsementRepository.save(endorsement1);
endorsementRepository.save(endorsement2);
endorsementRepository.save(endorsement3);

// Setup RDS service mock responses
when(rdsService.getUserDetails("super-user-id")).thenReturn(superUserDetails);
when(rdsService.getUserDetails("user-id-2")).thenReturn(normalUser2Details);
when(rdsService.getUserDetails("user-id")).thenReturn(normalUserDetails);

// Mock JWTUtils to bypass actual JWT verification
Claims mockClaims = mock(Claims.class);
when(mockClaims.get("userId", String.class)).thenReturn("super-user-id");
when(jwtUtils.validateToken(anyString())).thenReturn(mockClaims);
}

@Test
@DisplayName("Happy flow for SuperUser - should return all requests")
@WithCustomMockUser(
username = "super-user-id",
authorities = {"SUPERUSER"})
public void getAllRequests_asSuperUser_shouldReturnAllRequests() throws Exception {
mockMvc
.perform(MockMvcRequestBuilders.get(route).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(CustomResultMatchers.hasSkillRequest("Java", "user-id", "PENDING"))
.andExpect(
CustomResultMatchers.hasEndorsement(
"Java", "user-id", "super-user-id", "endorsement message"))
.andExpect(CustomResultMatchers.hasSkillRequest("Springboot", "user-id", "APPROVED"))
.andExpect(
CustomResultMatchers.hasEndorsement(
"Springboot", "user-id", "user-id-2", "skill2 for user-id"))
.andExpect(CustomResultMatchers.hasSkillRequest("Springboot", "user-id-2", "PENDING"))
.andExpect(
CustomResultMatchers.hasEndorsement(
"Springboot", "user-id-2", "super-user-id", "skill2 for user-id-2"))
.andExpect(CustomResultMatchers.hasUser("user-id", " "))
.andExpect(CustomResultMatchers.hasUser("user-id-2", " "))
.andExpect(CustomResultMatchers.hasUser("super-user-id", " "));
}

@Test
@DisplayName("Happy flow for normal user - Get all requests where user is endorser")
@WithCustomMockUser(
username = "user-id-2",
authorities = {"USER"})
public void getAllRequests_asNormalUser_shouldReturnAllRequestsByEndorser() throws Exception {
mockMvc
.perform(MockMvcRequestBuilders.get(route).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(CustomResultMatchers.hasSkillRequest("Springboot", "user-id", "APPROVED"))
.andExpect(
CustomResultMatchers.hasEndorsement(
"Springboot", "user-id", "user-id-2", "skill2 for user-id"))
.andExpect(CustomResultMatchers.hasUser("user-id", " "))
.andExpect(CustomResultMatchers.hasUser("user-id-2", " "));
}

@Test
@DisplayName("Filter requests by status - should return filtered requests")
@WithCustomMockUser(
username = "super-user-id",
authorities = {"SUPERUSER"})
public void getAllRequests_ByStatus_ShouldReturnFilteredRequests() throws Exception {
mockMvc
.perform(
MockMvcRequestBuilders.get(route + "?status=APPROVED")
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(CustomResultMatchers.hasSkillRequest("Springboot", "user-id", "APPROVED"))
.andExpect(
CustomResultMatchers.hasEndorsement(
"Springboot", "user-id", "user-id-2", "skill2 for user-id"))
.andExpect(CustomResultMatchers.hasUser("user-id", " "))
.andExpect(CustomResultMatchers.hasUser("user-id-2", " "));
}

@Test
@DisplayName("If no skill Requests endorsed by user then return empty lists")
@WithCustomMockUser(
username = "user-id",
authorities = {"USER"})
public void noSkillRequestsEndorsedByUser_ShouldReturnEmptyLists() throws Exception {
mockMvc
.perform(MockMvcRequestBuilders.get(route).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.requests").isEmpty())
.andExpect(MockMvcResultMatchers.jsonPath("$.users").isEmpty());
}

@Test
@DisplayName("If no matching skill requests by status then return empty lists")
@WithCustomMockUser(
username = "user-id",
authorities = {"USER"})
public void noMatchingRequestsByStatus_ShouldReturnEmptyLists() throws Exception {
mockMvc
.perform(
MockMvcRequestBuilders.get(route + "?status=REJECTED")
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.requests").isEmpty())
.andExpect(MockMvcResultMatchers.jsonPath("$.users").isEmpty());
}

@Test
@DisplayName("If no skill requests in DB - return empty lists")
@WithCustomMockUser(
username = "super-user-id",
authorities = {"SUPERUSER"})
public void getAllRequests_NoData_ShouldReturnEmptyLists() throws Exception {
skillRepository.deleteAll();
endorsementRepository.deleteAll();
userSkillRepository.deleteAll();

mockMvc
.perform(MockMvcRequestBuilders.get(route).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.requests").isEmpty())
.andExpect(MockMvcResultMatchers.jsonPath("$.users").isEmpty());
}

@Test
@DisplayName("if invalid cookie, return 401")
public void ifInvalidCoolie_ShouldReturnUnauthorized() throws Exception {
Cookie authCookie =
new Cookie(
"cookie",
"eyJhbGciOiJSUzI1NiIsInR5cCI.eyJ1c2VySWQiOiI2N2lSeXJOTWQ.E-EtcPOj7Ca5l8JuE0hwky0rRikYSNZBvC");

mockMvc
.perform(
MockMvcRequestBuilders.get(route)
.cookie(authCookie)
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isUnauthorized());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import utils.WithCustomMockUser;

@SpringBootTest
@AutoConfigureMockMvc
Expand All @@ -30,15 +31,10 @@ public class GetAllSkillsIntegrationTest {

@Autowired private MockMvc mockMvc;

private Cookie authCookie;
private final String route = "/v1/skills";

@BeforeEach
public void setUp() {
authCookie =
new Cookie(
"rds-session-v2-development",
"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJzOXpRVW00WGJWRXo3eHpSa2FadiIsInJvbGUiOiJzdXBlcl91c2VyIiwiaWF0IjoxNzI4NjY0NjA2LCJleHAiOjE3MzEyNTY2MDZ9.EyOFKrVcbleuTjUGic3GzOzYRDoLU4IShyoboe0MHlvWFOAfU2pchpXLE4NcyvdGUZ_tvoUecHd4kUkR8MkhxnkRNU3HE7N-1c1tFeYXZL0KfScJE9YzDXAl113Hx3eZVvYbhNjNUttbDlH4s_kR6YABC3sdbLGKEiLfmp9VeAs");

skillRepository.deleteAll();
Skill skill1 = new Skill();
skill1.setName("Java");
Expand All @@ -54,14 +50,13 @@ public void setUp() {
}

@Test
@WithCustomMockUser(
username = "rds-user",
authorities = {"SUPERUSER"})
@DisplayName("happy flow - returns all skills that are in db")
public void getAllSkillsHappyFlow() throws Exception {

mockMvc
.perform(
MockMvcRequestBuilders.get("/v1/skills")
.cookie(authCookie)
.accept(MediaType.APPLICATION_JSON))
.perform(MockMvcRequestBuilders.get(route).accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value("Java"))
.andExpect(MockMvcResultMatchers.jsonPath("$[1].name").value("Springboot"))
Expand All @@ -70,26 +65,29 @@ public void getAllSkillsHappyFlow() throws Exception {

@Test
@DisplayName("if no skills available, return empty list")
@WithCustomMockUser(
username = "rds-user",
authorities = {"SUPERUSER"})
public void noSkillsAvailable_shouldReturnEmptyList() throws Exception {
skillRepository.deleteAll();

mockMvc
.perform(
MockMvcRequestBuilders.get("/v1/skills")
.cookie(authCookie)
.accept(MediaType.APPLICATION_JSON))
.perform(MockMvcRequestBuilders.get(route).accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$").isEmpty());
}

@Test
@DisplayName("if invalid cookie, return 401")
public void ifInvalidCoolie_returnUnauthorized() throws Exception {
Cookie authCookie =
new Cookie(
"cookie",
"eyJhbGciOiJSUzI1NiIsInR5cCI.eyJ1c2VySWQiOiI2N2lSeXJOTWQ.E-EtcPOj7Ca5l8JuE0hwky0rRikYSNZBvC");

mockMvc
.perform(
MockMvcRequestBuilders.get("/v1/skills")
.cookie(new Cookie("cookie1", "eyJhbGciOiJSUz.eyJhbGciOiJSUz.EyJhbGciOiJSUz"))
.accept(MediaType.APPLICATION_JSON))
MockMvcRequestBuilders.get(route).cookie(authCookie).accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isUnauthorized());
}
}
Loading
Loading