Skip to content

Commit

Permalink
feat: Implementing the linking between documents and activities (#267)
Browse files Browse the repository at this point in the history
* feat: Implementing the linking between documents and activities

* test: Updating the tests for the new function to delete a document, so that when deleting a document, it is also unlinked from the activities using transactions to avoid incoherency

* test: Updating the UI tests for Activity list and Document Preview

* tests: Updating UI tests

* test: Removing an assertion of a former floating button when images were displayed of activity cards. Now it is removed

* test: Adding UI tests for the linking of a document to an activity when being in the prevew screen

* test: Adding a test on the delete button for document preview to increase coverage

* test: Improving the test in activity repository so that we also have the conversion of a DocumentContainer while converting a documentSnapshot to an activity

* fix(dialog): Adjust dialog colors and size

Adjust dialog color options to fit with the applications theme.
Change vertical height to be adaptive instead of fixed.

* docs: Removing useless comments and updating previous documentation for document repository and view model

* test: Updating the text displayed in the column when trying to link a document to an activity

---------

Co-authored-by: Remismywaifuu <victor.rydmark@epfl.ch>
Co-authored-by: RemIsMyWaifuu <160653991+RemIsMyWaifuu@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 19, 2024
1 parent a128a61 commit d8627ec
Show file tree
Hide file tree
Showing 21 changed files with 440 additions and 161 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class AddActivityScreenTest {
"description",
Location(0.0, 0.0, Timestamp(0, 0), "location"),
Timestamp(0, 0),
mapOf())
emptyList())

@get:Rule val composeTestRule = createComposeRule()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class EditActivityScreenTest {
"description",
Location(0.0, 0.0, Timestamp(0, 0), "location"),
Timestamp(0, 0),
mapOf())
emptyList())

@get:Rule val composeTestRule = createComposeRule()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import androidx.compose.ui.test.performClick
import com.github.se.travelpouch.model.activity.Activity
import com.github.se.travelpouch.model.activity.ActivityRepository
import com.github.se.travelpouch.model.activity.ActivityViewModel
import com.github.se.travelpouch.model.documents.DocumentRepository
import com.github.se.travelpouch.model.documents.DocumentViewModel
import com.github.se.travelpouch.model.travels.Location
import com.github.se.travelpouch.ui.navigation.NavigationActions
import com.google.firebase.Timestamp
Expand All @@ -26,6 +28,8 @@ class TravelActivityScreenCopy {
private lateinit var mockActivityRepositoryFirebase: ActivityRepository
private lateinit var mockActivityModelView: ActivityViewModel
private lateinit var navigationActions: NavigationActions
private lateinit var mockDocumentViewModel: DocumentViewModel
private lateinit var mockDocumentRepository: DocumentRepository

val activites_test =
listOf(
Expand All @@ -35,14 +39,14 @@ class TravelActivityScreenCopy {
"description1",
Location(0.0, 0.0, Timestamp(0, 0), "lcoation1"),
Timestamp(0, 0),
mapOf<String, Int>()),
emptyList()),
Activity(
"2",
"title2",
"description2",
Location(0.0, 0.0, Timestamp(0, 0), "lcoation2"),
Timestamp(0, 0),
mapOf<String, Int>()))
emptyList()))

@get:Rule val composeTestRule = createComposeRule()

Expand All @@ -51,12 +55,17 @@ class TravelActivityScreenCopy {
navigationActions = mock(NavigationActions::class.java)
mockActivityRepositoryFirebase = mock(ActivityRepository::class.java)
mockActivityModelView = ActivityViewModel(mockActivityRepositoryFirebase)
mockDocumentRepository = mock()
mockDocumentViewModel = DocumentViewModel(mockDocumentRepository, mock(), mock())
}

