Skip to content

Commit

Permalink
Delete contact logic migrated to service and status handled with the …
Browse files Browse the repository at this point in the history
…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().
  • Loading branch information
Badri Paudel committed Mar 17, 2024
1 parent b65a06c commit 2aac07f
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 22 deletions.
8 changes: 8 additions & 0 deletions src/main/java/info/keeper/AppEnum.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package info.keeper;

public enum AppEnum {
NOT_AUTHORIZED,
AUTHORIZED,
OPERATION_FAILED,
OPERATION_SUCCESS
}
22 changes: 8 additions & 14 deletions src/main/java/info/keeper/controllers/ContactController.java
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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<Contact> 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";
}

Expand Down
23 changes: 23 additions & 0 deletions src/main/java/info/keeper/service/ContactService.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
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 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 {
Expand Down Expand Up @@ -43,6 +48,24 @@ public boolean saveAllImportedContactsToDatabase( MultipartFile file, Principal
}
}

public AppEnum deleteNote(int id, Principal principal) throws IOException {
Optional<Contact> 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<Contact> findContactsByUser(String username, int pageNumber ) {
User user = userRepository.findUserByUsername(username);
//Pageable has current page and number of notes per page
Expand Down
72 changes: 64 additions & 8 deletions src/test/java/info/keeper/service/ContactServiceTest.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -33,6 +38,7 @@ class ContactServiceTest {

private User user;
private Integer userId;
private Integer contactId;
private String username;
private Integer pageNumber;
private Long expectedNumberOfContacts;
Expand All @@ -47,29 +53,79 @@ void setUp() {
user = new User();
user.setEmail(username);
user.setId(userId);
contactId = 22;
}
@AfterEach
void cleanUp() {
// Any cleanup after each test.
}

@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<Contact> 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<Contact> 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<Contact> 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<Contact> getContactsWithPaginationForUser() {
List<Contact> contacts = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
Expand Down

0 comments on commit 2aac07f

Please sign in to comment.