diff --git a/skill-tree/pom.xml b/skill-tree/pom.xml
index ac132714..c840309b 100644
--- a/skill-tree/pom.xml
+++ b/skill-tree/pom.xml
@@ -90,6 +90,11 @@
org.springframework.boot
spring-boot-starter-security
+
+ org.springframework.security
+ spring-security-test
+ test
+
diff --git a/skill-tree/src/main/resources/application-test.properties b/skill-tree/src/main/resources/application-test.properties
index 02c453f3..5d9cfc71 100644
--- a/skill-tree/src/main/resources/application-test.properties
+++ b/skill-tree/src/main/resources/application-test.properties
@@ -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
diff --git a/skill-tree/src/test/java/com/RDS/skilltree/skills/GetAllSkillRequestIntegrationTest.java b/skill-tree/src/test/java/com/RDS/skilltree/skills/GetAllSkillRequestIntegrationTest.java
new file mode 100644
index 00000000..90dbcd91
--- /dev/null
+++ b/skill-tree/src/test/java/com/RDS/skilltree/skills/GetAllSkillRequestIntegrationTest.java
@@ -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());
+ }
+}
diff --git a/skill-tree/src/test/java/com/RDS/skilltree/skills/GetAllSkillsIntegrationTest.java b/skill-tree/src/test/java/com/RDS/skilltree/skills/GetAllSkillsIntegrationTest.java
index b16ac200..cca60e09 100644
--- a/skill-tree/src/test/java/com/RDS/skilltree/skills/GetAllSkillsIntegrationTest.java
+++ b/skill-tree/src/test/java/com/RDS/skilltree/skills/GetAllSkillsIntegrationTest.java
@@ -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
@@ -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");
@@ -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"))
@@ -70,14 +65,14 @@ 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());
}
@@ -85,11 +80,14 @@ public void noSkillsAvailable_shouldReturnEmptyList() throws Exception {
@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());
}
}
diff --git a/skill-tree/src/test/java/utils/CustomResultMatchers.java b/skill-tree/src/test/java/utils/CustomResultMatchers.java
new file mode 100644
index 00000000..5eb85e6c
--- /dev/null
+++ b/skill-tree/src/test/java/utils/CustomResultMatchers.java
@@ -0,0 +1,99 @@
+package utils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.test.web.servlet.ResultMatcher;
+
+public class CustomResultMatchers {
+
+ public static ResultMatcher hasSkillRequest(String skillName, String endorseId, String status) {
+ return result -> {
+ String json = result.getResponse().getContentAsString();
+ ObjectMapper objectMapper = new ObjectMapper();
+ JsonNode root = objectMapper.readTree(json);
+
+ // Find the request for the given skillName and endorseId
+ JsonNode matchingSkillRequest = findMatchingSkillRequest(root, skillName, endorseId);
+ assertThat(matchingSkillRequest).isNotNull().isNotEmpty();
+
+ assertThat(matchingSkillRequest.get("endorseId").asText()).isEqualTo(endorseId);
+ assertThat(matchingSkillRequest.get("status").asText()).isEqualTo(status);
+ };
+ }
+
+ public static ResultMatcher hasEndorsement(
+ String skillName, String endorseId, String endorserId, String message) {
+ return result -> {
+ String json = result.getResponse().getContentAsString();
+ ObjectMapper objectMapper = new ObjectMapper();
+ JsonNode root = objectMapper.readTree(json);
+
+ // Find the request for the given skillName and endorseId
+ JsonNode matchingSkillRequest = findMatchingSkillRequest(root, skillName, endorseId);
+ assertThat(matchingSkillRequest).isNotNull().isNotEmpty();
+
+ // Check endorsements
+ JsonNode endorsements = matchingSkillRequest.get("endorsements");
+ assertThat(endorsements).isNotNull().isNotEmpty();
+
+ // Find matching endorsement by endorserId
+ JsonNode matchingEndorsement = findByField(endorsements, "endorserId", endorserId);
+ assertThat(matchingEndorsement).isNotNull();
+
+ // Assert endorsement details
+ assertThat(matchingEndorsement.get("endorserId").asText()).isEqualTo(endorserId);
+ assertThat(matchingEndorsement.get("message").asText()).isEqualTo(message);
+ };
+ }
+
+ public static ResultMatcher hasUser(String userId, String name) {
+ return result -> {
+ String json = result.getResponse().getContentAsString();
+ ObjectMapper objectMapper = new ObjectMapper();
+ JsonNode root = objectMapper.readTree(json);
+
+ JsonNode users = root.get("users");
+ assertThat(users).isNotNull().isNotEmpty();
+
+ // Find user by userId
+ JsonNode matchingUser = findByField(users, "id", userId);
+ assertThat(matchingUser).isNotNull();
+
+ // Assert user details
+ assertThat(matchingUser.get("id").asText()).isEqualTo(userId);
+ assertThat(matchingUser.get("name").asText()).isEqualTo(name);
+ };
+ }
+
+ private static JsonNode findByField(JsonNode array, String fieldName, String value) {
+ for (JsonNode node : array) {
+ if (node.has(fieldName) && node.get(fieldName).asText().equals(value)) {
+ return node;
+ }
+ }
+ return null;
+ }
+
+ private static JsonNode findMatchingSkillRequest(
+ JsonNode root, String skillName, String endorseId) {
+ JsonNode requests = root.get("requests");
+ assertThat(requests).isNotNull().isNotEmpty();
+
+ return findBySkillAndEndorseId(requests, skillName, endorseId);
+ }
+
+ private static JsonNode findBySkillAndEndorseId(
+ JsonNode array, String skillName, String endorseId) {
+ for (JsonNode node : array) {
+ if (node.has("skillName")
+ && node.get("skillName").asText().equals(skillName)
+ && node.has("endorseId")
+ && node.get("endorseId").asText().equals(endorseId)) {
+ return node;
+ }
+ }
+ return null;
+ }
+}
diff --git a/skill-tree/src/test/java/utils/CustomSecurityContextFactory.java b/skill-tree/src/test/java/utils/CustomSecurityContextFactory.java
new file mode 100644
index 00000000..bcb98cac
--- /dev/null
+++ b/skill-tree/src/test/java/utils/CustomSecurityContextFactory.java
@@ -0,0 +1,39 @@
+package utils;
+
+import com.RDS.skilltree.enums.UserRoleEnum;
+import com.RDS.skilltree.models.JwtUser;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.test.context.support.WithSecurityContextFactory;
+
+public class CustomSecurityContextFactory
+ implements WithSecurityContextFactory {
+ @Override
+ public SecurityContext createSecurityContext(WithCustomMockUser customMockUser) {
+ SecurityContext context = SecurityContextHolder.createEmptyContext();
+
+ List roles =
+ Arrays.stream(customMockUser.authorities()).map(UserRoleEnum::valueOf).toList();
+ UserRoleEnum mainRole = roles.isEmpty() ? UserRoleEnum.USER : roles.get(0);
+
+ // Create jwt user
+ JwtUser jwtUser = new JwtUser(customMockUser.username(), mainRole);
+
+ // Map roles to Spring Security authorities
+ List authorities =
+ roles.stream()
+ .map(role -> new SimpleGrantedAuthority(role.name()))
+ .collect(Collectors.toList());
+
+ // Set JwtUser as the principal in Authentication
+ Authentication auth = new UsernamePasswordAuthenticationToken(jwtUser, null, authorities);
+ context.setAuthentication(auth);
+ return context;
+ }
+}
diff --git a/skill-tree/src/test/java/utils/WithCustomMockUser.java b/skill-tree/src/test/java/utils/WithCustomMockUser.java
new file mode 100644
index 00000000..c913d2fd
--- /dev/null
+++ b/skill-tree/src/test/java/utils/WithCustomMockUser.java
@@ -0,0 +1,13 @@
+package utils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import org.springframework.security.test.context.support.WithSecurityContext;
+
+@Retention(RetentionPolicy.RUNTIME)
+@WithSecurityContext(factory = CustomSecurityContextFactory.class)
+public @interface WithCustomMockUser {
+ String username() default "test-user";
+
+ String[] authorities() default {};
+}