@Test
fun verifiesEverythingIsDisplayed() {
composeTestRule.setContent {
TravelActivitiesScreen(navigationActions, activityModelView = mockActivityModelView)
TravelActivitiesScreen(
navigationActions,
activityModelView = mockActivityModelView,
documentViewModel = mockDocumentViewModel)
}

`when`(mockActivityRepositoryFirebase.getAllActivities(any(), any())).then {
Expand All @@ -75,7 +84,10 @@ class TravelActivityScreenCopy {
@Test
fun verifiesEmptyPromptWhenEmptyList() {
composeTestRule.setContent {
TravelActivitiesScreen(navigationActions, activityModelView = mockActivityModelView)
TravelActivitiesScreen(
navigationActions,
activityModelView = mockActivityModelView,
documentViewModel = mockDocumentViewModel)
}

`when`(mockActivityRepositoryFirebase.getAllActivities(any(), any())).then {
Expand All @@ -90,57 +102,22 @@ class TravelActivityScreenCopy {
@Test
fun verifyActivityCardWorksCorrectly() {
val activity = activites_test[0]
val images =
listOf(
"https://img.yumpu.com/30185842/1/500x640/afps-attestation-de-formation-aux-premiers-secours-programme-.jpg",
"https://wallpapercrafter.com/desktop6/1606440-architecture-buildings-city-downtown-finance-financial.jpg",
"https://assets.entrepreneur.com/content/3x2/2000/20151023204134-poker-game-gambling-gamble-cards-money-chips-game.jpeg")
composeTestRule.setContent { ActivityItem(activity, {}, LocalContext.current, images) }

composeTestRule.setContent {
ActivityItem(activity, {}, LocalContext.current, mockDocumentViewModel)
}
composeTestRule.waitForIdle()
composeTestRule.onNodeWithTag("activityItem").assertIsDisplayed()
composeTestRule.onNodeWithTag("activityItem").assertTextContains(activity.title)
composeTestRule.onNodeWithTag("activityItem").assertTextContains(activity.location.name)
composeTestRule.onNodeWithTag("activityItem").assertTextContains("1/1/1970")
composeTestRule.onNodeWithTag("extraDocumentButton").assertIsDisplayed().performClick()
}

@Test
fun verify1ImageActivity() {
val activity = activites_test[0]
val images =
listOf(
"https://img.yumpu.com/30185842/1/500x640/afps-attestation-de-formation-aux-premiers-secours-programme-.jpg",
"https://wallpapercrafter.com/desktop6/1606440-architecture-buildings-city-downtown-finance-financial.jpg",
"https://assets.entrepreneur.com/content/3x2/2000/20151023204134-poker-game-gambling-gamble-cards-money-chips-game.jpeg")
composeTestRule.setContent {
ActivityItem(activity, {}, LocalContext.current, listOf(images[0]))
}
composeTestRule.waitForIdle()
}

@Test
fun verify2ImagesActivity() {
val activity = activites_test[0]
val images =
listOf(
"https://img.yumpu.com/30185842/1/500x640/afps-attestation-de-formation-aux-premiers-secours-programme-.jpg",
"https://wallpapercrafter.com/desktop6/1606440-architecture-buildings-city-downtown-finance-financial.jpg",
"https://assets.entrepreneur.com/content/3x2/2000/20151023204134-poker-game-gambling-gamble-cards-money-chips-game.jpeg")
composeTestRule.setContent {
ActivityItem(activity, {}, LocalContext.current, listOf(images[0], images[1]))
}
composeTestRule.waitForIdle()
}

@Test
fun runDefaultErrorUIToCheckFailure() {
composeTestRule.setContent { DefaultErrorUI() }
}

fun runAsyncLoadingSpinner() {
composeTestRule.setContent { AdvancedImageDisplayWithEffects("https://epic.gamer.huh") }
}

@Test
fun verifyBannerIsDisplayedCorrectly() {
val nowSeconds = Timestamp.now().seconds
Expand All @@ -152,14 +129,14 @@ class TravelActivityScreenCopy {
"description1",
Location(0.0, 0.0, Timestamp(0, 0), "lcoation1"),
Timestamp(nowSeconds + 3600L, 0),
mapOf<String, Int>()),
emptyList()),
Activity(
"2",
"title2",
"description2",
Location(0.0, 0.0, Timestamp(0, 0), "lcoation2"),
Timestamp(nowSeconds + 3600L, 0),
mapOf<String, Int>()))
emptyList()))

composeTestRule.setContent { NextActivitiesBanner(activitiesNow, {}) }
composeTestRule.onNodeWithTag("NextActivitiesBannerBox").assertIsDisplayed()
Expand Down Expand Up @@ -190,14 +167,14 @@ class TravelActivityScreenCopy {
"description1",
Location(0.0, 0.0, Timestamp(0, 0), "location1"),
Timestamp(nowSeconds - 100_000L, 0),
mapOf<String, Int>()),
emptyList()),
Activity(
"2",
"title2",
"description2",
Location(0.0, 0.0, Timestamp(0, 0), "location2"),
Timestamp(nowSeconds + 100_000L, 0),
mapOf<String, Int>()))
emptyList()))

