Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import androidx.compose.ui.test.assertIsOn
import androidx.compose.ui.test.assertIsSelected
import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.isEnabled
import androidx.compose.ui.test.isOff
import androidx.compose.ui.test.isOn
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onAllNodesWithContentDescription
import androidx.compose.ui.test.onAllNodesWithText
Expand All @@ -28,19 +30,17 @@ import com.google.accompanist.permissions.PermissionStatus
import com.mbta.tid.mbta_app.android.loadKoinMocks
import com.mbta.tid.mbta_app.android.testUtils.assertCanBeDisplayed
import com.mbta.tid.mbta_app.android.testUtils.hasTextMatching
import com.mbta.tid.mbta_app.android.testUtils.waitUntilDefaultTimeout
import com.mbta.tid.mbta_app.android.testUtils.waitUntilExactlyOneExistsDefaultTimeout
import com.mbta.tid.mbta_app.android.util.ConstantPermissionState
import com.mbta.tid.mbta_app.model.FavoriteSettings
import com.mbta.tid.mbta_app.repositories.MockSentryRepository
import com.mbta.tid.mbta_app.repositories.MockSettingsRepository
import com.mbta.tid.mbta_app.repositories.Settings
import com.mbta.tid.mbta_app.utils.EasternTimeInstant
import kotlin.test.assertEquals
import kotlinx.datetime.DayOfWeek
import com.mbta.tid.mbta_app.viewModel.NotificationSettingsViewModel
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.LocalTime
import org.junit.Rule
import org.junit.Test
import org.koin.compose.koinInject
import org.koin.test.KoinTest

@OptIn(ExperimentalPermissionsApi::class, ExperimentalTestApi::class)
Expand All @@ -62,20 +62,15 @@ class NotificationSettingsWidgetTest : KoinTest {
)
}

lateinit var settings: MutableState<FavoriteSettings.Notifications>
composeTestRule.setContent {
settings = remember { mutableStateOf(FavoriteSettings.Notifications.disabled) }
var settings by settings
NotificationSettingsWidget(
settings,
setSettings = { settings = it },
viewModel = koinInject(),
notificationPermissionState = permissionGranted,
hasRequestedPermission = true,
)
}

composeTestRule.onNodeWithText("Get disruption notifications").performClick()
composeTestRule.waitUntilDefaultTimeout { 1 == settings.value.windows.size }
composeTestRule.waitUntilExactlyOneExistsDefaultTimeout(
(hasTextMatching(Regex("8:00\\sAM", RegexOption.IGNORE_CASE)))
)
Expand All @@ -91,7 +86,6 @@ class NotificationSettingsWidgetTest : KoinTest {
composeTestRule.onNodeWithText("Saturday").assertIsOff()
composeTestRule.onNodeWithContentDescription("Delete").assertDoesNotExist()
composeTestRule.onNodeWithText("Add another time period").performClick()
assertEquals(2, settings.value.windows.size)
composeTestRule.waitUntilExactlyOneExistsDefaultTimeout(
(hasTextMatching(Regex("12:00\\sPM", RegexOption.IGNORE_CASE)))
)
Expand All @@ -117,13 +111,11 @@ class NotificationSettingsWidgetTest : KoinTest {
)
}

lateinit var settings: MutableState<FavoriteSettings.Notifications>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these tests were testing a mix of UI changes + data changes - I've opted to update them to just UI changes rather than testing the innerworkings of calls to the VM

