Skip to content

Commit

Permalink
Merge branch 'main' into es-stop-details-page-vm-refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
EmmaSimon authored Dec 19, 2024
2 parents a6c0736 + 50336f1 commit d998583
Show file tree
Hide file tree
Showing 19 changed files with 314 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mbta.tid.mbta_app.android.nearbyTransit

import androidx.compose.material3.Text
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.hasText
Expand All @@ -22,6 +23,8 @@ import com.mbta.tid.mbta_app.repositories.IPinnedRoutesRepository
import com.mbta.tid.mbta_app.repositories.IPredictionsRepository
import com.mbta.tid.mbta_app.repositories.IRailRouteShapeRepository
import com.mbta.tid.mbta_app.repositories.ISchedulesRepository
import com.mbta.tid.mbta_app.repositories.MockNearbyRepository
import com.mbta.tid.mbta_app.repositories.MockPredictionsRepository
import com.mbta.tid.mbta_app.repositories.MockRailRouteShapeRepository
import com.mbta.tid.mbta_app.repositories.MockScheduleRepository
import com.mbta.tid.mbta_app.usecases.TogglePinnedRouteUsecase
Expand Down Expand Up @@ -242,7 +245,8 @@ class NearbyTransitViewTest : KoinTest {
targetLocation = Position(0.0, 0.0),
setLastLocation = {},
setSelectingLocation = {},
onOpenStopDetails = { _, _ -> }
onOpenStopDetails = { _, _ -> },
noNearbyStopsView = {}
)
}
}
Expand All @@ -258,4 +262,50 @@ class NearbyTransitViewTest : KoinTest {
composeTestRule.onNodeWithText("Green Line Head Sign").assertIsDisplayed()
composeTestRule.onNodeWithText("5 min").assertIsDisplayed()
}

