Skip to content
Merged
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
22 changes: 13 additions & 9 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,34 @@ 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
run: |
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
23 changes: 23 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.20.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
156 changes: 156 additions & 0 deletions src/test/java/br/com/notehub/implementation/user/UserCreationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
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.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 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 = createUser("tester@notehub.com.br", "tester");
}

@Test
void shouldEncodePasswordAndSaveUser_whenDataIsValid() {

mockExistsByEmail(user, false);
mockExistsByUsername(user, false);
mockSave(user);
when(encoder.encode(user.getPassword())).thenReturn("encoded");

User result = service.create(user);

verify(repository).existsByEmail(user.getEmail());
verify(repository).existsByUsername(user.getUsername());
verify(encoder).encode("123");
verify(repository).save(user);

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");

}

@Test
void shouldThrowException_whenEmailAlreadyExists() {

mockExistsByEmail(user, true);
mockExistsByUsername(user, false);

assertThatThrownBy(() -> service.create(user))
.isInstanceOf(DataIntegrityViolationException.class)
.hasMessage("email");

verify(repository, never()).save(user);

}

@Test
void shouldThrowException_whenUsernameAlreadyExists() {

mockExistsByEmail(user, false);
mockExistsByUsername(user, true);

assertThatThrownBy(() -> service.create(user))
.isInstanceOf(DataIntegrityViolationException.class)
.hasMessage("username");

verify(repository, never()).save(user);

}

@Test
void shouldThrowException_whenEmailAndUsernameAlreadyExist() {

mockExistsByEmail(user, true);
mockExistsByUsername(user, true);

assertThatThrownBy(() -> service.create(user))
.isInstanceOf(DataIntegrityViolationException.class)
.hasMessage("both");

verify(repository, never()).save(user);

}

@Test
void shouldReturnToken_whenGeneratingActivationToken() {
when(tokenService.generateActivationToken(user)).thenReturn("token");
String token = service.generateActivationToken(user);
assertThat(token).isEqualTo("token");
}

@Test
void shouldSetActiveTrueAndLogHistory_whenActivatingUser() {

User inactive = createUser("inactive@notehub.com.br", "inactive");
inactive.setActive(false);

when(repository.findById(inactive.getId())).thenReturn(Optional.of(inactive));
mockSave(inactive);

service.activate(inactive.getId());

verify(repository).save(inactive);
verify(historian).setHistory(inactive, "active", "false", "true");

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
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 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", "123");
user.setId(UUID.randomUUID());
user.setActive(true);
}

@Test
void shouldDeleteUser_whenPasswordMatches() {

mockFindById(user);
mockMatches(true);

service.delete(user.getId(), user.getPassword());

verify(repository).findById(user.getId());
verify(repository).delete(user);
verify(noteService).deleteAllUserHiddenNotes(user);

}

@Test
void shouldThrowBadCredentialsException_whenPasswordDoesNotMatch() {

mockFindById(user);
mockMatches(false);

assertThatThrownBy(() ->
service.delete(user.getId(), user.getPassword()))
.isInstanceOf(BadCredentialsException.class);

verify(repository).findById(user.getId());
verify(repository, never()).delete(user);
verify(noteService, never()).deleteAllUserHiddenNotes(user);

}

}
Loading
Loading