Skip to content

Commit

Permalink
Add EventControllerTest and ImageControllerTest
Browse files Browse the repository at this point in the history
  • Loading branch information
yifeng15 committed Apr 8, 2024
1 parent fecb8f4 commit c9fd70e
Show file tree
Hide file tree
Showing 6 changed files with 288 additions and 45 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,5 @@ dependencies {

implementation("de.hdodenhof:circleimageview:3.1.0")
testImplementation("org.mockito:mockito-core:3.12.4")
testImplementation("org.mockito:mockito-inline:3.12.4")
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class EventController {
private final FirebaseFirestore database;
protected ImageController imageController;
protected AttendeeController attendeeController;
protected QrCodeController qrCodeController;

/**
* Constructs an EventController with a reference to a Firestore database.
Expand All @@ -46,18 +47,21 @@ public EventController() {
database = FirebaseFirestore.getInstance();
imageController = new ImageController();
attendeeController = new AttendeeController(database);
qrCodeController = new QrCodeController();
}

/**
* Constructs an EventController with a reference to a Firestore database and Firebase storage.
* @param database The Firestore database instance.
* @param storage The Firebase storage instance.
* @param imageController The image controller instance.
* @param attendeeController The attendee controller instance.
* @param qrCodeController The QR code controller instance.
*/
public EventController(FirebaseFirestore database, FirebaseStorage storage, ImageController imageController) {
public EventController(FirebaseFirestore database, ImageController imageController, AttendeeController attendeeController, QrCodeController qrCodeController) {
this.database = database;
this.storage = storage;
this.imageController = imageController;
this.attendeeController = attendeeController;
this.qrCodeController = qrCodeController;
}

/**
Expand Down Expand Up @@ -107,7 +111,6 @@ public void addEvent(Event event, String ID) {
eventMap.put("participants", participantRefs);

// Generate Qr Code or get custom code
QrCodeController qrCodeController = new QrCodeController();
qrCodeController.generateAndStoreQrCode(event, eventMap); // auto generate a qr code

DocumentReference eventRef = database.collection("Events").document(event.getId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@
* Controller class for managing image uploads and retrievals with Firebase Storage.
*/
public class ImageController {
protected FirebaseStorage storage = FirebaseStorage.getInstance();
protected FirebaseStorage storage;

public ImageController() {
storage = FirebaseStorage.getInstance();
}

public ImageController(FirebaseStorage storage) {
this.storage = storage;
}

/**
* Uploads an image file to Firebase Storage within a specified folder.
Expand Down
201 changes: 178 additions & 23 deletions app/src/test/java/com/example/scanpal/EventControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,47 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.openMocks;

import android.net.Uri;
import android.util.Log;

import com.example.scanpal.Callbacks.DeleteAllAttendeesCallback;
import com.example.scanpal.Callbacks.EventDeleteCallback;
import com.example.scanpal.Callbacks.EventIDsFetchCallback;
import com.example.scanpal.Callbacks.UserFetchCallback;
import com.example.scanpal.Controllers.AttendeeController;
import com.example.scanpal.Controllers.EventController;
import com.example.scanpal.Controllers.ImageController;
import com.example.scanpal.Controllers.QrCodeController;
import com.example.scanpal.Models.Event;
import com.example.scanpal.Models.User;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.QuerySnapshot;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.TaskState;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

@RunWith(MockitoJUnitRunner.class)
public class EventControllerTest {
Expand All @@ -38,42 +59,53 @@ public class EventControllerTest {
private EventDeleteCallback eventDeleteCallback;
private EventController eventController;
@Mock
private Task<Void> mockDeleteTask;
private CollectionReference collectionReference;
@Mock
private AttendeeController attendeeController;
@Mock
private QrCodeController qrCodeController;


@Before
public void setUp() {
database = mock(FirebaseFirestore.class);
documentReference = mock(DocumentReference.class);
eventDeleteCallback = mock(EventDeleteCallback.class);
CollectionReference collectionReference = mock(CollectionReference.class);
mockDeleteTask = mock(Task.class);

when(database.collection(any())).thenReturn(collectionReference);
when(collectionReference.document(any())).thenReturn(documentReference);
when(documentReference.delete()).thenReturn(mockDeleteTask);
when(mockDeleteTask.addOnSuccessListener(any())).thenReturn(mockDeleteTask);
when(mockDeleteTask.addOnFailureListener(any())).thenReturn(mockDeleteTask);
collectionReference = mock(CollectionReference.class);
attendeeController = mock(AttendeeController.class);
qrCodeController = mock(QrCodeController.class);
eventController = new EventController(database, imageController, attendeeController, qrCodeController);
}

/**
* Test the deleteEvent method in the EventController class.
*/
@Test
public void testDeleteEvent() {
Task<Void> mockDeleteTask = mock(Task.class);
DeleteAllAttendeesCallback deleteAllAttendeesCallback = mock(DeleteAllAttendeesCallback.class);

when(database.collection(any())).thenReturn(collectionReference);
when(collectionReference.document(any())).thenReturn(documentReference);
when(documentReference.delete()).thenReturn(mockDeleteTask);

doAnswer(invocation -> {
DeleteAllAttendeesCallback callback = invocation.getArgument(1);
callback.onSuccess();
return null;
}).when(attendeeController).deleteAllAttendeesForEvent(any(), any());

String eventID = "123";
eventController = new EventController(database, storage, imageController);

// Mock the delete operation to return a successful task
doAnswer(invocation -> {
OnSuccessListener<Void> onSuccess = invocation.getArgument(0);
onSuccess.onSuccess(null);
return mockDeleteTask;
}).when(mockDeleteTask).addOnSuccessListener(any());
}).when(mockDeleteTask).addOnSuccessListener(any(OnSuccessListener.class));

eventController.deleteEvent(eventID, eventDeleteCallback);

verify(imageController, times(1)).deleteImage("events", "event_" + eventID + ".jpg");
verify(imageController, times(1)).deleteImage("events", eventID + ".jpg");
verify(imageController, times(1)).deleteImage("qr-codes", eventID + "-check-in.png");
verify(imageController, times(1)).deleteImage("qr-codes", eventID + "-event.png");
verify(eventDeleteCallback, times(1)).onSuccess();
Expand All @@ -85,23 +117,146 @@ public void testDeleteEvent() {
*/
@Test
public void testDeleteEventFail() {
String eventID = "123";
eventController = new EventController(database, storage, imageController);
Task<Void> mockDeleteTask = mock(Task.class);
when(database.collection(any())).thenReturn(collectionReference);
when(collectionReference.document(any())).thenReturn(documentReference);

// Mock the delete operation to return a failed task
doAnswer(invocation -> {
OnFailureListener onFailureListener = invocation.getArgument(0);
onFailureListener.onFailure(null);
return mockDeleteTask;
}).when(mockDeleteTask).addOnFailureListener(any());
DeleteAllAttendeesCallback callback = invocation.getArgument(1);
callback.onError(mock(Exception.class));
return null;
}).when(attendeeController).deleteAllAttendeesForEvent(any(), any());

String eventID = "123";

eventController.deleteEvent(eventID, eventDeleteCallback);

verify(imageController, times(1)).deleteImage("events", "event_" + eventID + ".jpg");
verify(imageController, times(1)).deleteImage("qr-codes", eventID + "-check-in.png");
verify(imageController, times(1)).deleteImage("qr-codes", eventID + "-event.png");
verify(imageController, times(0)).deleteImage("events", eventID + ".jpg");
verify(imageController, times(0)).deleteImage("qr-codes", eventID + "-check-in.png");
verify(imageController, times(0)).deleteImage("qr-codes", eventID + "-event.png");
verify(eventDeleteCallback, never()).onSuccess();
verify(eventDeleteCallback, times(1)).onError(any());
}

/**
* Test the getAllEventIds method in the EventController class.
*/
@Test
public void testGetAllEventIds() {
Task<QuerySnapshot> task = mock(Task.class);
QuerySnapshot querySnapshot = mock(QuerySnapshot.class);
EventIDsFetchCallback callback = mock(EventIDsFetchCallback.class);
QueryDocumentSnapshot documentSnapshot1 = mock(QueryDocumentSnapshot.class);
QueryDocumentSnapshot documentSnapshot2 = mock(QueryDocumentSnapshot.class);
List<QueryDocumentSnapshot> documentSnapshots = Arrays.asList(documentSnapshot1, documentSnapshot2);

when(database.collection("Events")).thenReturn(collectionReference);
when(collectionReference.get()).thenReturn(task);
when(task.addOnCompleteListener(any())).thenAnswer(invocation -> {
OnCompleteListener<QuerySnapshot> listener = invocation.getArgument(0);
// simulate a successful task completion
when(task.isSuccessful()).thenReturn(true);
when(task.getResult()).thenReturn(querySnapshot);
// manually trigger the listener with the mocked task
listener.onComplete(task);
return null;
});
when(task.isSuccessful()).thenReturn(true);
when(task.getResult()).thenReturn(querySnapshot);
when(querySnapshot.iterator()).thenReturn(documentSnapshots.iterator());
when(documentSnapshot1.getId()).thenReturn("id1");
when(documentSnapshot2.getId()).thenReturn("id2");

eventController.getAllEventIds(callback);

// Verify that the callback is called with the correct event IDs
ArgumentCaptor<List<String>> argumentCaptor = ArgumentCaptor.forClass(List.class);
verify(callback).onSuccess(argumentCaptor.capture());
List<String> eventIDs = argumentCaptor.getValue();

assertEquals(2, eventIDs.size());
assertTrue(eventIDs.contains("id1"));
assertTrue(eventIDs.contains("id2"));
}

/**
* Test the getAllEventIds method in the EventController class when the documentReference is null.
*/
@Test
public void testFetchEventOrganizerByRef_DocumentReferenceIsNull() {
UserFetchCallback callback = mock(UserFetchCallback.class);
try (MockedStatic<Log> mockedLog = mockStatic(Log.class)) {
mockedLog.when(() -> Log.e(anyString(), anyString())).thenReturn(0);
eventController.fetchEventOrganizerByRef(null, callback);
}
verify(callback).onError(any(NullPointerException.class));
}

/**
* Test the fetchEventOrganizerByRef method in the EventController class.
*/
@Test
public void testFetchEventOrganizerByRef() {
DocumentSnapshot documentSnapshot = mock(DocumentSnapshot.class);
when(documentSnapshot.getString("firstName")).thenReturn("John");
when(documentSnapshot.getString("lastName")).thenReturn("Doe");
when(documentSnapshot.getString("homepage")).thenReturn("https://example.com");
when(documentSnapshot.getString("photo")).thenReturn("uri_photo");
when(documentSnapshot.getString("deviceToken")).thenReturn("token");
when(documentSnapshot.getBoolean("administrator")).thenReturn(true);
when(documentSnapshot.exists()).thenReturn(true);

DocumentReference eventRef = mock(DocumentReference.class);
Task<DocumentSnapshot> task = mock(Task.class);
when(eventRef.get()).thenReturn(task);

when(task.addOnCompleteListener(any())).thenAnswer(invocation -> {
OnCompleteListener<DocumentSnapshot> listener = invocation.getArgument(0);
when(task.isSuccessful()).thenReturn(true);
when(task.getResult()).thenReturn(documentSnapshot);
listener.onComplete(task);
return null;
});

UserFetchCallback callback = mock(UserFetchCallback.class);
eventController.fetchEventOrganizerByRef(eventRef, callback);

ArgumentCaptor<User> argumentCaptor = ArgumentCaptor.forClass(User.class);
verify(callback).onSuccess(argumentCaptor.capture());
User user = argumentCaptor.getValue();

assertEquals("John", user.getFirstName());
assertEquals("Doe", user.getLastName());
assertEquals("https://example.com", user.getHomepage());
assertEquals("uri_photo", user.getPhoto());
assertEquals("token", user.getDeviceToken());
assertTrue(user.isAdministrator());
}

/**
* Test addEvent method
*/
@Test
public void testAddEvent() {
Event mockEvent = mock(Event.class);
User mockUser = mock(User.class);
String id = "123";

when(database.collection(any())).thenReturn(collectionReference);
when(collectionReference.document(any())).thenReturn(documentReference);

when(mockEvent.getOrganizer()).thenReturn(mockUser);
when(mockUser.getUsername()).thenReturn(id);

doAnswer(invocation -> {
OnSuccessListener<Uri> onSuccess = invocation.getArgument(3);
onSuccess.onSuccess(mock(Uri.class));
return null;
}).when(imageController).uploadImage(any(), any(), any(), any(), any());

eventController.addEvent(mockEvent, id);
verify(qrCodeController, times(1)).generateAndStoreQrCode(any(Event.class), any(Map.class));
verify(documentReference, times(1)).update(anyString(), any());
}

}
17 changes: 0 additions & 17 deletions app/src/test/java/com/example/scanpal/ExampleUnitTest.java

This file was deleted.

Loading

0 comments on commit c9fd70e

Please sign in to comment.