@OptIn(ExperimentalTestApi::class)
@Test
fun testNearbyTransitViewNoNearbyStops() {
val emptyNearbyKoinApplication = koinApplication {
modules(
module {
single<INearbyRepository> { MockNearbyRepository() }
single<ISchedulesRepository> { MockScheduleRepository() }
single<IPredictionsRepository> {
MockPredictionsRepository(
connectV2Response =
PredictionsByStopJoinResponse(emptyMap(), emptyMap(), emptyMap())
)
}
single<IPinnedRoutesRepository> {
object : IPinnedRoutesRepository {
override suspend fun getPinnedRoutes(): Set<String> {
return emptySet()
}

override suspend fun setPinnedRoutes(routes: Set<String>) {}
}
}
single<TogglePinnedRouteUsecase> { TogglePinnedRouteUsecase(get()) }
}
)
}
composeTestRule.setContent {
KoinContext(emptyNearbyKoinApplication.koin) {
NearbyTransitView(
alertData = AlertsStreamDataResponse(emptyMap()),
globalResponse = globalResponse,
targetLocation = Position(0.0, 0.0),
setLastLocation = {},
setSelectingLocation = {},
onOpenStopDetails = { _, _ -> },
noNearbyStopsView = { Text("This would be the no nearby stops view") }
)
}
}

composeTestRule.waitForIdle()
composeTestRule.waitUntilExactlyOneExists(hasText("This would be the no nearby stops view"))
composeTestRule.onNodeWithText("This would be the no nearby stops view").assertIsDisplayed()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.mbta.tid.mbta_app.android.nearbyTransit

import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import kotlin.test.assertTrue
import org.junit.Rule
import org.junit.Test

class NoNearbyStopsViewTest {
@get:Rule val composeTestRule = createComposeRule()

@Test
fun displaysText() {
composeTestRule.setContent { NoNearbyStopsView({}, {}) }

composeTestRule.onNodeWithText("No nearby stops").assertIsDisplayed()
composeTestRule.onNodeWithText("You’re outside the MBTA service area.").assertIsDisplayed()
composeTestRule.onNodeWithText("Search by stop").assertIsDisplayed()
composeTestRule.onNodeWithText("View transit near Boston").assertIsDisplayed()
}

@Test
fun buttonsWork() {
var openedSearch = false
var pannedToDefaultCenter = false
composeTestRule.setContent {
NoNearbyStopsView(
onOpenSearch = { openedSearch = true },
onPanToDefaultCenter = { pannedToDefaultCenter = true }
)
}

composeTestRule.onNodeWithText("Search by stop").performClick()
assertTrue(openedSearch)
composeTestRule.onNodeWithText("View transit near Boston").performClick()
assertTrue(pannedToDefaultCenter)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import com.mbta.tid.mbta_app.model.ObjectCollectionBuilder
import com.mbta.tid.mbta_app.model.response.ApiResult
import com.mbta.tid.mbta_app.model.response.ScheduleResponse
import com.mbta.tid.mbta_app.repositories.ISchedulesRepository
import com.mbta.tid.mbta_app.repositories.MockScheduleRepository
import kotlin.test.assertNotNull
import kotlinx.coroutines.test.runTest
import kotlinx.datetime.Instant
import org.junit.Assert.assertEquals
Expand Down Expand Up @@ -61,4 +63,20 @@ class GetScheduleTest {
composeTestRule.awaitIdle()
assertEquals(expectedSchedules2, actualSchedules)
}

@Test
fun testScheduleNoStops() {
val schedulesRepo =
MockScheduleRepository(
callback = { stopIds -> assertEquals(emptyList<String>(), stopIds) }
)
var actualSchedules: ScheduleResponse? = null

composeTestRule.setContent {
actualSchedules = getSchedule(stopIds = emptyList(), schedulesRepo)
}

composeTestRule.waitUntil { actualSchedules != null }
assertNotNull(actualSchedules)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import com.mbta.tid.mbta_app.model.ObjectCollectionBuilder
import com.mbta.tid.mbta_app.model.response.PredictionsByStopJoinResponse
import com.mbta.tid.mbta_app.model.response.PredictionsStreamDataResponse
import com.mbta.tid.mbta_app.repositories.MockPredictionsRepository
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Rule
Expand Down Expand Up @@ -54,7 +56,7 @@ class SubscribeToPredictionsTest {

composeTestRule.waitUntil {
predictions != null &&
predictions == predictionsOnJoin?.toPredictionsStreamDataResponse()
predictions == predictionsOnJoin.toPredictionsStreamDataResponse()
}

assertEquals(0, disconnectCount)
Expand Down Expand Up @@ -105,4 +107,28 @@ class SubscribeToPredictionsTest {
composeTestRule.waitUntil { connectCount == 2 }
assertEquals(1, disconnectCount)
}

@Test
fun testEmptyStopList() {
var connected = false
val predictionsRepo =
MockPredictionsRepository(
onConnectV2 = { stopIds ->
assertEquals(emptyList<String>(), stopIds)
connected = true
},
connectV2Response =
PredictionsByStopJoinResponse(emptyMap(), emptyMap(), emptyMap())
)

var predictions: PredictionsStreamDataResponse? = null

composeTestRule.setContent {
predictions = subscribeToPredictions(emptyList(), predictionsRepo)
}

composeTestRule.waitUntil { predictions != null }
assertNotNull(predictions)
assertTrue(connected)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package com.mbta.tid.mbta_app.android.nearbyTransit

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
Expand All @@ -30,13 +33,13 @@ import kotlin.time.Duration.Companion.seconds

@Composable
fun NearbyTransitView(
modifier: Modifier = Modifier,
alertData: AlertsStreamDataResponse?,
globalResponse: GlobalResponse?,
targetLocation: Position?,
setLastLocation: (Position) -> Unit,
setSelectingLocation: (Boolean) -> Unit,
onOpenStopDetails: (String, StopDetailsFilter?) -> Unit,
noNearbyStopsView: @Composable () -> Unit,
) {
var nearby: NearbyStaticData? =
getNearby(
Expand Down Expand Up @@ -79,28 +82,25 @@ fun NearbyTransitView(
}
}

Column(modifier) {
Column {
Text(
text = stringResource(R.string.nearby_transit),
modifier = Modifier.padding(bottom = 12.dp, start = 16.dp, end = 16.dp),
style = MaterialTheme.typography.titleLarge
)

if (nearbyWithRealtimeInfo == null) {
Text(text = stringResource(R.string.loading), modifier)
Text(text = stringResource(R.string.loading))
} else if (nearbyWithRealtimeInfo.isEmpty()) {
Column(Modifier.padding(8.dp).weight(1f), verticalArrangement = Arrangement.Center) {
Text(
stringResource(R.string.no_stops_nearby_title),
style = MaterialTheme.typography.titleMedium
)
Text(
stringResource(R.string.no_stops_nearby),
style = MaterialTheme.typography.bodyMedium
)
Column(
Modifier.verticalScroll(rememberScrollState()).padding(8.dp).weight(1f),
verticalArrangement = Arrangement.Center
) {
noNearbyStopsView()
Spacer(Modifier.weight(1f))
}
} else {
LazyColumn(modifier) {
LazyColumn {
items(nearbyWithRealtimeInfo) {
when (it) {
is StopsAssociated.WithRoute ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package com.mbta.tid.mbta_app.android.nearbyTransit

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeightIn
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.mbta.tid.mbta_app.android.MyApplicationTheme
import com.mbta.tid.mbta_app.android.R

@Composable
fun NoNearbyStopsView(onOpenSearch: () -> Unit, onPanToDefaultCenter: () -> Unit) {
Column(
modifier =
Modifier.clip(RoundedCornerShape(8.dp))
.background(colorResource(R.color.fill3))
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
horizontalAlignment = Alignment.Start
) {
Row(
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
painterResource(R.drawable.mbta_logo),
contentDescription = null,
modifier = Modifier.size(48.dp),
tint = Color.Unspecified
)
Text(
stringResource(R.string.no_stops_nearby_title),
style = MaterialTheme.typography.titleLarge
)
}
Text(stringResource(R.string.no_stops_nearby), style = MaterialTheme.typography.bodyMedium)
Button(
onClick = onOpenSearch,
modifier = Modifier.requiredHeightIn(min = 48.dp),
shape = RoundedCornerShape(8.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically
) {
Text(
stringResource(R.string.no_stops_nearby_search),
style = MaterialTheme.typography.bodyMedium
)
Icon(
painterResource(R.drawable.fa_magnifying_glass_solid),
contentDescription = null,
modifier = Modifier.size(16.dp)
)
}
}
OutlinedButton(
onClick = onPanToDefaultCenter,
modifier = Modifier.requiredHeightIn(min = 48.dp),
shape = RoundedCornerShape(8.dp),
border = BorderStroke(1.dp, colorResource(R.color.key))
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally),
verticalAlignment = Alignment.CenterVertically
) {
Text(
stringResource(R.string.no_stops_nearby_pan),
style = MaterialTheme.typography.bodyMedium
)
Icon(
painterResource(R.drawable.fa_map),
contentDescription = null,
modifier = Modifier.size(16.dp)
)
}
}
}
}

@Preview
@Composable
private fun NoNearbyStopsViewPreview() {
MyApplicationTheme { NoNearbyStopsView({}, {}) }
}
Loading

0 comments on commit d998583

Please sign in to comment.