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++) {