summaryrefslogtreecommitdiffhomepage
path: root/android/app
diff options
context:
space:
mode:
authorJonatan Rhodin <jonatan.rhodin@mullvad.net>2024-01-11 11:49:30 +0100
committerJonatan Rhodin <jonatan.rhodin@mullvad.net>2024-01-11 11:49:30 +0100
commit6c754c3a45fdb93bcb6f9e615c00e70aaa8d90ba (patch)
tree7d25c5e9a9066c7c97517bfbe39469242e0e08e5 /android/app
parentb5decd12a264c3e37092211eb0951dac6c640670 (diff)
parentb4167469808206ecc7ff2f788befe05e1d7ea57b (diff)
downloadmullvadvpn-6c754c3a45fdb93bcb6f9e615c00e70aaa8d90ba.tar.xz
mullvadvpn-6c754c3a45fdb93bcb6f9e615c00e70aaa8d90ba.zip
Merge branch 'update-to-junit5-droid-569'
Diffstat (limited to 'android/app')
-rw-r--r--android/app/build.gradle.kts12
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/ComposeRuleExtensions.kt4
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialogTest.kt43
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialogTest.kt130
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialogTest.kt181
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/PaymentDialogTest.kt81
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt425
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogDialogTest.kt54
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt1163
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreenTest.kt73
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreenTest.kt179
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt456
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/RedeemVoucherDialogTest.kt206
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreenTest.kt203
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt76
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreenTest.kt274
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt759
-rw-r--r--android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt494
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreen.kt2
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/InAppNotificationControllerTest.kt17
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsIconManagerTest.kt10
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt6
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/relaylist/RelayNameComparatorTest.kt8
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxyTest.kt10
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSourceTest.kt10
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/AccountExpiryNotificationUseCaseTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/NewDeviceUseNotificationCaseTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCaseTest.kt6
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/PlayPaymentUseCaseTest.kt2
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCaseTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/VersionNotificationUseCaseTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/utils/VoucherRegexHelperParameterizedTest.kt31
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ChangelogViewModelTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt264
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModelTest.kt16
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/FilterViewModelTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt12
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModelTest.kt106
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/PaymentViewModelTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ReportProblemViewModelTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt238
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModelTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt14
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt87
47 files changed, 2980 insertions, 2840 deletions
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index a49db33415..e7403733d0 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -1,3 +1,4 @@
+import Dependencies.Plugin.ksp
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import com.android.build.gradle.internal.tasks.factory.dependsOn
import java.io.FileInputStream
@@ -10,6 +11,7 @@ plugins {
id(Dependencies.Plugin.kotlinAndroidId)
id(Dependencies.Plugin.kotlinParcelizeId)
id(Dependencies.Plugin.ksp) version Versions.Plugin.ksp
+ id(Dependencies.Plugin.junit5) version Versions.Plugin.junit5
}
val repoRootPath = rootProject.projectDir.absoluteFile.parentFile.absolutePath
@@ -349,21 +351,25 @@ dependencies {
// Leak canary
leakCanaryImplementation(Dependencies.leakCanary)
- // Test dependencies
+ // Needed for createComposeExtension() and createAndroidComposeExtension()
+ debugImplementation(Dependencies.Compose.uiTestManifest)
testImplementation(project(Dependencies.Mullvad.commonTestLib))
testImplementation(Dependencies.Kotlin.test)
testImplementation(Dependencies.KotlinX.coroutinesTest)
testImplementation(Dependencies.MockK.core)
- testImplementation(Dependencies.junit)
testImplementation(Dependencies.turbine)
+ testImplementation(Dependencies.junitApi)
+ testRuntimeOnly(Dependencies.junitEngine)
+ testImplementation(Dependencies.junitParams)
// UI test dependencies
debugImplementation(Dependencies.AndroidX.fragmentTestning)
// Fixes: https://github.com/android/android-test/issues/1589
debugImplementation(Dependencies.AndroidX.testMonitor)
debugImplementation(Dependencies.Compose.testManifest)
- androidTestImplementation(Dependencies.Compose.junit)
androidTestImplementation(Dependencies.Koin.test)
androidTestImplementation(Dependencies.Kotlin.test)
androidTestImplementation(Dependencies.MockK.android)
+ androidTestImplementation(Dependencies.junitApi)
+ androidTestImplementation(Dependencies.Compose.junit5)
}
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/ComposeRuleExtensions.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/ComposeRuleExtensions.kt
index 69cd530b19..7566051c45 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/ComposeRuleExtensions.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/ComposeRuleExtensions.kt
@@ -1,9 +1,9 @@
package net.mullvad.mullvadvpn.compose
import androidx.compose.runtime.Composable
-import androidx.compose.ui.test.junit4.ComposeContentTestRule
+import de.mannodermaus.junit5.compose.ComposeContext
import net.mullvad.mullvadvpn.lib.theme.AppTheme
-fun ComposeContentTestRule.setContentWithTheme(content: @Composable () -> Unit) {
+fun ComposeContext.setContentWithTheme(content: @Composable () -> Unit) {
setContent { AppTheme { content() } }
}
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialogTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialogTest.kt
index 43e385b65d..1fd106379d 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialogTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/CustomPortDialogTest.kt
@@ -2,22 +2,26 @@ package net.mullvad.mullvadvpn.compose.dialog
import android.annotation.SuppressLint
import androidx.compose.runtime.Composable
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performTextInput
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.compose.test.CUSTOM_PORT_DIALOG_INPUT_TEST_TAG
import net.mullvad.mullvadvpn.model.PortRange
import net.mullvad.mullvadvpn.onNodeWithTagAndText
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
class CustomPortDialogTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @OptIn(ExperimentalTestApi::class)
+ @JvmField
+ @RegisterExtension
+ val composeExtension = createComposeExtension()
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
}
@@ -40,23 +44,22 @@ class CustomPortDialogTest {
}
@Test
- fun testShowWireguardCustomPortDialogInvalidInt() {
- // Input a number to make sure that a too long number does not show and it does not crash
- // the app
+ fun testShowWireguardCustomPortDialogInvalidInt() =
+ composeExtension.use {
+ // Input a number to make sure that a too long number does not show and it does not
+ // crash
+ // the app
- // Arrange
- composeTestRule.setContentWithTheme { testWireguardCustomPortDialog() }
+ // Arrange
+ setContentWithTheme { testWireguardCustomPortDialog() }
- // Act
- composeTestRule
- .onNodeWithTag(CUSTOM_PORT_DIALOG_INPUT_TEST_TAG)
- .performTextInput(invalidCustomPort)
+ // Act
+ onNodeWithTag(CUSTOM_PORT_DIALOG_INPUT_TEST_TAG).performTextInput(invalidCustomPort)
- // Assert
- composeTestRule
- .onNodeWithTagAndText(CUSTOM_PORT_DIALOG_INPUT_TEST_TAG, invalidCustomPort)
- .assertDoesNotExist()
- }
+ // Assert
+ onNodeWithTagAndText(CUSTOM_PORT_DIALOG_INPUT_TEST_TAG, invalidCustomPort)
+ .assertDoesNotExist()
+ }
companion object {
const val invalidCustomPort = "21474836471"
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialogTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialogTest.kt
index bc8d87b244..5f9ffaea95 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialogTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/DnsDialogTest.kt
@@ -2,16 +2,20 @@ package net.mullvad.mullvadvpn.compose.dialog
import android.annotation.SuppressLint
import androidx.compose.runtime.Composable
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.assertIsNotEnabled
-import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
+import de.mannodermaus.junit5.compose.createComposeExtension
import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.viewmodel.DnsDialogViewState
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
class DnsDialogTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @OptIn(ExperimentalTestApi::class)
+ @JvmField
+ @RegisterExtension
+ val composeExtension = createComposeExtension()
private val defaultState =
DnsDialogViewState(
@@ -35,80 +39,86 @@ class DnsDialogTest {
}
@Test
- fun testDnsDialogLanWarningShownWhenLanTrafficDisabledAndLocalAddressUsed() {
- // Arrange
- composeTestRule.setContentWithTheme {
- testDnsDialog(defaultState.copy(isAllowLanEnabled = false, isLocal = true))
- }
+ fun testDnsDialogLanWarningShownWhenLanTrafficDisabledAndLocalAddressUsed() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ testDnsDialog(defaultState.copy(isAllowLanEnabled = false, isLocal = true))
+ }
- // Assert
- composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertExists()
- }
+ // Assert
+ onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertExists()
+ }
@Test
- fun testDnsDialogLanWarningNotShownWhenLanTrafficEnabledAndLocalAddressUsed() {
- // Arrange
- composeTestRule.setContentWithTheme {
- testDnsDialog(defaultState.copy(isAllowLanEnabled = true, isLocal = true))
- }
+ fun testDnsDialogLanWarningNotShownWhenLanTrafficEnabledAndLocalAddressUsed() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ testDnsDialog(defaultState.copy(isAllowLanEnabled = true, isLocal = true))
+ }
- // Assert
- composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist()
- }
+ // Assert
+ onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist()
+ }
@Test
- fun testDnsDialogLanWarningNotShownWhenLanTrafficEnabledAndNonLocalAddressUsed() {
- // Arrange
- composeTestRule.setContentWithTheme {
- testDnsDialog(defaultState.copy(isAllowLanEnabled = true, isLocal = false))
- }
+ fun testDnsDialogLanWarningNotShownWhenLanTrafficEnabledAndNonLocalAddressUsed() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ testDnsDialog(defaultState.copy(isAllowLanEnabled = true, isLocal = false))
+ }
- // Assert
- composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist()
- }
+ // Assert
+ onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist()
+ }
@Test
- fun testDnsDialogLanWarningNotShownWhenLanTrafficDisabledAndNonLocalAddressUsed() {
- // Arrange
- composeTestRule.setContentWithTheme {
- testDnsDialog(defaultState.copy(isAllowLanEnabled = false, isLocal = false))
- }
+ fun testDnsDialogLanWarningNotShownWhenLanTrafficDisabledAndNonLocalAddressUsed() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ testDnsDialog(defaultState.copy(isAllowLanEnabled = false, isLocal = false))
+ }
- // Assert
- composeTestRule.onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist()
- }
+ // Assert
+ onNodeWithText(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist()
+ }
@Test
- fun testDnsDialogSubmitButtonDisabledOnInvalidDnsAddress() {
- // Arrange
- composeTestRule.setContentWithTheme {
- testDnsDialog(
- defaultState.copy(
- ipAddress = invalidIpAddress,
- validationResult = DnsDialogViewState.ValidationResult.InvalidAddress,
+ fun testDnsDialogSubmitButtonDisabledOnInvalidDnsAddress() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ testDnsDialog(
+ defaultState.copy(
+ ipAddress = invalidIpAddress,
+ validationResult = DnsDialogViewState.ValidationResult.InvalidAddress,
+ )
)
- )
- }
+ }
- // Assert
- composeTestRule.onNodeWithText("Submit").assertIsNotEnabled()
- }
+ // Assert
+ onNodeWithText("Submit").assertIsNotEnabled()
+ }
@Test
- fun testDnsDialogSubmitButtonDisabledOnDuplicateDnsAddress() {
- // Arrange
- composeTestRule.setContentWithTheme {
- testDnsDialog(
- defaultState.copy(
- ipAddress = "192.168.0.1",
- validationResult = DnsDialogViewState.ValidationResult.DuplicateAddress,
+ fun testDnsDialogSubmitButtonDisabledOnDuplicateDnsAddress() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ testDnsDialog(
+ defaultState.copy(
+ ipAddress = "192.168.0.1",
+ validationResult = DnsDialogViewState.ValidationResult.DuplicateAddress,
+ )
)
- )
- }
+ }
- // Assert
- composeTestRule.onNodeWithText("Submit").assertIsNotEnabled()
- }
+ // Assert
+ onNodeWithText("Submit").assertIsNotEnabled()
+ }
companion object {
private const val LOCAL_DNS_SERVER_WARNING =
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialogTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialogTest.kt
index 38a3bd170d..28d089cc7e 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialogTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/MtuDialogTest.kt
@@ -2,24 +2,28 @@ package net.mullvad.mullvadvpn.compose.dialog
import android.annotation.SuppressLint
import androidx.compose.runtime.Composable
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
-import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import io.mockk.mockk
import io.mockk.verify
import net.mullvad.mullvadvpn.compose.setContentWithTheme
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
class MtuDialogTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @OptIn(ExperimentalTestApi::class)
+ @JvmField
+ @RegisterExtension
+ val composeExtension = createComposeExtension()
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
}
@@ -41,109 +45,114 @@ class MtuDialogTest {
}
@Test
- fun testMtuDialogWithDefaultValue() {
- // Arrange
- composeTestRule.setContentWithTheme { testMtuDialog() }
+ fun testMtuDialogWithDefaultValue() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme { testMtuDialog() }
- // Assert
- composeTestRule.onNodeWithText(EMPTY_STRING).assertExists()
- }
+ // Assert
+ onNodeWithText(EMPTY_STRING).assertExists()
+ }
@Test
- fun testMtuDialogWithEditValue() {
- // Arrange
- composeTestRule.setContentWithTheme {
- testMtuDialog(
- mtuInitial = VALID_DUMMY_MTU_VALUE,
- )
- }
+ fun testMtuDialogWithEditValue() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ testMtuDialog(
+ mtuInitial = VALID_DUMMY_MTU_VALUE,
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText(VALID_DUMMY_MTU_VALUE.toString()).assertExists()
- }
+ // Assert
+ onNodeWithText(VALID_DUMMY_MTU_VALUE.toString()).assertExists()
+ }
@Test
- fun testMtuDialogTextInput() {
- // Arrange
- composeTestRule.setContentWithTheme {
- testMtuDialog(
- null,
- )
- }
+ fun testMtuDialogTextInput() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ testMtuDialog(
+ null,
+ )
+ }
- // Act
- composeTestRule
- .onNodeWithText(EMPTY_STRING)
- .performTextInput(VALID_DUMMY_MTU_VALUE.toString())
+ // Act
+ onNodeWithText(EMPTY_STRING).performTextInput(VALID_DUMMY_MTU_VALUE.toString())
- // Assert
- composeTestRule.onNodeWithText(VALID_DUMMY_MTU_VALUE.toString()).assertExists()
- }
+ // Assert
+ onNodeWithText(VALID_DUMMY_MTU_VALUE.toString()).assertExists()
+ }
@Test
- fun testMtuDialogSubmitOfValidValue() {
- // Arrange
- val mockedSubmitHandler: (Int) -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- testMtuDialog(
- VALID_DUMMY_MTU_VALUE,
- onSaveMtu = mockedSubmitHandler,
- )
- }
+ fun testMtuDialogSubmitOfValidValue() =
+ composeExtension.use {
+ // Arrange
+ val mockedSubmitHandler: (Int) -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ testMtuDialog(
+ VALID_DUMMY_MTU_VALUE,
+ onSaveMtu = mockedSubmitHandler,
+ )
+ }
- // Act
- composeTestRule.onNodeWithText("Submit").assertIsEnabled().performClick()
+ // Act
+ onNodeWithText("Submit").assertIsEnabled().performClick()
- // Assert
- verify { mockedSubmitHandler.invoke(VALID_DUMMY_MTU_VALUE) }
- }
+ // Assert
+ verify { mockedSubmitHandler.invoke(VALID_DUMMY_MTU_VALUE) }
+ }
@Test
- fun testMtuDialogSubmitButtonDisabledWhenInvalidInput() {
- // Arrange
- composeTestRule.setContentWithTheme {
- testMtuDialog(
- INVALID_DUMMY_MTU_VALUE,
- )
- }
+ fun testMtuDialogSubmitButtonDisabledWhenInvalidInput() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ testMtuDialog(
+ INVALID_DUMMY_MTU_VALUE,
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Submit").assertIsNotEnabled()
- }
+ // Assert
+ onNodeWithText("Submit").assertIsNotEnabled()
+ }
@Test
- fun testMtuDialogResetClick() {
- // Arrange
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- testMtuDialog(
- onResetMtu = mockedClickHandler,
- )
- }
+ fun testMtuDialogResetClick() =
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ testMtuDialog(
+ onResetMtu = mockedClickHandler,
+ )
+ }
- // Act
- composeTestRule.onNodeWithText("Reset to default").performClick()
+ // Act
+ onNodeWithText("Reset to default").performClick()
- // Assert
- verify { mockedClickHandler.invoke() }
- }
+ // Assert
+ verify { mockedClickHandler.invoke() }
+ }
@Test
- fun testMtuDialogCancelClick() {
- // Arrange
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- testMtuDialog(
- onDismiss = mockedClickHandler,
- )
- }
+ fun testMtuDialogCancelClick() =
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ testMtuDialog(
+ onDismiss = mockedClickHandler,
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Cancel").performClick()
+ // Assert
+ onNodeWithText("Cancel").performClick()
- // Assert
- verify { mockedClickHandler.invoke() }
- }
+ // Assert
+ verify { mockedClickHandler.invoke() }
+ }
companion object {
private const val EMPTY_STRING = ""
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/PaymentDialogTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/PaymentDialogTest.kt
index 1a626ecf19..9012b3144f 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/PaymentDialogTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/dialog/PaymentDialogTest.kt
@@ -1,57 +1,64 @@
package net.mullvad.mullvadvpn.compose.dialog
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithText
+import de.mannodermaus.junit5.compose.createComposeExtension
import net.mullvad.mullvadvpn.compose.dialog.payment.PaymentDialog
import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.lib.payment.model.ProductId
import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult
import net.mullvad.mullvadvpn.util.toPaymentDialogData
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
class PaymentDialogTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @OptIn(ExperimentalTestApi::class)
+ @JvmField
+ @RegisterExtension
+ val composeExtension = createComposeExtension()
@Test
- fun testShowPurchaseCompleteDialog() {
- // Arrange
- composeTestRule.setContentWithTheme {
- PaymentDialog(
- paymentDialogData = PurchaseResult.Completed.Success.toPaymentDialogData()!!
- )
- }
+ fun testShowPurchaseCompleteDialog() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ PaymentDialog(
+ paymentDialogData = PurchaseResult.Completed.Success.toPaymentDialogData()!!
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Time was successfully added").assertExists()
- }
+ // Assert
+ onNodeWithText("Time was successfully added").assertExists()
+ }
@Test
- fun testShowVerificationErrorDialog() {
- // Arrange
- composeTestRule.setContentWithTheme {
- PaymentDialog(
- paymentDialogData =
- PurchaseResult.Error.VerificationError(null).toPaymentDialogData()!!
- )
- }
+ fun testShowVerificationErrorDialog() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ PaymentDialog(
+ paymentDialogData =
+ PurchaseResult.Error.VerificationError(null).toPaymentDialogData()!!
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Verifying purchase").assertExists()
- }
+ // Assert
+ onNodeWithText("Verifying purchase").assertExists()
+ }
@Test
- fun testShowFetchProductsErrorDialog() {
- // Arrange
- composeTestRule.setContentWithTheme {
- PaymentDialog(
- paymentDialogData =
- PurchaseResult.Error.FetchProductsError(ProductId(""), null)
- .toPaymentDialogData()!!
- )
- }
+ fun testShowFetchProductsErrorDialog() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ PaymentDialog(
+ paymentDialogData =
+ PurchaseResult.Error.FetchProductsError(ProductId(""), null)
+ .toPaymentDialogData()!!
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Google Play unavailable").assertExists()
- }
+ // Assert
+ onNodeWithText("Google Play unavailable").assertExists()
+ }
}
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt
index 3b42cc1c3b..bead0a02e5 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt
@@ -1,10 +1,11 @@
package net.mullvad.mullvadvpn.compose.screen
import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.mockk
@@ -20,252 +21,272 @@ import net.mullvad.mullvadvpn.lib.payment.model.ProductId
import net.mullvad.mullvadvpn.lib.payment.model.ProductPrice
import net.mullvad.mullvadvpn.viewmodel.AccountUiState
import net.mullvad.mullvadvpn.viewmodel.AccountViewModel
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
+@ExperimentalTestApi
@OptIn(ExperimentalMaterial3Api::class)
class AccountScreenTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @JvmField @RegisterExtension val composeExtension = createComposeExtension()
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
}
@Test
- fun testDefaultState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- AccountScreen(
- uiState =
- AccountUiState(
- deviceName = DUMMY_DEVICE_NAME,
- accountNumber = DUMMY_ACCOUNT_NUMBER,
- accountExpiry = null,
- showSitePayment = false
- ),
- uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
- )
- }
+ fun testDefaultState() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ AccountScreen(
+ uiState =
+ AccountUiState(
+ deviceName = DUMMY_DEVICE_NAME,
+ accountNumber = DUMMY_ACCOUNT_NUMBER,
+ accountExpiry = null,
+ showSitePayment = false
+ ),
+ uiSideEffect =
+ MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("Redeem voucher").assertExists()
onNodeWithText("Log out").assertExists()
}
- }
@Test
- fun testManageAccountClick() {
- // Arrange
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- AccountScreen(
- uiState =
- AccountUiState(
- showSitePayment = true,
- deviceName = DUMMY_DEVICE_NAME,
- accountNumber = DUMMY_ACCOUNT_NUMBER,
- accountExpiry = null,
- ),
- uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
- onManageAccountClick = mockedClickHandler
- )
- }
+ fun testManageAccountClick() =
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ AccountScreen(
+ uiState =
+ AccountUiState(
+ showSitePayment = true,
+ deviceName = DUMMY_DEVICE_NAME,
+ accountNumber = DUMMY_ACCOUNT_NUMBER,
+ accountExpiry = null,
+ ),
+ uiSideEffect =
+ MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
+ onManageAccountClick = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithText("Manage account").performClick()
+ // Act
+ onNodeWithText("Manage account").performClick()
- // Assert
- verify { mockedClickHandler.invoke() }
- }
+ // Assert
+ verify(exactly = 1) { mockedClickHandler.invoke() }
+ }
@Test
- fun testRedeemVoucherClick() {
- // Arrange
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- AccountScreen(
- uiState =
- AccountUiState(
- deviceName = DUMMY_DEVICE_NAME,
- accountNumber = DUMMY_ACCOUNT_NUMBER,
- accountExpiry = null,
- showSitePayment = false
- ),
- uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
- onRedeemVoucherClick = mockedClickHandler
- )
- }
+ fun testRedeemVoucherClick() =
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ AccountScreen(
+ uiState =
+ AccountUiState(
+ deviceName = DUMMY_DEVICE_NAME,
+ accountNumber = DUMMY_ACCOUNT_NUMBER,
+ accountExpiry = null,
+ showSitePayment = false
+ ),
+ uiSideEffect =
+ MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
+ onRedeemVoucherClick = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithText("Redeem voucher").performClick()
+ // Act
+ onNodeWithText("Redeem voucher").performClick()
- // Assert
- verify { mockedClickHandler.invoke() }
- }
+ // Assert
+ verify { mockedClickHandler.invoke() }
+ }
@Test
- fun testLogoutClick() {
- // Arrange
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- AccountScreen(
- uiState =
- AccountUiState(
- deviceName = DUMMY_DEVICE_NAME,
- accountNumber = DUMMY_ACCOUNT_NUMBER,
- accountExpiry = null,
- showSitePayment = false
- ),
- uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
- onLogoutClick = mockedClickHandler
- )
- }
+ fun testLogoutClick() =
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ AccountScreen(
+ uiState =
+ AccountUiState(
+ deviceName = DUMMY_DEVICE_NAME,
+ accountNumber = DUMMY_ACCOUNT_NUMBER,
+ accountExpiry = null,
+ showSitePayment = false
+ ),
+ uiSideEffect =
+ MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
+ onLogoutClick = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithText("Log out").performClick()
+ // Act
+ onNodeWithText("Log out").performClick()
- // Assert
- verify { mockedClickHandler.invoke() }
- }
+ // Assert
+ verify { mockedClickHandler.invoke() }
+ }
@Test
- fun testShowBillingErrorPaymentButton() {
- // Arrange
- composeTestRule.setContentWithTheme {
- AccountScreen(
- uiState =
- AccountUiState.default().copy(billingPaymentState = PaymentState.Error.Billing),
- uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
- )
- }
+ fun testShowBillingErrorPaymentButton() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ AccountScreen(
+ uiState =
+ AccountUiState.default()
+ .copy(billingPaymentState = PaymentState.Error.Billing),
+ uiSideEffect =
+ MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Add 30 days time").assertExists()
- }
+ // Assert
+ onNodeWithText("Add 30 days time").assertExists()
+ }
@Test
- fun testShowBillingPaymentAvailable() {
- // Arrange
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.status } returns null
- composeTestRule.setContentWithTheme {
- AccountScreen(
- uiState =
- AccountUiState.default()
- .copy(
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
- ),
- uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
- )
- }
+ fun testShowBillingPaymentAvailable() =
+ composeExtension.use {
+ // Arrange
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.status } returns null
+ setContentWithTheme {
+ AccountScreen(
+ uiState =
+ AccountUiState.default()
+ .copy(
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
+ ),
+ uiSideEffect =
+ MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Add 30 days time ($10)").assertExists()
- }
+ // Assert
+ onNodeWithText("Add 30 days time ($10)").assertExists()
+ }
@Test
- fun testShowPendingPayment() {
- // Arrange
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.status } returns PaymentStatus.PENDING
- composeTestRule.setContentWithTheme {
- AccountScreen(
- uiState =
- AccountUiState.default()
- .copy(
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
- ),
- uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
- )
- }
+ fun testShowPendingPayment() =
+ composeExtension.use {
+ // Arrange
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.status } returns PaymentStatus.PENDING
+ setContentWithTheme {
+ AccountScreen(
+ uiState =
+ AccountUiState.default()
+ .copy(
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
+ ),
+ uiSideEffect =
+ MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Google Play payment pending").assertExists()
- }
+ // Assert
+ onNodeWithText("Google Play payment pending").assertExists()
+ }
@Test
- fun testShowPendingPaymentInfoDialog() {
- // Arrange
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.status } returns PaymentStatus.PENDING
- val mockNavigateToVerificationPending: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- AccountScreen(
- uiState =
- AccountUiState.default()
- .copy(
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
- ),
- uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
- navigateToVerificationPendingDialog = mockNavigateToVerificationPending
- )
- }
+ fun testShowPendingPaymentInfoDialog() =
+ composeExtension.use {
+ // Arrange
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.status } returns PaymentStatus.PENDING
+ val mockNavigateToVerificationPending: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ AccountScreen(
+ uiState =
+ AccountUiState.default()
+ .copy(
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
+ ),
+ uiSideEffect =
+ MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
+ navigateToVerificationPendingDialog = mockNavigateToVerificationPending
+ )
+ }
- // Act
- composeTestRule.onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).performClick()
+ // Act
+ onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).performClick()
- // Assert
- verify(exactly = 1) { mockNavigateToVerificationPending.invoke() }
- }
+ // Assert
+ verify(exactly = 1) { mockNavigateToVerificationPending.invoke() }
+ }
@Test
- fun testShowVerificationInProgress() {
- // Arrange
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.status } returns PaymentStatus.VERIFICATION_IN_PROGRESS
- composeTestRule.setContentWithTheme {
- AccountScreen(
- uiState =
- AccountUiState.default()
- .copy(
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
- ),
- uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
- )
- }
+ fun testShowVerificationInProgress() =
+ composeExtension.use {
+ // Arrange
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.status } returns PaymentStatus.VERIFICATION_IN_PROGRESS
+ setContentWithTheme {
+ AccountScreen(
+ uiState =
+ AccountUiState.default()
+ .copy(
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
+ ),
+ uiSideEffect =
+ MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Verifying purchase").assertExists()
- }
+ // Assert
+ onNodeWithText("Verifying purchase").assertExists()
+ }
@Test
- fun testOnPurchaseBillingProductClick() {
- // Arrange
- val clickHandler: (ProductId) -> Unit = mockk(relaxed = true)
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.productId } returns ProductId("PRODUCT_ID")
- every { mockPaymentProduct.status } returns null
- composeTestRule.setContentWithTheme {
- AccountScreen(
- uiState =
- AccountUiState.default()
- .copy(
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
- ),
- onPurchaseBillingProductClick = clickHandler,
- uiSideEffect = MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
- )
- }
+ fun testOnPurchaseBillingProductClick() =
+ composeExtension.use {
+ // Arrange
+ val clickHandler: (ProductId) -> Unit = mockk(relaxed = true)
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.productId } returns ProductId("PRODUCT_ID")
+ every { mockPaymentProduct.status } returns null
+ setContentWithTheme {
+ AccountScreen(
+ uiState =
+ AccountUiState.default()
+ .copy(
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
+ ),
+ onPurchaseBillingProductClick = clickHandler,
+ uiSideEffect =
+ MutableSharedFlow<AccountViewModel.UiSideEffect>().asSharedFlow(),
+ )
+ }
- // Act
- composeTestRule.onNodeWithText("Add 30 days time ($10)").performClick()
+ // Act
+ onNodeWithText("Add 30 days time ($10)").performClick()
- // Assert
- verify { clickHandler.invoke(ProductId("PRODUCT_ID")) }
- }
+ // Assert
+ verify { clickHandler.invoke(ProductId("PRODUCT_ID")) }
+ }
companion object {
private const val DUMMY_DEVICE_NAME = "fake_name"
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogDialogTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogDialogTest.kt
index 4e34fe0825..66ed6d25f6 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogDialogTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ChangelogDialogTest.kt
@@ -1,8 +1,9 @@
package net.mullvad.mullvadvpn.compose.screen
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import io.mockk.Runs
import io.mockk.every
@@ -13,44 +14,47 @@ import net.mullvad.mullvadvpn.compose.dialog.ChangelogDialog
import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.viewmodel.Changelog
import net.mullvad.mullvadvpn.viewmodel.ChangelogViewModel
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
+@OptIn(ExperimentalTestApi::class)
class ChangelogDialogTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @JvmField @RegisterExtension val composeExtension = createComposeExtension()
@MockK lateinit var mockedViewModel: ChangelogViewModel
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
}
@Test
- fun testShowChangelogWhenNeeded() {
- // Arrange
- every { mockedViewModel.markChangelogAsRead() } just Runs
+ fun testShowChangeLogWhenNeeded() =
+ composeExtension.use {
+ // Arrange
+ // Arrange
+ every { mockedViewModel.markChangelogAsRead() } just Runs
- composeTestRule.setContentWithTheme {
- ChangelogDialog(
- Changelog(
- changes = listOf(CHANGELOG_ITEM),
- version = CHANGELOG_VERSION,
- ),
- onDismiss = { mockedViewModel.markChangelogAsRead() }
- )
- }
+ setContentWithTheme {
+ ChangelogDialog(
+ Changelog(
+ changes = listOf(CHANGELOG_ITEM),
+ version = CHANGELOG_VERSION,
+ ),
+ onDismiss = { mockedViewModel.markChangelogAsRead() }
+ )
+ }
- // Check changelog content showed within dialog
- composeTestRule.onNodeWithText(CHANGELOG_ITEM).assertExists()
+ // Check changelog content showed within dialog
+ onNodeWithText(CHANGELOG_ITEM).assertExists()
- // perform click on Got It button to check if dismiss occur
- composeTestRule.onNodeWithText(CHANGELOG_BUTTON_TEXT).performClick()
+ // perform click on Got It button to check if dismiss occur
+ onNodeWithText(CHANGELOG_BUTTON_TEXT).performClick()
- // Assert
- verify { mockedViewModel.markChangelogAsRead() }
- }
+ // Assert
+ verify { mockedViewModel.markChangelogAsRead() }
+ }
companion object {
private const val CHANGELOG_BUTTON_TEXT = "Got it!"
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt
index 3838bdc7a0..39e11a3c14 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt
@@ -1,9 +1,10 @@
package net.mullvad.mullvadvpn.compose.screen
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.mockk
@@ -30,35 +31,38 @@ import net.mullvad.talpid.tunnel.ActionAfterDisconnect
import net.mullvad.talpid.tunnel.ErrorState
import net.mullvad.talpid.tunnel.ErrorStateCause
import org.joda.time.DateTime
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
class ConnectScreenTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @OptIn(ExperimentalTestApi::class)
+ @JvmField
+ @RegisterExtension
+ val composeExtension = createComposeExtension()
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
}
- @After
+ @AfterEach
fun teardown() {
unmockkAll()
}
@Test
fun testDefaultState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState = ConnectUiState.INITIAL,
- )
- }
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ ConnectScreen(
+ uiState = ConnectUiState.INITIAL,
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithTag(SCROLLABLE_COLUMN_TEST_TAG).assertExists()
onNodeWithText("UNSECURED CONNECTION").assertExists()
onNodeWithText("Secure my connection").assertExists()
@@ -67,28 +71,28 @@ class ConnectScreenTest {
@Test
fun testConnectingState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Connecting(null, null),
- tunnelRealState = TunnelState.Connecting(null, null),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = InAppNotification.TunnelStateBlocked,
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Connecting(null, null),
+ tunnelRealState = TunnelState.Connecting(null, null),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = InAppNotification.TunnelStateBlocked,
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithTag(CIRCULAR_PROGRESS_INDICATOR).assertExists()
onNodeWithText("CREATING SECURE CONNECTION").assertExists()
onNodeWithText("Switch location").assertExists()
@@ -99,31 +103,32 @@ class ConnectScreenTest {
@Test
fun testConnectingStateQuantumSecured() {
- // Arrange
- val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true)
- every { mockTunnelEndpoint.quantumResistant } returns true
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Connecting(endpoint = mockTunnelEndpoint, null),
- tunnelRealState =
- TunnelState.Connecting(endpoint = mockTunnelEndpoint, null),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = InAppNotification.TunnelStateBlocked,
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true)
+ every { mockTunnelEndpoint.quantumResistant } returns true
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState =
+ TunnelState.Connecting(endpoint = mockTunnelEndpoint, null),
+ tunnelRealState =
+ TunnelState.Connecting(endpoint = mockTunnelEndpoint, null),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = InAppNotification.TunnelStateBlocked,
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithTag(CIRCULAR_PROGRESS_INDICATOR).assertExists()
onNodeWithText("CREATING QUANTUM SECURE CONNECTION").assertExists()
onNodeWithText("Switch location").assertExists()
@@ -134,29 +139,29 @@ class ConnectScreenTest {
@Test
fun testConnectedState() {
- // Arrange
- val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Connected(mockTunnelEndpoint, null),
- tunnelRealState = TunnelState.Connected(mockTunnelEndpoint, null),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = null,
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true)
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Connected(mockTunnelEndpoint, null),
+ tunnelRealState = TunnelState.Connected(mockTunnelEndpoint, null),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = null,
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("SECURE CONNECTION").assertExists()
onNodeWithText("Switch location").assertExists()
onNodeWithText("Disconnect").assertExists()
@@ -165,30 +170,30 @@ class ConnectScreenTest {
@Test
fun testConnectedStateQuantumSecured() {
- // Arrange
- val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true)
- every { mockTunnelEndpoint.quantumResistant } returns true
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Connected(mockTunnelEndpoint, null),
- tunnelRealState = TunnelState.Connected(mockTunnelEndpoint, null),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = null,
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true)
+ every { mockTunnelEndpoint.quantumResistant } returns true
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Connected(mockTunnelEndpoint, null),
+ tunnelRealState = TunnelState.Connected(mockTunnelEndpoint, null),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = null,
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("QUANTUM SECURE CONNECTION").assertExists()
onNodeWithText("Switch location").assertExists()
onNodeWithText("Disconnect").assertExists()
@@ -197,31 +202,33 @@ class ConnectScreenTest {
@Test
fun testDisconnectingState() {
- // Arrange
- val mockRelayLocation: RelayItem = mockk(relaxed = true)
- val mockLocationName = "Home"
- every { mockRelayLocation.locationName } returns mockLocationName
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = mockRelayLocation,
- tunnelUiState = TunnelState.Disconnecting(ActionAfterDisconnect.Nothing),
- tunnelRealState = TunnelState.Disconnecting(ActionAfterDisconnect.Nothing),
- inAddress = null,
- outAddress = "",
- showLocation = true,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = null,
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockRelayLocation: RelayItem = mockk(relaxed = true)
+ val mockLocationName = "Home"
+ every { mockRelayLocation.locationName } returns mockLocationName
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = mockRelayLocation,
+ tunnelUiState =
+ TunnelState.Disconnecting(ActionAfterDisconnect.Nothing),
+ tunnelRealState =
+ TunnelState.Disconnecting(ActionAfterDisconnect.Nothing),
+ inAddress = null,
+ outAddress = "",
+ showLocation = true,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = null,
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("UNSECURED CONNECTION").assertExists()
onNodeWithText(mockLocationName).assertExists()
onNodeWithText("Disconnect").assertExists()
@@ -230,31 +237,31 @@ class ConnectScreenTest {
@Test
fun testDisconnectedState() {
- // Arrange
- val mockRelayLocation: RelayItem = mockk(relaxed = true)
- val mockLocationName = "Home"
- every { mockRelayLocation.locationName } returns mockLocationName
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = mockRelayLocation,
- tunnelUiState = TunnelState.Disconnected(),
- tunnelRealState = TunnelState.Disconnected(),
- inAddress = null,
- outAddress = "",
- showLocation = true,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = null,
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockRelayLocation: RelayItem = mockk(relaxed = true)
+ val mockLocationName = "Home"
+ every { mockRelayLocation.locationName } returns mockLocationName
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = mockRelayLocation,
+ tunnelUiState = TunnelState.Disconnected(),
+ tunnelRealState = TunnelState.Disconnected(),
+ inAddress = null,
+ outAddress = "",
+ showLocation = true,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = null,
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("UNSECURED CONNECTION").assertExists()
onNodeWithText(mockLocationName).assertExists()
onNodeWithText("Secure my connection").assertExists()
@@ -263,36 +270,40 @@ class ConnectScreenTest {
@Test
fun testErrorStateBlocked() {
- // Arrange
- val mockRelayLocation: RelayItem = mockk(relaxed = true)
- val mockLocationName = "Home"
- every { mockRelayLocation.locationName } returns mockLocationName
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = mockRelayLocation,
- tunnelUiState =
- TunnelState.Error(ErrorState(ErrorStateCause.StartTunnelError, true)),
- tunnelRealState =
- TunnelState.Error(ErrorState(ErrorStateCause.StartTunnelError, true)),
- inAddress = null,
- outAddress = "",
- showLocation = true,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification =
- InAppNotification.TunnelStateError(
- ErrorState(ErrorStateCause.StartTunnelError, true)
- ),
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockRelayLocation: RelayItem = mockk(relaxed = true)
+ val mockLocationName = "Home"
+ every { mockRelayLocation.locationName } returns mockLocationName
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = mockRelayLocation,
+ tunnelUiState =
+ TunnelState.Error(
+ ErrorState(ErrorStateCause.StartTunnelError, true)
+ ),
+ tunnelRealState =
+ TunnelState.Error(
+ ErrorState(ErrorStateCause.StartTunnelError, true)
+ ),
+ inAddress = null,
+ outAddress = "",
+ showLocation = true,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification =
+ InAppNotification.TunnelStateError(
+ ErrorState(ErrorStateCause.StartTunnelError, true)
+ ),
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("BLOCKED CONNECTION").assertExists()
onNodeWithText(mockLocationName).assertExists()
onNodeWithText("Disconnect").assertExists()
@@ -302,36 +313,40 @@ class ConnectScreenTest {
@Test
fun testErrorStateNotBlocked() {
- // Arrange
- val mockRelayLocation: RelayItem = mockk(relaxed = true)
- val mockLocationName = "Home"
- every { mockRelayLocation.locationName } returns mockLocationName
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = mockRelayLocation,
- tunnelUiState =
- TunnelState.Error(ErrorState(ErrorStateCause.StartTunnelError, false)),
- tunnelRealState =
- TunnelState.Error(ErrorState(ErrorStateCause.StartTunnelError, false)),
- inAddress = null,
- outAddress = "",
- showLocation = true,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification =
- InAppNotification.TunnelStateError(
- ErrorState(ErrorStateCause.StartTunnelError, false)
- ),
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockRelayLocation: RelayItem = mockk(relaxed = true)
+ val mockLocationName = "Home"
+ every { mockRelayLocation.locationName } returns mockLocationName
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = mockRelayLocation,
+ tunnelUiState =
+ TunnelState.Error(
+ ErrorState(ErrorStateCause.StartTunnelError, false)
+ ),
+ tunnelRealState =
+ TunnelState.Error(
+ ErrorState(ErrorStateCause.StartTunnelError, false)
+ ),
+ inAddress = null,
+ outAddress = "",
+ showLocation = true,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification =
+ InAppNotification.TunnelStateError(
+ ErrorState(ErrorStateCause.StartTunnelError, false)
+ ),
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("FAILED TO SECURE CONNECTION").assertExists()
onNodeWithText(mockLocationName).assertExists()
onNodeWithText("Dismiss").assertExists()
@@ -342,29 +357,30 @@ class ConnectScreenTest {
@Test
fun testReconnectingState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Disconnecting(ActionAfterDisconnect.Reconnect),
- tunnelRealState =
- TunnelState.Disconnecting(ActionAfterDisconnect.Reconnect),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = InAppNotification.TunnelStateBlocked,
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState =
+ TunnelState.Disconnecting(ActionAfterDisconnect.Reconnect),
+ tunnelRealState =
+ TunnelState.Disconnecting(ActionAfterDisconnect.Reconnect),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = InAppNotification.TunnelStateBlocked,
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithTag(CIRCULAR_PROGRESS_INDICATOR).assertExists()
onNodeWithText("CREATING SECURE CONNECTION").assertExists()
onNodeWithText("Switch location").assertExists()
@@ -375,31 +391,32 @@ class ConnectScreenTest {
@Test
fun testDisconnectingBlockState() {
- // Arrange
- val mockRelayLocation: RelayItem = mockk(relaxed = true)
- val mockLocationName = "Home"
- every { mockRelayLocation.locationName } returns mockLocationName
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = mockRelayLocation,
- tunnelUiState = TunnelState.Disconnecting(ActionAfterDisconnect.Block),
- tunnelRealState = TunnelState.Disconnecting(ActionAfterDisconnect.Block),
- inAddress = null,
- outAddress = "",
- showLocation = true,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = InAppNotification.TunnelStateBlocked,
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockRelayLocation: RelayItem = mockk(relaxed = true)
+ val mockLocationName = "Home"
+ every { mockRelayLocation.locationName } returns mockLocationName
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = mockRelayLocation,
+ tunnelUiState = TunnelState.Disconnecting(ActionAfterDisconnect.Block),
+ tunnelRealState =
+ TunnelState.Disconnecting(ActionAfterDisconnect.Block),
+ inAddress = null,
+ outAddress = "",
+ showLocation = true,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = InAppNotification.TunnelStateBlocked,
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("SECURE CONNECTION").assertExists()
onNodeWithText(mockLocationName).assertExists()
onNodeWithText("Disconnect").assertExists()
@@ -409,199 +426,210 @@ class ConnectScreenTest {
@Test
fun testClickSelectLocationButton() {
- // Arrange
- val mockRelayLocation: RelayItem = mockk(relaxed = true)
- val mockLocationName = "Home"
- every { mockRelayLocation.locationName } returns mockLocationName
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = mockRelayLocation,
- tunnelUiState = TunnelState.Disconnected(),
- tunnelRealState = TunnelState.Disconnected(),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = null,
- isPlayBuild = false
- ),
- onSwitchLocationClick = mockedClickHandler
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockRelayLocation: RelayItem = mockk(relaxed = true)
+ val mockLocationName = "Home"
+ every { mockRelayLocation.locationName } returns mockLocationName
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = mockRelayLocation,
+ tunnelUiState = TunnelState.Disconnected(),
+ tunnelRealState = TunnelState.Disconnected(),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = null,
+ isPlayBuild = false
+ ),
+ onSwitchLocationClick = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithTag(SELECT_LOCATION_BUTTON_TEST_TAG).performClick()
+ // Act
+ onNodeWithTag(SELECT_LOCATION_BUTTON_TEST_TAG).performClick()
- // Assert
- verify { mockedClickHandler.invoke() }
+ // Assert
+ verify { mockedClickHandler.invoke() }
+ }
}
@Test
fun testOnDisconnectClick() {
- // Arrange
- val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true)
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Connected(mockTunnelEndpoint, null),
- tunnelRealState = TunnelState.Connected(mockTunnelEndpoint, null),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = null,
- isPlayBuild = false
- ),
- onDisconnectClick = mockedClickHandler
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true)
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Connected(mockTunnelEndpoint, null),
+ tunnelRealState = TunnelState.Connected(mockTunnelEndpoint, null),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = null,
+ isPlayBuild = false
+ ),
+ onDisconnectClick = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithTag(CONNECT_BUTTON_TEST_TAG).performClick()
+ // Act
+ onNodeWithTag(CONNECT_BUTTON_TEST_TAG).performClick()
- // Assert
- verify { mockedClickHandler.invoke() }
+ // Assert
+ verify { mockedClickHandler.invoke() }
+ }
}
@Test
fun testOnReconnectClick() {
- // Arrange
- val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true)
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Connected(mockTunnelEndpoint, null),
- tunnelRealState = TunnelState.Connected(mockTunnelEndpoint, null),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = null,
- isPlayBuild = false
- ),
- onReconnectClick = mockedClickHandler
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true)
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Connected(mockTunnelEndpoint, null),
+ tunnelRealState = TunnelState.Connected(mockTunnelEndpoint, null),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = null,
+ isPlayBuild = false
+ ),
+ onReconnectClick = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithTag(RECONNECT_BUTTON_TEST_TAG).performClick()
+ // Act
+ onNodeWithTag(RECONNECT_BUTTON_TEST_TAG).performClick()
- // Assert
- verify { mockedClickHandler.invoke() }
+ // Assert
+ verify { mockedClickHandler.invoke() }
+ }
}
@Test
fun testOnConnectClick() {
- // Arrange
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Disconnected(),
- tunnelRealState = TunnelState.Disconnected(),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = null,
- isPlayBuild = false
- ),
- onConnectClick = mockedClickHandler
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Disconnected(),
+ tunnelRealState = TunnelState.Disconnected(),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = null,
+ isPlayBuild = false
+ ),
+ onConnectClick = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithTag(CONNECT_BUTTON_TEST_TAG).performClick()
+ // Act
+ onNodeWithTag(CONNECT_BUTTON_TEST_TAG).performClick()
- // Assert
- verify { mockedClickHandler.invoke() }
+ // Assert
+ verify { mockedClickHandler.invoke() }
+ }
}
@Test
fun testOnCancelClick() {
- // Arrange
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Connecting(null, null),
- tunnelRealState = TunnelState.Connecting(null, null),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = null,
- isPlayBuild = false
- ),
- onCancelClick = mockedClickHandler
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Connecting(null, null),
+ tunnelRealState = TunnelState.Connecting(null, null),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = null,
+ isPlayBuild = false
+ ),
+ onCancelClick = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithTag(CONNECT_BUTTON_TEST_TAG).performClick()
+ // Act
+ onNodeWithTag(CONNECT_BUTTON_TEST_TAG).performClick()
- // Assert
- verify { mockedClickHandler.invoke() }
+ // Assert
+ verify { mockedClickHandler.invoke() }
+ }
}
@Test
fun showLocationInfo() {
- // Arrange
- val mockLocation: GeoIpLocation = mockk(relaxed = true)
- val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true)
- val mockHostName = "Host-Name"
- val mockPort = 99
- val mockHost = "Host"
- val mockProtocol = TransportProtocol.Udp
- val mockInAddress = Triple(mockHost, mockPort, mockProtocol)
- val mockOutAddress = "HostAddressV4 / HostAddressV4"
- every { mockLocation.hostname } returns mockHostName
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = mockLocation,
- relayLocation = null,
- tunnelUiState = TunnelState.Connected(mockTunnelEndpoint, null),
- tunnelRealState = TunnelState.Connected(mockTunnelEndpoint, null),
- inAddress = mockInAddress,
- outAddress = mockOutAddress,
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = null,
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockLocation: GeoIpLocation = mockk(relaxed = true)
+ val mockTunnelEndpoint: TunnelEndpoint = mockk(relaxed = true)
+ val mockHostName = "Host-Name"
+ val mockPort = 99
+ val mockHost = "Host"
+ val mockProtocol = TransportProtocol.Udp
+ val mockInAddress = Triple(mockHost, mockPort, mockProtocol)
+ val mockOutAddress = "HostAddressV4 / HostAddressV4"
+ every { mockLocation.hostname } returns mockHostName
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = mockLocation,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Connected(mockTunnelEndpoint, null),
+ tunnelRealState = TunnelState.Connected(mockTunnelEndpoint, null),
+ inAddress = mockInAddress,
+ outAddress = mockOutAddress,
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = null,
+ isPlayBuild = false
+ ),
+ )
+ }
- composeTestRule.onNodeWithTag(LOCATION_INFO_TEST_TAG).performClick()
+ // Act
+ onNodeWithTag(LOCATION_INFO_TEST_TAG).performClick()
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText(mockHostName).assertExists()
onNodeWithText("WireGuard").assertExists()
onNodeWithText("In $mockHost:$mockPort UDP").assertExists()
@@ -611,35 +639,35 @@ class ConnectScreenTest {
@Test
fun testOutdatedVersionNotification() {
- // Arrange
- val versionInfo =
- VersionInfo(
- currentVersion = "1.0",
- upgradeVersion = "1.1",
- isOutdated = true,
- isSupported = true
- )
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Connecting(null, null),
- tunnelRealState = TunnelState.Connecting(null, null),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = InAppNotification.UpdateAvailable(versionInfo),
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val versionInfo =
+ VersionInfo(
+ currentVersion = "1.0",
+ upgradeVersion = "1.1",
+ isOutdated = true,
+ isSupported = true
+ )
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Connecting(null, null),
+ tunnelRealState = TunnelState.Connecting(null, null),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = InAppNotification.UpdateAvailable(versionInfo),
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("UPDATE AVAILABLE").assertExists()
onNodeWithText("Install Mullvad VPN (1.1) to stay up to date").assertExists()
}
@@ -647,35 +675,35 @@ class ConnectScreenTest {
@Test
fun testUnsupportedVersionNotification() {
- // Arrange
- val versionInfo =
- VersionInfo(
- currentVersion = "1.0",
- upgradeVersion = "1.1",
- isOutdated = true,
- isSupported = false
- )
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Connecting(null, null),
- tunnelRealState = TunnelState.Connecting(null, null),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = InAppNotification.UnsupportedVersion(versionInfo),
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val versionInfo =
+ VersionInfo(
+ currentVersion = "1.0",
+ upgradeVersion = "1.1",
+ isOutdated = true,
+ isSupported = false
+ )
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Connecting(null, null),
+ tunnelRealState = TunnelState.Connecting(null, null),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = InAppNotification.UnsupportedVersion(versionInfo),
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("UNSUPPORTED VERSION").assertExists()
onNodeWithText(
"Your privacy might be at risk with this unsupported app version. Please update now."
@@ -686,29 +714,29 @@ class ConnectScreenTest {
@Test
fun testAccountExpiredNotification() {
- // Arrange
- val expiryDate = DateTime(2020, 11, 11, 10, 10)
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Connecting(null, null),
- tunnelRealState = TunnelState.Connecting(null, null),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = InAppNotification.AccountExpiry(expiryDate),
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val expiryDate = DateTime(2020, 11, 11, 10, 10)
+ setContentWithTheme {
+ ConnectScreen(
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Connecting(null, null),
+ tunnelRealState = TunnelState.Connecting(null, null),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = InAppNotification.AccountExpiry(expiryDate),
+ isPlayBuild = false
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("ACCOUNT CREDIT EXPIRES SOON").assertExists()
onNodeWithText("Out of time").assertExists()
}
@@ -716,85 +744,94 @@ class ConnectScreenTest {
@Test
fun testOnUpdateVersionClick() {
- // Arrange
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- val versionInfo =
- VersionInfo(
- currentVersion = "1.0",
- upgradeVersion = "1.1",
- isOutdated = true,
- isSupported = false
- )
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- onUpdateVersionClick = mockedClickHandler,
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Connecting(null, null),
- tunnelRealState = TunnelState.Connecting(null, null),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = InAppNotification.UnsupportedVersion(versionInfo),
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ val versionInfo =
+ VersionInfo(
+ currentVersion = "1.0",
+ upgradeVersion = "1.1",
+ isOutdated = true,
+ isSupported = false
+ )
+ setContentWithTheme {
+ ConnectScreen(
+ onUpdateVersionClick = mockedClickHandler,
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Connecting(null, null),
+ tunnelRealState = TunnelState.Connecting(null, null),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = InAppNotification.UnsupportedVersion(versionInfo),
+ isPlayBuild = false
+ ),
+ )
+ }
- // Act
- composeTestRule.onNodeWithTag(NOTIFICATION_BANNER_ACTION).performClick()
+ // Act
+ onNodeWithTag(NOTIFICATION_BANNER_ACTION).performClick()
- // Assert
- verify { mockedClickHandler.invoke() }
+ // Assert
+ verify { mockedClickHandler.invoke() }
+ }
}
@Test
fun testOnShowAccountClick() {
- // Arrange
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- val expiryDate = DateTime(2020, 11, 11, 10, 10)
- composeTestRule.setContentWithTheme {
- ConnectScreen(
- onManageAccountClick = mockedClickHandler,
- uiState =
- ConnectUiState(
- location = null,
- relayLocation = null,
- tunnelUiState = TunnelState.Connecting(null, null),
- tunnelRealState = TunnelState.Connecting(null, null),
- inAddress = null,
- outAddress = "",
- showLocation = false,
- deviceName = "",
- daysLeftUntilExpiry = null,
- inAppNotification = InAppNotification.AccountExpiry(expiryDate),
- isPlayBuild = false
- ),
- )
- }
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ val expiryDate = DateTime(2020, 11, 11, 10, 10)
+ setContentWithTheme {
+ ConnectScreen(
+ onManageAccountClick = mockedClickHandler,
+ uiState =
+ ConnectUiState(
+ location = null,
+ relayLocation = null,
+ tunnelUiState = TunnelState.Connecting(null, null),
+ tunnelRealState = TunnelState.Connecting(null, null),
+ inAddress = null,
+ outAddress = "",
+ showLocation = false,
+ deviceName = "",
+ daysLeftUntilExpiry = null,
+ inAppNotification = InAppNotification.AccountExpiry(expiryDate),
+ isPlayBuild = false
+ ),
+ )
+ }
- // Act
- composeTestRule.onNodeWithTag(NOTIFICATION_BANNER_ACTION).performClick()
+ // Act
+ onNodeWithTag(NOTIFICATION_BANNER_ACTION).performClick()
- // Assert
- verify { mockedClickHandler.invoke() }
+ // Assert
+ verify { mockedClickHandler.invoke() }
+ }
}
@Test
fun testOpenAccountView() {
- // Arrange
- val onAccountClickMockk: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- ConnectScreen(uiState = ConnectUiState.INITIAL, onAccountClick = onAccountClickMockk)
- }
+ composeExtension.use {
+ // Arrange
+ val onAccountClickMockk: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ ConnectScreen(
+ uiState = ConnectUiState.INITIAL,
+ onAccountClick = onAccountClickMockk
+ )
+ }
- // Assert
- composeTestRule.onNodeWithTag(TOP_BAR_ACCOUNT_BUTTON).performClick()
+ // Assert
+ onNodeWithTag(TOP_BAR_ACCOUNT_BUTTON).performClick()
- verify(exactly = 1) { onAccountClickMockk() }
+ verify(exactly = 1) { onAccountClickMockk() }
+ }
}
}
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreenTest.kt
index 56e24b9a08..f65a23fa9c 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreenTest.kt
@@ -1,64 +1,69 @@
package net.mullvad.mullvadvpn.compose.screen
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import io.mockk.mockk
import io.mockk.verify
import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.compose.state.DeviceRevokedUiState
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
+@OptIn(ExperimentalTestApi::class)
class DeviceRevokedScreenTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @JvmField @RegisterExtension val composeExtension = createComposeExtension()
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
}
@Test
- fun testUnblockWarningShowingWhenSecured() {
- // Arrange
- val state = DeviceRevokedUiState.SECURED
+ fun testUnblockWarningShowingWhenSecured() =
+ composeExtension.use {
+ // Arrange
+ val state = DeviceRevokedUiState.SECURED
- // Act
- composeTestRule.setContentWithTheme { DeviceRevokedScreen(state) }
+ // Act
+ setContentWithTheme { DeviceRevokedScreen(state) }
- // Assert
- composeTestRule.onNodeWithText(UNBLOCK_WARNING).assertExists()
- }
+ // Assert
+ onNodeWithText(UNBLOCK_WARNING).assertExists()
+ }
@Test
- fun testUnblockWarningNotShowingWhenNotSecured() {
- // Arrange
- val state = DeviceRevokedUiState.UNSECURED
+ fun testUnblockWarningNotShowingWhenNotSecured() =
+ composeExtension.use {
+ // Arrange
+ val state = DeviceRevokedUiState.UNSECURED
- // Act
- composeTestRule.setContentWithTheme { DeviceRevokedScreen(state) }
+ // Act
+ setContentWithTheme { DeviceRevokedScreen(state) }
- // Assert
- composeTestRule.onNodeWithText(UNBLOCK_WARNING).assertDoesNotExist()
- }
+ // Assert
+ onNodeWithText(UNBLOCK_WARNING).assertDoesNotExist()
+ }
@Test
- fun testGoToLogin() {
- // Arrange
- val state = DeviceRevokedUiState.UNSECURED
- val mockOnGoToLoginClicked: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- DeviceRevokedScreen(state = state, onGoToLoginClicked = mockOnGoToLoginClicked)
- }
+ fun testGoToLogin() =
+ composeExtension.use {
+ // Arrange
+ val state = DeviceRevokedUiState.UNSECURED
+ val mockOnGoToLoginClicked: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ DeviceRevokedScreen(state = state, onGoToLoginClicked = mockOnGoToLoginClicked)
+ }
- // Act
- composeTestRule.onNodeWithText(GO_TO_LOGIN_BUTTON_TEXT).performClick()
+ // Act
+ onNodeWithText(GO_TO_LOGIN_BUTTON_TEXT).performClick()
- // Assert
- verify { mockOnGoToLoginClicked.invoke() }
- }
+ // Assert
+ verify { mockOnGoToLoginClicked.invoke() }
+ }
companion object {
private const val GO_TO_LOGIN_BUTTON_TEXT = "Go to login"
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreenTest.kt
index 32fd727329..11f15b7823 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreenTest.kt
@@ -1,8 +1,9 @@
package net.mullvad.mullvadvpn.compose.screen
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import io.mockk.mockk
import io.mockk.verify
@@ -10,132 +11,128 @@ import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.compose.state.RelayFilterState
import net.mullvad.mullvadvpn.model.Ownership
import net.mullvad.mullvadvpn.relaylist.Provider
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
+@OptIn(ExperimentalTestApi::class)
class FilterScreenTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @JvmField @RegisterExtension val composeExtension = createComposeExtension()
fun setup() {
MockKAnnotations.init(this)
}
@Test
- fun testDefaultState() {
- composeTestRule.setContentWithTheme {
- FilterScreen(
- uiState =
- RelayFilterState(
- allProviders = DUMMY_RELAY_ALL_PROVIDERS,
- selectedOwnership = null,
- selectedProviders = DUMMY_SELECTED_PROVIDERS,
- ),
- onSelectedProvider = { _, _ -> }
- )
- }
- composeTestRule.apply {
+ fun testDefaultState() =
+ composeExtension.use {
+ setContentWithTheme {
+ FilterScreen(
+ uiState =
+ RelayFilterState(
+ allProviders = DUMMY_RELAY_ALL_PROVIDERS,
+ selectedOwnership = null,
+ selectedProviders = DUMMY_SELECTED_PROVIDERS,
+ ),
+ onSelectedProvider = { _, _ -> }
+ )
+ }
onNodeWithText("Ownership").assertExists()
onNodeWithText("Providers").assertExists()
}
- }
@Test
- fun testIsAnyCellShowing() {
- composeTestRule.setContentWithTheme {
- FilterScreen(
- uiState =
- RelayFilterState(
- allProviders = DUMMY_RELAY_ALL_PROVIDERS,
- selectedOwnership = null,
- selectedProviders = DUMMY_SELECTED_PROVIDERS
- ),
- onSelectedProvider = { _, _ -> }
- )
- }
- composeTestRule.apply {
+ fun testIsAnyCellShowing() =
+ composeExtension.use {
+ setContentWithTheme {
+ FilterScreen(
+ uiState =
+ RelayFilterState(
+ allProviders = DUMMY_RELAY_ALL_PROVIDERS,
+ selectedOwnership = null,
+ selectedProviders = DUMMY_SELECTED_PROVIDERS
+ ),
+ onSelectedProvider = { _, _ -> }
+ )
+ }
onNodeWithText("Ownership").performClick()
onNodeWithText("Any").assertExists()
}
- }
@Test
- fun testIsMullvadCellShowing() {
- composeTestRule.setContentWithTheme {
- FilterScreen(
- uiState =
- RelayFilterState(
- allProviders = DUMMY_RELAY_ALL_PROVIDERS,
- selectedOwnership = Ownership.MullvadOwned,
- selectedProviders = DUMMY_SELECTED_PROVIDERS
- ),
- onSelectedProvider = { _, _ -> }
- )
- }
- composeTestRule.apply {
+ fun testIsMullvadCellShowing() =
+ composeExtension.use {
+ setContentWithTheme {
+ FilterScreen(
+ uiState =
+ RelayFilterState(
+ allProviders = DUMMY_RELAY_ALL_PROVIDERS,
+ selectedOwnership = Ownership.MullvadOwned,
+ selectedProviders = DUMMY_SELECTED_PROVIDERS
+ ),
+ onSelectedProvider = { _, _ -> }
+ )
+ }
onNodeWithText("Ownership").performClick()
onNodeWithText("Mullvad owned only").assertExists()
}
- }
@Test
- fun testIsRentedCellShowing() {
- composeTestRule.setContentWithTheme {
- FilterScreen(
- uiState =
- RelayFilterState(
- allProviders = DUMMY_RELAY_ALL_PROVIDERS,
- selectedOwnership = Ownership.Rented,
- selectedProviders = DUMMY_SELECTED_PROVIDERS
- ),
- onSelectedProvider = { _, _ -> }
- )
- }
- composeTestRule.apply {
+ fun testIsRentedCellShowing() =
+ composeExtension.use {
+ setContentWithTheme {
+ FilterScreen(
+ uiState =
+ RelayFilterState(
+ allProviders = DUMMY_RELAY_ALL_PROVIDERS,
+ selectedOwnership = Ownership.Rented,
+ selectedProviders = DUMMY_SELECTED_PROVIDERS
+ ),
+ onSelectedProvider = { _, _ -> }
+ )
+ }
onNodeWithText("Ownership").performClick()
onNodeWithText("Rented only").assertExists()
}
- }
@Test
- fun testShowProviders() {
- composeTestRule.setContentWithTheme {
- FilterScreen(
- uiState =
- RelayFilterState(
- allProviders = DUMMY_RELAY_ALL_PROVIDERS,
- selectedOwnership = null,
- selectedProviders = DUMMY_SELECTED_PROVIDERS
- ),
- onSelectedProvider = { _, _ -> }
- )
- }
+ fun testShowProviders() =
+ composeExtension.use {
+ setContentWithTheme {
+ FilterScreen(
+ uiState =
+ RelayFilterState(
+ allProviders = DUMMY_RELAY_ALL_PROVIDERS,
+ selectedOwnership = null,
+ selectedProviders = DUMMY_SELECTED_PROVIDERS
+ ),
+ onSelectedProvider = { _, _ -> }
+ )
+ }
- composeTestRule.apply {
onNodeWithText("Providers").performClick()
onNodeWithText("Creanova").assertExists()
- onNodeWithText("Creanova").assertExists()
onNodeWithText("100TB").assertExists()
}
- }
@Test
- fun testApplyButtonClick() {
- val mockClickListener: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- FilterScreen(
- uiState =
- RelayFilterState(
- allProviders = listOf(),
- selectedOwnership = null,
- selectedProviders = listOf(Provider("31173", true))
- ),
- onSelectedProvider = { _, _ -> },
- onApplyClick = mockClickListener
- )
+ fun testApplyButtonClick() =
+ composeExtension.use {
+ val mockClickListener: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ FilterScreen(
+ uiState =
+ RelayFilterState(
+ allProviders = listOf(),
+ selectedOwnership = null,
+ selectedProviders = listOf(Provider("31173", true))
+ ),
+ onSelectedProvider = { _, _ -> },
+ onApplyClick = mockClickListener
+ )
+ }
+ onNodeWithText("Apply").performClick()
+ verify { mockClickListener() }
}
- composeTestRule.onNodeWithText("Apply").performClick()
- verify { mockClickListener() }
- }
companion object {
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt
index d43a0931a1..f3f1d0cba5 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt
@@ -1,9 +1,10 @@
package net.mullvad.mullvadvpn.compose.screen
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.mockk
@@ -17,34 +18,35 @@ import net.mullvad.mullvadvpn.lib.payment.model.PaymentStatus
import net.mullvad.mullvadvpn.lib.payment.model.ProductId
import net.mullvad.mullvadvpn.lib.payment.model.ProductPrice
import net.mullvad.mullvadvpn.model.TunnelState
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
+@OptIn(ExperimentalTestApi::class)
class OutOfTimeScreenTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @JvmField @RegisterExtension val composeExtension = createComposeExtension()
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
}
@Test
- fun testDisableSitePayment() {
- // Arrange
- composeTestRule.setContentWithTheme {
- OutOfTimeScreen(
- uiState = OutOfTimeUiState(deviceName = ""),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onDisconnectClick = {}
- )
- }
+ fun testDisableSitePayment() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ OutOfTimeScreen(
+ uiState = OutOfTimeUiState(deviceName = ""),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onDisconnectClick = {}
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText(
"Either buy credit on our website or redeem a voucher.",
substring = true
@@ -52,241 +54,251 @@ class OutOfTimeScreenTest {
.assertDoesNotExist()
onNodeWithText("Buy credit").assertDoesNotExist()
}
- }
@Test
- fun testOpenAccountView() {
- // Arrange
- composeTestRule.setContentWithTheme {
- OutOfTimeScreen(
- uiState = OutOfTimeUiState(deviceName = "", showSitePayment = true),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onDisconnectClick = {}
- )
- }
+ fun testOpenAccountView() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ OutOfTimeScreen(
+ uiState = OutOfTimeUiState(deviceName = "", showSitePayment = true),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onDisconnectClick = {}
+ )
+ }
- // Assert
- composeTestRule.apply { onNodeWithText("Congrats!").assertDoesNotExist() }
- }
+ // Assert
+ onNodeWithText("Congrats!").assertDoesNotExist()
+ }
@Test
- fun testClickSitePaymentButton() {
- // Arrange
- val mockClickListener: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- OutOfTimeScreen(
- uiState = OutOfTimeUiState(deviceName = "", showSitePayment = true),
- onSitePaymentClick = mockClickListener,
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onDisconnectClick = {}
- )
- }
+ fun testClickSitePaymentButton() =
+ composeExtension.use {
+ // Arrange
+ val mockClickListener: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ OutOfTimeScreen(
+ uiState = OutOfTimeUiState(deviceName = "", showSitePayment = true),
+ onSitePaymentClick = mockClickListener,
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onDisconnectClick = {}
+ )
+ }
- // Act
- composeTestRule.apply { onNodeWithText("Buy credit").performClick() }
+ // Act
+ onNodeWithText("Buy credit").performClick()
- // Assert
- verify(exactly = 1) { mockClickListener.invoke() }
- }
+ // Assert
+ verify(exactly = 1) { mockClickListener.invoke() }
+ }
@Test
- fun testClickRedeemVoucher() {
- // Arrange
- val mockClickListener: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- OutOfTimeScreen(
- uiState = OutOfTimeUiState(deviceName = "", showSitePayment = true),
- onSitePaymentClick = {},
- onRedeemVoucherClick = mockClickListener,
- onSettingsClick = {},
- onAccountClick = {},
- onDisconnectClick = {}
- )
- }
+ fun testClickRedeemVoucher() =
+ composeExtension.use {
+ // Arrange
+ val mockClickListener: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ OutOfTimeScreen(
+ uiState = OutOfTimeUiState(deviceName = "", showSitePayment = true),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = mockClickListener,
+ onSettingsClick = {},
+ onAccountClick = {},
+ onDisconnectClick = {}
+ )
+ }
- // Act
- composeTestRule.apply { onNodeWithText("Redeem voucher").performClick() }
+ // Act
+ onNodeWithText("Redeem voucher").performClick()
- // Assert
- verify(exactly = 1) { mockClickListener.invoke() }
- }
+ // Assert
+ verify(exactly = 1) { mockClickListener.invoke() }
+ }
@Test
- fun testClickDisconnect() {
- // Arrange
- val mockClickListener: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- OutOfTimeScreen(
- uiState =
- OutOfTimeUiState(
- tunnelState = TunnelState.Connecting(null, null),
- deviceName = "",
- showSitePayment = true
- ),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onDisconnectClick = mockClickListener
- )
- }
+ fun testClickDisconnect() =
+ composeExtension.use {
+ // Arrange
+ val mockClickListener: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ OutOfTimeScreen(
+ uiState =
+ OutOfTimeUiState(
+ tunnelState = TunnelState.Connecting(null, null),
+ deviceName = "",
+ showSitePayment = true
+ ),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onDisconnectClick = mockClickListener
+ )
+ }
- // Act
- composeTestRule.apply { onNodeWithText("Disconnect").performClick() }
+ // Act
+ onNodeWithText("Disconnect").performClick()
- // Assert
- verify(exactly = 1) { mockClickListener.invoke() }
- }
+ // Assert
+ verify(exactly = 1) { mockClickListener.invoke() }
+ }
@Test
- fun testShowBillingErrorPaymentButton() {
- // Arrange
- composeTestRule.setContentWithTheme {
- OutOfTimeScreen(
- uiState =
- OutOfTimeUiState(
- showSitePayment = true,
- billingPaymentState = PaymentState.Error.Billing
- ),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onPurchaseBillingProductClick = { _ -> }
- )
- }
+ fun testShowBillingErrorPaymentButton() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ OutOfTimeScreen(
+ uiState =
+ OutOfTimeUiState(
+ showSitePayment = true,
+ billingPaymentState = PaymentState.Error.Billing
+ ),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = { _ -> }
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Add 30 days time").assertExists()
- }
+ // Assert
+ onNodeWithText("Add 30 days time").assertExists()
+ }
@Test
- fun testShowBillingPaymentAvailable() {
- // Arrange
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.status } returns null
- composeTestRule.setContentWithTheme {
- OutOfTimeScreen(
- uiState =
- OutOfTimeUiState(
- showSitePayment = true,
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
- ),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onPurchaseBillingProductClick = { _ -> }
- )
- }
+ fun testShowBillingPaymentAvailable() =
+ composeExtension.use {
+ // Arrange
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.status } returns null
+ setContentWithTheme {
+ OutOfTimeScreen(
+ uiState =
+ OutOfTimeUiState(
+ showSitePayment = true,
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
+ ),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = { _ -> }
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Add 30 days time ($10)").assertExists()
- }
+ // Assert
+ onNodeWithText("Add 30 days time ($10)").assertExists()
+ }
@Test
- fun testShowPendingPayment() {
- // Arrange
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.status } returns PaymentStatus.PENDING
- composeTestRule.setContentWithTheme {
- OutOfTimeScreen(
- uiState =
- OutOfTimeUiState(
- showSitePayment = true,
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
- ),
- )
- }
+ fun testShowPendingPayment() =
+ composeExtension.use {
+ // Arrange
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.status } returns PaymentStatus.PENDING
+ setContentWithTheme {
+ OutOfTimeScreen(
+ uiState =
+ OutOfTimeUiState(
+ showSitePayment = true,
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
+ ),
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Google Play payment pending").assertExists()
- }
+ // Assert
+ onNodeWithText("Google Play payment pending").assertExists()
+ }
@Test
- fun testShowPendingPaymentInfoDialog() {
- // Arrange
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.status } returns PaymentStatus.PENDING
- val mockNavigateToVerificationPending: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- OutOfTimeScreen(
- uiState =
- OutOfTimeUiState(
- showSitePayment = true,
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
- ),
- navigateToVerificationPendingDialog = mockNavigateToVerificationPending
- )
- }
+ fun testShowPendingPaymentInfoDialog() =
+ composeExtension.use {
+ // Arrange
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.status } returns PaymentStatus.PENDING
+ val mockNavigateToVerificationPending: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ OutOfTimeScreen(
+ uiState =
+ OutOfTimeUiState(
+ showSitePayment = true,
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
+ ),
+ navigateToVerificationPendingDialog = mockNavigateToVerificationPending
+ )
+ }
- // Act
- composeTestRule.onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).performClick()
- composeTestRule.onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).assertExists()
+ // Act
+ onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).performClick()
+ onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).assertExists()
- verify(exactly = 1) { mockNavigateToVerificationPending.invoke() }
- }
+ // Assert
+ verify(exactly = 1) { mockNavigateToVerificationPending.invoke() }
+ }
@Test
- fun testShowVerificationInProgress() {
- // Arrange
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.status } returns PaymentStatus.VERIFICATION_IN_PROGRESS
- composeTestRule.setContentWithTheme {
- OutOfTimeScreen(
- uiState =
- OutOfTimeUiState(
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct)),
- showSitePayment = true,
- )
- )
- }
+ fun testShowVerificationInProgress() =
+ composeExtension.use {
+ // Arrange
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.status } returns PaymentStatus.VERIFICATION_IN_PROGRESS
+ setContentWithTheme {
+ OutOfTimeScreen(
+ uiState =
+ OutOfTimeUiState(
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct)),
+ showSitePayment = true,
+ )
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Verifying purchase").assertExists()
- }
+ // Assert
+ onNodeWithText("Verifying purchase").assertExists()
+ }
@Test
- fun testOnPurchaseBillingProductClick() {
- // Arrange
- val clickHandler: (ProductId) -> Unit = mockk(relaxed = true)
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.productId } returns ProductId("PRODUCT_ID")
- every { mockPaymentProduct.status } returns null
- composeTestRule.setContentWithTheme {
- OutOfTimeScreen(
- uiState =
- OutOfTimeUiState(
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct)),
- showSitePayment = true,
- ),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onPurchaseBillingProductClick = clickHandler
- )
- }
+ fun testOnPurchaseBillingProductClick() =
+ composeExtension.use {
+ // Arrange
+ val clickHandler: (ProductId) -> Unit = mockk(relaxed = true)
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.productId } returns ProductId("PRODUCT_ID")
+ every { mockPaymentProduct.status } returns null
+ setContentWithTheme {
+ OutOfTimeScreen(
+ uiState =
+ OutOfTimeUiState(
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct)),
+ showSitePayment = true,
+ ),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = clickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithText("Add 30 days time ($10)").performClick()
+ // Act
+ onNodeWithText("Add 30 days time ($10)").performClick()
- // Assert
- verify { clickHandler(ProductId("PRODUCT_ID")) }
- }
+ // Assert
+ verify { clickHandler(ProductId("PRODUCT_ID")) }
+ }
}
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/RedeemVoucherDialogTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/RedeemVoucherDialogTest.kt
index 5a51a8f885..9a2a9ce86d 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/RedeemVoucherDialogTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/RedeemVoucherDialogTest.kt
@@ -1,10 +1,11 @@
package net.mullvad.mullvadvpn.compose.screen
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.mockk
import io.mockk.mockkObject
import io.mockk.verify
@@ -14,131 +15,138 @@ import net.mullvad.mullvadvpn.compose.state.VoucherDialogState
import net.mullvad.mullvadvpn.compose.state.VoucherDialogUiState
import net.mullvad.mullvadvpn.compose.test.VOUCHER_INPUT_TEST_TAG
import net.mullvad.mullvadvpn.util.VoucherRegexHelper
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
+@OptIn(ExperimentalTestApi::class)
class RedeemVoucherDialogTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @JvmField @RegisterExtension val composeExtension = createComposeExtension()
- @Before
+ @BeforeEach
fun setup() {
mockkObject(VoucherRegexHelper)
}
@Test
- fun testDismissDialog() {
- // Arrange
- val mockedClickHandler: (Boolean) -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- RedeemVoucherDialog(
- uiState = VoucherDialogUiState.INITIAL,
- onVoucherInputChange = {},
- onRedeem = {},
- onDismiss = mockedClickHandler
- )
- }
+ fun testDismissDialog() =
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: (Boolean) -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ RedeemVoucherDialog(
+ uiState = VoucherDialogUiState.INITIAL,
+ onVoucherInputChange = {},
+ onRedeem = {},
+ onDismiss = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithText(CANCEL_BUTTON_TEXT).performClick()
+ // Act
+ onNodeWithText(CANCEL_BUTTON_TEXT).performClick()
- // Assert
- verify { mockedClickHandler.invoke(false) }
- }
+ // Assert
+ verify { mockedClickHandler.invoke(false) }
+ }
@Test
- fun testDismissDialogAfterSuccessfulRedeem() {
- // Arrange
- val mockedClickHandler: (Boolean) -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- RedeemVoucherDialog(
- uiState =
- VoucherDialogUiState(voucherViewModelState = VoucherDialogState.Success(0)),
- onVoucherInputChange = {},
- onRedeem = {},
- onDismiss = mockedClickHandler
- )
- }
+ fun testDismissDialogAfterSuccessfulRedeem() =
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: (Boolean) -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ RedeemVoucherDialog(
+ uiState =
+ VoucherDialogUiState(voucherViewModelState = VoucherDialogState.Success(0)),
+ onVoucherInputChange = {},
+ onRedeem = {},
+ onDismiss = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithText(GOT_IT_BUTTON_TEXT).performClick()
+ // Act
+ onNodeWithText(GOT_IT_BUTTON_TEXT).performClick()
- // Assert
- verify { mockedClickHandler.invoke(true) }
- }
+ // Assert
+ verify { mockedClickHandler.invoke(true) }
+ }
@Test
- fun testInsertVoucher() {
- // Arrange
- val mockedClickHandler: (String) -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- RedeemVoucherDialog(
- uiState = VoucherDialogUiState(),
- onVoucherInputChange = mockedClickHandler,
- onRedeem = {},
- onDismiss = {}
- )
- }
+ fun testInsertVoucher() =
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: (String) -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ RedeemVoucherDialog(
+ uiState = VoucherDialogUiState(),
+ onVoucherInputChange = mockedClickHandler,
+ onRedeem = {},
+ onDismiss = {}
+ )
+ }
- // Act
- composeTestRule.onNodeWithTag(VOUCHER_INPUT_TEST_TAG).performTextInput(DUMMY_VOUCHER)
+ // Act
+ onNodeWithTag(VOUCHER_INPUT_TEST_TAG).performTextInput(DUMMY_VOUCHER)
- // Assert
- verify { mockedClickHandler.invoke(DUMMY_VOUCHER) }
- }
+ // Assert
+ verify { mockedClickHandler.invoke(DUMMY_VOUCHER) }
+ }
@Test
- fun testVerifyingState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- RedeemVoucherDialog(
- uiState =
- VoucherDialogUiState(voucherViewModelState = VoucherDialogState.Verifying),
- onVoucherInputChange = {},
- onRedeem = {},
- onDismiss = {}
- )
- }
+ fun testVerifyingState() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ RedeemVoucherDialog(
+ uiState =
+ VoucherDialogUiState(voucherViewModelState = VoucherDialogState.Verifying),
+ onVoucherInputChange = {},
+ onRedeem = {},
+ onDismiss = {}
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Verifying voucher…").assertExists()
- }
+ // Assert
+ onNodeWithText("Verifying voucher…").assertExists()
+ }
@Test
- fun testSuccessState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- RedeemVoucherDialog(
- uiState =
- VoucherDialogUiState(voucherViewModelState = VoucherDialogState.Success(0)),
- onVoucherInputChange = {},
- onRedeem = {},
- onDismiss = {}
- )
- }
+ fun testSuccessState() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ RedeemVoucherDialog(
+ uiState =
+ VoucherDialogUiState(voucherViewModelState = VoucherDialogState.Success(0)),
+ onVoucherInputChange = {},
+ onRedeem = {},
+ onDismiss = {}
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Voucher was successfully redeemed.").assertExists()
- }
+ // Assert
+ onNodeWithText("Voucher was successfully redeemed.").assertExists()
+ }
@Test
- fun testErrorState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- RedeemVoucherDialog(
- uiState =
- VoucherDialogUiState(
- voucherViewModelState = VoucherDialogState.Error(ERROR_MESSAGE)
- ),
- onVoucherInputChange = {},
- onRedeem = {},
- onDismiss = {}
- )
- }
+ fun testErrorState() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ RedeemVoucherDialog(
+ uiState =
+ VoucherDialogUiState(
+ voucherViewModelState = VoucherDialogState.Error(ERROR_MESSAGE)
+ ),
+ onVoucherInputChange = {},
+ onRedeem = {},
+ onDismiss = {}
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText(ERROR_MESSAGE).assertExists()
- }
+ // Assert
+ onNodeWithText(ERROR_MESSAGE).assertExists()
+ }
companion object {
private const val REDEEM_BUTTON_TEXT = "Redeem"
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreenTest.kt
index ea1d261689..fbc8b046fd 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreenTest.kt
@@ -1,9 +1,10 @@
package net.mullvad.mullvadvpn.compose.screen
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performTextInput
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import io.mockk.mockk
import io.mockk.verify
@@ -19,49 +20,51 @@ import net.mullvad.mullvadvpn.model.RelayListCountry
import net.mullvad.mullvadvpn.model.WireguardEndpointData
import net.mullvad.mullvadvpn.model.WireguardRelayEndpointData
import net.mullvad.mullvadvpn.relaylist.toRelayCountries
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
+@OptIn(ExperimentalTestApi::class)
class SelectLocationScreenTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @JvmField @RegisterExtension val composeExtension = createComposeExtension()
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
}
@Test
- fun testDefaultState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- SelectLocationScreen(
- uiState = SelectLocationUiState.Loading,
- )
- }
+ fun testDefaultState() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ SelectLocationScreen(
+ uiState = SelectLocationUiState.Loading,
+ )
+ }
- // Assert
- composeTestRule.apply { onNodeWithTag(CIRCULAR_PROGRESS_INDICATOR).assertExists() }
- }
+ // Assert
+ onNodeWithTag(CIRCULAR_PROGRESS_INDICATOR).assertExists()
+ }
@Test
- fun testShowRelayListState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- SelectLocationScreen(
- uiState =
- SelectLocationUiState.ShowData(
- countries = DUMMY_RELAY_COUNTRIES,
- selectedRelay = null,
- selectedOwnership = null,
- selectedProvidersCount = 0,
- searchTerm = ""
- ),
- )
- }
+ fun testShowRelayListState() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ SelectLocationScreen(
+ uiState =
+ SelectLocationUiState.ShowData(
+ countries = DUMMY_RELAY_COUNTRIES,
+ selectedRelay = null,
+ selectedOwnership = null,
+ selectedProvidersCount = 0,
+ searchTerm = ""
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("Relay Country 1").assertExists()
onNodeWithText("Relay City 1").assertDoesNotExist()
onNodeWithText("Relay host 1").assertDoesNotExist()
@@ -69,37 +72,36 @@ class SelectLocationScreenTest {
onNodeWithText("Relay City 2").assertDoesNotExist()
onNodeWithText("Relay host 2").assertDoesNotExist()
}
- }
@Test
- fun testShowRelayListStateSelected() {
- val updatedDummyList =
- DUMMY_RELAY_COUNTRIES.let {
- val cities = it[0].cities.toMutableList()
- val city = cities.removeAt(0)
- cities.add(0, city.copy(expanded = true))
+ fun testShowRelayListStateSelected() =
+ composeExtension.use {
+ val updatedDummyList =
+ DUMMY_RELAY_COUNTRIES.let {
+ val cities = it[0].cities.toMutableList()
+ val city = cities.removeAt(0)
+ cities.add(0, city.copy(expanded = true))
- val mutableRelayList = it.toMutableList()
- mutableRelayList[0] = it[0].copy(expanded = true, cities = cities.toList())
- mutableRelayList
- }
+ val mutableRelayList = it.toMutableList()
+ mutableRelayList[0] = it[0].copy(expanded = true, cities = cities.toList())
+ mutableRelayList
+ }
- // Arrange
- composeTestRule.setContentWithTheme {
- SelectLocationScreen(
- uiState =
- SelectLocationUiState.ShowData(
- countries = updatedDummyList,
- selectedRelay = updatedDummyList[0].cities[0].relays[0],
- selectedOwnership = null,
- selectedProvidersCount = 0,
- searchTerm = ""
- ),
- )
- }
+ // Arrange
+ setContentWithTheme {
+ SelectLocationScreen(
+ uiState =
+ SelectLocationUiState.ShowData(
+ countries = updatedDummyList,
+ selectedRelay = updatedDummyList[0].cities[0].relays[0],
+ selectedOwnership = null,
+ selectedProvidersCount = 0,
+ searchTerm = ""
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("Relay Country 1").assertExists()
onNodeWithText("Relay City 1").assertExists()
onNodeWithText("Relay host 1").assertExists()
@@ -107,59 +109,58 @@ class SelectLocationScreenTest {
onNodeWithText("Relay City 2").assertDoesNotExist()
onNodeWithText("Relay host 2").assertDoesNotExist()
}
- }
@Test
- fun testSearchInput() {
- // Arrange
- val mockedSearchTermInput: (String) -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- SelectLocationScreen(
- uiState =
- SelectLocationUiState.ShowData(
- countries = emptyList(),
- selectedRelay = null,
- selectedOwnership = null,
- selectedProvidersCount = 0,
- searchTerm = ""
- ),
- onSearchTermInput = mockedSearchTermInput
- )
- }
- val mockSearchString = "SEARCH"
+ fun testSearchInput() =
+ composeExtension.use {
+ // Arrange
+ val mockedSearchTermInput: (String) -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ SelectLocationScreen(
+ uiState =
+ SelectLocationUiState.ShowData(
+ countries = emptyList(),
+ selectedRelay = null,
+ selectedOwnership = null,
+ selectedProvidersCount = 0,
+ searchTerm = ""
+ ),
+ onSearchTermInput = mockedSearchTermInput
+ )
+ }
+ val mockSearchString = "SEARCH"
- // Act
- composeTestRule.apply { onNodeWithText("Search for...").performTextInput(mockSearchString) }
+ // Act
+ onNodeWithText("Search for...").performTextInput(mockSearchString)
- // Assert
- verify { mockedSearchTermInput.invoke(mockSearchString) }
- }
+ // Assert
+ verify { mockedSearchTermInput.invoke(mockSearchString) }
+ }
@Test
- fun testSearchTermNotFound() {
- // Arrange
- val mockedSearchTermInput: (String) -> Unit = mockk(relaxed = true)
- val mockSearchString = "SEARCH"
- composeTestRule.setContentWithTheme {
- SelectLocationScreen(
- uiState =
- SelectLocationUiState.ShowData(
- countries = emptyList(),
- selectedRelay = null,
- selectedOwnership = null,
- selectedProvidersCount = 0,
- searchTerm = mockSearchString
- ),
- onSearchTermInput = mockedSearchTermInput
- )
- }
+ fun testSearchTermNotFound() =
+ composeExtension.use {
+ // Arrange
+ val mockedSearchTermInput: (String) -> Unit = mockk(relaxed = true)
+ val mockSearchString = "SEARCH"
+ setContentWithTheme {
+ SelectLocationScreen(
+ uiState =
+ SelectLocationUiState.ShowData(
+ countries = emptyList(),
+ selectedRelay = null,
+ selectedOwnership = null,
+ selectedProvidersCount = 0,
+ searchTerm = mockSearchString
+ ),
+ onSearchTermInput = mockedSearchTermInput
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("No result for $mockSearchString.", substring = true).assertExists()
onNodeWithText("Try a different search", substring = true).assertExists()
}
- }
companion object {
private val DUMMY_RELAY_1 =
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt
index f5daf29bb2..1c47082b14 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt
@@ -1,66 +1,66 @@
package net.mullvad.mullvadvpn.compose.screen
import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithText
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.compose.state.SettingsUiState
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
+@OptIn(ExperimentalTestApi::class)
class SettingsScreenTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @JvmField @RegisterExtension val composeExtension = createComposeExtension()
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
}
@Test
@OptIn(ExperimentalMaterial3Api::class)
- fun testLoggedInState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- SettingsScreen(
- uiState =
- SettingsUiState(
- appVersion = "",
- isLoggedIn = true,
- isUpdateAvailable = true,
- isPlayBuild = false
- ),
- )
- }
- // Assert
- composeTestRule.apply {
+ fun testLoggedInState() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ SettingsScreen(
+ uiState =
+ SettingsUiState(
+ appVersion = "",
+ isLoggedIn = true,
+ isUpdateAvailable = true,
+ isPlayBuild = false
+ ),
+ )
+ }
+ // Assert
onNodeWithText("VPN settings").assertExists()
onNodeWithText("Split tunneling").assertExists()
onNodeWithText("App version").assertExists()
}
- }
@Test
@OptIn(ExperimentalMaterial3Api::class)
- fun testLoggedOutState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- SettingsScreen(
- uiState =
- SettingsUiState(
- appVersion = "",
- isLoggedIn = false,
- isUpdateAvailable = true,
- isPlayBuild = false
- ),
- )
- }
- // Assert
- composeTestRule.apply {
+ fun testLoggedOutState() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ SettingsScreen(
+ uiState =
+ SettingsUiState(
+ appVersion = "",
+ isLoggedIn = false,
+ isUpdateAvailable = true,
+ isPlayBuild = false
+ ),
+ )
+ }
+ // Assert
onNodeWithText("VPN settings").assertDoesNotExist()
onNodeWithText("Split tunneling").assertDoesNotExist()
onNodeWithText("App version").assertExists()
}
- }
}
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreenTest.kt
index 7f4ee36d47..dc1362ad37 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SplitTunnelingScreenTest.kt
@@ -1,9 +1,10 @@
package net.mullvad.mullvadvpn.compose.screen
import android.graphics.Bitmap
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.mockk
@@ -14,15 +15,16 @@ import net.mullvad.mullvadvpn.applist.ApplicationsIconManager
import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.compose.state.SplitTunnelingUiState
import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
import org.koin.core.context.loadKoinModules
import org.koin.core.context.unloadKoinModules
import org.koin.dsl.module
+@OptIn(ExperimentalTestApi::class)
class SplitTunnelingScreenTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @JvmField @RegisterExtension val composeExtension = createComposeExtension()
private val mockBitmap: Bitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
private val testModule = module {
@@ -33,7 +35,7 @@ class SplitTunnelingScreenTest {
}
}
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
loadKoinModules(testModule)
@@ -46,42 +48,47 @@ class SplitTunnelingScreenTest {
}
@Test
- fun testLoadingState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- SplitTunnelingScreen(uiState = SplitTunnelingUiState.Loading)
- }
+ fun testLoadingState() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme { SplitTunnelingScreen(uiState = SplitTunnelingUiState.Loading) }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText(TITLE).assertExists()
onNodeWithText(DESCRIPTION).assertExists()
onNodeWithText(EXCLUDED_APPLICATIONS).assertDoesNotExist()
onNodeWithText(SHOW_SYSTEM_APPS).assertDoesNotExist()
onNodeWithText(ALL_APPLICATIONS).assertDoesNotExist()
}
- }
@Test
- fun testListDisplayed() {
- // Arrange
- val excludedApp =
- AppData(packageName = EXCLUDED_APP_PACKAGE_NAME, iconRes = 0, name = EXCLUDED_APP_NAME)
- val includedApp =
- AppData(packageName = INCLUDED_APP_PACKAGE_NAME, iconRes = 0, name = INCLUDED_APP_NAME)
- composeTestRule.setContentWithTheme {
- SplitTunnelingScreen(
- uiState =
- SplitTunnelingUiState.ShowAppList(
- excludedApps = listOf(excludedApp),
- includedApps = listOf(includedApp),
- showSystemApps = false
- )
- )
- }
+ fun testListDisplayed() =
+ composeExtension.use {
+ // Arrange
+ val excludedApp =
+ AppData(
+ packageName = EXCLUDED_APP_PACKAGE_NAME,
+ iconRes = 0,
+ name = EXCLUDED_APP_NAME
+ )
+ val includedApp =
+ AppData(
+ packageName = INCLUDED_APP_PACKAGE_NAME,
+ iconRes = 0,
+ name = INCLUDED_APP_NAME
+ )
+ setContentWithTheme {
+ SplitTunnelingScreen(
+ uiState =
+ SplitTunnelingUiState.ShowAppList(
+ excludedApps = listOf(excludedApp),
+ includedApps = listOf(includedApp),
+ showSystemApps = false
+ )
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText(TITLE).assertExists()
onNodeWithText(DESCRIPTION).assertExists()
onNodeWithText(EXCLUDED_APPLICATIONS).assertExists()
@@ -90,26 +97,29 @@ class SplitTunnelingScreenTest {
onNodeWithText(ALL_APPLICATIONS).assertExists()
onNodeWithText(INCLUDED_APP_NAME).assertExists()
}
- }
@Test
- fun testNoExcludedApps() {
- // Arrange
- val includedApp =
- AppData(packageName = INCLUDED_APP_PACKAGE_NAME, iconRes = 0, name = INCLUDED_APP_NAME)
- composeTestRule.setContentWithTheme {
- SplitTunnelingScreen(
- uiState =
- SplitTunnelingUiState.ShowAppList(
- excludedApps = emptyList(),
- includedApps = listOf(includedApp),
- showSystemApps = false
- )
- )
- }
+ fun testNoExcludedApps() =
+ composeExtension.use {
+ // Arrange
+ val includedApp =
+ AppData(
+ packageName = INCLUDED_APP_PACKAGE_NAME,
+ iconRes = 0,
+ name = INCLUDED_APP_NAME
+ )
+ setContentWithTheme {
+ SplitTunnelingScreen(
+ uiState =
+ SplitTunnelingUiState.ShowAppList(
+ excludedApps = emptyList(),
+ includedApps = listOf(includedApp),
+ showSystemApps = false
+ )
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText(TITLE).assertExists()
onNodeWithText(DESCRIPTION).assertExists()
onNodeWithText(EXCLUDED_APPLICATIONS).assertDoesNotExist()
@@ -118,88 +128,114 @@ class SplitTunnelingScreenTest {
onNodeWithText(ALL_APPLICATIONS).assertExists()
onNodeWithText(INCLUDED_APP_NAME).assertExists()
}
- }
@Test
- fun testClickIncludedItem() {
- // Arrange
- val excludedApp =
- AppData(packageName = EXCLUDED_APP_PACKAGE_NAME, iconRes = 0, name = EXCLUDED_APP_NAME)
- val includedApp =
- AppData(packageName = INCLUDED_APP_PACKAGE_NAME, iconRes = 0, name = INCLUDED_APP_NAME)
- val mockedClickHandler: (String) -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- SplitTunnelingScreen(
- uiState =
- SplitTunnelingUiState.ShowAppList(
- excludedApps = listOf(excludedApp),
- includedApps = listOf(includedApp),
- showSystemApps = false
- ),
- onExcludeAppClick = mockedClickHandler
- )
- }
+ fun testClickIncludedItem() =
+ composeExtension.use {
+ // Arrange
+ val excludedApp =
+ AppData(
+ packageName = EXCLUDED_APP_PACKAGE_NAME,
+ iconRes = 0,
+ name = EXCLUDED_APP_NAME
+ )
+ val includedApp =
+ AppData(
+ packageName = INCLUDED_APP_PACKAGE_NAME,
+ iconRes = 0,
+ name = INCLUDED_APP_NAME
+ )
+ val mockedClickHandler: (String) -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ SplitTunnelingScreen(
+ uiState =
+ SplitTunnelingUiState.ShowAppList(
+ excludedApps = listOf(excludedApp),
+ includedApps = listOf(includedApp),
+ showSystemApps = false
+ ),
+ onExcludeAppClick = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithText(INCLUDED_APP_NAME).performClick()
+ // Act
+ onNodeWithText(INCLUDED_APP_NAME).performClick()
- // Assert
- verify { mockedClickHandler.invoke(INCLUDED_APP_PACKAGE_NAME) }
- }
+ // Assert
+ verify { mockedClickHandler.invoke(INCLUDED_APP_PACKAGE_NAME) }
+ }
@Test
- fun testClickExcludedItem() {
- // Arrange
- val excludedApp =
- AppData(packageName = EXCLUDED_APP_PACKAGE_NAME, iconRes = 0, name = EXCLUDED_APP_NAME)
- val includedApp =
- AppData(packageName = INCLUDED_APP_PACKAGE_NAME, iconRes = 0, name = INCLUDED_APP_NAME)
- val mockedClickHandler: (String) -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- SplitTunnelingScreen(
- uiState =
- SplitTunnelingUiState.ShowAppList(
- excludedApps = listOf(excludedApp),
- includedApps = listOf(includedApp),
- showSystemApps = false
- ),
- onIncludeAppClick = mockedClickHandler
- )
- }
+ fun testClickExcludedItem() =
+ composeExtension.use {
+ // Arrange
+ val excludedApp =
+ AppData(
+ packageName = EXCLUDED_APP_PACKAGE_NAME,
+ iconRes = 0,
+ name = EXCLUDED_APP_NAME
+ )
+ val includedApp =
+ AppData(
+ packageName = INCLUDED_APP_PACKAGE_NAME,
+ iconRes = 0,
+ name = INCLUDED_APP_NAME
+ )
+ val mockedClickHandler: (String) -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ SplitTunnelingScreen(
+ uiState =
+ SplitTunnelingUiState.ShowAppList(
+ excludedApps = listOf(excludedApp),
+ includedApps = listOf(includedApp),
+ showSystemApps = false
+ ),
+ onIncludeAppClick = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithText(EXCLUDED_APP_NAME).performClick()
+ // Act
+ onNodeWithText(EXCLUDED_APP_NAME).performClick()
- // Assert
- verify { mockedClickHandler.invoke(EXCLUDED_APP_PACKAGE_NAME) }
- }
+ // Assert
+ verify { mockedClickHandler.invoke(EXCLUDED_APP_PACKAGE_NAME) }
+ }
@Test
- fun testClickShowSystemApps() {
- // Arrange
- val excludedApp =
- AppData(packageName = EXCLUDED_APP_PACKAGE_NAME, iconRes = 0, name = EXCLUDED_APP_NAME)
- val includedApp =
- AppData(packageName = INCLUDED_APP_PACKAGE_NAME, iconRes = 0, name = INCLUDED_APP_NAME)
- val mockedClickHandler: (Boolean) -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- SplitTunnelingScreen(
- uiState =
- SplitTunnelingUiState.ShowAppList(
- excludedApps = listOf(excludedApp),
- includedApps = listOf(includedApp),
- showSystemApps = false
- ),
- onShowSystemAppsClick = mockedClickHandler
- )
- }
+ fun testClickShowSystemApps() =
+ composeExtension.use {
+ // Arrange
+ val excludedApp =
+ AppData(
+ packageName = EXCLUDED_APP_PACKAGE_NAME,
+ iconRes = 0,
+ name = EXCLUDED_APP_NAME
+ )
+ val includedApp =
+ AppData(
+ packageName = INCLUDED_APP_PACKAGE_NAME,
+ iconRes = 0,
+ name = INCLUDED_APP_NAME
+ )
+ val mockedClickHandler: (Boolean) -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ SplitTunnelingScreen(
+ uiState =
+ SplitTunnelingUiState.ShowAppList(
+ excludedApps = listOf(excludedApp),
+ includedApps = listOf(includedApp),
+ showSystemApps = false
+ ),
+ onShowSystemAppsClick = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithText(SHOW_SYSTEM_APPS).performClick()
+ // Act
+ onNodeWithText(SHOW_SYSTEM_APPS).performClick()
- // Assert
- verify { mockedClickHandler.invoke(true) }
- }
+ // Assert
+ verify { mockedClickHandler.invoke(true) }
+ }
companion object {
private const val EXCLUDED_APP_PACKAGE_NAME = "excluded-pkg"
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt
index 1ca2b3e1f7..74c73553b2 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/VpnSettingsScreenTest.kt
@@ -1,12 +1,13 @@
package net.mullvad.mullvadvpn.compose.screen
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.hasTestTag
-import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollToNode
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import io.mockk.mockk
import io.mockk.verify
@@ -25,483 +26,483 @@ import net.mullvad.mullvadvpn.model.PortRange
import net.mullvad.mullvadvpn.model.QuantumResistantState
import net.mullvad.mullvadvpn.onNodeWithTagAndText
import net.mullvad.mullvadvpn.viewmodel.CustomDnsItem
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
+@OptIn(ExperimentalTestApi::class)
class VpnSettingsScreenTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @JvmField @RegisterExtension val composeExtension = createComposeExtension()
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
}
@Test
- fun testDefaultState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState = VpnSettingsUiState.createDefault(),
- )
- }
+ fun testDefaultState() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState = VpnSettingsUiState.createDefault(),
+ )
+ }
- composeTestRule.apply { onNodeWithText("Auto-connect").assertExists() }
+ apply { onNodeWithText("Auto-connect").assertExists() }
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
- // Assert
- composeTestRule.apply {
- onNodeWithText("WireGuard MTU").assertExists()
- onNodeWithText("Default").assertExists()
+ // Assert
+ apply {
+ onNodeWithText("WireGuard MTU").assertExists()
+ onNodeWithText("Default").assertExists()
+ }
}
- }
@Test
- fun testMtuCustomValue() {
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState = VpnSettingsUiState.createDefault(mtu = VALID_DUMMY_MTU_VALUE),
- )
- }
+ fun testMtuCustomValue() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState = VpnSettingsUiState.createDefault(mtu = VALID_DUMMY_MTU_VALUE),
+ )
+ }
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
- // Assert
- composeTestRule.onNodeWithText(VALID_DUMMY_MTU_VALUE).assertExists()
- }
+ // Assert
+ onNodeWithText(VALID_DUMMY_MTU_VALUE).assertExists()
+ }
@Test
- fun testCustomDnsAddressesAndAddButtonVisibleWhenCustomDnsEnabled() {
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(
- isCustomDnsEnabled = true,
- customDnsItems =
- listOf(
- CustomDnsItem(address = DUMMY_DNS_ADDRESS, false),
- CustomDnsItem(address = DUMMY_DNS_ADDRESS_2, false),
- CustomDnsItem(address = DUMMY_DNS_ADDRESS_3, false)
- )
- ),
- )
- }
+ fun testCustomDnsAddressesAndAddButtonVisibleWhenCustomDnsEnabled() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ isCustomDnsEnabled = true,
+ customDnsItems =
+ listOf(
+ CustomDnsItem(address = DUMMY_DNS_ADDRESS, false),
+ CustomDnsItem(address = DUMMY_DNS_ADDRESS_2, false),
+ CustomDnsItem(address = DUMMY_DNS_ADDRESS_3, false)
+ )
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText(DUMMY_DNS_ADDRESS).assertExists()
onNodeWithText(DUMMY_DNS_ADDRESS_2).assertExists()
onNodeWithText(DUMMY_DNS_ADDRESS_3).assertExists()
onNodeWithText("Add a server").assertExists()
}
- }
@Test
- fun testCustomDnsAddressesAndAddButtonNotVisibleWhenCustomDnsDisabled() {
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(
- isCustomDnsEnabled = false,
- customDnsItems = listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, false))
- ),
- )
+ fun testCustomDnsAddressesAndAddButtonNotVisibleWhenCustomDnsDisabled() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ isCustomDnsEnabled = false,
+ customDnsItems =
+ listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, false))
+ ),
+ )
+ }
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
+ // Assert
+ onNodeWithText(DUMMY_DNS_ADDRESS).assertDoesNotExist()
+ onNodeWithText("Add a server").assertDoesNotExist()
}
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
- // Assert
- composeTestRule.onNodeWithText(DUMMY_DNS_ADDRESS).assertDoesNotExist()
- composeTestRule.onNodeWithText("Add a server").assertDoesNotExist()
- }
@Test
- fun testLanWarningNotShownWhenLanTrafficEnabledAndLocalAddressIsUsed() {
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(
- isCustomDnsEnabled = true,
- isLocalNetworkSharingEnabled = true,
- customDnsItems =
- listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = true))
- ),
- )
- }
+ fun testLanWarningNotShownWhenLanTrafficEnabledAndLocalAddressIsUsed() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ isCustomDnsEnabled = true,
+ isLocalNetworkSharingEnabled = true,
+ customDnsItems =
+ listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = true))
+ ),
+ )
+ }
- // Assert
- composeTestRule.onNodeWithContentDescription(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist()
- }
+ // Assert
+ onNodeWithContentDescription(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist()
+ }
@Test
- fun testLanWarningNotShowedWhenLanTrafficDisabledAndLocalAddressIsNotUsed() {
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(
- isCustomDnsEnabled = true,
- customDnsItems =
- listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = false))
- ),
- )
- }
+ fun testLanWarningNotShowedWhenLanTrafficDisabledAndLocalAddressIsNotUsed() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ isCustomDnsEnabled = true,
+ customDnsItems =
+ listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = false))
+ ),
+ )
+ }
- // Assert
- composeTestRule.onNodeWithContentDescription(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist()
- }
+ // Assert
+ onNodeWithContentDescription(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist()
+ }
@Test
- fun testLanWarningNotShowedWhenLanTrafficEnabledAndLocalAddressIsNotUsed() {
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(
- isCustomDnsEnabled = true,
- customDnsItems =
- listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = false))
- ),
- )
- }
+ fun testLanWarningNotShowedWhenLanTrafficEnabledAndLocalAddressIsNotUsed() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ isCustomDnsEnabled = true,
+ customDnsItems =
+ listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = false))
+ ),
+ )
+ }
- // Assert
- composeTestRule.onNodeWithContentDescription(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist()
- }
+ // Assert
+ onNodeWithContentDescription(LOCAL_DNS_SERVER_WARNING).assertDoesNotExist()
+ }
@Test
- fun testLanWarningShowedWhenAllowLanEnabledAndLocalDnsAddressIsUsed() {
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(
- isCustomDnsEnabled = true,
- customDnsItems =
- listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = true))
- ),
- )
- }
+ fun testLanWarningShowedWhenAllowLanEnabledAndLocalDnsAddressIsUsed() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ isCustomDnsEnabled = true,
+ customDnsItems =
+ listOf(CustomDnsItem(address = DUMMY_DNS_ADDRESS, isLocal = true))
+ ),
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithContentDescription(LOCAL_DNS_SERVER_WARNING).assertExists()
}
- }
@Test
- fun testShowSelectedTunnelQuantumOption() {
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(quantumResistant = QuantumResistantState.On),
- )
- }
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(hasTestTag(LAZY_LIST_QUANTUM_ITEM_OFF_TEST_TAG))
+ fun testShowSelectedTunnelQuantumOption() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ quantumResistant = QuantumResistantState.On
+ ),
+ )
+ }
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_QUANTUM_ITEM_OFF_TEST_TAG))
- // Assert
- composeTestRule
- .onNodeWithTagAndText(testTag = LAZY_LIST_QUANTUM_ITEM_ON_TEST_TAG, text = "On")
- .assertExists()
- }
+ // Assert
+ onNodeWithTagAndText(testTag = LAZY_LIST_QUANTUM_ITEM_ON_TEST_TAG, text = "On")
+ .assertExists()
+ }
@Test
- fun testSelectTunnelQuantumOption() {
- // Arrange
- val mockSelectQuantumResistantSettingListener: (QuantumResistantState) -> Unit =
- mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(
- quantumResistant = QuantumResistantState.Auto,
- ),
- onSelectQuantumResistanceSetting = mockSelectQuantumResistantSettingListener
- )
- }
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(hasTestTag(LAZY_LIST_QUANTUM_ITEM_OFF_TEST_TAG))
+ fun testSelectTunnelQuantumOption() =
+ composeExtension.use {
+ // Arrange
+ val mockSelectQuantumResistantSettingListener: (QuantumResistantState) -> Unit =
+ mockk(relaxed = true)
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ quantumResistant = QuantumResistantState.Auto,
+ ),
+ onSelectQuantumResistanceSetting = mockSelectQuantumResistantSettingListener,
+ )
+ }
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_QUANTUM_ITEM_OFF_TEST_TAG))
- // Assert
- composeTestRule
- .onNodeWithTagAndText(testTag = LAZY_LIST_QUANTUM_ITEM_ON_TEST_TAG, text = "On")
- .performClick()
- verify(exactly = 1) {
- mockSelectQuantumResistantSettingListener.invoke(QuantumResistantState.On)
+ // Assert
+ onNodeWithTagAndText(testTag = LAZY_LIST_QUANTUM_ITEM_ON_TEST_TAG, text = "On")
+ .performClick()
+ verify(exactly = 1) {
+ mockSelectQuantumResistantSettingListener.invoke(QuantumResistantState.On)
+ }
}
- }
@Test
- fun testShowWireguardPortOptions() {
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(
- selectedWireguardPort = Constraint.Only(Port(53))
- ),
- )
- }
+ fun testShowWireguardPortOptions() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ selectedWireguardPort = Constraint.Only(Port(53))
+ ),
+ )
+ }
- // Act
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(
- hasTestTag(String.format(LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG, 53))
- )
+ // Act
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(
+ hasTestTag(String.format(LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG, 53))
+ )
- // Assert
- composeTestRule
- .onNodeWithTagAndText(
- testTag = String.format(LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG, 51820),
- text = "51820"
- )
- .assertExists()
- }
+ // Assert
+ onNodeWithTagAndText(
+ testTag = String.format(LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG, 51820),
+ text = "51820"
+ )
+ .assertExists()
+ }
@Test
- fun testSelectWireguardPortOption() {
- // Arrange
- val mockSelectWireguardPortSelectionListener: (Constraint<Port>) -> Unit =
- mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(
- selectedWireguardPort = Constraint.Only(Port(53))
- ),
- onWireguardPortSelected = mockSelectWireguardPortSelectionListener
- )
- }
+ fun testSelectWireguardPortOption() =
+ composeExtension.use {
+ // Arrange
+ val mockSelectWireguardPortSelectionListener: (Constraint<Port>) -> Unit =
+ mockk(relaxed = true)
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ selectedWireguardPort = Constraint.Only(Port(53))
+ ),
+ onWireguardPortSelected = mockSelectWireguardPortSelectionListener,
+ )
+ }
- // Act
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(
- hasTestTag(String.format(LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG, 53))
- )
- composeTestRule
- .onNodeWithTagAndText(
- testTag = String.format(LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG, 51820),
- text = "51820"
- )
- .performClick()
+ // Act
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(
+ hasTestTag(String.format(LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG, 53))
+ )
+ onNodeWithTagAndText(
+ testTag = String.format(LAZY_LIST_WIREGUARD_PORT_ITEM_X_TEST_TAG, 51820),
+ text = "51820"
+ )
+ .performClick()
- // Assert
- verify(exactly = 1) {
- mockSelectWireguardPortSelectionListener.invoke(Constraint.Only(Port(51820)))
+ // Assert
+ verify(exactly = 1) {
+ mockSelectWireguardPortSelectionListener.invoke(Constraint.Only(Port(51820)))
+ }
}
- }
@Test
- fun testShowWireguardCustomPort() {
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(
- customWireguardPort = Constraint.Only(Port(4000))
- ),
- )
- }
+ fun testShowWireguardCustomPort() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ customWireguardPort = Constraint.Only(Port(4000))
+ ),
+ )
+ }
- // Act
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG))
+ // Act
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG))
- // Assert
- composeTestRule.onNodeWithText("4000").assertExists()
- }
+ // Assert
+ onNodeWithText("4000").assertExists()
+ }
@Test
- fun testSelectWireguardCustomPort() {
- // Arrange
- val onWireguardPortSelected: (Constraint<Port>) -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(
- selectedWireguardPort = Constraint.Only(Port(4000)),
- customWireguardPort = Constraint.Only(Port(4000))
- ),
- onWireguardPortSelected = onWireguardPortSelected
- )
- }
+ fun testSelectWireguardCustomPort() =
+ composeExtension.use {
+ // Arrange
+ val onWireguardPortSelected: (Constraint<Port>) -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ selectedWireguardPort = Constraint.Only(Port(4000)),
+ customWireguardPort = Constraint.Only(Port(4000))
+ ),
+ onWireguardPortSelected = onWireguardPortSelected
+ )
+ }
- // Act
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG))
- composeTestRule
- .onNodeWithTag(testTag = LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG)
- .performClick()
+ // Act
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG))
+ onNodeWithTag(testTag = LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG).performClick()
- // Assert
- verify { onWireguardPortSelected.invoke(Constraint.Only(Port(4000))) }
- }
+ // Assert
+ verify { onWireguardPortSelected.invoke(Constraint.Only(Port(4000))) }
+ }
// Navigation Tests
@Test
- fun testMtuClick() {
- // Arrange
- val mockedClickHandler: (Int?) -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState = VpnSettingsUiState.createDefault(),
- navigateToMtuDialog = mockedClickHandler
- )
- }
+ fun testMtuClick() =
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: (Int?) -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState = VpnSettingsUiState.createDefault(),
+ navigateToMtuDialog = mockedClickHandler
+ )
+ }
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_LAST_ITEM_TEST_TAG))
- // Act
- composeTestRule.onNodeWithText("WireGuard MTU").performClick()
+ // Act
+ onNodeWithText("WireGuard MTU").performClick()
- // Assert
- verify { mockedClickHandler.invoke(null) }
- }
+ // Assert
+ verify { mockedClickHandler.invoke(null) }
+ }
@Test
- fun testClickAddDns() {
- // Arrange
- val mockedClickHandler: (Int?, String?) -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState = VpnSettingsUiState.createDefault(isCustomDnsEnabled = true),
- navigateToDns = mockedClickHandler
- )
- }
+ fun testClickAddDns() =
+ composeExtension.use {
+ // Arrange
+ val mockedClickHandler: (Int?, String?) -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState = VpnSettingsUiState.createDefault(isCustomDnsEnabled = true),
+ navigateToDns = mockedClickHandler
+ )
+ }
- // Act
- composeTestRule.onNodeWithText("Add a server").performClick()
+ // Act
+ onNodeWithText("Add a server").performClick()
- // Assert
- verify { mockedClickHandler.invoke(null, null) }
- }
+ // Assert
+ verify { mockedClickHandler.invoke(null, null) }
+ }
@Test
- fun testShowTunnelQuantumInfo() {
- val mockedShowTunnelQuantumInfoClick: () -> Unit = mockk(relaxed = true)
+ fun testShowTunnelQuantumInfo() =
+ composeExtension.use {
+ val mockedShowTunnelQuantumInfoClick: () -> Unit = mockk(relaxed = true)
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState = VpnSettingsUiState.createDefault(),
- navigateToQuantumResistanceInfo = mockedShowTunnelQuantumInfoClick
- )
- }
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState = VpnSettingsUiState.createDefault(),
+ navigateToQuantumResistanceInfo = mockedShowTunnelQuantumInfoClick
+ )
+ }
- // Act
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(hasTestTag(LAZY_LIST_QUANTUM_ITEM_ON_TEST_TAG))
- composeTestRule.onNodeWithText("Quantum-resistant tunnel").performClick()
+ // Act
- // Assert
- verify(exactly = 1) { mockedShowTunnelQuantumInfoClick() }
- }
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_QUANTUM_ITEM_ON_TEST_TAG))
+ onNodeWithText("Quantum-resistant tunnel").performClick()
+
+ // Assert
+ verify(exactly = 1) { mockedShowTunnelQuantumInfoClick() }
+ }
@Test
- fun testShowWireguardPortInfo() {
- val mockedClickHandler: (List<PortRange>) -> Unit = mockk(relaxed = true)
+ fun testShowWireguardPortInfo() =
+ composeExtension.use {
+ val mockedClickHandler: (List<PortRange>) -> Unit = mockk(relaxed = true)
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState = VpnSettingsUiState.createDefault(),
- navigateToWireguardPortInfo = mockedClickHandler
- )
- }
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState = VpnSettingsUiState.createDefault(),
+ navigateToWireguardPortInfo = mockedClickHandler
+ )
+ }
- composeTestRule.onNodeWithText("WireGuard port").performClick()
+ onNodeWithText("WireGuard port").performClick()
- verify(exactly = 1) { mockedClickHandler.invoke(any()) }
- }
+ verify(exactly = 1) { mockedClickHandler.invoke(any()) }
+ }
@Test
- fun testShowWireguardCustomPortDialog() {
- val mockedClickHandler: () -> Unit = mockk(relaxed = true)
+ fun testShowWireguardCustomPortDialog() =
+ composeExtension.use {
+ val mockedClickHandler: () -> Unit = mockk(relaxed = true)
- // Arrange
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState = VpnSettingsUiState.createDefault(),
- navigateToWireguardPortDialog = mockedClickHandler
- )
- }
+ // Arrange
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState = VpnSettingsUiState.createDefault(),
+ navigateToWireguardPortDialog = mockedClickHandler
+ )
+ }
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_NUMBER_TEST_TAG))
- composeTestRule.onNodeWithText("Custom").performClick()
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_NUMBER_TEST_TAG))
+ onNodeWithText("Custom").performClick()
- // Assert
- verify(exactly = 1) { mockedClickHandler.invoke() }
- }
+ // Assert
+ verify(exactly = 1) { mockedClickHandler.invoke() }
+ }
@Test
- fun testClickWireguardCustomPortMainCell() {
- // Arrange
- val mockOnShowCustomPortDialog: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState = VpnSettingsUiState.createDefault(),
- navigateToWireguardPortDialog = mockOnShowCustomPortDialog
- )
- }
+ fun testClickWireguardCustomPortMainCell() =
+ composeExtension.use {
+ // Arrange
+ val mockOnShowCustomPortDialog: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState = VpnSettingsUiState.createDefault(),
+ navigateToWireguardPortDialog = mockOnShowCustomPortDialog
+ )
+ }
- // Act
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG))
- composeTestRule.onNodeWithTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG).performClick()
+ // Act
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG))
+ onNodeWithTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG).performClick()
- // Assert
- verify { mockOnShowCustomPortDialog.invoke() }
- }
+ // Assert
+ verify { mockOnShowCustomPortDialog.invoke() }
+ }
@Test
- fun testClickWireguardCustomPortNumberCell() {
- // Arrange
- val mockOnShowCustomPortDialog: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- VpnSettingsScreen(
- uiState =
- VpnSettingsUiState.createDefault(
- selectedWireguardPort = Constraint.Only(Port(4000))
- ),
- navigateToWireguardPortDialog = mockOnShowCustomPortDialog
- )
- }
+ fun testClickWireguardCustomPortNumberCell() =
+ composeExtension.use {
+ // Arrange
+ val mockOnShowCustomPortDialog: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ VpnSettingsScreen(
+ uiState =
+ VpnSettingsUiState.createDefault(
+ selectedWireguardPort = Constraint.Only(Port(4000))
+ ),
+ navigateToWireguardPortDialog = mockOnShowCustomPortDialog
+ )
+ }
- // Act
- composeTestRule
- .onNodeWithTag(LAZY_LIST_TEST_TAG)
- .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG))
- composeTestRule
- .onNodeWithTag(testTag = LAZY_LIST_WIREGUARD_CUSTOM_PORT_NUMBER_TEST_TAG)
- .performClick()
+ // Act
+ onNodeWithTag(LAZY_LIST_TEST_TAG)
+ .performScrollToNode(hasTestTag(LAZY_LIST_WIREGUARD_CUSTOM_PORT_TEXT_TEST_TAG))
+ onNodeWithTag(testTag = LAZY_LIST_WIREGUARD_CUSTOM_PORT_NUMBER_TEST_TAG).performClick()
- // Assert
- verify { mockOnShowCustomPortDialog.invoke() }
- }
+ // Assert
+ verify { mockOnShowCustomPortDialog.invoke() }
+ }
companion object {
private const val LOCAL_DNS_SERVER_WARNING =
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt
index e62b1a399b..b1c9e5f817 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt
+++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt
@@ -1,9 +1,10 @@
package net.mullvad.mullvadvpn.compose.screen
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
+import de.mannodermaus.junit5.compose.createComposeExtension
import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.mockk
@@ -16,59 +17,59 @@ import net.mullvad.mullvadvpn.lib.payment.model.PaymentProduct
import net.mullvad.mullvadvpn.lib.payment.model.PaymentStatus
import net.mullvad.mullvadvpn.lib.payment.model.ProductId
import net.mullvad.mullvadvpn.lib.payment.model.ProductPrice
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
+@OptIn(ExperimentalTestApi::class)
class WelcomeScreenTest {
- @get:Rule val composeTestRule = createComposeRule()
+ @JvmField @RegisterExtension val composeExtension = createComposeExtension()
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
}
@Test
- fun testDefaultState() {
- // Arrange
- composeTestRule.setContentWithTheme {
- WelcomeScreen(
- uiState = WelcomeUiState(),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- navigateToDeviceInfoDialog = {},
- onPurchaseBillingProductClick = { _ -> },
- navigateToVerificationPendingDialog = {}
- )
- }
+ fun testDefaultState() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ WelcomeScreen(
+ uiState = WelcomeUiState(),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = { _ -> },
+ navigateToDeviceInfoDialog = {},
+ navigateToVerificationPendingDialog = {}
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText("Congrats!").assertExists()
onNodeWithText("Here’s your account number. Save it!").assertExists()
}
- }
@Test
- fun testDisableSitePayment() {
- // Arrange
- composeTestRule.setContentWithTheme {
- WelcomeScreen(
- uiState = WelcomeUiState(),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- navigateToDeviceInfoDialog = {},
- onPurchaseBillingProductClick = { _ -> },
- navigateToVerificationPendingDialog = {}
- )
- }
+ fun testDisableSitePayment() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ WelcomeScreen(
+ uiState = WelcomeUiState(),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = { _ -> },
+ navigateToDeviceInfoDialog = {},
+ navigateToVerificationPendingDialog = {}
+ )
+ }
- // Assert
- composeTestRule.apply {
+ // Assert
onNodeWithText(
"Either buy credit on our website or redeem a voucher.",
substring = true
@@ -76,242 +77,251 @@ class WelcomeScreenTest {
.assertDoesNotExist()
onNodeWithText("Buy credit").assertDoesNotExist()
}
- }
@Test
- fun testShowAccountNumber() {
- // Arrange
- val rawAccountNumber = "1111222233334444"
- val expectedAccountNumber = "1111 2222 3333 4444"
- composeTestRule.setContentWithTheme {
- WelcomeScreen(
- uiState = WelcomeUiState(accountNumber = rawAccountNumber),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onPurchaseBillingProductClick = { _ -> },
- navigateToDeviceInfoDialog = {},
- navigateToVerificationPendingDialog = {}
- )
- }
+ fun testShowAccountNumber() =
+ composeExtension.use {
+ // Arrange
+ val rawAccountNumber = "1111222233334444"
+ val expectedAccountNumber = "1111 2222 3333 4444"
+ setContentWithTheme {
+ WelcomeScreen(
+ uiState = WelcomeUiState(accountNumber = rawAccountNumber),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = { _ -> },
+ navigateToDeviceInfoDialog = {},
+ navigateToVerificationPendingDialog = {}
+ )
+ }
- // Assert
- composeTestRule.apply { onNodeWithText(expectedAccountNumber).assertExists() }
- }
+ // Assert
+ onNodeWithText(expectedAccountNumber).assertExists()
+ }
@Test
- fun testClickSitePaymentButton() {
- // Arrange
- val mockClickListener: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- WelcomeScreen(
- uiState = WelcomeUiState(showSitePayment = true),
- onSitePaymentClick = mockClickListener,
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onPurchaseBillingProductClick = { _ -> },
- navigateToVerificationPendingDialog = {},
- navigateToDeviceInfoDialog = {}
- )
- }
+ fun testClickSitePaymentButton() =
+ composeExtension.use {
+ // Arrange
+ val mockClickListener: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ WelcomeScreen(
+ uiState = WelcomeUiState(showSitePayment = true),
+ onSitePaymentClick = mockClickListener,
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = { _ -> },
+ navigateToDeviceInfoDialog = {},
+ navigateToVerificationPendingDialog = {}
+ )
+ }
- // Act
- composeTestRule.apply { onNodeWithText("Buy credit").performClick() }
+ // Act
+ onNodeWithText("Buy credit").performClick()
- // Assert
- verify(exactly = 1) { mockClickListener.invoke() }
- }
-
- @Test
- fun testClickRedeemVoucher() {
- // Arrange
- val mockClickListener: () -> Unit = mockk(relaxed = true)
- composeTestRule.setContentWithTheme {
- WelcomeScreen(
- uiState = WelcomeUiState(),
- onSitePaymentClick = {},
- onRedeemVoucherClick = mockClickListener,
- onSettingsClick = {},
- onAccountClick = {},
- onPurchaseBillingProductClick = { _ -> },
- navigateToVerificationPendingDialog = {},
- navigateToDeviceInfoDialog = {}
- )
+ // Assert
+ verify(exactly = 1) { mockClickListener.invoke() }
}
- // Act
- composeTestRule.apply { onNodeWithText("Redeem voucher").performClick() }
+ @Test
+ fun testClickRedeemVoucher() =
+ composeExtension.use {
+ // Arrange
+ val mockClickListener: () -> Unit = mockk(relaxed = true)
+ setContentWithTheme {
+ WelcomeScreen(
+ uiState = WelcomeUiState(),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = mockClickListener,
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = { _ -> },
+ navigateToDeviceInfoDialog = {},
+ navigateToVerificationPendingDialog = {}
+ )
+ }
- // Assert
- verify(exactly = 1) { mockClickListener.invoke() }
- }
+ // Act
+ onNodeWithText("Redeem voucher").performClick()
- @Test
- fun testShowBillingErrorPaymentButton() {
- // Arrange
- composeTestRule.setContentWithTheme {
- WelcomeScreen(
- uiState = WelcomeUiState().copy(billingPaymentState = PaymentState.Error.Billing),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onPurchaseBillingProductClick = { _ -> },
- navigateToVerificationPendingDialog = {},
- navigateToDeviceInfoDialog = {}
- )
+ // Assert
+ verify(exactly = 1) { mockClickListener.invoke() }
}
- // Assert
- composeTestRule.onNodeWithText("Add 30 days time").assertExists()
- }
-
@Test
- fun testShowBillingPaymentAvailable() {
- // Arrange
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.status } returns null
- composeTestRule.setContentWithTheme {
- WelcomeScreen(
- uiState =
- WelcomeUiState(
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
- ),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onPurchaseBillingProductClick = { _ -> },
- navigateToVerificationPendingDialog = {},
- navigateToDeviceInfoDialog = {}
- )
- }
+ fun testShowBillingErrorPaymentButton() =
+ composeExtension.use {
+ // Arrange
+ setContentWithTheme {
+ WelcomeScreen(
+ uiState =
+ WelcomeUiState().copy(billingPaymentState = PaymentState.Error.Billing),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = { _ -> },
+ navigateToDeviceInfoDialog = {},
+ navigateToVerificationPendingDialog = {}
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Add 30 days time ($10)").assertExists()
- }
+ // Assert
+ onNodeWithText("Add 30 days time").assertExists()
+ }
@Test
- fun testShowPendingPayment() {
- // Arrange
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.status } returns PaymentStatus.PENDING
- composeTestRule.setContentWithTheme {
- WelcomeScreen(
- uiState =
- WelcomeUiState()
- .copy(
+ fun testShowBillingPaymentAvailable() =
+ composeExtension.use {
+ // Arrange
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.status } returns null
+ setContentWithTheme {
+ WelcomeScreen(
+ uiState =
+ WelcomeUiState(
billingPaymentState =
PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onPurchaseBillingProductClick = { _ -> },
- navigateToVerificationPendingDialog = {},
- navigateToDeviceInfoDialog = {}
- )
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = { _ -> },
+ navigateToDeviceInfoDialog = {},
+ navigateToVerificationPendingDialog = {}
+ )
+ }
+
+ // Assert
+ onNodeWithText("Add 30 days time ($10)").assertExists()
}
- // Assert
- composeTestRule.onNodeWithText("Google Play payment pending").assertExists()
- }
+ @Test
+ fun testShowPendingPayment() =
+ composeExtension.use {
+ // Arrange
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.status } returns PaymentStatus.PENDING
+ setContentWithTheme {
+ WelcomeScreen(
+ uiState =
+ WelcomeUiState()
+ .copy(
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
+ ),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = { _ -> },
+ navigateToDeviceInfoDialog = {},
+ navigateToVerificationPendingDialog = {}
+ )
+ }
+
+ // Assert
+ onNodeWithText("Google Play payment pending").assertExists()
+ }
@Test
- fun testShowPendingPaymentInfoDialog() {
- // Arrange
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.status } returns PaymentStatus.PENDING
- val mockShowPendingInfo = mockk<() -> Unit>(relaxed = true)
- composeTestRule.setContentWithTheme {
- WelcomeScreen(
- uiState =
- WelcomeUiState()
- .copy(
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
- ),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onPurchaseBillingProductClick = { _ -> },
- navigateToVerificationPendingDialog = mockShowPendingInfo,
- navigateToDeviceInfoDialog = {}
- )
+ fun testShowPendingPaymentInfoDialog() =
+ composeExtension.use {
+ // Arrange
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.status } returns PaymentStatus.PENDING
+ val mockShowPendingInfo = mockk<() -> Unit>(relaxed = true)
+ setContentWithTheme {
+ WelcomeScreen(
+ uiState =
+ WelcomeUiState()
+ .copy(
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
+ ),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = { _ -> },
+ navigateToVerificationPendingDialog = mockShowPendingInfo,
+ navigateToDeviceInfoDialog = {}
+ )
+ }
+
+ // Act
+ onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).performClick()
+
+ // Assert
+ verify(exactly = 1) { mockShowPendingInfo() }
}
- // Act
- composeTestRule.onNodeWithTag(PLAY_PAYMENT_INFO_ICON_TEST_TAG).performClick()
+ @Test
+ fun testShowVerificationInProgress() =
+ composeExtension.use {
+ // Arrange
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.status } returns PaymentStatus.VERIFICATION_IN_PROGRESS
+ setContentWithTheme {
+ WelcomeScreen(
+ uiState =
+ WelcomeUiState()
+ .copy(
+ billingPaymentState =
+ PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
+ ),
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = { _ -> },
+ navigateToDeviceInfoDialog = {},
+ navigateToVerificationPendingDialog = {}
+ )
+ }
- // Assert
- verify(exactly = 1) { mockShowPendingInfo() }
- }
+ // Assert
+ onNodeWithText("Verifying purchase").assertExists()
+ }
@Test
- fun testShowVerificationInProgress() {
- // Arrange
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.status } returns PaymentStatus.VERIFICATION_IN_PROGRESS
- composeTestRule.setContentWithTheme {
- WelcomeScreen(
- uiState =
- WelcomeUiState()
- .copy(
+ fun testOnPurchaseBillingProductClick() =
+ composeExtension.use {
+ // Arrange
+ val clickHandler: (ProductId) -> Unit = mockk(relaxed = true)
+ val mockPaymentProduct: PaymentProduct = mockk()
+ every { mockPaymentProduct.price } returns ProductPrice("$10")
+ every { mockPaymentProduct.productId } returns ProductId("PRODUCT_ID")
+ every { mockPaymentProduct.status } returns null
+ setContentWithTheme {
+ WelcomeScreen(
+ uiState =
+ WelcomeUiState(
billingPaymentState =
PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onPurchaseBillingProductClick = { _ -> },
- navigateToVerificationPendingDialog = {},
- navigateToDeviceInfoDialog = {}
- )
- }
+ onSitePaymentClick = {},
+ onRedeemVoucherClick = {},
+ onSettingsClick = {},
+ onAccountClick = {},
+ onPurchaseBillingProductClick = clickHandler,
+ navigateToDeviceInfoDialog = {},
+ navigateToVerificationPendingDialog = {}
+ )
+ }
- // Assert
- composeTestRule.onNodeWithText("Verifying purchase").assertExists()
- }
+ // Act
+ onNodeWithText("Add 30 days time ($10)").performClick()
- @Test
- fun testOnPurchaseBillingProductClick() {
- // Arrange
- val clickHandler: (ProductId) -> Unit = mockk(relaxed = true)
- val mockPaymentProduct: PaymentProduct = mockk()
- every { mockPaymentProduct.price } returns ProductPrice("$10")
- every { mockPaymentProduct.productId } returns ProductId("PRODUCT_ID")
- every { mockPaymentProduct.status } returns null
- composeTestRule.setContentWithTheme {
- WelcomeScreen(
- uiState =
- WelcomeUiState(
- billingPaymentState =
- PaymentState.PaymentAvailable(listOf(mockPaymentProduct))
- ),
- onSitePaymentClick = {},
- onRedeemVoucherClick = {},
- onSettingsClick = {},
- onAccountClick = {},
- onPurchaseBillingProductClick = clickHandler,
- navigateToVerificationPendingDialog = {},
- navigateToDeviceInfoDialog = {}
- )
+ // Assert
+ verify { clickHandler(ProductId("PRODUCT_ID")) }
}
-
- // Act
- composeTestRule.onNodeWithText("Add 30 days time ($10)").performClick()
-
- // Assert
- verify { clickHandler(ProductId("PRODUCT_ID")) }
- }
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreen.kt
index b9db62d620..864f909421 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/FilterScreen.kt
@@ -96,7 +96,7 @@ fun FilterScreen(
onApplyClick: () -> Unit = {},
onSelectedOwnership: (ownership: Ownership?) -> Unit = {},
onAllProviderCheckChange: (isChecked: Boolean) -> Unit = {},
- onSelectedProvider: (checked: Boolean, provider: Provider) -> Unit
+ onSelectedProvider: (checked: Boolean, provider: Provider) -> Unit = { _, _ -> }
) {
var providerExpanded by rememberSaveable { mutableStateOf(false) }
var ownershipExpanded by rememberSaveable { mutableStateOf(false) }
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/InAppNotificationControllerTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/InAppNotificationControllerTest.kt
index 30b54cea11..9767d3930a 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/InAppNotificationControllerTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/InAppNotificationControllerTest.kt
@@ -9,6 +9,7 @@ import kotlin.test.assertEquals
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.repository.InAppNotification
@@ -19,13 +20,13 @@ import net.mullvad.mullvadvpn.usecase.TunnelStateNotificationUseCase
import net.mullvad.mullvadvpn.usecase.VersionNotificationUseCase
import net.mullvad.talpid.tunnel.ErrorState
import org.joda.time.DateTime
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class InAppNotificationControllerTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private lateinit var inAppNotificationController: InAppNotificationController
private val accountExpiryNotifications = MutableStateFlow(emptyList<InAppNotification>())
@@ -35,7 +36,7 @@ class InAppNotificationControllerTest {
private lateinit var job: Job
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
@@ -56,11 +57,11 @@ class InAppNotificationControllerTest {
newDeviceNotificationUseCase,
versionNotificationUseCase,
tunnelStateNotificationUseCase,
- CoroutineScope(job + testCoroutineRule.testDispatcher)
+ CoroutineScope(job + UnconfinedTestDispatcher())
)
}
- @After
+ @AfterEach
fun teardown() {
job.cancel()
unmockkAll()
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsIconManagerTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsIconManagerTest.kt
index 3e26a37c2c..3296243c56 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsIconManagerTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsIconManagerTest.kt
@@ -12,23 +12,23 @@ import io.mockk.unmockkAll
import io.mockk.verify
import kotlin.test.assertEquals
import kotlin.test.assertFails
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
class ApplicationsIconManagerTest {
private val mockedPackageManager = mockk<PackageManager>()
private val mockedMainLooper = mockk<Looper>()
private val testSubject = ApplicationsIconManager(mockedPackageManager)
- @Before
+ @BeforeEach
fun setUp() {
mockkStatic(Looper::class)
mockkStatic(DRAWABLE_EXTENSION_CLASS)
every { Looper.getMainLooper() } returns mockedMainLooper
}
- @After
+ @AfterEach
fun tearDown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt
index a74ab85fc4..1b37184915 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt
@@ -8,8 +8,8 @@ import io.mockk.mockk
import io.mockk.unmockkAll
import io.mockk.verifyAll
import net.mullvad.mullvadvpn.lib.common.test.assertLists
-import org.junit.After
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.Test
class ApplicationsProviderTest {
private val mockedPackageManager = mockk<PackageManager>()
@@ -17,7 +17,7 @@ class ApplicationsProviderTest {
private val testSubject = ApplicationsProvider(mockedPackageManager, selfPackageName)
private val internet = Manifest.permission.INTERNET
- @After
+ @AfterEach
fun tearDown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/relaylist/RelayNameComparatorTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/relaylist/RelayNameComparatorTest.kt
index 2ef1d1f02c..dc9c141f28 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/relaylist/RelayNameComparatorTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/relaylist/RelayNameComparatorTest.kt
@@ -2,13 +2,13 @@ package net.mullvad.mullvadvpn.relaylist
import io.mockk.mockk
import io.mockk.unmockkAll
-import org.junit.After
-import org.junit.Assert.assertTrue
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Test
class RelayNameComparatorTest {
- @After
+ @AfterEach
fun tearDown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxyTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxyTest.kt
index 52bbbee0a6..4da6c4fdaf 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxyTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxyTest.kt
@@ -19,9 +19,9 @@ import kotlin.test.assertEquals
import net.mullvad.mullvadvpn.lib.ipc.Event
import net.mullvad.mullvadvpn.lib.ipc.EventDispatcher
import net.mullvad.mullvadvpn.lib.ipc.Request
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
class ConnectionProxyTest {
@@ -32,7 +32,7 @@ class ConnectionProxyTest {
@MockK private lateinit var mockedDispatchingHandler: EventDispatcher
lateinit var connectionProxy: ConnectionProxy
- @Before
+ @BeforeEach
fun setup() {
mockkStatic(Looper::class)
mockkStatic(Log::class)
@@ -44,7 +44,7 @@ class ConnectionProxyTest {
every { Log.e(any(), any()) } returns mockk(relaxed = true)
}
- @After
+ @AfterEach
fun tearDown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSourceTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSourceTest.kt
index 50f930d2a5..d4fd349438 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSourceTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSourceTest.kt
@@ -17,9 +17,9 @@ import net.mullvad.mullvadvpn.lib.common.util.JobTracker
import net.mullvad.mullvadvpn.lib.ipc.Event
import net.mullvad.mullvadvpn.lib.ipc.EventDispatcher
import net.mullvad.mullvadvpn.lib.ipc.Request
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
class ServiceConnectionDeviceDataSourceTest {
private val tracker = JobTracker()
@@ -32,7 +32,7 @@ class ServiceConnectionDeviceDataSourceTest {
lateinit var serviceConnectionDeviceDataSource: ServiceConnectionDeviceDataSource
- @Before
+ @BeforeEach
fun setup() {
mockkStatic(Looper::class)
mockkStatic(android.util.Log::class)
@@ -44,7 +44,7 @@ class ServiceConnectionDeviceDataSourceTest {
every { android.util.Log.e(any(), any()) } returns mockk(relaxed = true)
}
- @After
+ @AfterEach
fun tearDown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/AccountExpiryNotificationUseCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/AccountExpiryNotificationUseCaseTest.kt
index 5341708d3b..f068642bec 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/AccountExpiryNotificationUseCaseTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/AccountExpiryNotificationUseCaseTest.kt
@@ -14,18 +14,18 @@ import net.mullvad.mullvadvpn.model.AccountExpiry
import net.mullvad.mullvadvpn.repository.AccountRepository
import net.mullvad.mullvadvpn.repository.InAppNotification
import org.joda.time.DateTime
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class AccountExpiryNotificationUseCaseTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val accountExpiry = MutableStateFlow<AccountExpiry>(AccountExpiry.Missing)
private lateinit var accountExpiryNotificationUseCase: AccountExpiryNotificationUseCase
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
@@ -35,7 +35,7 @@ class AccountExpiryNotificationUseCaseTest {
accountExpiryNotificationUseCase = AccountExpiryNotificationUseCase(accountRepository)
}
- @After
+ @AfterEach
fun teardown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/NewDeviceUseNotificationCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/NewDeviceUseNotificationCaseTest.kt
index bd375d729a..5e4403c38d 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/NewDeviceUseNotificationCaseTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/NewDeviceUseNotificationCaseTest.kt
@@ -15,13 +15,13 @@ import net.mullvad.mullvadvpn.model.Device
import net.mullvad.mullvadvpn.model.DeviceState
import net.mullvad.mullvadvpn.repository.DeviceRepository
import net.mullvad.mullvadvpn.repository.InAppNotification
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class NewDeviceUseNotificationCaseTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val deviceName = "Frank Zebra"
private val deviceState =
@@ -32,7 +32,7 @@ class NewDeviceUseNotificationCaseTest {
)
private lateinit var newDeviceNotificationUseCase: NewDeviceNotificationUseCase
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
@@ -42,7 +42,7 @@ class NewDeviceUseNotificationCaseTest {
NewDeviceNotificationUseCase(deviceRepository = mockDeviceRepository)
}
- @After
+ @AfterEach
fun teardown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCaseTest.kt
index bdc5ea49b8..6563f7e6e9 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCaseTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCaseTest.kt
@@ -16,8 +16,8 @@ import net.mullvad.mullvadvpn.repository.AccountRepository
import net.mullvad.talpid.tunnel.ErrorState
import net.mullvad.talpid.tunnel.ErrorStateCause
import org.joda.time.DateTime
-import org.junit.Before
-import org.junit.Test
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
class OutOfTimeUseCaseTest {
private val mockAccountRepository: AccountRepository = mockk()
@@ -28,7 +28,7 @@ class OutOfTimeUseCaseTest {
lateinit var outOfTimeUseCase: OutOfTimeUseCase
- @Before
+ @BeforeEach
fun setup() {
every { mockAccountRepository.accountExpiryState } returns expiry
every { mockMessageHandler.events<Event.TunnelStateChange>() } returns events
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/PlayPaymentUseCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/PlayPaymentUseCaseTest.kt
index a1d8bee37a..fb85629a9c 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/PlayPaymentUseCaseTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/PlayPaymentUseCaseTest.kt
@@ -12,7 +12,7 @@ import net.mullvad.mullvadvpn.lib.payment.PaymentRepository
import net.mullvad.mullvadvpn.lib.payment.model.PaymentAvailability
import net.mullvad.mullvadvpn.lib.payment.model.ProductId
import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult
-import org.junit.Test
+import org.junit.jupiter.api.Test
class PlayPaymentUseCaseTest {
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCaseTest.kt
index e67630642d..244c735ee9 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCaseTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCaseTest.kt
@@ -19,13 +19,13 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
import net.mullvad.talpid.tunnel.ActionAfterDisconnect
import net.mullvad.talpid.tunnel.ErrorState
import net.mullvad.talpid.util.EventNotifier
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class TunnelStateNotificationUseCaseTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val mockServiceConnectionManager: ServiceConnectionManager = mockk()
private val mockServiceConnectionContainer: ServiceConnectionContainer = mockk()
@@ -37,7 +37,7 @@ class TunnelStateNotificationUseCaseTest {
private val eventNotifierTunnelUiState = EventNotifier<TunnelState>(TunnelState.Disconnected())
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
every { mockConnectionProxy.onUiStateChange } returns eventNotifierTunnelUiState
@@ -49,7 +49,7 @@ class TunnelStateNotificationUseCaseTest {
TunnelStateNotificationUseCase(serviceConnectionManager = mockServiceConnectionManager)
}
- @After
+ @AfterEach
fun teardown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/VersionNotificationUseCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/VersionNotificationUseCaseTest.kt
index 5aba70c938..12f7207280 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/VersionNotificationUseCaseTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/VersionNotificationUseCaseTest.kt
@@ -18,13 +18,13 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionContainer
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
import net.mullvad.mullvadvpn.util.appVersionCallbackFlow
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class VersionNotificationUseCaseTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val mockServiceConnectionManager: ServiceConnectionManager = mockk()
private lateinit var mockAppVersionInfoCache: AppVersionInfoCache
@@ -43,7 +43,7 @@ class VersionNotificationUseCaseTest {
)
private lateinit var versionNotificationUseCase: VersionNotificationUseCase
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
mockkStatic(CACHE_EXTENSION_CLASS)
@@ -63,7 +63,7 @@ class VersionNotificationUseCaseTest {
)
}
- @After
+ @AfterEach
fun teardown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/utils/VoucherRegexHelperParameterizedTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/utils/VoucherRegexHelperParameterizedTest.kt
index 60db08b85f..1722e81a9d 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/utils/VoucherRegexHelperParameterizedTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/utils/VoucherRegexHelperParameterizedTest.kt
@@ -1,34 +1,29 @@
package net.mullvad.mullvadvpn.utils
+import java.util.stream.Stream
+import kotlin.test.assertEquals
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.util.VoucherRegexHelper
-import org.hamcrest.CoreMatchers.equalTo
-import org.hamcrest.MatcherAssert.assertThat
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
+import org.junit.jupiter.api.extension.ExtendWith
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.MethodSource
private const val IS_ACCEPTED_FORMAT = true
private const val IS_UNACCEPTED_FORMAT = false
-@RunWith(Parameterized::class)
-class VoucherRegexHelperParameterizedTest(
- private val isValid: Boolean,
- private val voucher: String
-) {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
+@ExtendWith(TestCoroutineRule::class)
+class VoucherRegexHelperParameterizedTest {
- @Test
- fun testVoucherFormat() {
- assertThat(VoucherRegexHelper.validate(voucher), equalTo(isValid))
+ @ParameterizedTest
+ @MethodSource("data")
+ fun testVoucherFormat(isValid: Boolean, voucher: String) {
+ assertEquals(VoucherRegexHelper.validate(voucher), isValid)
}
companion object {
@JvmStatic
- @Parameterized.Parameters
- fun data(): Collection<Array<Any>> =
- listOf(
+ fun data(): Stream<Array<Any>> =
+ Stream.of(
arrayOf(IS_ACCEPTED_FORMAT, "1"),
arrayOf(IS_ACCEPTED_FORMAT, "a"),
arrayOf(IS_ACCEPTED_FORMAT, "A"),
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt
index 22acc97986..637c531039 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt
@@ -30,13 +30,13 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.AuthTokenCache
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.authTokenCache
import net.mullvad.mullvadvpn.usecase.PaymentUseCase
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class AccountViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val mockAccountRepository: AccountRepository = mockk(relaxUnitFun = true)
private val mockServiceConnectionManager: ServiceConnectionManager = mockk()
@@ -62,7 +62,7 @@ class AccountViewModelTest {
private lateinit var viewModel: AccountViewModel
- @Before
+ @BeforeEach
fun setUp() {
mockkStatic(CACHE_EXTENSION_CLASS)
mockkStatic(PURCHASE_RESULT_EXTENSIONS_CLASS)
@@ -82,7 +82,7 @@ class AccountViewModelTest {
)
}
- @After
+ @AfterEach
fun tearDown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ChangelogViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ChangelogViewModelTest.kt
index 3350178ca3..d9a5ae534e 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ChangelogViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ChangelogViewModelTest.kt
@@ -12,19 +12,19 @@ import kotlin.test.assertNotNull
import kotlinx.coroutines.test.runTest
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.repository.ChangelogRepository
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class ChangelogViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
@MockK private lateinit var mockedChangelogRepository: ChangelogRepository
private lateinit var viewModel: ChangelogViewModel
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
mockkStatic(EVENT_NOTIFIER_EXTENSION_CLASS)
@@ -32,7 +32,7 @@ class ChangelogViewModelTest {
Runs
}
- @After
+ @AfterEach
fun teardown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt
index 47364652ce..a1e3ce57e5 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt
@@ -43,13 +43,13 @@ import net.mullvad.mullvadvpn.usecase.RelayListUseCase
import net.mullvad.mullvadvpn.util.appVersionCallbackFlow
import net.mullvad.talpid.tunnel.ErrorState
import net.mullvad.talpid.util.EventNotifier
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class ConnectViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val mockServiceConnectionManager: ServiceConnectionManager = mockk()
private lateinit var viewModel: ConnectViewModel
@@ -102,7 +102,7 @@ class ConnectViewModelTest {
private val outOfTimeUseCase: OutOfTimeUseCase = mockk()
private val outOfTimeViewFlow = MutableStateFlow(false)
- @Before
+ @BeforeEach
fun setup() {
mockkStatic(CACHE_EXTENSION_CLASS)
mockkStatic(SERVICE_CONNECTION_MANAGER_EXTENSIONS)
@@ -148,7 +148,7 @@ class ConnectViewModelTest {
)
}
- @After
+ @AfterEach
fun teardown() {
viewModel.viewModelScope.coroutineContext.cancel()
unmockkAll()
@@ -160,83 +160,79 @@ class ConnectViewModelTest {
}
@Test
- fun testTunnelRealStateUpdate() =
- runTest(testCoroutineRule.testDispatcher) {
- val tunnelRealStateTestItem = TunnelState.Connected(mockk(relaxed = true), null)
+ fun testTunnelRealStateUpdate() = runTest {
+ val tunnelRealStateTestItem = TunnelState.Connected(mockk(relaxed = true), null)
- viewModel.uiState.test {
- assertEquals(ConnectUiState.INITIAL, awaitItem())
- serviceConnectionState.value =
- ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
- eventNotifierTunnelRealState.notify(tunnelRealStateTestItem)
- val result = awaitItem()
- assertEquals(tunnelRealStateTestItem, result.tunnelRealState)
- }
+ viewModel.uiState.test {
+ assertEquals(ConnectUiState.INITIAL, awaitItem())
+ serviceConnectionState.value =
+ ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
+ eventNotifierTunnelRealState.notify(tunnelRealStateTestItem)
+ val result = awaitItem()
+ assertEquals(tunnelRealStateTestItem, result.tunnelRealState)
}
+ }
@Test
- fun testTunnelUiStateUpdate() =
- runTest(testCoroutineRule.testDispatcher) {
- val tunnelUiStateTestItem = TunnelState.Connected(mockk(), mockk())
+ fun testTunnelUiStateUpdate() = runTest {
+ val tunnelUiStateTestItem = TunnelState.Connected(mockk(), mockk())
- viewModel.uiState.test {
- assertEquals(ConnectUiState.INITIAL, awaitItem())
- serviceConnectionState.value =
- ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
- eventNotifierTunnelUiState.notify(tunnelUiStateTestItem)
- val result = awaitItem()
- assertEquals(tunnelUiStateTestItem, result.tunnelUiState)
- }
+ viewModel.uiState.test {
+ assertEquals(ConnectUiState.INITIAL, awaitItem())
+ serviceConnectionState.value =
+ ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
+ eventNotifierTunnelUiState.notify(tunnelUiStateTestItem)
+ val result = awaitItem()
+ assertEquals(tunnelUiStateTestItem, result.tunnelUiState)
}
+ }
@Test
- fun testRelayItemUpdate() =
- runTest(testCoroutineRule.testDispatcher) {
- val relayTestItem =
- RelayCountry(name = "Name", code = "Code", expanded = false, cities = emptyList())
- selectedRelayFlow.value = relayTestItem
+ fun testRelayItemUpdate() = runTest {
+ val relayTestItem =
+ RelayCountry(name = "Name", code = "Code", expanded = false, cities = emptyList())
+ selectedRelayFlow.value = relayTestItem
- viewModel.uiState.test {
- assertEquals(ConnectUiState.INITIAL, awaitItem())
- serviceConnectionState.value =
- ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
- val result = awaitItem()
- assertEquals(relayTestItem, result.relayLocation)
- }
+ viewModel.uiState.test {
+ assertEquals(ConnectUiState.INITIAL, awaitItem())
+ serviceConnectionState.value =
+ ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
+ val result = awaitItem()
+ assertEquals(relayTestItem, result.relayLocation)
}
+ }
@Test
- fun testLocationUpdate() =
- runTest(testCoroutineRule.testDispatcher) {
- val locationTestItem =
- GeoIpLocation(
- ipv4 = mockk(relaxed = true),
- ipv6 = mockk(relaxed = true),
- country = "Sweden",
- city = "Gothenburg",
- hostname = "Host"
- )
+ fun testLocationUpdate() = runTest {
+ val locationTestItem =
+ GeoIpLocation(
+ ipv4 = mockk(relaxed = true),
+ ipv6 = mockk(relaxed = true),
+ country = "Sweden",
+ city = "Gothenburg",
+ hostname = "Host"
+ )
- // Act, Assert
- viewModel.uiState.test {
- assertEquals(ConnectUiState.INITIAL, awaitItem())
- eventNotifierTunnelRealState.notify(TunnelState.Disconnected(null))
+ // Act, Assert
+ viewModel.uiState.test {
+ assertEquals(ConnectUiState.INITIAL, awaitItem())
+ eventNotifierTunnelRealState.notify(TunnelState.Disconnected(null))
- serviceConnectionState.value =
- ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
- // Start of with no location
- assertNull(awaitItem().location)
+ serviceConnectionState.value =
+ ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
+ // Start of with no location
+ assertNull(awaitItem().location)
- // After updated we show latest
- eventNotifierTunnelRealState.notify(TunnelState.Disconnected(locationTestItem))
- assertEquals(locationTestItem, awaitItem().location)
- }
+ // After updated we show latest
+ eventNotifierTunnelRealState.notify(TunnelState.Disconnected(locationTestItem))
+ assertEquals(locationTestItem, awaitItem().location)
}
+ }
@Test
fun testLocationUpdateNullLocation() =
// Arrange
- runTest(testCoroutineRule.testDispatcher) {
+ runTest {
val locationTestItem = null
// Act, Assert
@@ -251,99 +247,91 @@ class ConnectViewModelTest {
}
@Test
- fun testOnDisconnectClick() =
- runTest(testCoroutineRule.testDispatcher) {
- val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true)
- every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy
- viewModel.onDisconnectClick()
- verify { mockConnectionProxy.disconnect() }
- }
+ fun testOnDisconnectClick() = runTest {
+ val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true)
+ every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy
+ viewModel.onDisconnectClick()
+ verify { mockConnectionProxy.disconnect() }
+ }
@Test
- fun testOnReconnectClick() =
- runTest(testCoroutineRule.testDispatcher) {
- val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true)
- every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy
- viewModel.onReconnectClick()
- verify { mockConnectionProxy.reconnect() }
- }
+ fun testOnReconnectClick() = runTest {
+ val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true)
+ every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy
+ viewModel.onReconnectClick()
+ verify { mockConnectionProxy.reconnect() }
+ }
@Test
- fun testOnConnectClick() =
- runTest(testCoroutineRule.testDispatcher) {
- val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true)
- every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy
- viewModel.onConnectClick()
- verify { mockConnectionProxy.connect() }
- }
+ fun testOnConnectClick() = runTest {
+ val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true)
+ every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy
+ viewModel.onConnectClick()
+ verify { mockConnectionProxy.connect() }
+ }
@Test
- fun testOnCancelClick() =
- runTest(testCoroutineRule.testDispatcher) {
- val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true)
- every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy
- viewModel.onCancelClick()
- verify { mockConnectionProxy.disconnect() }
- }
+ fun testOnCancelClick() = runTest {
+ val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true)
+ every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy
+ viewModel.onCancelClick()
+ verify { mockConnectionProxy.disconnect() }
+ }
@Test
- fun testErrorNotificationState() =
- runTest(testCoroutineRule.testDispatcher) {
- // Arrange
- val mockErrorState: ErrorState = mockk()
- val expectedConnectNotificationState =
- InAppNotification.TunnelStateError(mockErrorState)
- val tunnelUiState = TunnelState.Error(mockErrorState)
- notifications.value = listOf(expectedConnectNotificationState)
+ fun testErrorNotificationState() = runTest {
+ // Arrange
+ val mockErrorState: ErrorState = mockk()
+ val expectedConnectNotificationState = InAppNotification.TunnelStateError(mockErrorState)
+ val tunnelUiState = TunnelState.Error(mockErrorState)
+ notifications.value = listOf(expectedConnectNotificationState)
- // Act, Assert
- viewModel.uiState.test {
- assertEquals(ConnectUiState.INITIAL, awaitItem())
- serviceConnectionState.value =
- ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
- eventNotifierTunnelUiState.notify(tunnelUiState)
- val result = awaitItem()
- assertEquals(expectedConnectNotificationState, result.inAppNotification)
- }
+ // Act, Assert
+ viewModel.uiState.test {
+ assertEquals(ConnectUiState.INITIAL, awaitItem())
+ serviceConnectionState.value =
+ ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
+ eventNotifierTunnelUiState.notify(tunnelUiState)
+ val result = awaitItem()
+ assertEquals(expectedConnectNotificationState, result.inAppNotification)
}
+ }
@Test
- fun testOnShowAccountClick() =
- runTest(testCoroutineRule.testDispatcher) {
- // Arrange
- val mockToken = "4444 5555 6666 7777"
- val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true)
- every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache
- coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken
+ fun testOnShowAccountClick() = runTest {
+ // Arrange
+ val mockToken = "4444 5555 6666 7777"
+ val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true)
+ every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache
+ coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken
- // Act, Assert
- viewModel.uiSideEffect.test {
- viewModel.onManageAccountClick()
- val action = awaitItem()
- assertIs<ConnectViewModel.UiSideEffect.OpenAccountManagementPageInBrowser>(action)
- assertEquals(mockToken, action.token)
- }
+ // Act, Assert
+ viewModel.uiSideEffect.test {
+ viewModel.onManageAccountClick()
+ val action = awaitItem()
+ assertIs<ConnectViewModel.UiSideEffect.OpenAccountManagementPageInBrowser>(action)
+ assertEquals(mockToken, action.token)
}
+ }
@Test
- fun testOutOfTimeUiSideEffect() =
- runTest(testCoroutineRule.testDispatcher) {
- // Arrange
- val deferred = async { viewModel.uiSideEffect.first() }
-
- // Act
- viewModel.uiState.test {
- awaitItem()
- serviceConnectionState.value =
- ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
- outOfTimeViewFlow.value = true
- awaitItem()
- }
+ fun testOutOfTimeUiSideEffect() = runTest {
+ // Arrange
+ val deferred = async { viewModel.uiSideEffect.first() }
- // Assert
- assertIs<ConnectViewModel.UiSideEffect.OutOfTime>(deferred.await())
+ // Act
+ viewModel.uiState.test {
+ awaitItem()
+ serviceConnectionState.value =
+ ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
+ outOfTimeViewFlow.value = true
+ awaitItem()
}
+ // Assert
+ assertIs<ConnectViewModel.UiSideEffect.OutOfTime>(deferred.await())
+ }
+
companion object {
private const val CACHE_EXTENSION_CLASS = "net.mullvad.mullvadvpn.util.CacheExtensionsKt"
private const val SERVICE_CONNECTION_MANAGER_EXTENSIONS =
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModelTest.kt
index 0fcf684afc..3f7966e8bd 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModelTest.kt
@@ -11,7 +11,6 @@ import io.mockk.mockkStatic
import io.mockk.unmockkAll
import io.mockk.verify
import io.mockk.verifyOrder
-import junit.framework.Assert.assertEquals
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
@@ -25,13 +24,14 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
import net.mullvad.talpid.util.EventNotifier
import net.mullvad.talpid.util.callbackFlowFromSubscription
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class DeviceRevokedViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
@MockK private lateinit var mockedAccountRepository: AccountRepository
@@ -42,7 +42,7 @@ class DeviceRevokedViewModelTest {
private lateinit var viewModel: DeviceRevokedViewModel
- @Before
+ @BeforeEach
fun setup() {
MockKAnnotations.init(this)
mockkStatic(EVENT_NOTIFIER_EXTENSION_CLASS)
@@ -55,7 +55,7 @@ class DeviceRevokedViewModelTest {
)
}
- @After
+ @AfterEach
fun teardown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/FilterViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/FilterViewModelTest.kt
index 9f61ea4a91..210ed88666 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/FilterViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/FilterViewModelTest.kt
@@ -20,13 +20,13 @@ import net.mullvad.mullvadvpn.model.Ownership
import net.mullvad.mullvadvpn.model.Providers
import net.mullvad.mullvadvpn.relaylist.Provider
import net.mullvad.mullvadvpn.usecase.RelayListFilterUseCase
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class FilterViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val mockRelayListFilterUseCase: RelayListFilterUseCase = mockk(relaxed = true)
private lateinit var viewModel: FilterViewModel
private val selectedOwnership =
@@ -54,7 +54,7 @@ class FilterViewModelTest {
private val mockSelectedProviders: List<Provider> =
listOf(Provider("31173", true), Provider("Blix", true), Provider("Creanova", true))
- @Before
+ @BeforeEach
fun setup() {
every { mockRelayListFilterUseCase.selectedOwnership() } returns selectedOwnership
every { mockRelayListFilterUseCase.availableProviders() } returns
@@ -64,7 +64,7 @@ class FilterViewModelTest {
viewModel = FilterViewModel(mockRelayListFilterUseCase)
}
- @After
+ @AfterEach
fun teardown() {
viewModel.viewModelScope.coroutineContext.cancel()
unmockkAll()
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt
index c402a3103e..f677615c24 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt
@@ -30,13 +30,13 @@ import net.mullvad.mullvadvpn.repository.DeviceRepository
import net.mullvad.mullvadvpn.usecase.ConnectivityUseCase
import net.mullvad.mullvadvpn.usecase.NewDeviceNotificationUseCase
import org.joda.time.DateTime
-import org.junit.Assert.assertEquals
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class LoginViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
@MockK private lateinit var connectivityUseCase: ConnectivityUseCase
@MockK private lateinit var mockedAccountRepository: AccountRepository
@@ -46,7 +46,7 @@ class LoginViewModelTest {
private lateinit var loginViewModel: LoginViewModel
private val accountHistoryTestEvents = MutableStateFlow<AccountHistory>(AccountHistory.Missing)
- @Before
+ @BeforeEach
fun setup() {
Dispatchers.setMain(UnconfinedTestDispatcher())
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModelTest.kt
index 50a9d8fb98..0df34e0747 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModelTest.kt
@@ -38,13 +38,13 @@ import net.mullvad.mullvadvpn.usecase.PaymentUseCase
import net.mullvad.talpid.util.EventNotifier
import org.joda.time.DateTime
import org.joda.time.ReadableInstant
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class OutOfTimeViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val serviceConnectionStateFlow =
MutableStateFlow<ServiceConnectionState>(ServiceConnectionState.Disconnected)
@@ -70,7 +70,7 @@ class OutOfTimeViewModelTest {
private lateinit var viewModel: OutOfTimeViewModel
- @Before
+ @BeforeEach
fun setUp() {
mockkStatic(SERVICE_CONNECTION_MANAGER_EXTENSIONS)
mockkStatic(PURCHASE_RESULT_EXTENSIONS_CLASS)
@@ -103,75 +103,71 @@ class OutOfTimeViewModelTest {
)
}
- @After
+ @AfterEach
fun tearDown() {
viewModel.viewModelScope.coroutineContext.cancel()
unmockkAll()
}
@Test
- fun testSitePaymentClick() =
- runTest(testCoroutineRule.testDispatcher) {
- // Arrange
- val mockToken = "4444 5555 6666 7777"
- val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true)
- every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache
- coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken
+ fun testSitePaymentClick() = runTest {
+ // Arrange
+ val mockToken = "4444 5555 6666 7777"
+ val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true)
+ every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache
+ coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken
- // Act, Assert
- viewModel.uiSideEffect.test {
- viewModel.onSitePaymentClick()
- val action = awaitItem()
- assertIs<OutOfTimeViewModel.UiSideEffect.OpenAccountView>(action)
- assertEquals(mockToken, action.token)
- }
+ // Act, Assert
+ viewModel.uiSideEffect.test {
+ viewModel.onSitePaymentClick()
+ val action = awaitItem()
+ assertIs<OutOfTimeViewModel.UiSideEffect.OpenAccountView>(action)
+ assertEquals(mockToken, action.token)
}
+ }
@Test
- fun testUpdateTunnelState() =
- runTest(testCoroutineRule.testDispatcher) {
- // Arrange
- val tunnelRealStateTestItem = TunnelState.Connected(mockk(), mockk())
+ fun testUpdateTunnelState() = runTest {
+ // Arrange
+ val tunnelRealStateTestItem = TunnelState.Connected(mockk(), mockk())
- // Act, Assert
- viewModel.uiState.test {
- assertEquals(OutOfTimeUiState(deviceName = ""), awaitItem())
- eventNotifierTunnelRealState.notify(tunnelRealStateTestItem)
- serviceConnectionStateFlow.value =
- ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
- val result = awaitItem()
- assertEquals(tunnelRealStateTestItem, result.tunnelState)
- }
+ // Act, Assert
+ viewModel.uiState.test {
+ assertEquals(OutOfTimeUiState(deviceName = ""), awaitItem())
+ eventNotifierTunnelRealState.notify(tunnelRealStateTestItem)
+ serviceConnectionStateFlow.value =
+ ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
+ val result = awaitItem()
+ assertEquals(tunnelRealStateTestItem, result.tunnelState)
}
+ }
@Test
- fun testOpenConnectScreen() =
- runTest(testCoroutineRule.testDispatcher) {
- // Arrange
- val mockExpiryDate: DateTime = mockk()
- every { mockExpiryDate.isAfter(any<ReadableInstant>()) } returns true
+ fun testOpenConnectScreen() = runTest {
+ // Arrange
+ val mockExpiryDate: DateTime = mockk()
+ every { mockExpiryDate.isAfter(any<ReadableInstant>()) } returns true
- // Act, Assert
- viewModel.uiSideEffect.test {
- outOfTimeFlow.value = false
- val action = awaitItem()
- assertIs<OutOfTimeViewModel.UiSideEffect.OpenConnectScreen>(action)
- }
+ // Act, Assert
+ viewModel.uiSideEffect.test {
+ outOfTimeFlow.value = false
+ val action = awaitItem()
+ assertIs<OutOfTimeViewModel.UiSideEffect.OpenConnectScreen>(action)
}
+ }
@Test
- fun testOnDisconnectClick() =
- runTest(testCoroutineRule.testDispatcher) {
- // Arrange
- val mockProxy: ConnectionProxy = mockk(relaxed = true)
- every { mockServiceConnectionManager.connectionProxy() } returns mockProxy
+ fun testOnDisconnectClick() = runTest {
+ // Arrange
+ val mockProxy: ConnectionProxy = mockk(relaxed = true)
+ every { mockServiceConnectionManager.connectionProxy() } returns mockProxy
- // Act
- viewModel.onDisconnectClick()
+ // Act
+ viewModel.onDisconnectClick()
- // Assert
- verify { mockProxy.disconnect() }
- }
+ // Assert
+ verify { mockProxy.disconnect() }
+ }
@Test
fun testBillingProductsUnavailableState() = runTest {
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/PaymentViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/PaymentViewModelTest.kt
index 665e23c3d4..1e2fba3c96 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/PaymentViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/PaymentViewModelTest.kt
@@ -12,13 +12,13 @@ import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult
import net.mullvad.mullvadvpn.usecase.PaymentUseCase
import net.mullvad.mullvadvpn.util.toPaymentDialogData
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class PaymentViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val mockPaymentUseCase: PaymentUseCase = mockk(relaxed = true)
@@ -26,14 +26,14 @@ class PaymentViewModelTest {
private lateinit var viewModel: PaymentViewModel
- @Before
+ @BeforeEach
fun setUp() {
coEvery { mockPaymentUseCase.purchaseResult } returns purchaseResult
viewModel = PaymentViewModel(paymentUseCase = mockPaymentUseCase)
}
- @After
+ @AfterEach
fun tearDown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ReportProblemViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ReportProblemViewModelTest.kt
index 5726c6249c..6ea1a85ed2 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ReportProblemViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ReportProblemViewModelTest.kt
@@ -15,13 +15,13 @@ import net.mullvad.mullvadvpn.dataproxy.SendProblemReportResult
import net.mullvad.mullvadvpn.dataproxy.UserReport
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.repository.ProblemReportRepository
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class ReportProblemViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
@MockK private lateinit var mockMullvadProblemReport: MullvadProblemReport
@@ -31,7 +31,7 @@ class ReportProblemViewModelTest {
private lateinit var viewModel: ReportProblemViewModel
- @Before
+ @BeforeEach
fun setUp() {
MockKAnnotations.init(this)
coEvery { mockMullvadProblemReport.collectLogs() } returns true
@@ -39,7 +39,7 @@ class ReportProblemViewModelTest {
viewModel = ReportProblemViewModel(mockMullvadProblemReport, mockProblemReportRepository)
}
- @After
+ @AfterEach
fun tearDown() {
viewModel.viewModelScope.coroutineContext.cancel()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt
index 5ad1af1182..46ea0bf3fb 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt
@@ -29,13 +29,13 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.connectionProxy
import net.mullvad.mullvadvpn.usecase.RelayListFilterUseCase
import net.mullvad.mullvadvpn.usecase.RelayListUseCase
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class SelectLocationViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val mockRelayListFilterUseCase: RelayListFilterUseCase = mockk(relaxed = true)
private val mockServiceConnectionManager: ServiceConnectionManager = mockk()
@@ -46,7 +46,7 @@ class SelectLocationViewModelTest {
private val selectedProvider = MutableStateFlow<Constraint<Providers>>(Constraint.Any())
private val allProvider = MutableStateFlow<List<Provider>>(emptyList())
- @Before
+ @BeforeEach
fun setup() {
every { mockRelayListFilterUseCase.selectedOwnership() } returns selectedOwnership
@@ -64,7 +64,7 @@ class SelectLocationViewModelTest {
)
}
- @After
+ @AfterEach
fun teardown() {
viewModel.viewModelScope.coroutineContext.cancel()
unmockkAll()
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt
index ff6804c953..b52ab53ef6 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt
@@ -19,13 +19,13 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionContainer
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
import net.mullvad.mullvadvpn.util.appVersionCallbackFlow
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class SettingsViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val mockDeviceRepository: DeviceRepository = mockk()
private val mockServiceConnectionManager: ServiceConnectionManager = mockk()
@@ -46,7 +46,7 @@ class SettingsViewModelTest {
private lateinit var viewModel: SettingsViewModel
- @Before
+ @BeforeEach
fun setUp() {
mockkStatic(CACHE_EXTENSION_CLASS)
val deviceState = MutableStateFlow<DeviceState>(DeviceState.LoggedOut)
@@ -68,7 +68,7 @@ class SettingsViewModelTest {
)
}
- @After
+ @AfterEach
fun tearDown() {
viewModel.viewModelScope.coroutineContext.cancel()
unmockkAll()
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt
index 5409b7f736..7b2b4cacd5 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt
@@ -15,6 +15,7 @@ import java.util.concurrent.TimeUnit
import kotlin.test.assertEquals
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import net.mullvad.mullvadvpn.applist.AppData
import net.mullvad.mullvadvpn.applist.ApplicationsProvider
@@ -24,174 +25,169 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionContainer
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
import net.mullvad.mullvadvpn.ui.serviceconnection.SplitTunneling
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.Timeout
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.Timeout
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
+@Timeout(3000L, unit = TimeUnit.MILLISECONDS)
class SplitTunnelingViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
- @get:Rule val timeout = Timeout(3000L, TimeUnit.MILLISECONDS)
private val mockedApplicationsProvider = mockk<ApplicationsProvider>()
private val mockedSplitTunneling = mockk<SplitTunneling>()
private val mockedServiceConnectionManager = mockk<ServiceConnectionManager>()
private val mockedServiceConnectionContainer = mockk<ServiceConnectionContainer>()
private lateinit var testSubject: SplitTunnelingViewModel
- @Before
+ @BeforeEach
fun setup() {
every { mockedSplitTunneling.enabled } returns true
}
- @After
+ @AfterEach
fun tearDown() {
testSubject.viewModelScope.coroutineContext.cancel()
unmockkAll()
}
@Test
- fun test_has_progress_on_start() =
- runTest(testCoroutineRule.testDispatcher) {
- initTestSubject(emptyList())
- val actualState: SplitTunnelingUiState = testSubject.uiState.value
+ fun test_has_progress_on_start() = runTest {
+ initTestSubject(emptyList())
+ val actualState: SplitTunnelingUiState = testSubject.uiState.value
- val initialExpectedState = SplitTunnelingUiState.Loading
+ val initialExpectedState = SplitTunnelingUiState.Loading
- assertEquals(initialExpectedState, actualState)
+ assertEquals(initialExpectedState, actualState)
- verify(exactly = 1) { mockedApplicationsProvider.getAppsList() }
- }
+ verify(exactly = 1) { mockedApplicationsProvider.getAppsList() }
+ }
@Test
- fun test_empty_app_list() =
- runTest(testCoroutineRule.testDispatcher) {
- every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers
- {
- lambda<(Set<String>) -> Unit>().invoke(emptySet())
- }
- initTestSubject(emptyList())
- val expectedState =
- SplitTunnelingUiState.ShowAppList(
- excludedApps = emptyList(),
- includedApps = emptyList(),
- showSystemApps = false
- )
- testSubject.uiState.test { assertEquals(expectedState, awaitItem()) }
- }
+ fun test_empty_app_list() = runTest {
+ every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers
+ {
+ lambda<(Set<String>) -> Unit>().invoke(emptySet())
+ }
+ initTestSubject(emptyList())
+ val expectedState =
+ SplitTunnelingUiState.ShowAppList(
+ excludedApps = emptyList(),
+ includedApps = emptyList(),
+ showSystemApps = false
+ )
+ testSubject.uiState.test { assertEquals(expectedState, awaitItem()) }
+ }
@Test
- fun test_apps_list_delivered() =
- runTest(testCoroutineRule.testDispatcher) {
- val appExcluded = AppData("test.excluded", 0, "testName1")
- val appNotExcluded = AppData("test.not.excluded", 0, "testName2")
- every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers
- {
- lambda<(Set<String>) -> Unit>().invoke(setOf(appExcluded.packageName))
- }
+ fun test_apps_list_delivered() = runTest {
+ val appExcluded = AppData("test.excluded", 0, "testName1")
+ val appNotExcluded = AppData("test.not.excluded", 0, "testName2")
+ every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers
+ {
+ lambda<(Set<String>) -> Unit>().invoke(setOf(appExcluded.packageName))
+ }
- initTestSubject(listOf(appExcluded, appNotExcluded))
+ initTestSubject(listOf(appExcluded, appNotExcluded))
- val expectedState =
- SplitTunnelingUiState.ShowAppList(
- excludedApps = listOf(appExcluded),
- includedApps = listOf(appNotExcluded),
- showSystemApps = false
- )
+ val expectedState =
+ SplitTunnelingUiState.ShowAppList(
+ excludedApps = listOf(appExcluded),
+ includedApps = listOf(appNotExcluded),
+ showSystemApps = false
+ )
- testSubject.uiState.test {
- val actualState = awaitItem()
- assertEquals(expectedState, actualState)
- verifyAll {
- mockedSplitTunneling.enabled
- mockedSplitTunneling.excludedAppsChange = any()
- }
+ testSubject.uiState.test {
+ val actualState = awaitItem()
+ assertEquals(expectedState, actualState)
+ verifyAll {
+ mockedSplitTunneling.enabled
+ mockedSplitTunneling.excludedAppsChange = any()
}
}
+ }
@Test
- fun test_include_app() =
- runTest(testCoroutineRule.testDispatcher) {
- var excludedAppsCallback = slot<(Set<String>) -> Unit>()
- val app = AppData("test", 0, "testName")
- every { mockedSplitTunneling.includeApp(app.packageName) } just runs
- every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers
- {
- excludedAppsCallback = lambda()
- excludedAppsCallback.invoke(setOf(app.packageName))
- }
+ fun test_include_app() = runTest {
+ var excludedAppsCallback = slot<(Set<String>) -> Unit>()
+ val app = AppData("test", 0, "testName")
+ every { mockedSplitTunneling.includeApp(app.packageName) } just runs
+ every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers
+ {
+ excludedAppsCallback = lambda()
+ excludedAppsCallback.invoke(setOf(app.packageName))
+ }
- initTestSubject(listOf(app))
+ initTestSubject(listOf(app))
- val expectedStateBeforeAction =
- SplitTunnelingUiState.ShowAppList(
- excludedApps = listOf(app),
- includedApps = emptyList(),
- showSystemApps = false
- )
- val expectedStateAfterAction =
- SplitTunnelingUiState.ShowAppList(
- excludedApps = emptyList(),
- includedApps = listOf(app),
- showSystemApps = false
- )
+ val expectedStateBeforeAction =
+ SplitTunnelingUiState.ShowAppList(
+ excludedApps = listOf(app),
+ includedApps = emptyList(),
+ showSystemApps = false
+ )
+ val expectedStateAfterAction =
+ SplitTunnelingUiState.ShowAppList(
+ excludedApps = emptyList(),
+ includedApps = listOf(app),
+ showSystemApps = false
+ )
- testSubject.uiState.test {
- assertEquals(expectedStateBeforeAction, awaitItem())
- testSubject.onIncludeAppClick(app.packageName)
- excludedAppsCallback.invoke(emptySet())
- assertEquals(expectedStateAfterAction, awaitItem())
+ testSubject.uiState.test {
+ assertEquals(expectedStateBeforeAction, awaitItem())
+ testSubject.onIncludeAppClick(app.packageName)
+ excludedAppsCallback.invoke(emptySet())
+ assertEquals(expectedStateAfterAction, awaitItem())
- verifyAll {
- mockedSplitTunneling.enabled
- mockedSplitTunneling.excludedAppsChange = any()
- mockedSplitTunneling.includeApp(app.packageName)
- }
+ verifyAll {
+ mockedSplitTunneling.enabled
+ mockedSplitTunneling.excludedAppsChange = any()
+ mockedSplitTunneling.includeApp(app.packageName)
}
}
+ }
@Test
- fun test_add_app_to_excluded() =
- runTest(testCoroutineRule.testDispatcher) {
- var excludedAppsCallback = slot<(Set<String>) -> Unit>()
- val app = AppData("test", 0, "testName")
- every { mockedSplitTunneling.excludeApp(app.packageName) } just runs
- every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers
- {
- excludedAppsCallback = lambda()
- excludedAppsCallback.invoke(emptySet())
- }
+ fun test_add_app_to_excluded() = runTest {
+ var excludedAppsCallback = slot<(Set<String>) -> Unit>()
+ val app = AppData("test", 0, "testName")
+ every { mockedSplitTunneling.excludeApp(app.packageName) } just runs
+ every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers
+ {
+ excludedAppsCallback = lambda()
+ excludedAppsCallback.invoke(emptySet())
+ }
- initTestSubject(listOf(app))
+ initTestSubject(listOf(app))
- val expectedStateBeforeAction =
- SplitTunnelingUiState.ShowAppList(
- excludedApps = emptyList(),
- includedApps = listOf(app),
- showSystemApps = false
- )
+ val expectedStateBeforeAction =
+ SplitTunnelingUiState.ShowAppList(
+ excludedApps = emptyList(),
+ includedApps = listOf(app),
+ showSystemApps = false
+ )
- val expectedStateAfterAction =
- SplitTunnelingUiState.ShowAppList(
- excludedApps = listOf(app),
- includedApps = emptyList(),
- showSystemApps = false
- )
+ val expectedStateAfterAction =
+ SplitTunnelingUiState.ShowAppList(
+ excludedApps = listOf(app),
+ includedApps = emptyList(),
+ showSystemApps = false
+ )
- testSubject.uiState.test {
- assertEquals(expectedStateBeforeAction, awaitItem())
- testSubject.onExcludeAppClick(app.packageName)
- excludedAppsCallback.invoke(setOf(app.packageName))
- assertEquals(expectedStateAfterAction, awaitItem())
+ testSubject.uiState.test {
+ assertEquals(expectedStateBeforeAction, awaitItem())
+ testSubject.onExcludeAppClick(app.packageName)
+ excludedAppsCallback.invoke(setOf(app.packageName))
+ assertEquals(expectedStateAfterAction, awaitItem())
- verifyAll {
- mockedSplitTunneling.enabled
- mockedSplitTunneling.excludedAppsChange = any()
- mockedSplitTunneling.excludeApp(app.packageName)
- }
+ verifyAll {
+ mockedSplitTunneling.enabled
+ mockedSplitTunneling.excludedAppsChange = any()
+ mockedSplitTunneling.excludeApp(app.packageName)
}
}
+ }
private fun initTestSubject(appList: List<AppData>) {
every { mockedApplicationsProvider.getAppsList() } returns appList
@@ -204,7 +200,7 @@ class SplitTunnelingViewModelTest {
SplitTunnelingViewModel(
mockedApplicationsProvider,
mockedServiceConnectionManager,
- testCoroutineRule.testDispatcher
+ UnconfinedTestDispatcher()
)
}
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModelTest.kt
index bfa068a381..7c54cd2c5e 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModelTest.kt
@@ -22,13 +22,13 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
import net.mullvad.mullvadvpn.ui.serviceconnection.VoucherRedeemer
import net.mullvad.mullvadvpn.ui.serviceconnection.voucherRedeemer
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class VoucherDialogViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val mockServiceConnectionManager: ServiceConnectionManager = mockk()
private val mockServiceConnectionContainer: ServiceConnectionContainer = mockk()
@@ -41,7 +41,7 @@ class VoucherDialogViewModelTest {
private lateinit var viewModel: VoucherDialogViewModel
- @Before
+ @BeforeEach
fun setUp() {
every { mockServiceConnectionManager.connectionState } returns serviceConnectionState
@@ -52,7 +52,7 @@ class VoucherDialogViewModelTest {
)
}
- @After
+ @AfterEach
fun tearDown() {
unmockkAll()
}
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt
index 0ac13777cd..51bbe3057c 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt
@@ -27,13 +27,13 @@ import net.mullvad.mullvadvpn.model.WireguardTunnelOptions
import net.mullvad.mullvadvpn.repository.SettingsRepository
import net.mullvad.mullvadvpn.usecase.PortRangeUseCase
import net.mullvad.mullvadvpn.usecase.RelayListUseCase
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class VpnSettingsViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val mockSettingsRepository: SettingsRepository = mockk()
private val mockResources: Resources = mockk()
@@ -45,7 +45,7 @@ class VpnSettingsViewModelTest {
private lateinit var viewModel: VpnSettingsViewModel
- @Before
+ @BeforeEach
fun setUp() {
every { mockSettingsRepository.settingsUpdates } returns mockSettingsUpdate
every { mockPortRangeUseCase.portRanges() } returns portRangeFlow
@@ -60,7 +60,7 @@ class VpnSettingsViewModelTest {
)
}
- @After
+ @AfterEach
fun tearDown() {
viewModel.viewModelScope.coroutineContext.cancel()
unmockkAll()
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt
index 29b0dfde75..d0461a4ee5 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt
+++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt
@@ -37,13 +37,13 @@ import net.mullvad.mullvadvpn.usecase.PaymentUseCase
import net.mullvad.talpid.util.EventNotifier
import org.joda.time.DateTime
import org.joda.time.ReadableInstant
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class WelcomeViewModelTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val serviceConnectionStateFlow =
MutableStateFlow<ServiceConnectionState>(ServiceConnectionState.Disconnected)
@@ -68,7 +68,7 @@ class WelcomeViewModelTest {
private lateinit var viewModel: WelcomeViewModel
- @Before
+ @BeforeEach
fun setUp() {
mockkStatic(SERVICE_CONNECTION_MANAGER_EXTENSIONS)
mockkStatic(PURCHASE_RESULT_EXTENSIONS_CLASS)
@@ -101,46 +101,44 @@ class WelcomeViewModelTest {
)
}
- @After
+ @AfterEach
fun tearDown() {
viewModel.viewModelScope.coroutineContext.cancel()
unmockkAll()
}
@Test
- fun testSitePaymentClick() =
- runTest(testCoroutineRule.testDispatcher) {
- // Arrange
- val mockToken = "4444 5555 6666 7777"
- val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true)
- every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache
- coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken
+ fun testSitePaymentClick() = runTest {
+ // Arrange
+ val mockToken = "4444 5555 6666 7777"
+ val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true)
+ every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache
+ coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken
- // Act, Assert
- viewModel.uiSideEffect.test {
- viewModel.onSitePaymentClick()
- val action = awaitItem()
- assertIs<WelcomeViewModel.UiSideEffect.OpenAccountView>(action)
- assertEquals(mockToken, action.token)
- }
+ // Act, Assert
+ viewModel.uiSideEffect.test {
+ viewModel.onSitePaymentClick()
+ val action = awaitItem()
+ assertIs<WelcomeViewModel.UiSideEffect.OpenAccountView>(action)
+ assertEquals(mockToken, action.token)
}
+ }
@Test
- fun testUpdateTunnelState() =
- runTest(testCoroutineRule.testDispatcher) {
- // Arrange
- val tunnelUiStateTestItem = TunnelState.Connected(mockk(), mockk())
+ fun testUpdateTunnelState() = runTest {
+ // Arrange
+ val tunnelUiStateTestItem = TunnelState.Connected(mockk(), mockk())
- // Act, Assert
- viewModel.uiState.test {
- assertEquals(WelcomeUiState(), awaitItem())
- eventNotifierTunnelUiState.notify(tunnelUiStateTestItem)
- serviceConnectionStateFlow.value =
- ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
- val result = awaitItem()
- assertEquals(tunnelUiStateTestItem, result.tunnelState)
- }
+ // Act, Assert
+ viewModel.uiState.test {
+ assertEquals(WelcomeUiState(), awaitItem())
+ eventNotifierTunnelUiState.notify(tunnelUiStateTestItem)
+ serviceConnectionStateFlow.value =
+ ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer)
+ val result = awaitItem()
+ assertEquals(tunnelUiStateTestItem, result.tunnelState)
}
+ }
@Test
fun testUpdateAccountNumber() = runTest {
@@ -165,19 +163,18 @@ class WelcomeViewModelTest {
}
@Test
- fun testOpenConnectScreen() =
- runTest(testCoroutineRule.testDispatcher) {
- // Arrange
- val mockExpiryDate: DateTime = mockk()
- every { mockExpiryDate.isAfter(any<ReadableInstant>()) } returns true
+ fun testOpenConnectScreen() = runTest {
+ // Arrange
+ val mockExpiryDate: DateTime = mockk()
+ every { mockExpiryDate.isAfter(any<ReadableInstant>()) } returns true
- // Act, Assert
- viewModel.uiSideEffect.test {
- outOfTimeFlow.value = false
- val action = awaitItem()
- assertIs<WelcomeViewModel.UiSideEffect.OpenConnectScreen>(action)
- }
+ // Act, Assert
+ viewModel.uiSideEffect.test {
+ outOfTimeFlow.value = false
+ val action = awaitItem()
+ assertIs<WelcomeViewModel.UiSideEffect.OpenConnectScreen>(action)
}
+ }
@Test
fun testBillingProductsUnavailableState() = runTest {