From 2aac07f95f9ed608725369f255c345ccce3334f4 Mon Sep 17 00:00:00 2001 From: Badri Paudel Date: Sun, 17 Mar 2024 17:45:44 +0545 Subject: [PATCH] Delete contact logic migrated to service and status handled with the help of enum(created). Test for deleting contac for the given user added. Assertions updated for other tests as well with control like @Order() (for test method's order), @RepeatedTest() and @Tag(). --- src/main/java/info/keeper/AppEnum.java | 8 +++ .../keeper/controllers/ContactController.java | 22 +++--- .../info/keeper/service/ContactService.java | 23 ++++++ .../keeper/service/ContactServiceTest.java | 72 ++++++++++++++++--- 4 files changed, 103 insertions(+), 22 deletions(-) create mode 100644 src/main/java/info/keeper/AppEnum.java diff --git a/src/main/java/info/keeper/AppEnum.java b/src/main/java/info/keeper/AppEnum.java new file mode 100644 index 0000000..3317a8b --- /dev/null +++ b/src/main/java/info/keeper/AppEnum.java @@ -0,0 +1,8 @@ +package info.keeper; + +public enum AppEnum { + NOT_AUTHORIZED, + AUTHORIZED, + OPERATION_FAILED, + OPERATION_SUCCESS +} diff --git a/src/main/java/info/keeper/controllers/ContactController.java b/src/main/java/info/keeper/controllers/ContactController.java index 0d28b82..76f9490 100644 --- a/src/main/java/info/keeper/controllers/ContactController.java +++ b/src/main/java/info/keeper/controllers/ContactController.java @@ -1,5 +1,6 @@ package info.keeper.controllers; +import info.keeper.AppEnum; import info.keeper.models.Contact; import info.keeper.models.User; import info.keeper.repositories.ContactRepository; @@ -150,24 +151,17 @@ public String getNoteDetails(@PathVariable(value = "id") Integer id, @DeleteMapping("/notes/delete/{id}") public String deleteNote(@PathVariable(value = "id") int id, Model model, HttpSession session, Principal principal) throws IOException { - Optional optionalContact = contactRepository.findById(id); - Contact contact = optionalContact.get(); - - User user = userRepository.findUserByUsername(principal.getName()); - if(user.getId() != contact.getUser().getId()) { + AppEnum appEnum = this.contactService.deleteNote(id, principal); + if(appEnum == AppEnum.OPERATION_FAILED) { session.setAttribute("deleteMsg", new Message("Not Authorized", "alert-danger")); return "redirect:/users/notes/0"; } - // delete image also if its not the default image - if(!(contact.getImageURL()).equals("default.png")) { - File folderToDeleteFile = new ClassPathResource("static/images").getFile(); - File file = new File(folderToDeleteFile, contact.getImageURL()); - file.delete(); + if(appEnum == AppEnum.OPERATION_SUCCESS) { + session.setAttribute("deleteMsg", new Message("Note Deleted Successfully", "alert-success")); + return "redirect:/users/notes/0"; } - - contactRepository.delete(contact); - session.setAttribute("deleteMsg", new Message("Note Deleted Successfully", "alert-success")); - + // Some message for unknown error. + session.setAttribute("deleteMsg", new Message("Unknown Error Occurred", "alert-danger")); return "redirect:/users/notes/0"; } diff --git a/src/main/java/info/keeper/service/ContactService.java b/src/main/java/info/keeper/service/ContactService.java index 253e423..025fd97 100644 --- a/src/main/java/info/keeper/service/ContactService.java +++ b/src/main/java/info/keeper/service/ContactService.java @@ -1,5 +1,6 @@ package info.keeper.service; +import info.keeper.AppEnum; import info.keeper.models.Contact; import info.keeper.models.User; import info.keeper.repositories.ContactRepository; @@ -7,14 +8,18 @@ import info.keeper.utils.CsvUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.io.ClassPathResource; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import java.io.File; +import java.io.IOException; import java.security.Principal; import java.util.List; +import java.util.Optional; @Service public class ContactService { @@ -43,6 +48,24 @@ public boolean saveAllImportedContactsToDatabase( MultipartFile file, Principal } } + public AppEnum deleteNote(int id, Principal principal) throws IOException { + Optional optionalContact = contactRepository.findById(id); + Contact contact = optionalContact.get(); + + User user = userRepository.findUserByUsername(principal.getName()); + if(user.getId() != contact.getUser().getId()) { + return AppEnum.NOT_AUTHORIZED; + } + // delete image also if it's not the default image + if(!(contact.getImageURL()).equals("default.png")) { + File folderToDeleteFile = new ClassPathResource("static/images").getFile(); + File file = new File(folderToDeleteFile, contact.getImageURL()); + file.delete(); + } + contactRepository.delete(contact); + return AppEnum.OPERATION_SUCCESS; + } + public Page findContactsByUser(String username, int pageNumber ) { User user = userRepository.findUserByUsername(username); //Pageable has current page and number of notes per page diff --git a/src/test/java/info/keeper/service/ContactServiceTest.java b/src/test/java/info/keeper/service/ContactServiceTest.java index 82e2825..3e61588 100644 --- a/src/test/java/info/keeper/service/ContactServiceTest.java +++ b/src/test/java/info/keeper/service/ContactServiceTest.java @@ -1,27 +1,32 @@ package info.keeper.service; +import info.keeper.AppEnum; import info.keeper.models.Contact; import info.keeper.models.User; import info.keeper.repositories.ContactRepository; import info.keeper.repositories.UserRepository; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.*; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; import org.springframework.boot.test.context.SpringBootTest; 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 static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.*; +import java.io.IOException; +import java.security.Principal; import java.util.ArrayList; import java.util.List; +import java.util.Optional; @SpringBootTest +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) // only for ordering. class ContactServiceTest { @Mock private ContactRepository contactRepository; @@ -33,6 +38,7 @@ class ContactServiceTest { private User user; private Integer userId; + private Integer contactId; private String username; private Integer pageNumber; private Long expectedNumberOfContacts; @@ -47,6 +53,7 @@ void setUp() { user = new User(); user.setEmail(username); user.setId(userId); + contactId = 22; } @AfterEach void cleanUp() { @@ -54,22 +61,71 @@ void cleanUp() { } @Test + // @Order(2) + @DisplayName("Assert that method returns the correct contacts for the given user.") + @Tag("Contact_Service_Test") void findContactsByUser() { - Mockito.when(userRepository.findUserByUsername(username)).thenReturn(user); + when(userRepository.findUserByUsername(username)).thenReturn(user); Pageable pageable = PageRequest.of(pageNumber, 5); - Mockito.when(contactRepository.findContactsByUser(userId, pageable)).thenReturn(getContactsWithPaginationForUser()); + when(contactRepository.findContactsByUser(userId, pageable)).thenReturn(getContactsWithPaginationForUser()); Page allContacts = serviceUnderTest.findContactsByUser(username, pageNumber); assertThat(allContacts.getTotalElements()).isEqualTo(expectedNumberOfContacts); Assertions.assertAll("Assert that returned elements have My Contact Name in name and 123456789 in phone number", () -> { allContacts.getContent().forEach( contact -> { - Assertions.assertTrue(contact.getName().contains("My Contact Name") && + assertTrue(contact.getName().contains("My Contact Name") && contact.getPhoneNumber().contains("123456789")); }); } ); } + @Test + @DisplayName("Test for deleting contact/note provided that the note belongs to the current user.") + @Tag("Contact_Service_Test") + void deleteNote() throws IOException { + Optional contactOptional = getOptionalContact(); + Principal principal = mock(Principal.class); + when(principal.getName()).thenReturn(username); + when(this.contactRepository.findById(contactId)).thenReturn(contactOptional); + when(this.userRepository.findUserByUsername(username)).thenReturn(user); + // Perform delete operation + AppEnum appEnum = serviceUnderTest.deleteNote(contactId, principal); + // Assert that there was a correct return type. + assertThat(appEnum).isEqualTo(AppEnum.OPERATION_SUCCESS); + // Assert that contactRepository was invoked only once for delete method. + verify(this.contactRepository, times(1)).delete(contactOptional.get()); + } + + @RepeatedTest(2) // repeat this two times. + @Order(1) + @DisplayName("Assert for required field's null values: With order 1, executes first.") + @Tag("NullCheck") + void assertNullValues() { + assert this.contactRepository != null; + assertThat(this.userRepository).isNotNull(); + assertThat(user.getId() >= 0); + assertEquals(this.serviceUnderTest.getClass(), ContactService.class); + assertTrue(this.contactRepository instanceof ContactRepository); + } + + @DisplayName("Disabled until bug #42 has been resolved") + @Tag("disabled") + @Disabled() + void disableTest() { + // Nothing here + } + + @NotNull + private Optional getOptionalContact() { + Contact contact = new Contact(); + contact.setId(contactId); + contact.setPhoneNumber("+1234567890"); + contact.setImageURL("http://abc.io"); + contact.setUser(user); + return Optional.of(contact); + } + private Page getContactsWithPaginationForUser() { List contacts = new ArrayList<>(); for (int i = 1; i <= 5; i++) {