composeTestRule.setContent { NextActivitiesBanner(activitiesOutOfDate, {}) }
composeTestRule.onNodeWithTag("NextActivitiesBannerBox").assertDoesNotExist()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,21 +58,21 @@ class ActivitiesMapScreenTest {
description = "Monthly team meeting to discuss project progress.",
location = Location(48.8566, 2.3522, Timestamp.now(), "Paris"),
date = createTimestamp("20/12/2024 12:00"),
documentsNeeded = mapOf("Agenda" to 1, "Meeting Notes" to 2)),
documentsNeeded = emptyList()),
Activity(
uid = "2",
title = "Client Presentation",
description = "Presentation to showcase the project to the client.",
location = Location(49.8566, 2.3522, Timestamp.now(), "Paris"),
date = createTimestamp("21/12/2024 13:00"),
documentsNeeded = null),
documentsNeeded = emptyList()),
Activity(
uid = "3",
title = "Workshop",
description = "Workshop on team building and skill development.",
location = Location(49.02, 2.5, Timestamp.now(), "Paris"),
date = createTimestamp("23/12/2024 14:00"),
documentsNeeded = mapOf("Workshop Material" to 1)))
documentsNeeded = emptyList()))

private val mockLeg =
Leg(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,30 @@ import android.content.Context
import android.provider.DocumentsContract
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.assertTextContains
import androidx.compose.ui.test.isDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.core.net.toUri
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.preferencesOf
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import com.github.se.travelpouch.di.AppModule
import com.github.se.travelpouch.model.activity.Activity
import com.github.se.travelpouch.model.activity.ActivityRepository
import com.github.se.travelpouch.model.activity.ActivityViewModel
import com.github.se.travelpouch.model.documents.DocumentContainer
import com.github.se.travelpouch.model.documents.DocumentFileFormat
import com.github.se.travelpouch.model.documents.DocumentRepository
import com.github.se.travelpouch.model.documents.DocumentViewModel
import com.github.se.travelpouch.model.documents.DocumentVisibility
import com.github.se.travelpouch.model.documents.DocumentsManager
import com.github.se.travelpouch.model.travels.Location
import com.github.se.travelpouch.ui.navigation.NavigationActions
import com.google.firebase.FirebaseApp
import com.google.firebase.Timestamp
Expand All @@ -36,7 +43,9 @@ import org.junit.Rule
import org.junit.Test
import org.mockito.Mockito.mock
import org.mockito.Mockito.`when`
import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.spy
import org.mockito.kotlin.verify

@HiltAndroidTest
@UninstallModules(AppModule::class)
Expand All @@ -51,10 +60,16 @@ class DocumentPreviewTest {
private lateinit var mockDataStore: DataStore<Preferences>
private lateinit var file: File

private lateinit var mockActivityRepository: ActivityRepository
private lateinit var mockActivityViewModel: ActivityViewModel

@get:Rule val composeTestRule = createComposeRule()

@Before
fun setUp() {
mockActivityRepository = mock()
mockActivityViewModel = ActivityViewModel(mockActivityRepository)

mockDocumentReference = mock(DocumentReference::class.java)
`when`(mockDocumentReference.id).thenReturn("ref_id")

Expand Down Expand Up @@ -106,17 +121,86 @@ class DocumentPreviewTest {

@Test
fun testsEverythingIsDisplayed() {
composeTestRule.setContent { DocumentPreview(mockDocumentViewModel, navigationActions) }
composeTestRule.setContent {
DocumentPreview(mockDocumentViewModel, navigationActions, mockActivityViewModel)
}

composeTestRule.onNodeWithTag("documentPreviewScreen").assertIsDisplayed()
composeTestRule.onNodeWithTag("documentTitleTopBarApp").assertIsDisplayed()
composeTestRule.onNodeWithTag("documentTitleTopBarApp").assertTextContains(document.title)

composeTestRule.onNodeWithTag("goBackButton").assertIsDisplayed()
composeTestRule.onNodeWithTag("deleteButton").assertIsDisplayed()
composeTestRule.onNodeWithTag("linkingButton").assertIsDisplayed()
composeTestRule
.onNodeWithTag("documentTitle", useUnmergedTree = true)
.assertTextContains("Document ID: ref_id")
composeTestRule.waitUntil(1000) { composeTestRule.onNodeWithTag("document").isDisplayed() }
}

@Test
fun testLinkingNotavailableWhenNoActivities() {
`when`(mockActivityRepository.getAllActivities(anyOrNull(), anyOrNull())).then {
it.getArgument<(List<Activity>) -> Unit>(0)(emptyList())
}
mockActivityViewModel.getAllActivities()

composeTestRule.setContent {
DocumentPreview(mockDocumentViewModel, navigationActions, mockActivityViewModel)
}

composeTestRule.onNodeWithTag("linkingButton").assertIsDisplayed().performClick()
composeTestRule.onNodeWithTag("activitiesDialog").assertIsNotDisplayed()
}

@Test
fun testLinkingActivityWhenActivityAvailable() {
val activity =
Activity(
"qwertzuiopasdfghjkly",
"titleAc",
"descriptionAc",
Location(0.0, 0.0, Timestamp.now(), "nameAc"),
Timestamp(0, 0),
emptyList())

`when`(mockActivityRepository.getAllActivities(anyOrNull(), anyOrNull())).then {
it.getArgument<(List<Activity>) -> Unit>(0)(listOf(activity))
}
mockActivityViewModel.getAllActivities()

composeTestRule.setContent {
DocumentPreview(mockDocumentViewModel, navigationActions, mockActivityViewModel)
}

composeTestRule.onNodeWithTag("linkingButton").assertIsDisplayed().performClick()
composeTestRule.onNodeWithTag("activitiesDialog").assertIsDisplayed()
composeTestRule.onNodeWithText("Activity to link the image to").assertIsDisplayed()
composeTestRule.onNodeWithTag("activitiesList").assertIsDisplayed()
composeTestRule.onNodeWithTag("activityItem_qwertzuiopasdfghjkly").assertIsDisplayed()
composeTestRule.onNodeWithTag("activityItem_qwertzuiopasdfghjkly").assertTextContains("titleAc")
composeTestRule.onNodeWithTag("activityItem_qwertzuiopasdfghjkly").assertTextContains("nameAc")
composeTestRule
.onNodeWithTag("activityItem_qwertzuiopasdfghjkly")
.assertTextContains("1/1/1970")

composeTestRule.onNodeWithTag("activityItem_qwertzuiopasdfghjkly").performClick()
composeTestRule.onNodeWithTag("activitiesDialog").assertIsNotDisplayed()
composeTestRule.onNodeWithText("Activity to link the image to").assertIsNotDisplayed()
composeTestRule.onNodeWithTag("activitiesList").assertIsNotDisplayed()
composeTestRule.onNodeWithTag("activityItem_qwertzuiopasdfghjkly").assertIsNotDisplayed()

verify(mockActivityRepository).updateActivity(anyOrNull(), anyOrNull(), anyOrNull())
}

@Test
fun testDeleteCallsDelete() {
composeTestRule.setContent {
DocumentPreview(mockDocumentViewModel, navigationActions, mockActivityViewModel)
}

composeTestRule.onNodeWithTag("deleteButton").performClick()
verify(mockDocumentRepository)
.deleteDocumentById(anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class CalendarScreenTest {
date = Timestamp(today),
description = "This is a mock activity for today.",
location = Location(0.0, 0.0, Timestamp(0, 0), "location"),
documentsNeeded = mapOf())
documentsNeeded = emptyList())

val listOfActivities = listOf(activityToday)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class MainActivity : ComponentActivity() {
})
}
composable(Screen.DOCUMENT_PREVIEW) {
DocumentPreview(documentViewModel, navigationActions)
DocumentPreview(documentViewModel, navigationActions, activityModelView)
}
composable(Screen.TIMELINE) { TimelineScreen(eventsViewModel, navigationActions) }

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Portions of this code were generated and or inspired by the help of GitHub Copilot or Chatgpt
package com.github.se.travelpouch.model.activity

import com.github.se.travelpouch.model.documents.DocumentContainer
import com.github.se.travelpouch.model.travels.Location
import com.google.firebase.Timestamp

Expand All @@ -13,14 +14,14 @@ import com.google.firebase.Timestamp
* @property description (String) : the description of the travel
* @property location (Location) : the location where the activity takes place
* @property date (Timestamp) : the date when the activity will occur
* @property documentsNeeded (Map<String, Int>?) : the list of documents needed for the activity. If
* no document is needed the map is null
* @property documentsNeeded (List<DocumentContainer>) : the list of documents needed for the
* activity.
*/
data class Activity(
val uid: String,
val title: String,
val description: String,
val location: Location,
val date: Timestamp,
val documentsNeeded: Map<String, Int>?
val documentsNeeded: List<DocumentContainer> = emptyList()
)
Loading

0 comments on commit d8627ec

Please sign in to comment.