composeTestRule.setContent {
settings = remember { mutableStateOf(FavoriteSettings.Notifications.disabled) }
var settings by settings
val viewModel = NotificationSettingsViewModel(MockSentryRepository())

NotificationSettingsWidget(
settings,
setSettings = { settings = it },
viewModel,
notificationPermissionState = permissionGranted,
hasRequestedPermission = true,
)
Expand All @@ -145,7 +137,9 @@ class NotificationSettingsWidgetTest : KoinTest {
composeTestRule.onNodeWithContentDescription("Select minutes").performClick()
composeTestRule.onNodeWithContentDescription("45 minutes").performClick()
composeTestRule.onNodeWithText("Okay").performClick()
assertEquals(LocalTime(7, 45), settings.value.windows.single().startTime)
composeTestRule.waitUntilExactlyOneExistsDefaultTimeout(
hasTextMatching(Regex("7:45\\sAM", RegexOption.IGNORE_CASE))
)
composeTestRule
.onNode(hasTextMatching(Regex("9:00\\sAM", RegexOption.IGNORE_CASE)))
.performClick()
Expand All @@ -154,48 +148,47 @@ class NotificationSettingsWidgetTest : KoinTest {
composeTestRule.onNodeWithContentDescription("for hour").performTextReplacement("9")
composeTestRule.onNodeWithContentDescription("for minutes").performTextReplacement("10")
composeTestRule.onNodeWithText("Okay").performClick()
assertEquals(LocalTime(9, 10), settings.value.windows.single().endTime)
composeTestRule.waitUntilExactlyOneExistsDefaultTimeout(
hasTextMatching(Regex("9:10\\sAM", RegexOption.IGNORE_CASE))
)
}

@Test
fun testChangeDays() {
lateinit var settings: MutableState<FavoriteSettings.Notifications>
val now = EasternTimeInstant(LocalDateTime(2026, 8, 27, 12, 30, 0))
val viewModel = NotificationSettingsViewModel(MockSentryRepository())

composeTestRule.setContent {
settings = remember { mutableStateOf(FavoriteSettings.Notifications.disabled) }
var settings by settings
NotificationSettingsWidget(
settings,
setSettings = { settings = it },
viewModel = viewModel,
notificationPermissionState = permissionGranted,
hasRequestedPermission = true,
now = now,
)
}

composeTestRule.onNodeWithText("Get disruption notifications").performClick()
composeTestRule.waitUntilExactlyOneExistsDefaultTimeout(
hasText("Get disruption notifications").and(isEnabled())
)
composeTestRule.onNodeWithText("Sunday").performClick()
composeTestRule.waitUntilExactlyOneExistsDefaultTimeout(hasText("Sunday").and(isOn()))
composeTestRule.onNodeWithText("Wednesday").performClick()
composeTestRule.onNodeWithText("Friday").performClick()
assertEquals(
setOf(DayOfWeek.SUNDAY, DayOfWeek.MONDAY, DayOfWeek.TUESDAY, DayOfWeek.THURSDAY),
settings.value.windows.single().daysOfWeek,
)
composeTestRule.waitUntilExactlyOneExistsDefaultTimeout(hasText("Wednesday").and(isOff()))
}

@Test
fun testValidatesTime() {
fun testValidatesStartTime() {
loadKoinMocks {
settings =
MockSettingsRepository(
settings = mapOf(Settings.NotificationPresetWindows to false)
)
}
lateinit var settings: MutableState<FavoriteSettings.Notifications>

composeTestRule.setContent {
settings = remember { mutableStateOf(FavoriteSettings.Notifications.disabled) }
var settings by settings
NotificationSettingsWidget(
settings,
setSettings = { settings = it },
koinInject(),
notificationPermissionState = permissionGranted,
hasRequestedPermission = true,
)
Expand All @@ -215,12 +208,42 @@ class NotificationSettingsWidgetTest : KoinTest {
composeTestRule.onNodeWithContentDescription("Select minutes").performClick()
composeTestRule.onNodeWithContentDescription("45 minutes").performClick()
composeTestRule.onNodeWithText("Okay").performClick()
assertEquals(LocalTime(10, 45), settings.value.windows.single().startTime)
assertEquals(LocalTime(11, 45), settings.value.windows.single().endTime)
composeTestRule.waitUntilExactlyOneExistsDefaultTimeout(
hasTextMatching(Regex("10:45\\sAM", RegexOption.IGNORE_CASE))
)
composeTestRule.waitUntilExactlyOneExistsDefaultTimeout(
hasTextMatching(Regex("11:45\\sAM", RegexOption.IGNORE_CASE))
)
}

@Test
fun testValidatesEndTime() {
loadKoinMocks {
settings =
MockSettingsRepository(
settings = mapOf(Settings.NotificationPresetWindows to false)
)
}

composeTestRule.setContent {
NotificationSettingsWidget(
koinInject(),
notificationPermissionState = permissionGranted,
hasRequestedPermission = true,
)
}

composeTestRule.onNodeWithText("Get disruption notifications").performClick()
composeTestRule.waitUntilExactlyOneExistsDefaultTimeout(
hasText("Get disruption notifications").and(isEnabled())
)
composeTestRule.waitUntilExactlyOneExistsDefaultTimeout(
hasTextMatching(Regex("8:00\\sAM", RegexOption.IGNORE_CASE))
)
composeTestRule
.onNode(hasTextMatching(Regex("11:45\\sAM", RegexOption.IGNORE_CASE)))
.onNode(hasTextMatching(Regex("9:00\\sAM", RegexOption.IGNORE_CASE)))
.performClick()
composeTestRule.onNodeWithContentDescription("10 o'clock").performClick()
composeTestRule.onNodeWithContentDescription("7 o'clock").performClick()
composeTestRule.onNodeWithContentDescription("Select minutes").performClick()
composeTestRule.onNodeWithContentDescription("40 minutes").performClick()
composeTestRule.onNodeWithText("Okay").assertIsNotEnabled()
Expand All @@ -229,13 +252,13 @@ class NotificationSettingsWidgetTest : KoinTest {
@Test
fun testPermissionDenied() {
lateinit var hasRequestedPermission: MutableState<Boolean>
val viewModel = NotificationSettingsViewModel(MockSentryRepository())

composeTestRule.setContent {
hasRequestedPermission = remember { mutableStateOf(false) }
var hasRequestedPermission by hasRequestedPermission
NotificationSettingsWidget(
FavoriteSettings.Notifications.disabled,
setSettings = {},
viewModel,
notificationPermissionState =
ConstantPermissionState(
Manifest.permission.POST_NOTIFICATIONS,
Expand All @@ -259,11 +282,12 @@ class NotificationSettingsWidgetTest : KoinTest {
settings = mapOf(Settings.NotificationPresetWindows to false)
)
}

val viewModel = NotificationSettingsViewModel(MockSentryRepository())

composeTestRule.setContent {
var settings by remember { mutableStateOf(FavoriteSettings.Notifications.disabled) }
NotificationSettingsWidget(
settings,
setSettings = { settings = it },
viewModel,
notificationPermissionState = permissionGranted,
hasRequestedPermission = true,
)
Expand All @@ -284,11 +308,12 @@ class NotificationSettingsWidgetTest : KoinTest {
settings =
MockSettingsRepository(settings = mapOf(Settings.NotificationPresetWindows to true))
}

val viewModel = NotificationSettingsViewModel(MockSentryRepository())

composeTestRule.setContent {
var settings by remember { mutableStateOf(FavoriteSettings.Notifications.disabled) }
NotificationSettingsWidget(
settings,
setSettings = { settings = it },
viewModel,
notificationPermissionState = permissionGranted,
hasRequestedPermission = true,
)
Expand All @@ -309,11 +334,11 @@ class NotificationSettingsWidgetTest : KoinTest {
settings =
MockSettingsRepository(settings = mapOf(Settings.NotificationPresetWindows to true))
}
val viewModel = NotificationSettingsViewModel(MockSentryRepository())

composeTestRule.setContent {
var settings by remember { mutableStateOf(FavoriteSettings.Notifications.disabled) }
NotificationSettingsWidget(
settings,
setSettings = { settings = it },
viewModel,
notificationPermissionState = permissionGranted,
hasRequestedPermission = true,
)
Expand Down Expand Up @@ -341,11 +366,11 @@ class NotificationSettingsWidgetTest : KoinTest {
settings =
MockSettingsRepository(settings = mapOf(Settings.NotificationPresetWindows to true))
}
val viewModel = NotificationSettingsViewModel(MockSentryRepository())

composeTestRule.setContent {
var settings by remember { mutableStateOf(FavoriteSettings.Notifications.disabled) }
NotificationSettingsWidget(
settings,
setSettings = { settings = it },
viewModel,
notificationPermissionState = permissionGranted,
hasRequestedPermission = true,
)
Expand All @@ -367,13 +392,12 @@ class NotificationSettingsWidgetTest : KoinTest {
settings =
MockSettingsRepository(settings = mapOf(Settings.NotificationPresetWindows to true))
}
lateinit var settings: MutableState<FavoriteSettings.Notifications>

val viewModel = NotificationSettingsViewModel(MockSentryRepository())

composeTestRule.setContent {
settings = remember { mutableStateOf(FavoriteSettings.Notifications.disabled) }
var notificationSettings by settings
NotificationSettingsWidget(
notificationSettings,
setSettings = { notificationSettings = it },
viewModel,
notificationPermissionState = permissionGranted,
hasRequestedPermission = true,
now = EasternTimeInstant(LocalDateTime(2026, 8, 27, 12, 30, 0)),
Expand Down
Loading
Loading