diff --git a/pom.xml b/pom.xml index c14905c..6d44c88 100644 --- a/pom.xml +++ b/pom.xml @@ -1,13 +1,17 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + + jar + org.springframework.boot spring-boot-starter-parent - 3.4.0 + 3.4.2 + com.stelliocode backend 0.0.1-SNAPSHOT @@ -28,17 +32,13 @@ 17 + 0.8.11 org.springframework.boot spring-boot-starter-data-jpa - - io.jsonwebtoken - jjwt - 0.9.1 - org.springframework.boot spring-boot-starter-security @@ -47,11 +47,11 @@ org.springframework.boot spring-boot-starter-validation + org.springframework.boot spring-boot-starter-web - org.postgresql postgresql @@ -74,8 +74,31 @@ org.springframework.boot - spring-boot-configuration-processor - true + spring-boot-starter-mail + + + io.jsonwebtoken + jjwt-api + 0.11.5 + + + io.jsonwebtoken + jjwt-impl + 0.11.5 + runtime + + + io.jsonwebtoken + jjwt-jackson + 0.11.5 + runtime + + + + jakarta.servlet + jakarta.servlet-api + 6.0.0 + provided @@ -105,7 +128,25 @@ + + org.jacoco + jacoco-maven-plugin + ${jacoco.version} + + + + prepare-agent + + + + report + test + + report + + + + - diff --git a/src/main/java/com/stelliocode/backend/config/JwtAuthenticationFilter.java b/src/main/java/com/stelliocode/backend/config/JwtAuthenticationFilter.java index e4496e0..4e87db0 100644 --- a/src/main/java/com/stelliocode/backend/config/JwtAuthenticationFilter.java +++ b/src/main/java/com/stelliocode/backend/config/JwtAuthenticationFilter.java @@ -11,6 +11,7 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; + import java.io.IOException; @Component diff --git a/src/main/java/com/stelliocode/backend/config/MailConfig.java b/src/main/java/com/stelliocode/backend/config/MailConfig.java new file mode 100644 index 0000000..6ee6bfc --- /dev/null +++ b/src/main/java/com/stelliocode/backend/config/MailConfig.java @@ -0,0 +1,32 @@ +package com.stelliocode.backend.config; + + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; + +import java.util.Properties; + +@Configuration +public class MailConfig { + + @Bean + public JavaMailSender javaMailSender() { + JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + mailSender.setHost("smtp.gmail.com"); // Servidor SMTP do Gmail + mailSender.setPort(587); // Porta para TLS + + // Credenciais do e-mail + mailSender.setUsername("seu-email@gmail.com"); // Substitua pelo seu e-mail + mailSender.setPassword("sua-senha"); // Substitua pela sua senha + + // Propriedades adicionais + Properties props = mailSender.getJavaMailProperties(); + props.put("mail.smtp.auth", "true"); // Autenticação SMTP + props.put("mail.smtp.starttls.enable", "true"); // Habilita STARTTLS + + return mailSender; + } +} \ No newline at end of file diff --git a/src/main/java/com/stelliocode/backend/config/SecurityConfig.java b/src/main/java/com/stelliocode/backend/config/SecurityConfig.java index 786b797..68621a4 100644 --- a/src/main/java/com/stelliocode/backend/config/SecurityConfig.java +++ b/src/main/java/com/stelliocode/backend/config/SecurityConfig.java @@ -1,32 +1,19 @@ + + package com.stelliocode.backend.config; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.CorsConfigurationSource; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; - -import java.util.Arrays; -import java.util.List; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @Configuration -@EnableWebSecurity public class SecurityConfig { private final JwtAuthenticationFilter jwtAuthenticationFilter; - // Use the correct configuration for the origin - @Value("${app.cors.allowed-origin}") - private String[] allowedOrigins; - - // Constructor injection for JwtAuthenticationFilter public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) { this.jwtAuthenticationFilter = jwtAuthenticationFilter; } @@ -34,33 +21,14 @@ public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http - .csrf(csrf -> csrf.disable()) - .cors(cors -> cors.configurationSource(corsConfigurationSource())) + .csrf(csrf -> csrf.disable()) // Desabilita CSRF (útil para APIs stateless) .authorizeHttpRequests(auth -> auth - .requestMatchers("/api/public/**").permitAll() - .anyRequest().authenticated() + .requestMatchers(new AntPathRequestMatcher("/api/public/**")).permitAll() // Permite acesso público + .anyRequest().authenticated() // Exige autenticação para outros endpoints ) - .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); + .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); // Adiciona o filtro JWT return http.build(); } - - @Bean - public CorsConfigurationSource corsConfigurationSource() { - CorsConfiguration configuration = new CorsConfiguration(); - configuration.setAllowedOrigins(List.of(allowedOrigins)); // Fix variable name - configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); - configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type")); - configuration.setExposedHeaders(Arrays.asList("Authorization")); - configuration.setAllowCredentials(true); - - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", configuration); - return source; - } - - @Bean - public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { - return authConfig.getAuthenticationManager(); - } } + diff --git a/src/main/java/com/stelliocode/backend/model/MeetingRequest.java b/src/main/java/com/stelliocode/backend/model/MeetingRequest.java new file mode 100644 index 0000000..f083bc2 --- /dev/null +++ b/src/main/java/com/stelliocode/backend/model/MeetingRequest.java @@ -0,0 +1,189 @@ +package com.stelliocode.backend.model; + +import jakarta.persistence.*; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import java.time.LocalDateTime; +import java.util.Objects; + +/** + * Representa uma solicitação de reunião feita por um cliente. + */ +@Entity +@Table(name = "meeting_requests") +public class MeetingRequest { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotBlank + @Column(nullable = false, length = 100) + private String clientId; + + @NotBlank + @Column(nullable = false, length = 100) + private String clientName; + + @Email + @NotBlank + @Column(nullable = false, length = 100) + private String clientEmail; + + @NotBlank + @Column(nullable = false, length = 20) + private String clientPhone; + + @NotBlank + @Column(nullable = false, length = 100) + private String title; // Adicionado o campo title + + @NotNull + @Column(nullable = false) + private LocalDateTime meetingDateTime; + + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private Status status; + + @Size(max = 500, message = "As notas não podem ter mais de 500 caracteres") + @Column(length = 500) + private String notes; + + public MeetingRequest() { + this.status = Status.PENDENTE; // Define o status padrão como "PENDENTE" + } + + public MeetingRequest(String clientId, String clientName, String clientEmail, String clientPhone, String title, LocalDateTime meetingDateTime, String notes) { + this.clientId = clientId; + this.clientName = clientName; + this.clientEmail = clientEmail; + this.clientPhone = clientPhone; + this.title = title; // Inicializa o campo title + this.meetingDateTime = meetingDateTime; + this.notes = notes; + this.status = Status.PENDENTE; // Define o status padrão como "PENDENTE" + } + + public enum Status { + PENDENTE("Pendente"), + ACEITA("Aceita"), + RECUSADA("Recusada"), + REALIZADA("Realizada"); + + private final String descricao; + + Status(String descricao) { + this.descricao = descricao; + } + + public String getDescricao() { + return descricao; + } + } + + // Getters e Setters + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientName() { + return clientName; + } + + public void setClientName(String clientName) { + this.clientName = clientName; + } + + public String getClientEmail() { + return clientEmail; + } + + public void setClientEmail(String clientEmail) { + this.clientEmail = clientEmail; + } + + public String getClientPhone() { + return clientPhone; + } + + public void setClientPhone(String clientPhone) { + this.clientPhone = clientPhone; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public LocalDateTime getMeetingDateTime() { + return meetingDateTime; + } + + public void setMeetingDateTime(LocalDateTime meetingDateTime) { + this.meetingDateTime = meetingDateTime; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public String getNotes() { + return notes; + } + + public void setNotes(String notes) { + this.notes = notes; + } + + @Override + public String toString() { + return "MeetingRequest{" + + "id=" + id + + ", clientId='" + clientId + '\'' + + ", clientName='" + clientName + '\'' + + ", clientEmail='" + clientEmail + '\'' + + ", clientPhone='" + clientPhone + '\'' + + ", title='" + title + '\'' + + ", meetingDateTime=" + meetingDateTime + + ", status=" + status + + ", notes='" + notes + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MeetingRequest that = (MeetingRequest) o; + return Objects.equals(id, that.id) && + Objects.equals(clientId, that.clientId) && + Objects.equals(meetingDateTime, that.meetingDateTime); + } + + @Override + public int hashCode() { + return Objects.hash(id, clientId, meetingDateTime); + } +} \ No newline at end of file diff --git a/src/main/java/com/stelliocode/backend/repository/MeetingRequestRepository.java b/src/main/java/com/stelliocode/backend/repository/MeetingRequestRepository.java new file mode 100644 index 0000000..7b0642e --- /dev/null +++ b/src/main/java/com/stelliocode/backend/repository/MeetingRequestRepository.java @@ -0,0 +1,13 @@ +package com.stelliocode.backend.repository; + + +import org.springframework.data.jpa.repository.JpaRepository; +import com.stelliocode.backend.model.MeetingRequest; +import java.util.List; + +public interface MeetingRequestRepository extends JpaRepository { + // JpaRepository oferece métodos CRUD padrão + List findByStatus(MeetingRequest.Status status); +} + + diff --git a/src/main/java/com/stelliocode/backend/service/EmailService.java b/src/main/java/com/stelliocode/backend/service/EmailService.java new file mode 100644 index 0000000..55c91b6 --- /dev/null +++ b/src/main/java/com/stelliocode/backend/service/EmailService.java @@ -0,0 +1,92 @@ +package com.stelliocode.backend.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; + +@Service +public class EmailService { + + private static final Logger logger = LoggerFactory.getLogger(EmailService.class); + + @Autowired + private JavaMailSender emailSender; + + public void sendSimpleMessage(String to, String subject, String text) { + // Validação dos parâmetros + if (!StringUtils.hasText(to)) { + throw new IllegalArgumentException("O endereço de email do destinatário não pode estar vazio"); + } + if (!StringUtils.hasText(subject)) { + throw new IllegalArgumentException("O assunto do email não pode estar vazio"); + } + if (!StringUtils.hasText(text)) { + throw new IllegalArgumentException("O conteúdo do email não pode estar vazio"); + } + + try { + SimpleMailMessage message = new SimpleMailMessage(); + message.setTo(to); + message.setSubject(subject); + message.setText(text); + + emailSender.send(message); + logger.info("Email enviado com sucesso para: {}", to); + } catch (Exception e) { + logger.error("Erro ao enviar email para: {} - Erro: {}", to, e.getMessage()); + throw new RuntimeException("Falha ao enviar email", e); + } + } +} + +//package com.stelliocode.backend.service; +// +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.mail.SimpleMailMessage; +//import org.springframework.mail.javamail.JavaMailSender; +//import org.springframework.stereotype.Service; +//import org.springframework.util.StringUtils; +// +// +// +//@Service +//public class EmailService { +// +// private static final Logger logger = LoggerFactory.getLogger(EmailService.class); +// +// @Autowired +// private JavaMailSender emailSender; +// +// public void sendSimpleMessage(String to, String subject, String text) { +// try { +// // Validação dos parâmetros +// if (!StringUtils.hasText(to)) { +// throw new IllegalArgumentException("O endereço de email do destinatário não pode estar vazio"); +// } +// if (!StringUtils.hasText(subject)) { +// throw new IllegalArgumentException("O assunto do email não pode estar vazio"); +// } +// if (!StringUtils.hasText(text)) { +// throw new IllegalArgumentException("O conteúdo do email não pode estar vazio"); +// } +// +// SimpleMailMessage message = new SimpleMailMessage(); +// message.setTo(to); +// message.setSubject(subject); +// message.setText(text); +// +// emailSender.send(message); +// logger.info("Email enviado com sucesso para: {}", to); +// } catch (Exception e) { +// logger.error("Erro ao enviar email para: {} - Erro: {}", to, e.getMessage()); +// throw new RuntimeException("Falha ao enviar email", e); +// } +// } +//} +// diff --git a/src/main/java/com/stelliocode/backend/service/MeetingRequestService.java b/src/main/java/com/stelliocode/backend/service/MeetingRequestService.java new file mode 100644 index 0000000..97bbbca --- /dev/null +++ b/src/main/java/com/stelliocode/backend/service/MeetingRequestService.java @@ -0,0 +1,61 @@ +package com.stelliocode.backend.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.stelliocode.backend.model.MeetingRequest; +import com.stelliocode.backend.repository.MeetingRequestRepository; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; + +@Service // Marca a classe como um serviço Spring +public class MeetingRequestService { + + @Autowired // Injeta o repositório automaticamente + private MeetingRequestRepository repository; + + // Salva uma nova solicitação de reunião + public MeetingRequest saveMeetingRequest(MeetingRequest meetingRequest) { + if (meetingRequest == null) { + throw new IllegalArgumentException("MeetingRequest não pode ser nulo"); + } + meetingRequest.setStatus(MeetingRequest.Status.PENDENTE); // Define o status inicial como "Pendente" + return repository.save(meetingRequest); // Salva no banco de dados + } + + // Retorna todas as solicitações de reunião + public List getAllMeetingRequests() { + return repository.findAll(); // Busca todas as entradas no banco de dados + } + + // Atualiza o status de uma solicitação de reunião + public MeetingRequest updateMeetingRequestStatus(Long id, MeetingRequest.Status status) { + if (id == null || status == null) { + throw new IllegalArgumentException("ID e Status não podem ser nulos"); + } + MeetingRequest meetingRequest = repository.findById(id) + .orElseThrow(() -> new NoSuchElementException("MeetingRequest com ID " + id + " não encontrada")); + meetingRequest.setStatus(status); // Define o novo status + return repository.save(meetingRequest); // Salva a atualização no banco de dados + } + + // Deleta uma solicitação de reunião + public void deleteMeetingRequest(Long id) { + if (id == null) { + throw new IllegalArgumentException("ID não pode ser nulo"); + } + if (!repository.existsById(id)) { + throw new NoSuchElementException("MeetingRequest com ID " + id + " não encontrada"); + } + repository.deleteById(id); // Remove a entrada do banco de dados + } + + // Método adicional para buscar solicitações por status + public List getMeetingRequestsByStatus(MeetingRequest.Status status) { + if (status == null) { + throw new IllegalArgumentException("Status não pode ser nulo"); + } + return repository.findByStatus(status); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index c613173..cb73788 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -2,7 +2,7 @@ spring: datasource: url: ${DB_URL:jdbc:postgresql://localhost:5432/stelliocode} username: ${DB_USERNAME:postgres} - password: ${DB_PASSWORD:postgres} + password: ${DB_PASSWORD:1234} jpa: hibernate: ddl-auto: update diff --git a/src/test/java/com/stelliocode/backend/service/EmailServiceTest.java b/src/test/java/com/stelliocode/backend/service/EmailServiceTest.java new file mode 100644 index 0000000..b8ab4e6 --- /dev/null +++ b/src/test/java/com/stelliocode/backend/service/EmailServiceTest.java @@ -0,0 +1,95 @@ +package com.stelliocode.backend.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +public class EmailServiceTest { + + @Mock + private JavaMailSender emailSender; + + @InjectMocks + private EmailService emailService; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); // Inicializa os mocks + } + + @Test + public void testSendSimpleMessage_Success() { + String to = "destinatario@example.com"; + String subject = "Assunto do Email"; + String text = "Conteúdo do Email"; + + emailService.sendSimpleMessage(to, subject, text); + + verify(emailSender, times(1)).send(any(SimpleMailMessage.class)); + } + + @Test + public void testSendSimpleMessage_EmptyTo() { + String to = ""; + String subject = "Assunto do Email"; + String text = "Conteúdo do Email"; + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + emailService.sendSimpleMessage(to, subject, text); + }); + + assertEquals("O endereço de email do destinatário não pode estar vazio", exception.getMessage()); + verify(emailSender, never()).send(any(SimpleMailMessage.class)); + } + + @Test + public void testSendSimpleMessage_EmptySubject() { + String to = "destinatario@example.com"; + String subject = ""; + String text = "Conteúdo do Email"; + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + emailService.sendSimpleMessage(to, subject, text); + }); + + assertEquals("O assunto do email não pode estar vazio", exception.getMessage()); + verify(emailSender, never()).send(any(SimpleMailMessage.class)); + } + + @Test + public void testSendSimpleMessage_EmptyText() { + String to = "destinatario@example.com"; + String subject = "Assunto do Email"; + String text = ""; + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + emailService.sendSimpleMessage(to, subject, text); + }); + + assertEquals("O conteúdo do email não pode estar vazio", exception.getMessage()); + verify(emailSender, never()).send(any(SimpleMailMessage.class)); + } + + @Test + public void testSendSimpleMessage_Exception() { + String to = "destinatario@example.com"; + String subject = "Assunto do Email"; + String text = "Conteúdo do Email"; + + doThrow(new RuntimeException("Erro ao enviar email")).when(emailSender).send(any(SimpleMailMessage.class)); + + RuntimeException exception = assertThrows(RuntimeException.class, () -> { + emailService.sendSimpleMessage(to, subject, text); + }); + + assertEquals("Falha ao enviar email", exception.getMessage()); + verify(emailSender, times(1)).send(any(SimpleMailMessage.class)); + } +} \ No newline at end of file diff --git a/src/test/java/com/stelliocode/backend/service/MeetingRequestServiceTest.java b/src/test/java/com/stelliocode/backend/service/MeetingRequestServiceTest.java new file mode 100644 index 0000000..e1950a8 --- /dev/null +++ b/src/test/java/com/stelliocode/backend/service/MeetingRequestServiceTest.java @@ -0,0 +1,190 @@ +package com.stelliocode.backend.service; + +import com.stelliocode.backend.model.MeetingRequest; +import com.stelliocode.backend.repository.MeetingRequestRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +public class MeetingRequestServiceTest { + + @Mock + private MeetingRequestRepository repository; + + @InjectMocks + private MeetingRequestService service; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); // Inicializa os mocks + } + + // Teste para salvar uma MeetingRequest com sucesso + @Test + public void testSaveMeetingRequest_Success() { + MeetingRequest meetingRequest = new MeetingRequest(); + meetingRequest.setId(1L); + meetingRequest.setTitle("Reunião de Planejamento"); + + when(repository.save(any(MeetingRequest.class))).thenReturn(meetingRequest); + + MeetingRequest savedRequest = service.saveMeetingRequest(meetingRequest); + + assertNotNull(savedRequest); + assertEquals(MeetingRequest.Status.PENDENTE, savedRequest.getStatus()); // Verifica o status padrão + assertEquals("Reunião de Planejamento", savedRequest.getTitle()); + verify(repository, times(1)).save(meetingRequest); // Verifica se o repositório foi chamado + } + + // Teste para salvar uma MeetingRequest nula + @Test + public void testSaveMeetingRequest_NullRequest() { + assertThrows(IllegalArgumentException.class, () -> { + service.saveMeetingRequest(null); + }); + verify(repository, never()).save(any()); // Verifica se o repositório NÃO foi chamado + } + + // Teste para buscar todas as MeetingRequests + @Test + public void testGetAllMeetingRequests() { + MeetingRequest meetingRequest1 = new MeetingRequest(); + meetingRequest1.setId(1L); + meetingRequest1.setTitle("Reunião 1"); + + MeetingRequest meetingRequest2 = new MeetingRequest(); + meetingRequest2.setId(2L); + meetingRequest2.setTitle("Reunião 2"); + + when(repository.findAll()).thenReturn(List.of(meetingRequest1, meetingRequest2)); + + List requests = service.getAllMeetingRequests(); + + assertNotNull(requests); + assertEquals(2, requests.size()); + assertEquals("Reunião 1", requests.get(0).getTitle()); + assertEquals("Reunião 2", requests.get(1).getTitle()); + verify(repository, times(1)).findAll(); // Verifica se o repositório foi chamado + } + + // Teste para atualizar o status de uma MeetingRequest com sucesso + @Test + public void testUpdateMeetingRequestStatus_Success() { + MeetingRequest meetingRequest = new MeetingRequest(); + meetingRequest.setId(1L); + meetingRequest.setStatus(MeetingRequest.Status.PENDENTE); + + when(repository.findById(1L)).thenReturn(Optional.of(meetingRequest)); + when(repository.save(any(MeetingRequest.class))).thenReturn(meetingRequest); + + MeetingRequest updatedRequest = service.updateMeetingRequestStatus(1L, MeetingRequest.Status.ACEITA); + + assertNotNull(updatedRequest); + assertEquals(MeetingRequest.Status.ACEITA, updatedRequest.getStatus()); + verify(repository, times(1)).findById(1L); // Verifica se o repositório foi chamado + verify(repository, times(1)).save(meetingRequest); // Verifica se o repositório foi chamado + } + + // Teste para atualizar o status de uma MeetingRequest com ID inválido + @Test + public void testUpdateMeetingRequestStatus_InvalidId() { + when(repository.findById(1L)).thenReturn(Optional.empty()); + + assertThrows(NoSuchElementException.class, () -> { + service.updateMeetingRequestStatus(1L, MeetingRequest.Status.ACEITA); + }); + verify(repository, times(1)).findById(1L); // Verifica se o repositório foi chamado + verify(repository, never()).save(any()); // Verifica se o repositório NÃO foi chamado + } + + // Teste para deletar uma MeetingRequest com sucesso + @Test + public void testDeleteMeetingRequest_Success() { + when(repository.existsById(1L)).thenReturn(true); + doNothing().when(repository).deleteById(1L); + + assertDoesNotThrow(() -> { + service.deleteMeetingRequest(1L); + }); + + verify(repository, times(1)).existsById(1L); // Verifica se o repositório foi chamado + verify(repository, times(1)).deleteById(1L); // Verifica se o repositório foi chamado + } + + // Teste para deletar uma MeetingRequest com ID inválido + @Test + public void testDeleteMeetingRequest_InvalidId() { + when(repository.existsById(1L)).thenReturn(false); + + assertThrows(NoSuchElementException.class, () -> { + service.deleteMeetingRequest(1L); + }); + verify(repository, times(1)).existsById(1L); // Verifica se o repositório foi chamado + verify(repository, never()).deleteById(any()); // Verifica se o repositório NÃO foi chamado + } + + // Teste para buscar MeetingRequests por status + @Test + public void testGetMeetingRequestsByStatus() { + MeetingRequest meetingRequest1 = new MeetingRequest(); + meetingRequest1.setId(1L); + meetingRequest1.setStatus(MeetingRequest.Status.ACEITA); + + MeetingRequest meetingRequest2 = new MeetingRequest(); + meetingRequest2.setId(2L); + meetingRequest2.setStatus(MeetingRequest.Status.ACEITA); + + when(repository.findByStatus(MeetingRequest.Status.ACEITA)) + .thenReturn(List.of(meetingRequest1, meetingRequest2)); + + List requests = service.getMeetingRequestsByStatus(MeetingRequest.Status.ACEITA); + + assertNotNull(requests); + assertEquals(2, requests.size()); + assertEquals(MeetingRequest.Status.ACEITA, requests.get(0).getStatus()); + assertEquals(MeetingRequest.Status.ACEITA, requests.get(1).getStatus()); + verify(repository, times(1)).findByStatus(MeetingRequest.Status.ACEITA); // Verifica se o repositório foi chamado + } + + // Teste para buscar MeetingRequests por status nulo + @Test + public void testGetMeetingRequestsByStatus_NullStatus() { + assertThrows(IllegalArgumentException.class, () -> { + service.getMeetingRequestsByStatus(null); + }); + verify(repository, never()).findByStatus(any()); // Verifica se o repositório NÃO foi chamado + } + + // Teste para atualizar o status de uma MeetingRequest com status nulo + @Test + public void testUpdateMeetingRequestStatus_NullStatus() { + MeetingRequest meetingRequest = new MeetingRequest(); + meetingRequest.setId(1L); + meetingRequest.setStatus(MeetingRequest.Status.PENDENTE); + + when(repository.findById(1L)).thenReturn(Optional.of(meetingRequest)); + + assertThrows(IllegalArgumentException.class, () -> { + service.updateMeetingRequestStatus(1L, null); + }); + verify(repository, never()).save(any()); // Verifica se o repositório NÃO foi chamado + } + + // Teste para atualizar o status de uma MeetingRequest com ID nulo + @Test + public void testUpdateMeetingRequestStatus_NullId() { + assertThrows(IllegalArgumentException.class, () -> { + service.updateMeetingRequestStatus(null, MeetingRequest.Status.ACEITA); + }); + verify(repository, never()).findById(any()); // Verifica se o repositório NÃO foi chamado + } +} \ No newline at end of file