From 613b10301c787a5de4040504f1b5989abb3214d8 Mon Sep 17 00:00:00 2001 From: Lucas Aguiar Date: Thu, 13 Nov 2025 16:18:52 -0300 Subject: [PATCH 1/9] chore(dependencies): add mockito-core --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index 401a7ce..d1ecfb8 100644 --- a/pom.xml +++ b/pom.xml @@ -113,6 +113,12 @@ jackson-databind 2.15.2 + + org.mockito + mockito-core + 5.20.0 + test + From a9ea111ce9ccb1796aa4b16da9acd367e26f9d52 Mon Sep 17 00:00:00 2001 From: Lucas Aguiar Date: Thu, 13 Nov 2025 16:21:08 -0300 Subject: [PATCH 2/9] test(user): add creation tests --- .../implementation/user/UserCreationTest.java | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 src/test/java/br/com/notehub/implementation/user/UserCreationTest.java diff --git a/src/test/java/br/com/notehub/implementation/user/UserCreationTest.java b/src/test/java/br/com/notehub/implementation/user/UserCreationTest.java new file mode 100644 index 0000000..6f80e84 --- /dev/null +++ b/src/test/java/br/com/notehub/implementation/user/UserCreationTest.java @@ -0,0 +1,144 @@ +package br.com.notehub.implementation.user; + +import br.com.notehub.application.implementation.user.UserServiceImpl; +import br.com.notehub.domain.history.UserHistoryService; +import br.com.notehub.domain.token.TokenService; +import br.com.notehub.domain.user.User; +import br.com.notehub.domain.user.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.security.crypto.password.PasswordEncoder; + +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class UserCreationTest { + + @InjectMocks + private UserServiceImpl service; + + @Mock + private UserRepository repository; + + @Mock + private TokenService tokenService; + + @Mock + private UserHistoryService historian; + + @Mock + private PasswordEncoder encoder; + + private User user; + private UUID id; + + @BeforeEach + void setup() { + user = new User("tester@notehub.com.br", "tester", "Tester", "1234"); + id = UUID.randomUUID(); + user.setId(id); + user.setActive(true); + } + + @Test + void shouldEncodePasswordAndSaveUser_whenDataIsValid() { + + when(repository.existsByEmail(anyString())).thenReturn(false); + when(repository.existsByUsername(anyString())).thenReturn(false); + when(encoder.encode(anyString())).thenReturn("encoded"); + when(repository.save(any(User.class))).thenAnswer(i -> i.getArgument(0)); + + User result = service.create(user); + + verify(repository).existsByEmail("tester@notehub.com.br"); + verify(repository).existsByUsername("tester"); + verify(encoder).encode("1234"); + verify(repository).save(any(User.class)); + + assertThat(result).isInstanceOf(User.class); + assertThat(result.getEmail()).isEqualTo("tester@notehub.com.br"); + assertThat(result.getUsername()).isEqualTo("tester"); + assertThat(result.getDisplayName()).isEqualTo("Tester"); + assertThat(result.getPassword()).isEqualTo("encoded"); + + } + + @Test + void shouldThrowException_whenEmailAlreadyExists() { + + when(repository.existsByEmail(anyString())).thenReturn(true); + when(repository.existsByUsername(anyString())).thenReturn(false); + + assertThatThrownBy(() -> service.create(user)) + .isInstanceOf(DataIntegrityViolationException.class) + .hasMessage("email"); + + verify(repository, never()).save(any()); + + } + + @Test + void shouldThrowException_whenUsernameAlreadyExists() { + + when(repository.existsByEmail(anyString())).thenReturn(false); + when(repository.existsByUsername(anyString())).thenReturn(true); + + assertThatThrownBy(() -> service.create(user)) + .isInstanceOf(DataIntegrityViolationException.class) + .hasMessage("username"); + + verify(repository, never()).save(any()); + + } + + @Test + void shouldThrowException_whenEmailAndUsernameAlreadyExist() { + + when(repository.existsByEmail(anyString())).thenReturn(true); + when(repository.existsByUsername(anyString())).thenReturn(true); + + assertThatThrownBy(() -> service.create(user)) + .isInstanceOf(DataIntegrityViolationException.class) + .hasMessage("both"); + + verify(repository, never()).save(any()); + + } + + @Test + void shouldReturnToken_whenGeneratingActivationToken() { + when(tokenService.generateActivationToken(any(User.class))).thenReturn("token"); + String token = service.generateActivationToken(user); + assertThat(token).isEqualTo("token"); + } + + @Test + void shouldSetActiveTrueAndLogHistory_whenActivatingUser() { + + User inactiveUser = new User("inactive@notehub.com.br", "inactive", "Inactive", "1234"); + inactiveUser.setId(id); + inactiveUser.setActive(false); + + when(repository.findById(id)).thenReturn(Optional.of(inactiveUser)); + when(repository.save(any(User.class))).thenReturn(inactiveUser); + + service.activate(id); + + verify(repository).save(any(User.class)); + verify(historian).setHistory(any(), eq("active"), eq("false"), eq("true")); + + } + +} \ No newline at end of file From d07a2fdc7359f245377b13571049394a6e1d337a Mon Sep 17 00:00:00 2001 From: Lucas Aguiar Date: Fri, 14 Nov 2025 10:33:41 -0300 Subject: [PATCH 3/9] test(user): add edition tests --- .../implementation/user/UserEditionTest.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/test/java/br/com/notehub/implementation/user/UserEditionTest.java diff --git a/src/test/java/br/com/notehub/implementation/user/UserEditionTest.java b/src/test/java/br/com/notehub/implementation/user/UserEditionTest.java new file mode 100644 index 0000000..fb562f1 --- /dev/null +++ b/src/test/java/br/com/notehub/implementation/user/UserEditionTest.java @@ -0,0 +1,95 @@ +package br.com.notehub.implementation.user; + +import br.com.notehub.application.implementation.user.UserServiceImpl; +import br.com.notehub.domain.history.UserHistoryService; +import br.com.notehub.domain.user.User; +import br.com.notehub.domain.user.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.dao.DataIntegrityViolationException; + +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class UserEditionTest { + + @InjectMocks + private UserServiceImpl service; + + @Mock + private UserRepository repository; + + @Mock + private UserHistoryService historian; + + private User user; + private UUID id; + + @BeforeEach + void setup() { + user = new User("tester@notehub.com.br", "tester", "Tester", "1234"); + id = UUID.randomUUID(); + user.setId(id); + user.setActive(true); + } + + @Test + void shouldSaveHistoryAndPersistChanges_whenDataIsModified() { + + User updated = new User("updated", "Updated", null, null, null, true); + + when(repository.findById(id)).thenReturn(Optional.of(user)); + + assertThat(updated).isEqualTo(service.edit(id, updated)); + + verify(repository, times(6)).findById(id); + verify(repository, times(3)).save(any(User.class)); + verify(historian).setHistory(any(User.class), eq("username"), eq("tester"), eq("updated")); + verify(historian).setHistory(any(User.class), eq("display_name"), eq("Tester"), eq("Updated")); + verify(historian).setHistory(any(User.class), eq("profile_private"), eq("false"), eq("true")); + + } + + @Test + void shouldSkipSaveAndHistory_whenUserDataIsUnchanged() { + + User updated = new User("tester", "Tester", null, null, null, false); + + when(repository.findById(id)).thenReturn(Optional.of(user)); + + assertThat(updated).isEqualTo(service.edit(id, updated)); + + verify(repository, times(6)).findById(id); + verify(repository, never()).save(any(User.class)); + verify(historian, never()).setHistory(any(), any(), any(), any()); + + } + + @Test + void shouldThrowException_whenUsernameAlreadyExists() { + + User updated = new User("tester", "Updated", null, null, null, false); + + when(repository.findByUsername("tester")).thenReturn(Optional.of(user)); + when(repository.findById(id)).thenReturn(Optional.of(updated)); + + assertThatThrownBy(() -> service.edit(id, updated)) + .isInstanceOf(DataIntegrityViolationException.class) + .hasMessage("username"); + + verify(repository, times(1)).findById(id); + verify(repository, never()).save(any(User.class)); + verify(historian, never()).setHistory(any(), any(), any(), any()); + + } + +} \ No newline at end of file From 2b56109609cfa468291763c0479fda12b440a8c5 Mon Sep 17 00:00:00 2001 From: Lucas Aguiar Date: Mon, 17 Nov 2025 10:13:33 -0300 Subject: [PATCH 4/9] test(user): add relationship tests --- .../user/UserRelationshipTest.java | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 src/test/java/br/com/notehub/implementation/user/UserRelationshipTest.java diff --git a/src/test/java/br/com/notehub/implementation/user/UserRelationshipTest.java b/src/test/java/br/com/notehub/implementation/user/UserRelationshipTest.java new file mode 100644 index 0000000..20f48af --- /dev/null +++ b/src/test/java/br/com/notehub/implementation/user/UserRelationshipTest.java @@ -0,0 +1,137 @@ +package br.com.notehub.implementation.user; + +import br.com.notehub.application.counter.Counter; +import br.com.notehub.application.dto.notification.MessageNotification; +import br.com.notehub.application.implementation.user.UserServiceImpl; +import br.com.notehub.domain.notification.NotificationService; +import br.com.notehub.domain.user.User; +import br.com.notehub.domain.user.UserRepository; +import br.com.notehub.infra.exception.CustomExceptions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class UserRelationshipTest { + + @InjectMocks + private UserServiceImpl service; + + @Mock + private UserRepository repository; + + @Mock + private NotificationService notifier; + + @Mock + private Counter counter; + + private User follower; + private User following; + private UUID followerId; + + @BeforeEach + void setup() { + follower = new User("follower@notehub.com.br", "follower", "Follower", "1234"); + following = new User("following@notehub.com.br", "following", "Following", "1234"); + followerId = UUID.randomUUID(); + follower.setId(followerId); + } + + @Test + void shouldFollowUserAndSendNotification_whenNotAlreadyFollowing() { + + when(repository.findByIdWithFollowersAndFollowing(followerId)).thenReturn(Optional.of(follower)); + when(repository.findByUsernameWithFollowersAndFollowing(following.getUsername())).thenReturn(Optional.of(following)); + + service.follow(followerId, following.getUsername()); + + verify(repository, times(1)).findByIdWithFollowersAndFollowing(followerId); + verify(repository, times(1)).findByUsernameWithFollowersAndFollowing(following.getUsername()); + verify(counter, times(1)).updateFollowersAndFollowingCount(eq(follower), eq(following), eq(true)); + verify(notifier, times(1)).notify(eq(follower), eq(following), eq(follower), eq(MessageNotification.of(follower))); + + } + + @Test + void shouldUnfollowUserWithoutNotification_whenAlreadyFollowing() { + + when(repository.findByIdWithFollowersAndFollowing(followerId)).thenReturn(Optional.of(follower)); + when(repository.findByUsernameWithFollowersAndFollowing(following.getUsername())).thenReturn(Optional.of(following)); + + follower.getFollowing().add(following); + following.getFollowers().add(follower); + service.unfollow(followerId, following.getUsername()); + + verify(repository, times(1)).findByIdWithFollowersAndFollowing(followerId); + verify(repository, times(1)).findByUsernameWithFollowersAndFollowing(following.getUsername()); + verify(counter, times(1)).updateFollowersAndFollowingCount(eq(follower), eq(following), eq(false)); + verify(notifier, never()).notify(any(), any(), any(), any()); + + } + + @Test + void shouldThrowSelfFollowException_whenTryingToFollowSelf() { + + when(repository.findByIdWithFollowersAndFollowing(followerId)).thenReturn(Optional.of(follower)); + when(repository.findByUsernameWithFollowersAndFollowing(following.getUsername())).thenReturn(Optional.of(follower)); + + assertThatThrownBy(() -> + service.follow(followerId, following.getUsername())) + .isInstanceOf(CustomExceptions.SelfFollowException.class); + + verify(repository, times(1)).findByIdWithFollowersAndFollowing(followerId); + verify(repository, times(1)).findByUsernameWithFollowersAndFollowing(following.getUsername()); + verify(counter, never()).updateFollowersAndFollowingCount(any(), any(), any(Boolean.class)); + verify(notifier, never()).notify(any(), any(), any(), any()); + + } + + @Test + void shouldThrowAlreadyFollowingException_whenFollowingUserAgain() { + + when(repository.findByIdWithFollowersAndFollowing(followerId)).thenReturn(Optional.of(follower)); + when(repository.findByUsernameWithFollowersAndFollowing(following.getUsername())).thenReturn(Optional.of(following)); + + follower.getFollowing().add(following); + following.getFollowers().add(follower); + + assertThatThrownBy(() -> + service.follow(followerId, following.getUsername())) + .isInstanceOf(CustomExceptions.AlreadyFollowingException.class); + + verify(repository, times(1)).findByIdWithFollowersAndFollowing(followerId); + verify(repository, times(1)).findByUsernameWithFollowersAndFollowing(following.getUsername()); + verify(counter, never()).updateFollowersAndFollowingCount(any(), any(), any(Boolean.class)); + verify(notifier, never()).notify(any(), any(), any(), any()); + + } + + @Test + void shouldThrowNotFollowingException_whenUnfollowingUserNotFollowed() { + + when(repository.findByIdWithFollowersAndFollowing(followerId)).thenReturn(Optional.of(follower)); + when(repository.findByUsernameWithFollowersAndFollowing(following.getUsername())).thenReturn(Optional.of(following)); + + assertThatThrownBy(() -> + service.unfollow(followerId, following.getUsername())) + .isInstanceOf(CustomExceptions.NotFollowingException.class); + + verify(repository, times(1)).findByIdWithFollowersAndFollowing(followerId); + verify(repository, times(1)).findByUsernameWithFollowersAndFollowing(following.getUsername()); + verify(counter, never()).updateFollowersAndFollowingCount(any(), any(), any(Boolean.class)); + verify(notifier, never()).notify(any(), any(), any(), any()); + + } + +} \ No newline at end of file From 149bdb41d0f0953501408f7c40e8452ba85ab23c Mon Sep 17 00:00:00 2001 From: Lucas Aguiar Date: Mon, 17 Nov 2025 10:59:07 -0300 Subject: [PATCH 5/9] test(user): add deletion tests --- .../implementation/user/UserDeletionTest.java | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/test/java/br/com/notehub/implementation/user/UserDeletionTest.java diff --git a/src/test/java/br/com/notehub/implementation/user/UserDeletionTest.java b/src/test/java/br/com/notehub/implementation/user/UserDeletionTest.java new file mode 100644 index 0000000..af37ae5 --- /dev/null +++ b/src/test/java/br/com/notehub/implementation/user/UserDeletionTest.java @@ -0,0 +1,77 @@ +package br.com.notehub.implementation.user; + +import br.com.notehub.application.implementation.user.UserServiceImpl; +import br.com.notehub.domain.note.NoteService; +import br.com.notehub.domain.user.User; +import br.com.notehub.domain.user.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.crypto.password.PasswordEncoder; + +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class UserDeletionTest { + + @InjectMocks + private UserServiceImpl service; + + @Mock + private UserRepository repository; + + @Mock + private NoteService noteService; + + @Mock + private PasswordEncoder encoder; + + private User user; + private UUID id; + + @BeforeEach + void setup() { + user = new User("tester@notehub.com.br", "tester", "Tester", "1234"); + id = UUID.randomUUID(); + user.setId(id); + } + + @Test + void shouldDeleteUser_whenPasswordMatches() { + + when(repository.findById(id)).thenReturn(Optional.of(user)); + when(encoder.matches(anyString(), anyString())).thenReturn(true); + + service.delete(id, user.getPassword()); + + verify(repository, times(1)).findById(id); + verify(repository, times(1)).delete(user); + verify(noteService, times(1)).deleteAllUserHiddenNotes(eq(user)); + + } + + @Test + void shouldThrowBadCredentialsException_whenPasswordDoesNotMatch() { + + when(repository.findById(id)).thenReturn(Optional.of(user)); + when(encoder.matches(anyString(), anyString())).thenReturn(false); + + assertThatThrownBy(() -> + service.delete(id, user.getPassword())) + .isInstanceOf(BadCredentialsException.class); + + verify(repository, times(1)).findById(id); + verify(repository, never()).delete(user); + verify(noteService, never()).deleteAllUserHiddenNotes(eq(user)); + + } + +} \ No newline at end of file From fc6c87da94f4c14a031a1f6ede886401ae7393a6 Mon Sep 17 00:00:00 2001 From: Lucas Aguiar Date: Tue, 18 Nov 2025 10:56:55 -0300 Subject: [PATCH 6/9] test(user): add retrieval tests --- .../user/UserRetrievalTest.java | 325 ++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 src/test/java/br/com/notehub/implementation/user/UserRetrievalTest.java diff --git a/src/test/java/br/com/notehub/implementation/user/UserRetrievalTest.java b/src/test/java/br/com/notehub/implementation/user/UserRetrievalTest.java new file mode 100644 index 0000000..7025495 --- /dev/null +++ b/src/test/java/br/com/notehub/implementation/user/UserRetrievalTest.java @@ -0,0 +1,325 @@ +package br.com.notehub.implementation.user; + +import br.com.notehub.application.implementation.user.UserServiceImpl; +import br.com.notehub.domain.history.UserHistoryService; +import br.com.notehub.domain.user.Subscription; +import br.com.notehub.domain.user.User; +import br.com.notehub.domain.user.UserRepository; +import jakarta.persistence.EntityNotFoundException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.security.access.AccessDeniedException; + +import java.util.*; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class UserRetrievalTest { + + @InjectMocks + private UserServiceImpl service; + + @Mock + private UserRepository repository; + + @Mock + private UserHistoryService historian; + + private User user; + private Pageable pageable; + + private User createUser(String email, String username) { + User u = new User(email, username, username.toUpperCase(), "123"); + u.setId(UUID.randomUUID()); + u.setActive(true); + return u; + } + + private void mockFindById(User u) { + when(repository.findById(u.getId())).thenReturn(Optional.of(u)); + } + + private void mockFindByUsername(User u) { + when(repository.findByUsername(u.getUsername())).thenReturn(Optional.of(u)); + } + + @BeforeEach + void setup() { + user = createUser("tester@notehub.com.br", "tester"); + pageable = PageRequest.of(0, 10); + } + + @Test + void shouldReturnUser_whenUsernameWasFoundAndUserIsActive() { + + mockFindByUsername(user); + + User result = service.getUser(user.getUsername()); + + verify(repository).findByUsername(user.getUsername()); + + assertThat(result).isEqualTo(user); + + } + + @Test + void shouldThrowEntityNotFoundException_whenUsernameWasNotFoundOrUserIsInactive() { + + when(repository.findByUsername(anyString())).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> service.getUser(user.getUsername())) + .isInstanceOf(EntityNotFoundException.class); + + verify(repository).findByUsername(user.getUsername()); + + } + + @Test + void shouldReturnListOfActiveUsers() { + + when(repository.findAllByActiveTrue()).thenReturn(List.of(user)); + + List result = service.getAllActiveUsers(); + + verify(repository).findAllByActiveTrue(); + + assertThat(result).containsExactly(user); + + } + + @Test + void shouldReturnPageOfActiveUsersByQuery() { + + String query = "tester"; + Page page = new PageImpl<>(List.of(user)); + + when(repository.findAllActiveUsersByUsernameOrDisplayName(pageable, query)).thenReturn(page); + + Page result = service.findAll(pageable, query); + + verify(repository).findAllActiveUsersByUsernameOrDisplayName(pageable, query); + + assertThat(result).isEqualTo(page); + + } + + @Test + void shouldReturnPageOfUsersThatRequestedUserIsFollowing() { + + User requesting = user; + User target = createUser("target@mail.com", "target"); + User u1 = createUser("a@mail.com", "a"); + User u2 = createUser("b@mail.com", "b"); + + List users = List.of(u1, u2); + Set ids = Set.of(u1.getId(), u2.getId()); + target.getFollowing().addAll(users); + + Page expected = new PageImpl<>(users); + + mockFindById(requesting); + mockFindByUsername(target); + + when(repository.findAllByIdIn( + eq(pageable), + eq("q"), + argThat(list -> new HashSet<>(list).equals(ids)) + )).thenReturn(expected); + + Page result = service.getUserFollowing(pageable, "q", requesting.getId(), target.getUsername()); + + verify(repository).findById(requesting.getId()); + verify(repository).findByUsername(target.getUsername()); + verify(repository).findAllByIdIn( + eq(pageable), + eq("q"), + argThat(list -> new HashSet<>(list).equals(ids)) + ); + + assertThat(result).isEqualTo(expected); + + } + + @Test + void shouldReturnPageOfUsersThatFollowsRequestedUser() { + + User requesting = user; + User target = createUser("target@mail.com", "target"); + User u1 = createUser("a@mail.com", "a"); + User u2 = createUser("b@mail.com", "b"); + + List users = List.of(u1, u2); + Set ids = Set.of(u1.getId(), u2.getId()); + target.getFollowers().addAll(users); + + Page expected = new PageImpl<>(users); + + mockFindById(requesting); + mockFindByUsername(target); + + when(repository.findAllByIdIn( + eq(pageable), + eq("q"), + argThat(list -> new HashSet<>(list).equals(ids)) + )).thenReturn(expected); + + Page result = service.getUserFollowers(pageable, "q", requesting.getId(), target.getUsername()); + + verify(repository).findById(requesting.getId()); + verify(repository).findByUsername(target.getUsername()); + verify(repository).findAllByIdIn( + eq(pageable), + eq("q"), + argThat(list -> new HashSet<>(list).equals(ids)) + ); + + assertThat(result).isEqualTo(expected); + + } + + @Test + void shouldThrowEntityNotFoundException_whenRequestingUserNotFound() { + + UUID id = UUID.randomUUID(); + + when(repository.findById(id)).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> + service.getUserFollowing(pageable, "q", id, "someone")) + .isInstanceOf(EntityNotFoundException.class); + + verify(repository).findById(id); + verify(repository, never()).findByUsername(anyString()); + verify(repository, never()).findAllByIdIn(any(), anyString(), anyList()); + + } + + @Test + void shouldThrowEntityNotFoundException_whenRequestedUserNotFound() { + + mockFindById(user); + when(repository.findByUsername(anyString())).thenReturn(Optional.empty()); + + assertThatThrownBy(() -> + service.getUserFollowing(pageable, "q", user.getId(), "unknown")) + .isInstanceOf(EntityNotFoundException.class); + + verify(repository).findById(user.getId()); + verify(repository).findByUsername("unknown"); + verify(repository, never()).findAllByIdIn(any(), anyString(), anyList()); + + } + + @Test + void shouldThrowAccessDeniedException_whenAccessIsNotAllowed() { + + User requesting = createUser("req@mail.com", "req"); + User target = createUser("tar@mail.com", "tar"); + target.setProfilePrivate(true); + + mockFindById(requesting); + mockFindByUsername(target); + + assertThatThrownBy(() -> + service.getUserFollowing(pageable, "q", requesting.getId(), "tar")) + .isInstanceOf(AccessDeniedException.class); + + verify(repository).findById(requesting.getId()); + verify(repository).findByUsername("tar"); + verify(repository, never()).findAllByIdIn(any(), anyString(), anyList()); + + } + + @Test + void shouldReturnStringSetOfAllUserMutuals() { + + User u1 = createUser("a@mail.com", "a"); + User u2 = createUser("b@mail.com", "b"); + + List users = List.of(u1, u2); + + user.getFollowers().addAll(users); + user.getFollowing().addAll(users); + + when(repository.findByIdWithFollowersAndFollowing(user.getId())).thenReturn(Optional.of(user)); + + Set mutuals = service.getUserMutualConnections(user.getId()); + + verify(repository).findByIdWithFollowersAndFollowing(user.getId()); + + assertThat(mutuals).containsExactlyInAnyOrder("a", "b"); + + } + + @Test + void shouldReturnEmptySet_whenUserHasNoMutualConnections() { + + user.getFollowers().add(createUser("a@mail.com", "a")); + user.getFollowing().add(createUser("b@mail.com", "b")); + + when(repository.findByIdWithFollowersAndFollowing(user.getId())).thenReturn(Optional.of(user)); + + Set mutuals = service.getUserMutualConnections(user.getId()); + + verify(repository).findByIdWithFollowersAndFollowing(user.getId()); + + assertThat(mutuals).isEmpty(); + + } + + @Test + void shouldReturnListOfUserUsernameHistory() { + + List expected = List.of("tester", "new"); + + mockFindByUsername(user); + when(historian.getLastFiveUserDisplayName(user)).thenReturn(expected); + + List history = service.getUserDisplayNameHistory(user.getUsername()); + + assertThat(history).containsExactlyElementsOf(expected); + + } + + @Test + void shouldReturnListOfUserSubscriptions() { + + mockFindById(user); + + Set expected = Set.of(Subscription.MAINTENANCE, Subscription.RELEASE); + Set subscriptions = service.getUserSubscriptions(user.getId()); + + verify(repository).findById(user.getId()); + + assertThat(subscriptions).containsExactlyInAnyOrderElementsOf(expected); + + } + + @Test + void shouldCleanUsersWithExpiredActivationTime() { + + User u1 = createUser("a@mail.com", "a"); + User u2 = createUser("b@mail.com", "b"); + List expired = List.of(u1, u2); + + when(repository.findUsersWithExpiredActivationTime(any())).thenReturn(expired); + + service.cleanUsersWithExpiredActivationTime(); + + verify(repository).findUsersWithExpiredActivationTime(any()); + verify(repository).deleteAll(expired); + + } + +} \ No newline at end of file From 809f84e219e26b81d599fed729b8ffdef073dfb7 Mon Sep 17 00:00:00 2001 From: Lucas Aguiar Date: Tue, 18 Nov 2025 16:01:45 -0300 Subject: [PATCH 7/9] refactor(test-user): abstract repetitive code and simplify verify calls --- .../implementation/user/UserCreationTest.java | 86 +++++++++++-------- .../implementation/user/UserDeletionTest.java | 37 ++++---- .../implementation/user/UserEditionTest.java | 54 ++++++------ .../user/UserRelationshipTest.java | 78 ++++++++++------- 4 files changed, 146 insertions(+), 109 deletions(-) diff --git a/src/test/java/br/com/notehub/implementation/user/UserCreationTest.java b/src/test/java/br/com/notehub/implementation/user/UserCreationTest.java index 6f80e84..9ddb517 100644 --- a/src/test/java/br/com/notehub/implementation/user/UserCreationTest.java +++ b/src/test/java/br/com/notehub/implementation/user/UserCreationTest.java @@ -19,8 +19,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) @@ -42,35 +40,50 @@ class UserCreationTest { private PasswordEncoder encoder; private User user; - private UUID id; + + private User createUser(String email, String username) { + User u = new User(email, username, username.toUpperCase(), "123"); + u.setId(UUID.randomUUID()); + u.setActive(true); + return u; + } + + private void mockExistsByEmail(User u, boolean condition) { + when(repository.existsByEmail(u.getEmail())).thenReturn(condition); + } + + private void mockExistsByUsername(User u, boolean condition) { + when(repository.existsByUsername(u.getUsername())).thenReturn(condition); + } + + private void mockSave(User u) { + when(repository.save(u)).thenReturn(u); + } @BeforeEach void setup() { - user = new User("tester@notehub.com.br", "tester", "Tester", "1234"); - id = UUID.randomUUID(); - user.setId(id); - user.setActive(true); + user = createUser("tester@notehub.com.br", "tester"); } @Test void shouldEncodePasswordAndSaveUser_whenDataIsValid() { - when(repository.existsByEmail(anyString())).thenReturn(false); - when(repository.existsByUsername(anyString())).thenReturn(false); - when(encoder.encode(anyString())).thenReturn("encoded"); - when(repository.save(any(User.class))).thenAnswer(i -> i.getArgument(0)); + mockExistsByEmail(user, false); + mockExistsByUsername(user, false); + mockSave(user); + when(encoder.encode(user.getPassword())).thenReturn("encoded"); User result = service.create(user); - verify(repository).existsByEmail("tester@notehub.com.br"); - verify(repository).existsByUsername("tester"); - verify(encoder).encode("1234"); - verify(repository).save(any(User.class)); + verify(repository).existsByEmail(user.getEmail()); + verify(repository).existsByUsername(user.getUsername()); + verify(encoder).encode("123"); + verify(repository).save(user); - assertThat(result).isInstanceOf(User.class); - assertThat(result.getEmail()).isEqualTo("tester@notehub.com.br"); - assertThat(result.getUsername()).isEqualTo("tester"); - assertThat(result.getDisplayName()).isEqualTo("Tester"); + assertThat(result).isEqualTo(user); + assertThat(result.getEmail()).isEqualTo(user.getEmail()); + assertThat(result.getUsername()).isEqualTo(user.getUsername()); + assertThat(result.getDisplayName()).isEqualTo(user.getDisplayName()); assertThat(result.getPassword()).isEqualTo("encoded"); } @@ -78,48 +91,48 @@ void shouldEncodePasswordAndSaveUser_whenDataIsValid() { @Test void shouldThrowException_whenEmailAlreadyExists() { - when(repository.existsByEmail(anyString())).thenReturn(true); - when(repository.existsByUsername(anyString())).thenReturn(false); + mockExistsByEmail(user, true); + mockExistsByUsername(user, false); assertThatThrownBy(() -> service.create(user)) .isInstanceOf(DataIntegrityViolationException.class) .hasMessage("email"); - verify(repository, never()).save(any()); + verify(repository, never()).save(user); } @Test void shouldThrowException_whenUsernameAlreadyExists() { - when(repository.existsByEmail(anyString())).thenReturn(false); - when(repository.existsByUsername(anyString())).thenReturn(true); + mockExistsByEmail(user, false); + mockExistsByUsername(user, true); assertThatThrownBy(() -> service.create(user)) .isInstanceOf(DataIntegrityViolationException.class) .hasMessage("username"); - verify(repository, never()).save(any()); + verify(repository, never()).save(user); } @Test void shouldThrowException_whenEmailAndUsernameAlreadyExist() { - when(repository.existsByEmail(anyString())).thenReturn(true); - when(repository.existsByUsername(anyString())).thenReturn(true); + mockExistsByEmail(user, true); + mockExistsByUsername(user, true); assertThatThrownBy(() -> service.create(user)) .isInstanceOf(DataIntegrityViolationException.class) .hasMessage("both"); - verify(repository, never()).save(any()); + verify(repository, never()).save(user); } @Test void shouldReturnToken_whenGeneratingActivationToken() { - when(tokenService.generateActivationToken(any(User.class))).thenReturn("token"); + when(tokenService.generateActivationToken(user)).thenReturn("token"); String token = service.generateActivationToken(user); assertThat(token).isEqualTo("token"); } @@ -127,17 +140,16 @@ void shouldReturnToken_whenGeneratingActivationToken() { @Test void shouldSetActiveTrueAndLogHistory_whenActivatingUser() { - User inactiveUser = new User("inactive@notehub.com.br", "inactive", "Inactive", "1234"); - inactiveUser.setId(id); - inactiveUser.setActive(false); + User inactive = createUser("inactive@notehub.com.br", "inactive"); + inactive.setActive(false); - when(repository.findById(id)).thenReturn(Optional.of(inactiveUser)); - when(repository.save(any(User.class))).thenReturn(inactiveUser); + when(repository.findById(inactive.getId())).thenReturn(Optional.of(inactive)); + mockSave(inactive); - service.activate(id); + service.activate(inactive.getId()); - verify(repository).save(any(User.class)); - verify(historian).setHistory(any(), eq("active"), eq("false"), eq("true")); + verify(repository).save(inactive); + verify(historian).setHistory(inactive, "active", "false", "true"); } diff --git a/src/test/java/br/com/notehub/implementation/user/UserDeletionTest.java b/src/test/java/br/com/notehub/implementation/user/UserDeletionTest.java index af37ae5..ddf169a 100644 --- a/src/test/java/br/com/notehub/implementation/user/UserDeletionTest.java +++ b/src/test/java/br/com/notehub/implementation/user/UserDeletionTest.java @@ -35,42 +35,49 @@ public class UserDeletionTest { private PasswordEncoder encoder; private User user; - private UUID id; + + private void mockFindById(User u) { + when(repository.findById(u.getId())).thenReturn(Optional.of(u)); + } + + private void mockMatches(boolean condition) { + when(encoder.matches(anyString(), anyString())).thenReturn(condition); + } @BeforeEach void setup() { - user = new User("tester@notehub.com.br", "tester", "Tester", "1234"); - id = UUID.randomUUID(); - user.setId(id); + user = new User("tester@notehub.com.br", "tester", "TESTER", "123"); + user.setId(UUID.randomUUID()); + user.setActive(true); } @Test void shouldDeleteUser_whenPasswordMatches() { - when(repository.findById(id)).thenReturn(Optional.of(user)); - when(encoder.matches(anyString(), anyString())).thenReturn(true); + mockFindById(user); + mockMatches(true); - service.delete(id, user.getPassword()); + service.delete(user.getId(), user.getPassword()); - verify(repository, times(1)).findById(id); - verify(repository, times(1)).delete(user); - verify(noteService, times(1)).deleteAllUserHiddenNotes(eq(user)); + verify(repository).findById(user.getId()); + verify(repository).delete(user); + verify(noteService).deleteAllUserHiddenNotes(user); } @Test void shouldThrowBadCredentialsException_whenPasswordDoesNotMatch() { - when(repository.findById(id)).thenReturn(Optional.of(user)); - when(encoder.matches(anyString(), anyString())).thenReturn(false); + mockFindById(user); + mockMatches(false); assertThatThrownBy(() -> - service.delete(id, user.getPassword())) + service.delete(user.getId(), user.getPassword())) .isInstanceOf(BadCredentialsException.class); - verify(repository, times(1)).findById(id); + verify(repository).findById(user.getId()); verify(repository, never()).delete(user); - verify(noteService, never()).deleteAllUserHiddenNotes(eq(user)); + verify(noteService, never()).deleteAllUserHiddenNotes(user); } diff --git a/src/test/java/br/com/notehub/implementation/user/UserEditionTest.java b/src/test/java/br/com/notehub/implementation/user/UserEditionTest.java index fb562f1..46f8277 100644 --- a/src/test/java/br/com/notehub/implementation/user/UserEditionTest.java +++ b/src/test/java/br/com/notehub/implementation/user/UserEditionTest.java @@ -32,62 +32,68 @@ public class UserEditionTest { private UserHistoryService historian; private User user; - private UUID id; + + private User updateUser(String name, boolean profilePrivate) { + return new User(name, name.toUpperCase(), null, null, null, profilePrivate); + } + + private void mockFindById(User user) { + when(repository.findById(user.getId())).thenReturn(Optional.of(user)); + } @BeforeEach void setup() { - user = new User("tester@notehub.com.br", "tester", "Tester", "1234"); - id = UUID.randomUUID(); - user.setId(id); + user = new User("tester@notehub.com.br", "tester", "TESTER", "123"); + user.setId(UUID.randomUUID()); user.setActive(true); } @Test void shouldSaveHistoryAndPersistChanges_whenDataIsModified() { - User updated = new User("updated", "Updated", null, null, null, true); + User updated = updateUser("updated", true); - when(repository.findById(id)).thenReturn(Optional.of(user)); + mockFindById(user); - assertThat(updated).isEqualTo(service.edit(id, updated)); + assertThat(updated).isEqualTo(service.edit(user.getId(), updated)); - verify(repository, times(6)).findById(id); - verify(repository, times(3)).save(any(User.class)); - verify(historian).setHistory(any(User.class), eq("username"), eq("tester"), eq("updated")); - verify(historian).setHistory(any(User.class), eq("display_name"), eq("Tester"), eq("Updated")); - verify(historian).setHistory(any(User.class), eq("profile_private"), eq("false"), eq("true")); + verify(repository, times(6)).findById(user.getId()); + verify(repository, times(3)).save(user); + verify(historian).setHistory(user, "username", "tester", "updated"); + verify(historian).setHistory(user, "display_name", "TESTER", "UPDATED"); + verify(historian).setHistory(user, "profile_private", "false", "true"); } @Test void shouldSkipSaveAndHistory_whenUserDataIsUnchanged() { - User updated = new User("tester", "Tester", null, null, null, false); + User updated = updateUser("tester", false); - when(repository.findById(id)).thenReturn(Optional.of(user)); + mockFindById(user); - assertThat(updated).isEqualTo(service.edit(id, updated)); + assertThat(updated).isEqualTo(service.edit(user.getId(), updated)); - verify(repository, times(6)).findById(id); - verify(repository, never()).save(any(User.class)); + verify(repository, times(6)).findById(user.getId()); + verify(repository, never()).save(user); verify(historian, never()).setHistory(any(), any(), any(), any()); } @Test - void shouldThrowException_whenUsernameAlreadyExists() { + void shouldThrowDataIntegrityViolationException_whenUsernameAlreadyExists() { - User updated = new User("tester", "Updated", null, null, null, false); + User updated = updateUser("tester", false); - when(repository.findByUsername("tester")).thenReturn(Optional.of(user)); - when(repository.findById(id)).thenReturn(Optional.of(updated)); + mockFindById(user); + when(repository.findByUsername("tester")).thenReturn(Optional.of(updated)); - assertThatThrownBy(() -> service.edit(id, updated)) + assertThatThrownBy(() -> service.edit(user.getId(), updated)) .isInstanceOf(DataIntegrityViolationException.class) .hasMessage("username"); - verify(repository, times(1)).findById(id); - verify(repository, never()).save(any(User.class)); + verify(repository).findById(user.getId()); + verify(repository, never()).save(user); verify(historian, never()).setHistory(any(), any(), any(), any()); } diff --git a/src/test/java/br/com/notehub/implementation/user/UserRelationshipTest.java b/src/test/java/br/com/notehub/implementation/user/UserRelationshipTest.java index 20f48af..c0d5e0b 100644 --- a/src/test/java/br/com/notehub/implementation/user/UserRelationshipTest.java +++ b/src/test/java/br/com/notehub/implementation/user/UserRelationshipTest.java @@ -38,44 +38,56 @@ public class UserRelationshipTest { private User follower; private User following; - private UUID followerId; + + private User createUser(String email, String username) { + User u = new User(email, username, username.toUpperCase(), "123"); + u.setId(UUID.randomUUID()); + u.setActive(true); + return u; + } + + private void mockfindByIdWithFollowersAndFollowing(User u) { + when(repository.findByIdWithFollowersAndFollowing(u.getId())).thenReturn(Optional.of(u)); + } + + private void mockfindByUsernameWithFollowersAndFollowing(User u) { + when(repository.findByUsernameWithFollowersAndFollowing(u.getUsername())).thenReturn(Optional.of(u)); + } @BeforeEach void setup() { - follower = new User("follower@notehub.com.br", "follower", "Follower", "1234"); - following = new User("following@notehub.com.br", "following", "Following", "1234"); - followerId = UUID.randomUUID(); - follower.setId(followerId); + follower = createUser("follower@notehub.com.br", "follower"); + following = createUser("following@notehub.com.br", "following"); } @Test void shouldFollowUserAndSendNotification_whenNotAlreadyFollowing() { - when(repository.findByIdWithFollowersAndFollowing(followerId)).thenReturn(Optional.of(follower)); - when(repository.findByUsernameWithFollowersAndFollowing(following.getUsername())).thenReturn(Optional.of(following)); + mockfindByIdWithFollowersAndFollowing(follower); + mockfindByUsernameWithFollowersAndFollowing(following); - service.follow(followerId, following.getUsername()); + service.follow(follower.getId(), following.getUsername()); - verify(repository, times(1)).findByIdWithFollowersAndFollowing(followerId); - verify(repository, times(1)).findByUsernameWithFollowersAndFollowing(following.getUsername()); - verify(counter, times(1)).updateFollowersAndFollowingCount(eq(follower), eq(following), eq(true)); - verify(notifier, times(1)).notify(eq(follower), eq(following), eq(follower), eq(MessageNotification.of(follower))); + verify(repository).findByIdWithFollowersAndFollowing(follower.getId()); + verify(repository).findByUsernameWithFollowersAndFollowing(following.getUsername()); + verify(counter).updateFollowersAndFollowingCount(eq(follower), eq(following), eq(true)); + verify(notifier).notify(eq(follower), eq(following), eq(follower), eq(MessageNotification.of(follower))); } @Test void shouldUnfollowUserWithoutNotification_whenAlreadyFollowing() { - when(repository.findByIdWithFollowersAndFollowing(followerId)).thenReturn(Optional.of(follower)); - when(repository.findByUsernameWithFollowersAndFollowing(following.getUsername())).thenReturn(Optional.of(following)); + mockfindByIdWithFollowersAndFollowing(follower); + mockfindByUsernameWithFollowersAndFollowing(following); follower.getFollowing().add(following); following.getFollowers().add(follower); - service.unfollow(followerId, following.getUsername()); + service.unfollow(follower.getId(), following.getUsername()); - verify(repository, times(1)).findByIdWithFollowersAndFollowing(followerId); - verify(repository, times(1)).findByUsernameWithFollowersAndFollowing(following.getUsername()); - verify(counter, times(1)).updateFollowersAndFollowingCount(eq(follower), eq(following), eq(false)); + verify(repository).findByIdWithFollowersAndFollowing(follower.getId()); + verify(repository).findByUsernameWithFollowersAndFollowing(following.getUsername()); + verify(counter).updateFollowersAndFollowingCount(eq(follower), eq(following), eq(false)); verify(notifier, never()).notify(any(), any(), any(), any()); } @@ -83,15 +95,15 @@ void shouldUnfollowUserWithoutNotification_whenAlreadyFollowing() { @Test void shouldThrowSelfFollowException_whenTryingToFollowSelf() { - when(repository.findByIdWithFollowersAndFollowing(followerId)).thenReturn(Optional.of(follower)); - when(repository.findByUsernameWithFollowersAndFollowing(following.getUsername())).thenReturn(Optional.of(follower)); + mockfindByIdWithFollowersAndFollowing(follower); + mockfindByUsernameWithFollowersAndFollowing(follower); assertThatThrownBy(() -> - service.follow(followerId, following.getUsername())) + service.follow(follower.getId(), follower.getUsername())) .isInstanceOf(CustomExceptions.SelfFollowException.class); - verify(repository, times(1)).findByIdWithFollowersAndFollowing(followerId); - verify(repository, times(1)).findByUsernameWithFollowersAndFollowing(following.getUsername()); + verify(repository).findByIdWithFollowersAndFollowing(follower.getId()); + verify(repository).findByUsernameWithFollowersAndFollowing(follower.getUsername()); verify(counter, never()).updateFollowersAndFollowingCount(any(), any(), any(Boolean.class)); verify(notifier, never()).notify(any(), any(), any(), any()); @@ -100,18 +112,18 @@ void shouldThrowSelfFollowException_whenTryingToFollowSelf() { @Test void shouldThrowAlreadyFollowingException_whenFollowingUserAgain() { - when(repository.findByIdWithFollowersAndFollowing(followerId)).thenReturn(Optional.of(follower)); - when(repository.findByUsernameWithFollowersAndFollowing(following.getUsername())).thenReturn(Optional.of(following)); + mockfindByIdWithFollowersAndFollowing(follower); + mockfindByUsernameWithFollowersAndFollowing(following); follower.getFollowing().add(following); following.getFollowers().add(follower); assertThatThrownBy(() -> - service.follow(followerId, following.getUsername())) + service.follow(follower.getId(), following.getUsername())) .isInstanceOf(CustomExceptions.AlreadyFollowingException.class); - verify(repository, times(1)).findByIdWithFollowersAndFollowing(followerId); - verify(repository, times(1)).findByUsernameWithFollowersAndFollowing(following.getUsername()); + verify(repository).findByIdWithFollowersAndFollowing(follower.getId()); + verify(repository).findByUsernameWithFollowersAndFollowing(following.getUsername()); verify(counter, never()).updateFollowersAndFollowingCount(any(), any(), any(Boolean.class)); verify(notifier, never()).notify(any(), any(), any(), any()); @@ -120,15 +132,15 @@ void shouldThrowAlreadyFollowingException_whenFollowingUserAgain() { @Test void shouldThrowNotFollowingException_whenUnfollowingUserNotFollowed() { - when(repository.findByIdWithFollowersAndFollowing(followerId)).thenReturn(Optional.of(follower)); - when(repository.findByUsernameWithFollowersAndFollowing(following.getUsername())).thenReturn(Optional.of(following)); + mockfindByIdWithFollowersAndFollowing(follower); + mockfindByUsernameWithFollowersAndFollowing(following); assertThatThrownBy(() -> - service.unfollow(followerId, following.getUsername())) + service.unfollow(follower.getId(), following.getUsername())) .isInstanceOf(CustomExceptions.NotFollowingException.class); - verify(repository, times(1)).findByIdWithFollowersAndFollowing(followerId); - verify(repository, times(1)).findByUsernameWithFollowersAndFollowing(following.getUsername()); + verify(repository).findByIdWithFollowersAndFollowing(follower.getId()); + verify(repository).findByUsernameWithFollowersAndFollowing(following.getUsername()); verify(counter, never()).updateFollowersAndFollowingCount(any(), any(), any(Boolean.class)); verify(notifier, never()).notify(any(), any(), any(), any()); From e9069221ad47fdc21b329e504ef9a740bac5df10 Mon Sep 17 00:00:00 2001 From: Lucas Aguiar Date: Wed, 19 Nov 2025 09:12:51 -0300 Subject: [PATCH 8/9] chore(ci): generalize workflow and preserve .dockerignore and fly.toml --- .github/workflows/deploy.yml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index a4b4bac..c402990 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -22,13 +22,15 @@ jobs: ref: main fetch-depth: 0 - - name: Save fly.toml from deploy branch + - name: Save files from deploy branch run: | git fetch origin deploy || echo "No deploy branch yet" mkdir temp if git ls-remote --exit-code origin deploy; then - git checkout origin/deploy -- fly.toml || echo "No fly.toml to copy" - cp fly.toml temp/ || echo "No fly.toml found to copy" + for file in fly.toml .dockerignore; do + git checkout origin/deploy -- "$file" 2>/dev/null || echo "No $file to copy" + [ -f "$file" ] && cp "$file" temp/ || echo "$file not found" + done fi - name: Create/overwrite deploy branch @@ -36,16 +38,18 @@ jobs: git checkout -B deploy git reset --hard main - - name: Restore fly.toml + - name: Restore files run: | - if [ -f temp/fly.toml ]; then - cp temp/fly.toml fly.toml - fi + for file in fly.toml .dockerignore; do + if [ -f temp/$file ]; then + cp temp/$file $file + fi + done - name: Commit and push to deploy run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git add -A - git commit -m "Sync main -> deploy (keeping fly.toml)" || echo "No changes to commit" - git push -f origin deploy + git commit -m "Sync main -> deploy (keeping fly.toml and .dockerignore)" || echo "No changes to commit" + git push -f origin deploy \ No newline at end of file From 7b6704c0085f7a92db1e74788bbd1bbd39d94988 Mon Sep 17 00:00:00 2001 From: Lucas Aguiar Date: Wed, 19 Nov 2025 09:41:21 -0300 Subject: [PATCH 9/9] chore(ci): add workflow to run unit tests on pull requests --- .github/workflows/tests.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..2240980 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,23 @@ +name: Run Unit Tests + +on: + pull_request: + branches: + - main + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up JDK + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: '21' + + - name: Run unit tests + run: mvn test \ No newline at end of file