Skip to content

Commit f4cf07d

Browse files
M4 Submission (#357)
Removed mocked API calls and fixed Spoonacular bugs (#355) * Bug fixes * Fixed broken navigation * Fixed broken tests * Fixed flaky test * Fixed flaky test * Removed Previous impl test
1 parent 5149e86 commit f4cf07d

File tree

13 files changed

+74
-331
lines changed

13 files changed

+74
-331
lines changed

app/src/androidTest/java/com/github/se/polyfit/data/api/SpoonacularApiCallerTest.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,7 @@ class SpoonacularApiCallerTest {
333333

334334
val response = spoonacularApiCaller.getCompleteRecipesFromIngredients(listOf("apple", "banana"))
335335

336-
assert(response.first().recipeInformation.ingredients.isEmpty())
337-
assert(response.first().recipeInformation.instructions.isEmpty())
336+
assert(response.isEmpty())
338337
}
339338

340339
@After

app/src/androidTest/java/com/github/se/polyfit/ui/screen/RecipeRecommendationScreenTest.kt

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@ package com.github.se.polyfit.ui.screen
33
import androidx.compose.ui.test.assertIsDisplayed
44
import androidx.compose.ui.test.junit4.createComposeRule
55
import androidx.compose.ui.test.onNodeWithTag
6-
import androidx.compose.ui.test.onNodeWithText
6+
import androidx.lifecycle.MutableLiveData
77
import androidx.navigation.NavHostController
88
import androidx.test.ext.junit.runners.AndroidJUnit4
9-
import com.github.se.polyfit.model.recipe.Recipe
10-
import com.github.se.polyfit.ui.components.button.LikeButtonScreen
119
import com.github.se.polyfit.ui.screen.recipeRec.RecommendationScreen
1210
import com.github.se.polyfit.viewmodel.qrCode.BarCodeCodeViewModel
1311
import com.github.se.polyfit.viewmodel.recipe.RecipeRecommendationViewModel
@@ -27,38 +25,15 @@ class RecipeRecommendationScreenTest {
2725

2826
private val barcodeViewModel: BarCodeCodeViewModel = mockk<BarCodeCodeViewModel>(relaxed = true)
2927

30-
@Test
31-
fun testEverythingIsDisplayed() {
32-
val mockkNavigation = mockk<NavHostController>(relaxed = true)
33-
val mockkRecommendationViewModel = mockk<RecipeRecommendationViewModel>()
34-
35-
val recipeList = mutableListOf<Recipe>()
36-
for (i in 1..10) {
37-
recipeList.add(Recipe.default())
38-
}
39-
coEvery { mockkRecommendationViewModel.ingredientList() } returns listOf("apple", "banana")
40-
coEvery { mockkRecommendationViewModel.recipeFromIngredients(any()) } returns recipeList
41-
42-
composeTestRule.setContent {
43-
RecommendationScreen(mockkNavigation, mockkRecommendationViewModel, {}, barcodeViewModel)
44-
}
45-
composeTestRule.waitForIdle()
46-
47-
ComposeScreen.onComposeScreen<LikeButtonScreen>(composeTestRule) {
48-
composeTestRule.onNodeWithText("Recommended Recipes").assertIsDisplayed()
49-
composeTestRule.onNodeWithTag("RecipeList").assertExists().assertIsDisplayed()
50-
}
51-
}
52-
5328
@Test
5429
fun testLoadingAnimation() {
5530
val mockkNavigation = mockk<NavHostController>(relaxed = true)
5631

5732
val mockkRecommendationViewModel = mockk<RecipeRecommendationViewModel>()
5833

59-
coEvery { mockkRecommendationViewModel.recipeFromIngredients(any()) } returns emptyList()
60-
coEvery { mockkRecommendationViewModel.ingredientList() } returns listOf("apple", "banana")
61-
34+
coEvery { mockkRecommendationViewModel.recipeFromIngredients() } returns emptyList()
35+
coEvery { mockkRecommendationViewModel.recipes } returns MutableLiveData(listOf())
36+
coEvery { mockkRecommendationViewModel.isFetching } returns MutableLiveData(true)
6237
composeTestRule.setContent {
6338
RecommendationScreen(mockkNavigation, mockkRecommendationViewModel, {}, barcodeViewModel)
6439
}

app/src/androidTest/java/com/github/se/polyfit/viewmodel/recipe/RecipeRecommendationViewModelTest.kt

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,6 @@ class RecipeRecommendationViewModelTest {
2525
viewModel = RecipeRecommendationViewModel(spoonacularApiCaller)
2626
}
2727

28-
@Test
29-
fun recipeFromIngredientsReturnsRecipes() = runBlocking {
30-
val ingredients = listOf("apple", "banana")
31-
val expectedRecipes = listOf(Recipe.default())
32-
33-
coEvery { spoonacularApiCaller.recipeByIngredients(any()) } returns
34-
RecipeFromIngredientsResponseAPI(APIResponse.SUCCESS, expectedRecipes)
35-
coEvery { spoonacularApiCaller.getCompleteRecipesFromIngredients(any()) } returns
36-
listOf(Recipe.default())
37-
38-
val actualRecipes = viewModel.recipeFromIngredients(listOf("apple", "banana"))
39-
40-
assertEquals(listOf(Recipe.default()), actualRecipes)
41-
}
42-
4328
@Test
4429
fun recipeFromIngredientsReturnsEmptyWhenInvalid() = runBlocking {
4530
val ingredients = listOf("invalid", "ingredients")
@@ -48,16 +33,8 @@ class RecipeRecommendationViewModelTest {
4833
coEvery { spoonacularApiCaller.recipeByIngredients(ingredients) } returns
4934
RecipeFromIngredientsResponseAPI(APIResponse.FAILURE, expectedRecipes)
5035

51-
val actualRecipes = viewModel.recipeFromIngredients(ingredients)
36+
val actualRecipes = viewModel.recipeFromIngredients()
5237

5338
assertEquals(listOf<Recipe>(), actualRecipes)
5439
}
55-
56-
@Test
57-
fun testIngredientListReturns() {
58-
val expectedIngredients = listOf("apple", "banana")
59-
val actualIngredients = viewModel.ingredientList()
60-
61-
assertEquals(expectedIngredients, actualIngredients)
62-
}
6340
}

app/src/main/java/com/github/se/polyfit/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ class MainActivity : ComponentActivity() {
125125
}
126126

127127
// the navcontroller is needed for the generic screen
128-
composable(Route.RecipeRecFlow) { RecipeRecFlow() }
128+
composable(Route.RecipeRecFlow) { RecipeRecFlow(navAction = navigation) }
129129
}
130130
}
131131
}

app/src/main/java/com/github/se/polyfit/data/api/Spoonacular/SpoonacularAPI.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,12 +228,11 @@ class SpoonacularApiCaller {
228228
* @throws Exception if the response is not successful or an error occurs
229229
*/
230230
fun getCompleteRecipesFromIngredients(ingredients: List<String>): List<Recipe> {
231-
// val recipesResponse = recipeByIngredients(ingredients)
231+
232232
return try {
233233

234-
// done to avoid making a bunch of API calls, will need to remove later
235-
val recipesResponse =
236-
RecipeFromIngredientsResponseAPI(APIResponse.SUCCESS, listOf(Recipe.default()))
234+
val recipesResponse = recipeByIngredients(ingredients)
235+
237236
recipesResponse.recipes.forEach { recipe ->
238237
val recipeInfo = getRecipeSteps(recipe.id)
239238

app/src/main/java/com/github/se/polyfit/di/HiltProvides.kt

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import com.github.se.polyfit.model.data.User
1515
import com.github.se.polyfit.model.post.PostLocationModel
1616
import com.github.se.polyfit.viewmodel.graph.GraphViewModel
1717
import com.github.se.polyfit.viewmodel.map.MapViewModel
18-
import com.github.se.polyfit.viewmodel.qrCode.BarCodeCodeViewModel
1918
import com.github.se.polyfit.viewmodel.recipe.RecipeRecommendationViewModel
2019
import com.google.firebase.auth.FirebaseAuth
2120
import dagger.Module
@@ -107,15 +106,6 @@ object HiltProvides {
107106
return FirebaseAuth.getInstance()
108107
}
109108

110-
@Provides
111-
@Singleton
112-
fun providesBarCodeCodeViewModel(
113-
recipeRecommendationViewModel: RecipeRecommendationViewModel,
114-
foodFactsApi: OpenFoodFactsApi
115-
): BarCodeCodeViewModel {
116-
return BarCodeCodeViewModel(recipeRecommendationViewModel, foodFactsApi)
117-
}
118-
119109
@Provides
120110
@Singleton
121111
fun provideFoodFactsApi(): OpenFoodFactsApi {

app/src/main/java/com/github/se/polyfit/ui/flow/RecipeRecFlow.kt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,30 @@ import com.github.se.polyfit.ui.navigation.Navigation
99
import com.github.se.polyfit.ui.navigation.Route
1010
import com.github.se.polyfit.ui.screen.recipeRec.MoreDetailScreen
1111
import com.github.se.polyfit.ui.screen.recipeRec.RecommendationScreen
12-
import com.github.se.polyfit.viewmodel.qrCode.BarCodeCodeViewModel
1312
import com.github.se.polyfit.viewmodel.recipe.RecipeRecommendationViewModel
1413

1514
@Composable
1615
fun RecipeRecFlow(
1716
recipeRecommendationViewModel: RecipeRecommendationViewModel = hiltViewModel(),
18-
barcodeViewModel: BarCodeCodeViewModel = hiltViewModel<BarCodeCodeViewModel>()
17+
navAction: Navigation
1918
) {
20-
val navigation = rememberNavController()
19+
// Needed because of the nested navigation
20+
// Will cause a crash if a different one is not used
21+
val navController = rememberNavController()
22+
val navigation = Navigation(navController)
2123

22-
val navAction = Navigation(navigation)
23-
24-
NavHost(navController = navigation, startDestination = Route.RecipeRecommendation) {
24+
NavHost(navController = navController, startDestination = Route.RecipeRecommendation) {
2525
composable(Route.RecipeRecommendation) {
2626
RecommendationScreen(
27-
navigation,
27+
navAction.navHostController,
2828
recipeRecommendationViewModel,
29-
navAction::navigateToRecipeRecommendationMore,
29+
navigation::navigateToRecipeRecommendationMore,
3030
)
3131
}
3232
composable(Route.RecipeRecommendationMore) {
3333
MoreDetailScreen(
3434
recipeRecommendationViewModel,
35-
navigateBack = navAction::goBack,
35+
navigateBack = navigation::goBack,
3636
)
3737
}
3838
}

app/src/main/java/com/github/se/polyfit/ui/navigation/Navigation.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package com.github.se.polyfit.ui.navigation
33
import android.util.Log
44
import androidx.navigation.NavHostController
55

6-
class Navigation(private val navHostController: NavHostController) {
6+
class Navigation(val navHostController: NavHostController) {
77
fun goBack() {
88
navHostController.popBackStack()
99
}

app/src/main/java/com/github/se/polyfit/ui/screen/recipeRec/RecommendationScreen.kt

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ import androidx.compose.material3.MaterialTheme
1010
import androidx.compose.material3.Text
1111
import androidx.compose.runtime.Composable
1212
import androidx.compose.runtime.LaunchedEffect
13-
import androidx.compose.runtime.getValue
14-
import androidx.compose.runtime.mutableStateOf
15-
import androidx.compose.runtime.remember
16-
import androidx.compose.runtime.setValue
13+
import androidx.compose.runtime.livedata.observeAsState
1714
import androidx.compose.ui.Alignment
1815
import androidx.compose.ui.Modifier
1916
import androidx.compose.ui.platform.LocalContext
@@ -24,8 +21,6 @@ import androidx.core.content.ContextCompat
2421
import androidx.hilt.navigation.compose.hiltViewModel
2522
import androidx.navigation.NavHostController
2623
import com.github.se.polyfit.R
27-
import com.github.se.polyfit.data.local.ingredientscanned.IngredientsScanned
28-
import com.github.se.polyfit.model.recipe.Recipe
2924
import com.github.se.polyfit.ui.components.GenericScreen
3025
import com.github.se.polyfit.ui.components.recipe.RecipeCard
3126
import com.github.se.polyfit.viewmodel.qrCode.BarCodeCodeViewModel
@@ -41,27 +36,23 @@ fun RecommendationScreen(
4136
GenericScreen(
4237
navController = navController,
4338
content = { paddingValues ->
44-
RecipeDisplay(
45-
recipeRecViewModel, barcodeViewModel, paddingValues, navigateToRecipeRecommendationMore)
39+
RecipeDisplay(recipeRecViewModel, paddingValues, navigateToRecipeRecommendationMore)
4640
},
4741
modifier = Modifier.testTag("RecipeDisplay"))
4842
}
4943

5044
@Composable
5145
fun RecipeDisplay(
5246
recipesRec: RecipeRecommendationViewModel,
53-
barcodeViewModel: BarCodeCodeViewModel,
5447
paddingValues: PaddingValues,
5548
navigateToRecipeRecommendationMore: () -> Unit
5649
) {
5750
val context = LocalContext.current
5851

59-
val recipes = remember { mutableStateOf(listOf<Recipe>()) }
60-
var ingredientList by remember { mutableStateOf(listOf<IngredientsScanned>()) }
61-
LaunchedEffect(Unit) {
62-
barcodeViewModel.listIngredients.observeForever { ingredientList = it }
63-
recipes.value = recipesRec.recipeFromIngredients(ingredientList.map { it.name })
64-
}
52+
val recipes = recipesRec.recipes.observeAsState(initial = emptyList())
53+
val fetching = recipesRec.isFetching.observeAsState(initial = true)
54+
55+
LaunchedEffect(Unit) { recipesRec.recipeFromIngredients() }
6556

6657
LazyColumn(
6758
horizontalAlignment = Alignment.CenterHorizontally,
@@ -73,9 +64,21 @@ fun RecipeDisplay(
7364
fontWeight = FontWeight.Bold,
7465
)
7566
}
76-
if (recipes.value.isEmpty()) {
67+
if (fetching.value) {
7768
item { Loader(paddingValues) }
7869
return@LazyColumn
70+
} else if (recipes.value.isEmpty()) {
71+
72+
item {
73+
Box(
74+
modifier = Modifier.fillMaxSize().padding(paddingValues),
75+
contentAlignment = Alignment.Center) {
76+
Text(
77+
text = context.getString(R.string.noRecipesFound),
78+
fontSize = MaterialTheme.typography.bodyLarge.fontSize)
79+
}
80+
}
81+
return@LazyColumn
7982
}
8083

8184
recipes.value.forEach {
@@ -93,6 +96,7 @@ fun RecipeDisplay(
9396
}
9497
}
9598

99+
/** Animation displayed while waiting for the data to be fetched */
96100
@Composable
97101
fun Loader(paddingValues: PaddingValues) {
98102
Box(

app/src/main/java/com/github/se/polyfit/viewmodel/qrCode/barcodeViewModel.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ constructor(
122122
_listIngredients.postValue(list)
123123
} catch (e: Exception) {
124124
removeId(id)
125-
Log.w("QrCodeViewModel", "Error in getting ingredient, surely not a food id: $e")
125+
Log.e("QrCodeViewModel", "Error in getting ingredient, surely not a food id: $e")
126126
}
127127
}
128128
}

0 commit comments

Comments
 (0)