Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Java CI with Maven

on:
push:
branches: [ "main", "test" ]
pull_request:
branches: [ "main" ]

jobs:
build:

runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

- name: Build with Maven
run: mvn clean install

- name: Run tests
run: mvn test
123 changes: 123 additions & 0 deletions src/test/java/me/eddypbr/todolist/IntegrationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package me.eddypbr.todolist;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import java.util.UUID;

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.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.RequestPostProcessor;

import me.eddypbr.todolist.user.UserModel;

@SpringBootTest
@AutoConfigureMockMvc
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class IntegrationTest {

@Autowired
private MockMvc mockMvc;

private static String createdTaskId;
private static final UUID FIXED_USER_ID = UUID.fromString("11111111-1111-1111-1111-111111111111");

private static RequestPostProcessor withMockUser() {
return request -> {
UserModel user = new UserModel();
user.setId(FIXED_USER_ID);
user.setUsername("testuser");
request.setAttribute("user", user);
return request;
};
}

@Test
@Order(1)
public void testCreateTask() throws Exception {
String taskJson = """
{
"title": "Integration Task",
"description": "Test",
"startAt": "2026-04-20T10:00:00",
"endAt": "2026-04-21T10:00:00"
}
""";

String response = mockMvc.perform(post("/tasks")
.with(withMockUser())
.contentType(MediaType.APPLICATION_JSON)
.content(taskJson))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").exists())
.andReturn()
.getResponse()
.getContentAsString();

createdTaskId = com.jayway.jsonpath.JsonPath.read(response, "$.id");
System.out.println("Created Task ID: " + createdTaskId);
}

@Test
@Order(2)
public void testUpdateTask() throws Exception {
System.out.println("Created Task ID: " + createdTaskId);
String updateJson = """
{
"title": "Updated Integration Task"
}
""";

mockMvc.perform(put("/tasks/" + createdTaskId)
.with(withMockUser())
.contentType(MediaType.APPLICATION_JSON)
.content(updateJson))
.andExpect(status().isOk())
.andExpect(jsonPath("$.title").value("Updated Integration Task"));
}

@Test
@Order(3)
public void testDeleteTask() throws Exception {
System.out.println("Deleting Task ID: " + createdTaskId);

mockMvc.perform(delete("/tasks/" + createdTaskId)
.with(withMockUser()))
.andDo(result -> {
System.out.println("Delete Status: " + result.getResponse().getStatus());
})
.andExpect(status().isOk());
}

@Test
@Order(4)
public void testCreateTaskWithInvalidDate() throws Exception {
String invalidJson = """
{
"title": "Invalid Task",
"startAt": "2026-04-21T10:00:00",
"endAt": "2026-04-20T10:00:00"
}
""";

mockMvc.perform(post("/tasks")
.with(withMockUser())
.contentType(MediaType.APPLICATION_JSON)
.content(invalidJson))
.andExpect(status().isBadRequest());
}

@Test
@Order(5)
public void testDeleteNonExistingTask() throws Exception {
String invalidId = "00000000-0000-0000-0000-000000000000";

mockMvc.perform(delete("/tasks/" + invalidId)
.with(withMockUser()))
.andExpect(status().isNotFound());
}
}
114 changes: 114 additions & 0 deletions src/test/java/me/eddypbr/todolist/UpdateTask.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package me.eddypbr.todolist;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

import java.util.Optional;
import java.util.UUID;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.mockito.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import jakarta.servlet.http.HttpServletRequest;

import me.eddypbr.todolist.task.*;
import me.eddypbr.todolist.user.UserModel;

public class UpdateTask {

@InjectMocks
private TaskController controller;

@Mock
private ITaskRepository repo;

@Mock
private HttpServletRequest request;

private UUID userId;
private UUID taskId;

@BeforeEach
public void setUp() {
MockitoAnnotations.openMocks(this);
userId = UUID.randomUUID();
taskId = UUID.randomUUID();
}

private UserModel mockUser() {
UserModel user = new UserModel();
user.setId(userId);
return user;
}

private TaskModel mockTask() {
TaskModel task = new TaskModel();
task.setId(taskId);
task.setIdUser(userId);
return task;
}

@ParameterizedTest
@CsvSource({"Updated Title 1, Updated Desc 1"})
public void testUpdateTaskSuccess(String title, String description) throws Exception {
when(request.getAttribute("user")).thenReturn(mockUser());
when(repo.findById(taskId)).thenReturn(Optional.of(mockTask()));
when(repo.save(any())).thenReturn(mockTask());
TaskModel update = new TaskModel();
update.setTitle(title);
update.setDescription(description);
ResponseEntity response = controller.update(update, request, taskId);
assertEquals(HttpStatus.OK, response.getStatusCode());
verify(repo, times(1)).save(any());
}

@ParameterizedTest
@CsvSource({"00000000-0000-0000-0000-000000000001"})
public void testUpdateTaskNotFound(String idStr) throws Exception {
UUID id = UUID.fromString(idStr);
when(repo.findById(id)).thenReturn(Optional.empty());
ResponseEntity response = controller.update(new TaskModel(), request, id);
assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
}

@Test
void testUpdateTaskEmptyTitle() throws Exception {
when(request.getAttribute("user")).thenReturn(mockUser());
when(repo.findById(taskId)).thenReturn(Optional.of(mockTask()));
TaskModel update = new TaskModel();
update.setTitle("");
update.setDescription("desc");
ResponseEntity response = controller.update(update, request, taskId);
assertEquals(HttpStatus.OK, response.getStatusCode());
}

@Test
void testUpdateTaskNullDescription() throws Exception {
when(request.getAttribute("user")).thenReturn(mockUser());
when(repo.findById(taskId)).thenReturn(Optional.of(mockTask()));
TaskModel update = new TaskModel();
update.setTitle("Valid Title");
update.setDescription(null);
ResponseEntity response = controller.update(update, request, taskId);
assertEquals(HttpStatus.OK, response.getStatusCode());
}

@Test
public void testUpdateTaskUnauthorizedUser() throws Exception {
UUID otherUserId = UUID.randomUUID();
TaskModel existing = new TaskModel();
existing.setId(taskId);
existing.setIdUser(otherUserId);
when(request.getAttribute("user")).thenReturn(mockUser());
when(repo.findById(taskId)).thenReturn(Optional.of(existing));
TaskModel update = new TaskModel();
update.setTitle("Test");
ResponseEntity response = controller.update(update, request, taskId);
assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode());
}
}