diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml
index a418f74..7a7c8d0 100644
--- a/.github/workflows/run_tests.yml
+++ b/.github/workflows/run_tests.yml
@@ -49,8 +49,8 @@ jobs:
report_paths: 'target/surefire-reports/*.xml'
check_name: JUnit Test Report
- - name: Codacy Coverage Reporter
- uses: codacy/codacy-coverage-reporter-action@v1.3.0
- with:
- project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
- coverage-reports: target/site/jacoco/jacoco.xml
+# - name: Codacy Coverage Reporter
+# uses: codacy/codacy-coverage-reporter-action@v1.3.0
+# with:
+# project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
+# coverage-reports: target/site/jacoco/jacoco.xml
diff --git a/pom.xml b/pom.xml
index 2fb6e9b..ea50390 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,260 +1,292 @@
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 3.4.5
-
-
- ua.com.javarush.gnew
- contact-manager
- 0.0.1-SNAPSHOT
- contact-manager-spring-boot
- contact-manager-spring-boot
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 17
- v20.9.0
-
-
-
- org.springframework.boot
- spring-boot-starter-data-jpa
-
-
- org.springframework.boot
- spring-boot-starter-hateoas
-
-
- org.springframework.boot
- spring-boot-starter-thymeleaf
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-validation
-
-
- org.springframework.boot
- spring-boot-devtools
- runtime
- true
-
-
- org.springframework.boot
- spring-boot-docker-compose
- runtime
- true
-
-
- org.postgresql
- postgresql
- runtime
-
-
- org.projectlombok
- lombok
- 1.18.30
- true
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.springframework.restdocs
- spring-restdocs-mockmvc
- test
-
-
- org.springframework.boot
- spring-boot-starter-actuator
-
-
-
- com.google.code.gson
- gson
- 2.11.0
-
-
- org.springframework.boot
- spring-boot-starter-security
-
-
- org.springframework.security
- spring-security-test
- test
-
-
- org.thymeleaf.extras
- thymeleaf-extras-springsecurity6
-
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.4.5
+
+
+ ua.com.javarush.gnew
+ contact-manager
+ 0.0.1-SNAPSHOT
+ contact-manager-spring-boot
+ contact-manager-spring-boot
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 17
+ v20.9.0
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.boot
+ spring-boot-starter-hateoas
+
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ runtime
+ true
+
+
+ org.springframework.boot
+ spring-boot-docker-compose
+ runtime
+ true
+
+
+ org.postgresql
+ postgresql
+ runtime
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.restdocs
+ spring-restdocs-mockmvc
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+ com.google.code.gson
+ gson
+ 2.11.0
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+ org.thymeleaf.extras
+ thymeleaf-extras-springsecurity6
+
-
- org.mapstruct
- mapstruct
- 1.6.0.Beta1
-
+
+ org.mapstruct
+ mapstruct
+ 1.6.0.Beta1
+
-
- org.springdoc
- springdoc-openapi-starter-webmvc-ui
- 2.5.0
-
-
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.5.0
+
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
-
-
- org.projectlombok
- lombok
- 1.18.30
-
-
- org.mapstruct
- mapstruct-processor
- 1.6.0.Beta1
-
-
-
-
-
- org.asciidoctor
- asciidoctor-maven-plugin
- 2.2.1
-
-
- generate-docs
- prepare-package
-
- process-asciidoc
-
-
- html
- book
-
-
-
-
-
- org.springframework.restdocs
- spring-restdocs-asciidoctor
- ${spring-restdocs.version}
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
- org.projectlombok
- lombok
-
-
-
-
-
- com.spotify.fmt
- fmt-maven-plugin
- 2.25
-
-
- format-code
- verify
-
- format
-
-
-
-
+
+ com.h2database
+ h2
+ runtime
+
-
- com.github.eirslett
- frontend-maven-plugin
- 1.15.1
-
-
-
- install node and npm
-
- install-node-and-npm
-
-
- ${node.version}
-
-
-
-
- npm install
-
- npm
-
-
- install
-
-
-
-
- npm build
-
- npm
-
-
- run build
-
-
-
-
- ${node.version}
- src/main/frontend
- target
-
-
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+ 2.5.0
+
+
-
- maven-clean-plugin
- 3.1.0
-
-
-
-
-
- ${project.basedir}/src/main/resources/static
-
- main.css
-
-
-
-
-
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+
+
+ org.mapstruct
+ mapstruct-processor
+ 1.6.0.Beta1
+
+
+
+
+
+ org.asciidoctor
+ asciidoctor-maven-plugin
+ 2.2.1
+
+
+ generate-docs
+ prepare-package
+
+ process-asciidoc
+
+
+ html
+ book
+
+
+
+
+
+ org.springframework.restdocs
+ spring-restdocs-asciidoctor
+ ${spring-restdocs.version}
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+ com.spotify.fmt
+ fmt-maven-plugin
+ 2.25
+
+
+ format-code
+ verify
+
+ format
+
+
+
+
-
-
+
+ com.github.eirslett
+ frontend-maven-plugin
+ 1.15.1
+
+
+
+ install node and npm
+
+ install-node-and-npm
+
+
+ ${node.version}
+
+
+
+
+ npm install
+
+ npm
+
+
+ install
+
+
+
+
+ npm build
+
+ npm
+
+
+ run build
+
+
+
+
+ ${node.version}
+ src/main/frontend
+ target
+
+
+
+
+ maven-clean-plugin
+ 3.1.0
+
+
+
+
+
+ ${project.basedir}/src/main/resources/static
+
+
+ main.css
+
+
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.12
+
+
+
+ prepare-agent
+
+
+
+ report
+ test
+
+ report
+
+
+
+
+
+
diff --git a/src/main/java/ua/com/javarush/gnew/contactm/DTOs/AppUserDTO.java b/src/main/java/ua/com/javarush/gnew/contactm/DTOs/AppUserDTO.java
index 24166af..20acd2d 100644
--- a/src/main/java/ua/com/javarush/gnew/contactm/DTOs/AppUserDTO.java
+++ b/src/main/java/ua/com/javarush/gnew/contactm/DTOs/AppUserDTO.java
@@ -1,13 +1,12 @@
package ua.com.javarush.gnew.contactm.DTOs;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
+import lombok.*;
@Getter
@Setter
@NoArgsConstructor
+@AllArgsConstructor
+@Builder
public class AppUserDTO {
private long id;
private String firstName;
diff --git a/src/main/java/ua/com/javarush/gnew/contactm/DTOs/ContactDTO.java b/src/main/java/ua/com/javarush/gnew/contactm/DTOs/ContactDTO.java
index dd57bc8..94bc791 100644
--- a/src/main/java/ua/com/javarush/gnew/contactm/DTOs/ContactDTO.java
+++ b/src/main/java/ua/com/javarush/gnew/contactm/DTOs/ContactDTO.java
@@ -1,13 +1,13 @@
package ua.com.javarush.gnew.contactm.DTOs;
import java.util.List;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
+import lombok.*;
@Getter
@Setter
@NoArgsConstructor
+@AllArgsConstructor
+@Builder
public class ContactDTO {
private long id;
private String name;
diff --git a/src/main/java/ua/com/javarush/gnew/contactm/config/SecurityConfig.java b/src/main/java/ua/com/javarush/gnew/contactm/config/SecurityConfig.java
index ff61c01..bb23c53 100644
--- a/src/main/java/ua/com/javarush/gnew/contactm/config/SecurityConfig.java
+++ b/src/main/java/ua/com/javarush/gnew/contactm/config/SecurityConfig.java
@@ -20,7 +20,17 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.authorizeHttpRequests(
requests ->
requests
- .requestMatchers("/", "/main.css", "/img/**", "/register", "/login", "/api/**", "/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**", "/webjars/**")
+ .requestMatchers(
+ "/",
+ "/main.css",
+ "/img/**",
+ "/register",
+ "/login",
+ "/api/**",
+ "/swagger-ui.html",
+ "/swagger-ui/**",
+ "/v3/api-docs/**",
+ "/webjars/**")
.permitAll()
.anyRequest()
.authenticated())
@@ -34,5 +44,4 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
-
}
diff --git a/src/main/java/ua/com/javarush/gnew/contactm/controller/rest/ContactControllerApi.java b/src/main/java/ua/com/javarush/gnew/contactm/controller/rest/ContactControllerApi.java
index 46dd581..fddfa6b 100644
--- a/src/main/java/ua/com/javarush/gnew/contactm/controller/rest/ContactControllerApi.java
+++ b/src/main/java/ua/com/javarush/gnew/contactm/controller/rest/ContactControllerApi.java
@@ -1,6 +1,7 @@
package ua.com.javarush.gnew.contactm.controller.rest;
import java.util.Optional;
+import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@@ -9,6 +10,7 @@
import ua.com.javarush.gnew.contactm.mapper.ContactMapper;
import ua.com.javarush.gnew.contactm.repository.ContactRepository;
+@RequiredArgsConstructor
@RestController
@RequestMapping("/api/v1/contact")
public class ContactControllerApi {
@@ -16,11 +18,6 @@ public class ContactControllerApi {
private final ContactRepository contactRepository;
private final ContactMapper contactMapper;
- public ContactControllerApi(ContactRepository contactRepository, ContactMapper contactMapper) {
- this.contactRepository = contactRepository;
- this.contactMapper = contactMapper;
- }
-
@GetMapping
public ResponseEntity getContact(@RequestParam("id") Long id) {
return contactRepository
diff --git a/src/main/java/ua/com/javarush/gnew/contactm/controller/web/auth/LoginController.java b/src/main/java/ua/com/javarush/gnew/contactm/controller/web/auth/LoginController.java
index a6f4382..b047912 100644
--- a/src/main/java/ua/com/javarush/gnew/contactm/controller/web/auth/LoginController.java
+++ b/src/main/java/ua/com/javarush/gnew/contactm/controller/web/auth/LoginController.java
@@ -12,8 +12,7 @@ public class LoginController {
@GetMapping("/login")
public String getLoginPage() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
- if (auth != null && auth.isAuthenticated() &&
- !(auth instanceof AnonymousAuthenticationToken)) {
+ if (auth != null && auth.isAuthenticated() && !(auth instanceof AnonymousAuthenticationToken)) {
return "redirect:/";
}
return "login";
diff --git a/src/main/java/ua/com/javarush/gnew/contactm/entity/Contact.java b/src/main/java/ua/com/javarush/gnew/contactm/entity/Contact.java
index bd19b72..8340dc3 100644
--- a/src/main/java/ua/com/javarush/gnew/contactm/entity/Contact.java
+++ b/src/main/java/ua/com/javarush/gnew/contactm/entity/Contact.java
@@ -6,10 +6,7 @@
import java.util.Date;
import java.util.List;
import java.util.Objects;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
+import lombok.*;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
@@ -17,6 +14,8 @@
@Getter
@Setter
@NoArgsConstructor
+@AllArgsConstructor
+@Builder
@Entity
@Table(name = "contact")
public class Contact {
@@ -38,9 +37,9 @@ public class Contact {
@Expose
private List emails = new ArrayList<>();
- @Column(name = "last_name")
- @Expose
- private String lastName;
+ @Column(name = "last_name")
+ @Expose
+ private String lastName;
@OneToMany(mappedBy = "contact", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@Expose
@@ -60,14 +59,16 @@ public class Contact {
@Column(name = "modify_date")
private Date modifyDate;
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof Contact contact)) return false;
- return getId() == contact.getId() && Objects.equals(getName(), contact.getName()) && Objects.equals(getLastName(), contact.getLastName());
- }
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Contact contact)) return false;
+ return getId() == contact.getId()
+ && Objects.equals(getName(), contact.getName())
+ && Objects.equals(getLastName(), contact.getLastName());
+ }
- @Override
- public int hashCode() {
- return Objects.hash(getId(), getName(), getLastName());
- }
+ @Override
+ public int hashCode() {
+ return Objects.hash(getId(), getName(), getLastName());
+ }
}
diff --git a/src/test/java/ua/com/javarush/gnew/contactm/controller/rest/ContactControllerApiTest.java b/src/test/java/ua/com/javarush/gnew/contactm/controller/rest/ContactControllerApiTest.java
new file mode 100644
index 0000000..b0dddd0
--- /dev/null
+++ b/src/test/java/ua/com/javarush/gnew/contactm/controller/rest/ContactControllerApiTest.java
@@ -0,0 +1,54 @@
+package ua.com.javarush.gnew.contactm.controller.rest;
+
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+import ua.com.javarush.gnew.contactm.DTOs.ContactDTO;
+import ua.com.javarush.gnew.contactm.entity.Contact;
+import ua.com.javarush.gnew.contactm.mapper.ContactMapper;
+import ua.com.javarush.gnew.contactm.repository.ContactRepository;
+
+@WebMvcTest(
+ value = ContactControllerApi.class,
+ excludeAutoConfiguration = SecurityAutoConfiguration.class)
+class ContactControllerApiTest {
+
+ @Autowired private MockMvc mvc;
+
+ @MockitoBean private ContactRepository contactRepository;
+
+ @MockitoBean private ContactMapper contactMapper;
+
+ @Test
+ void getContact_ShouldReturnContactDTOAndStatus200WhenContactExists() throws Exception {
+ // Arrange
+ long id = 1L;
+ String name = "name";
+
+ Contact contact = Contact.builder().id(id).name(name).build();
+
+ ContactDTO contactDTO = ContactDTO.builder().id(id).name(name).build();
+
+ when(contactRepository.findById(id)).thenReturn(java.util.Optional.of(contact));
+ when(contactMapper.toDto(contact)).thenReturn(contactDTO);
+
+ // Act & Assert
+ String path = "/api/v1/contact";
+
+ mvc.perform(get(path).param("id", "1").accept(MediaType.APPLICATION_JSON))
+ .andExpect(status().isOk())
+ .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+ .andExpect(MockMvcResultMatchers.jsonPath("$.id").value(id))
+ .andExpect(MockMvcResultMatchers.jsonPath("$.name").value(name));
+ }
+}
diff --git a/src/test/java/ua/com/javarush/gnew/contactm/services/AppUserServiceTest.java b/src/test/java/ua/com/javarush/gnew/contactm/services/AppUserServiceTest.java
new file mode 100644
index 0000000..01f302b
--- /dev/null
+++ b/src/test/java/ua/com/javarush/gnew/contactm/services/AppUserServiceTest.java
@@ -0,0 +1,56 @@
+package ua.com.javarush.gnew.contactm.services;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import ua.com.javarush.gnew.contactm.DTOs.AppUserDTO;
+import ua.com.javarush.gnew.contactm.entity.AppUser;
+import ua.com.javarush.gnew.contactm.repository.AppUserRepository;
+
+@ExtendWith(MockitoExtension.class)
+class AppUserServiceTest {
+
+ @Mock private AppUserRepository appUserRepository;
+
+ @Mock private PasswordEncoder passwordEncoder;
+
+ @InjectMocks private AppUserService appUserService;
+
+ @Test
+ void register_ShouldEncodePasswordAndSaveUser() {
+ // Arrange
+ String username = "username";
+ String password = "password";
+
+ String encodedPassword = "encodedPassword";
+
+ AppUserDTO appUserDTO = AppUserDTO.builder().username(username).password(password).build();
+
+ when(passwordEncoder.encode(password)).thenReturn(encodedPassword);
+
+ ArgumentCaptor appUserArgumentCaptor = ArgumentCaptor.forClass(AppUser.class);
+
+ // Act
+ appUserService.register(appUserDTO);
+
+ // Assert
+ verify(passwordEncoder, times(1)).encode(password);
+
+ verify(appUserRepository, times(1)).save(appUserArgumentCaptor.capture());
+
+ AppUser savedAppUser = appUserArgumentCaptor.getValue();
+
+ assertEquals(username, savedAppUser.getUsername());
+ assertEquals(encodedPassword, savedAppUser.getPassword());
+ }
+
+ @Test
+ void findByUserName() {}
+}