summaryrefslogtreecommitdiffhomepage
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
parentb5decd12a264c3e37092211eb0951dac6c640670 (diff)
parentb4167469808206ecc7ff2f788befe05e1d7ea57b (diff)
downloadmullvadvpn-6c754c3a45fdb93bcb6f9e615c00e70aaa8d90ba.tar.xz
mullvadvpn-6c754c3a45fdb93bcb6f9e615c00e70aaa8d90ba.zip
Merge branch 'update-to-junit5-droid-569'
-rw-r--r--.github/workflows/android-app.yml1
-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
-rw-r--r--android/buildSrc/src/main/kotlin/Dependencies.kt55
-rw-r--r--android/buildSrc/src/main/kotlin/Versions.kt4
-rw-r--r--android/gradle/verification-metadata.xml197
-rw-r--r--android/lib/billing/build.gradle.kts8
-rw-r--r--android/lib/billing/src/androidTest/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt14
-rw-r--r--android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt10
-rw-r--r--android/lib/common-test/build.gradle.kts12
-rw-r--r--android/lib/common-test/src/main/java/net/mullvad/mullvadvpn/lib/common/test/TestCoroutineRule.kt14
-rwxr-xr-xandroid/scripts/run-instrumented-tests.sh2
-rw-r--r--android/test/arch/build.gradle.kts2
-rw-r--r--android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/ArchitectureTests.kt2
-rw-r--r--android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/GeneralTests.kt2
-rw-r--r--android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/KonsistTests.kt2
-rw-r--r--android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/ViewModelTests.kt2
-rw-r--r--android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/ClassTests.kt2
-rw-r--r--android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/DataClassTests.kt2
-rw-r--r--android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/ValueClassTests.kt3
-rw-r--r--android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/compose/ComposePreviewTests.kt2
-rw-r--r--android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/compose/ComposeTests.kt2
-rw-r--r--android/test/arch/src/test/resources/junit-platform.properties6
-rw-r--r--android/test/common/build.gradle.kts12
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/CaptureScreenshotOnFailedTestRule.kt12
-rw-r--r--android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/ForgetAllVpnAppsInSettingsTestRule.kt8
-rw-r--r--android/test/e2e/build.gradle.kts18
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/ConnectionTest.kt12
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/EndToEndTest.kt25
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LaunchAppTest.kt5
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LoginTest.kt9
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/WebLinkTest.kt2
-rw-r--r--android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/CleanupAccountTestRule.kt11
-rw-r--r--android/test/firebase-test-lab.yml1
-rw-r--r--android/test/mockapi/build.gradle.kts17
-rw-r--r--android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LoginMockApiTest.kt7
-rw-r--r--android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LogoutMockApiTest.kt7
-rw-r--r--android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiTest.kt23
83 files changed, 3323 insertions, 3010 deletions
diff --git a/.github/workflows/android-app.yml b/.github/workflows/android-app.yml
index 97040b1cf5..70b5c3ca7d 100644
--- a/.github/workflows/android-app.yml
+++ b/.github/workflows/android-app.yml
@@ -220,6 +220,7 @@ jobs:
testDebugUnitTest -x :test:arch:testDebugUnitTest
:app:testOssProdDebugUnitTest
:service:testOssProdDebugUnitTest
+ :lib:billing:testDebugUnitTest
gradle-version: wrapper
build-root-directory: android
execution-only-caches: true
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 {
diff --git a/android/buildSrc/src/main/kotlin/Dependencies.kt b/android/buildSrc/src/main/kotlin/Dependencies.kt
index 8e38491f41..c68e6b417c 100644
--- a/android/buildSrc/src/main/kotlin/Dependencies.kt
+++ b/android/buildSrc/src/main/kotlin/Dependencies.kt
@@ -2,7 +2,15 @@ object Dependencies {
const val androidVolley = "com.android.volley:volley:${Versions.Android.volley}"
const val commonsValidator = "commons-validator:commons-validator:${Versions.commonsValidator}"
const val jodaTime = "joda-time:joda-time:${Versions.jodaTime}"
- const val junit = "junit:junit:${Versions.junit}"
+ const val junitApi = "org.junit.jupiter:junit-jupiter-api:${Versions.junit}"
+ const val junitEngine = "org.junit.jupiter:junit-jupiter-engine:${Versions.junit}"
+ const val junitParams = "org.junit.jupiter:junit-jupiter-params:${Versions.junit}"
+ const val junitAndroidTestExtensions =
+ "de.mannodermaus.junit5:android-test-core:${Versions.Android.junit}"
+ const val junitAndroidTestCore =
+ "de.mannodermaus.junit5:android-test-extensions:${Versions.Android.junit}"
+ const val junitAndroidTestRunner =
+ "de.mannodermaus.junit5:android-test-runner:${Versions.Android.junit}"
const val konsist = "com.lemonappdev:konsist:${Versions.konsist}"
const val leakCanary = "com.squareup.leakcanary:leakcanary-android:${Versions.leakCanary}"
const val mockkWebserver = "com.squareup.okhttp3:mockwebserver:${Versions.mockWebserver}"
@@ -22,14 +30,10 @@ object Dependencies {
"androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.AndroidX.lifecycle}"
const val espressoCore =
"androidx.test.espresso:espresso-core:${Versions.AndroidX.espresso}"
- const val testCore =
- "androidx.test:core:${Versions.AndroidX.test}"
- const val testMonitor =
- "androidx.test:monitor:${Versions.AndroidX.testMonitor}"
- const val testRunner =
- "androidx.test:runner:${Versions.AndroidX.testRunner}"
- const val testRules =
- "androidx.test:rules:${Versions.AndroidX.test}"
+ const val testCore = "androidx.test:core:${Versions.AndroidX.test}"
+ const val testMonitor = "androidx.test:monitor:${Versions.AndroidX.testMonitor}"
+ const val testRunner = "androidx.test:runner:${Versions.AndroidX.testRunner}"
+ const val testRules = "androidx.test:rules:${Versions.AndroidX.test}"
const val testUiAutomator =
"androidx.test.uiautomator:uiautomator:${Versions.AndroidX.uiautomator}"
const val testOrchestrator =
@@ -37,25 +41,27 @@ object Dependencies {
}
object Compose {
- const val destinations = "io.github.raamcosta.compose-destinations:core:${Versions.Compose.destinations}"
- const val destinationsKsp = "io.github.raamcosta.compose-destinations:ksp:${Versions.Compose.destinations}"
const val constrainLayout =
"androidx.constraintlayout:constraintlayout-compose:${Versions.Compose.constrainLayout}"
+ const val destinations =
+ "io.github.raamcosta.compose-destinations:core:${Versions.Compose.destinations}"
+ const val destinationsKsp =
+ "io.github.raamcosta.compose-destinations:ksp:${Versions.Compose.destinations}"
const val foundation =
"androidx.compose.foundation:foundation:${Versions.Compose.foundation}"
- const val junit = "androidx.compose.ui:ui-test-junit4:${Versions.Compose.base}"
+ const val junit5 = "de.mannodermaus.junit5:android-test-compose:${Versions.Android.junit}"
const val material3 = "androidx.compose.material3:material3:${Versions.Compose.material3}"
const val testManifest = "androidx.compose.ui:ui-test-manifest:${Versions.Compose.base}"
+ const val ui = "androidx.compose.ui:ui:${Versions.Compose.base}"
const val uiController =
"com.google.accompanist:accompanist-systemuicontroller:${Versions.Compose.uiController}"
- const val ui = "androidx.compose.ui:ui:${Versions.Compose.base}"
- const val uiUtil = "androidx.compose.ui:ui-util:${Versions.Compose.base}"
+ const val uiTestManifest = "androidx.compose.ui:ui-test-manifest:${Versions.Compose.base}"
const val uiTooling = "androidx.compose.ui:ui-tooling:${Versions.Compose.base}"
- const val uiToolingPreview =
- "androidx.compose.ui:ui-tooling-preview:${Versions.Compose.base}"
const val uiToolingAndroidPreview =
"androidx.compose.ui:ui-tooling-preview-android:${Versions.Compose.base}"
-
+ const val uiToolingPreview =
+ "androidx.compose.ui:ui-tooling-preview:${Versions.Compose.base}"
+ const val uiUtil = "androidx.compose.ui:ui-util:${Versions.Compose.base}"
}
object Koin {
@@ -111,17 +117,18 @@ object Dependencies {
const val androidApplicationId = "com.android.application"
const val androidLibraryId = "com.android.library"
const val androidTestId = "com.android.test"
- const val playPublisher =
- "com.github.triplet.gradle:play-publisher:${Versions.Plugin.playPublisher}"
- const val playPublisherId = "com.github.triplet.play"
- const val kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}"
- const val kotlinAndroidId = "kotlin-android"
- const val kotlinParcelizeId = "kotlin-parcelize"
const val dependencyCheck =
"org.owasp:dependency-check-gradle:${Versions.Plugin.dependencyCheck}"
const val dependencyCheckId = "org.owasp.dependencycheck"
const val gradleVersionsId = "com.github.ben-manes.versions"
- const val ktfmtId = "com.ncorti.ktfmt.gradle"
+ const val junit5 = "de.mannodermaus.android-junit5"
+ const val kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}"
+ const val kotlinAndroidId = "kotlin-android"
+ const val kotlinParcelizeId = "kotlin-parcelize"
const val ksp = "com.google.devtools.ksp"
+ const val ktfmtId = "com.ncorti.ktfmt.gradle"
+ const val playPublisher =
+ "com.github.triplet.gradle:play-publisher:${Versions.Plugin.playPublisher}"
+ const val playPublisherId = "com.github.triplet.play"
}
}
diff --git a/android/buildSrc/src/main/kotlin/Versions.kt b/android/buildSrc/src/main/kotlin/Versions.kt
index fede1556f7..dc5c5d923b 100644
--- a/android/buildSrc/src/main/kotlin/Versions.kt
+++ b/android/buildSrc/src/main/kotlin/Versions.kt
@@ -1,7 +1,7 @@
object Versions {
const val commonsValidator = "1.7"
const val jodaTime = "2.12.5"
- const val junit = "4.13.2"
+ const val junit = "5.10.0"
const val jvmTarget = "17"
const val konsist = "0.13.0"
const val kotlin = "1.9.20"
@@ -15,6 +15,7 @@ object Versions {
object Android {
const val compileSdkVersion = 34
+ const val junit = "1.4.0"
const val minSdkVersion = 26
const val targetSdkVersion = 34
const val volley = "1.2.1"
@@ -52,6 +53,7 @@ object Versions {
const val playPublisher = "3.8.4"
const val dependencyCheck = "8.3.1"
const val gradleVersions = "0.47.0"
+ const val junit5 = "1.10.0.0"
const val ktfmt = "0.13.0"
// Ksp version is linked with kotlin version, find matching release here:
// https://github.com/google/ksp/releases
diff --git a/android/gradle/verification-metadata.xml b/android/gradle/verification-metadata.xml
index e485d83a53..407f9ac4ae 100644
--- a/android/gradle/verification-metadata.xml
+++ b/android/gradle/verification-metadata.xml
@@ -540,9 +540,6 @@
<artifact name="ui-test-1.5.4.module">
<sha256 value="6ad78d22dfff246664b3caf88dd91d4c837f47d14315331a4b8d0700da51ff1d" origin="Generated by Gradle"/>
</artifact>
- <artifact name="ui-test-metadata-1.5.4.jar">
- <sha256 value="a9f9ce977bc3a5c57e12340087834ebc9f52343aab6bd8b7dcf9c08b775a93b1" origin="Generated by Gradle"/>
- </artifact>
</component>
<component group="androidx.compose.ui" name="ui-test-android" version="1.5.4">
<artifact name="ui-test-android-1.5.4.module">
@@ -556,9 +553,6 @@
<artifact name="ui-test-junit4-1.5.4.module">
<sha256 value="14aad961ae38615114c12864cef8452df919a5e26b1d6cbe54b352e4aaf8fab5" origin="Generated by Gradle"/>
</artifact>
- <artifact name="ui-test-junit4-metadata-1.5.4.jar">
- <sha256 value="06bb89cb0c2afd886b48a04e7c70a027f08f52916b7b3b175f0b873cab3d8473" origin="Generated by Gradle"/>
- </artifact>
</component>
<component group="androidx.compose.ui" name="ui-test-junit4-android" version="1.5.4">
<artifact name="ui-test-junit4-android-1.5.4.module">
@@ -1000,6 +994,11 @@
<sha256 value="19a287b46d1b1ffe297bee0df7dee5183aeba95600ec0de8742adeb5b67c8bab" origin="Generated by Gradle"/>
</artifact>
</component>
+ <component group="androidx.lifecycle" name="lifecycle-livedata-core" version="2.3.0">
+ <artifact name="lifecycle-livedata-core-2.3.0.module">
+ <sha256 value="1db780dc703f46140f87c8c6ad856e3d7bbd3ec1312dfdbb6467083913fe333b" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
<component group="androidx.lifecycle" name="lifecycle-livedata-core" version="2.3.1">
<artifact name="lifecycle-livedata-core-2.3.1.module">
<sha256 value="b1e095d550d39a7d6c815761d6dbe3fd64eb31a39dc28146e78bbf2c01ba8f41" origin="Generated by Gradle"/>
@@ -1959,6 +1958,11 @@
<sha256 value="7f94aa7d964719faa5d9bff42c7960f906e738f16b84e28a7a6dcc2955140041" origin="Generated by Gradle"/>
</artifact>
</component>
+ <component group="com.github.zafarkhaja" name="java-semver" version="0.9.0">
+ <artifact name="java-semver-0.9.0.jar">
+ <sha256 value="2218c73b40f9af98b570d084420c1b4a81332297bd7fc27ddd552e903be8e93c" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
<component group="com.google.accompanist" name="accompanist-systemuicontroller" version="0.30.1">
<artifact name="accompanist-systemuicontroller-0.30.1.aar">
<sha256 value="82a6e25cf7ba1aa1e7e8505056b1651a785360e78aebcbc1f1c1731ddba39c26" origin="Generated by Gradle"/>
@@ -2536,6 +2540,44 @@
<sha256 value="4d74f4ce4fb68b2617edad086df6defdf9338467d2377d2c62e69038e1c4f02f" origin="Generated by Gradle"/>
</artifact>
</component>
+ <component group="de.mannodermaus.gradle.plugins" name="android-junit5" version="1.10.0.0">
+ <artifact name="android-junit5-1.10.0.0.jar">
+ <sha256 value="ca2c6bda5007c4090b22678988ff4587a1b81aa18a206c67629bfb1a293233bc" origin="Generated by Gradle"/>
+ </artifact>
+ <artifact name="android-junit5-1.10.0.0.module">
+ <sha256 value="40503f74e4d4467d5f6e5dd784b3e06c4add9b56abf45d1b5b5d7304609cd5fa" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="de.mannodermaus.junit5" name="android-test-compose" version="1.4.0">
+ <artifact name="android-test-compose-1.4.0.aar">
+ <sha256 value="7c05bc0331d64e7491dc65b1d370ecd96d49d84e7325e4c6f6c64b4a07e600e9" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="de.mannodermaus.junit5" name="android-test-core" version="1.3.0">
+ <artifact name="android-test-core-1.3.0.aar">
+ <sha256 value="fdf2d6bab38e81ff203c6a2fc7da7ccea248f034fdf722fad6be7d4a4f5bc9b9" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="de.mannodermaus.junit5" name="android-test-core" version="1.4.0">
+ <artifact name="android-test-core-1.4.0.aar">
+ <sha256 value="2f404bae82a203ca8b8e7fef7a7081649587c425aef4ad8f014e0f6d2f816c5a" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="de.mannodermaus.junit5" name="android-test-extensions" version="1.4.0">
+ <artifact name="android-test-extensions-1.4.0.aar">
+ <sha256 value="afc316c7348b03e4aeaf37d1595804ffd1efa216d59b326b7d2e96265023daa3" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="de.mannodermaus.junit5" name="android-test-runner" version="1.3.0">
+ <artifact name="android-test-runner-1.3.0.aar">
+ <sha256 value="c1708cddbf2720aa8b65820b91a7e4e3ccb658c491e13670500b3c6ba784dfdd" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="de.mannodermaus.junit5" name="android-test-runner" version="1.4.0">
+ <artifact name="android-test-runner-1.4.0.aar">
+ <sha256 value="9c17ca630fc6f92a3ad41025eee82a2b6d09cce05b82975daa1b8c10420d8a9e" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
<component group="io.github.java-diff-utils" name="java-diff-utils" version="4.12">
<artifact name="java-diff-utils-4.12.jar">
<sha256 value="9990a2039778f6b4cc94790141c2868864eacee0620c6c459451121a901cd5b5" origin="Generated by Gradle"/>
@@ -3023,6 +3065,14 @@
<sha256 value="b086cee8fd8183e240b4afcf54fe38ec33dd8eb0da414636e5bf7aa4d9856629" origin="Generated by Gradle"/>
</artifact>
</component>
+ <component group="org.apiguardian" name="apiguardian-api" version="1.1.2">
+ <artifact name="apiguardian-api-1.1.2.jar">
+ <sha256 value="b509448ac506d607319f182537f0b35d71007582ec741832a1f111e5b5b70b38" origin="Generated by Gradle"/>
+ </artifact>
+ <artifact name="apiguardian-api-1.1.2.module">
+ <sha256 value="e08028131375b357d1d28734e9a4fb4216da84b240641cb3ef7e7c7d628223fc" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
<component group="org.bitbucket.b_c" name="jose4j" version="0.7.0">
<artifact name="jose4j-0.7.0.jar">
<sha256 value="eb14f69c0395d4a106c6c46fe6dff080c4608ccabc99b1f03933d374383d9bbe" origin="Generated by Gradle"/>
@@ -3681,6 +3731,14 @@
<sha256 value="8d0e9afded89a5d6fa4fa66b588f8e42548019f8eaf7d19229492a270b056003" origin="Generated by Gradle"/>
</artifact>
</component>
+ <component group="org.jetbrains.kotlin" name="kotlin-test-junit5" version="1.9.20">
+ <artifact name="kotlin-test-junit5-1.9.20.jar">
+ <sha256 value="f4a6326ba68ad10649f8cae24787934e3a0592604d47a3ac5ed2be946aa24513" origin="Generated by Gradle"/>
+ </artifact>
+ <artifact name="kotlin-test-junit5-1.9.20.module">
+ <sha256 value="473995a0eeb48b5c42b8da5edeea86c6fb3c0807d168f5ae3ee48c7b84415fee" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
<component group="org.jetbrains.kotlin" name="kotlin-tooling-core" version="1.8.20">
<artifact name="kotlin-tooling-core-1.8.20.jar">
<sha256 value="7a412677e73a59588cdad4cb9c7f8e3bb70bae5db66933b4b3f3ece0071b4cad" origin="Generated by Gradle"/>
@@ -3867,11 +3925,6 @@
<sha256 value="2ddfad185b7cc7e3a2e4707c916525d37ce62cf6572ad5fcac2b9f4ba70e010a" origin="Generated by Gradle"/>
</artifact>
</component>
- <component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-test-jvm" version="1.6.4">
- <artifact name="kotlinx-coroutines-test-jvm-1.6.4.module">
- <sha256 value="1de1976cdf3f5625e88815795259c6046a5de7c0121143bd9ce55353017169a6" origin="Generated by Gradle"/>
- </artifact>
- </component>
<component group="org.jetbrains.kotlinx" name="kotlinx-coroutines-test-jvm" version="1.7.3">
<artifact name="kotlinx-coroutines-test-jvm-1.7.3.jar">
<sha256 value="d19742a65dbdabc9ffdcb9f84a15c776e511a14da602d54ea4e078d6f7227a26" origin="Generated by Gradle"/>
@@ -3885,11 +3938,21 @@
<sha256 value="1f115726540ddf71958c14bc517ebfc49cf481e91cd917b0face84f01272e901" origin="Generated by Gradle"/>
</artifact>
</component>
+ <component group="org.junit" name="junit-bom" version="5.10.0">
+ <artifact name="junit-bom-5.10.0.module">
+ <sha256 value="eb3ee6127608010694a898056e7407d117296003aba5f5db801df430b9887fcf" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
<component group="org.junit" name="junit-bom" version="5.7.1">
<artifact name="junit-bom-5.7.1.module">
<sha256 value="9854e3894d64b2485207e0046bca07b3d42d169e782f4fa8c9ce229a78faee04" origin="Generated by Gradle"/>
</artifact>
</component>
+ <component group="org.junit" name="junit-bom" version="5.8.0">
+ <artifact name="junit-bom-5.8.0.module">
+ <sha256 value="2b1e09d9c309fce558a52972f37e833cf5a22a3e19899ab20c08c872c01983f6" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
<component group="org.junit" name="junit-bom" version="5.8.0-M1">
<artifact name="junit-bom-5.8.0-M1.module">
<sha256 value="be051471303a503f4c22467075b2749041377ddd6d5a8cb0739ded67d916d82d" origin="Generated by Gradle"/>
@@ -3925,52 +3988,99 @@
<sha256 value="b401fd25901e582a524aa5343c4b39e28bc56e24961c1069bf2b4bbfcee46b93" origin="Generated by Gradle"/>
</artifact>
</component>
- <component group="org.junit.jupiter" name="junit-jupiter" version="5.8.2">
- <artifact name="junit-jupiter-5.8.2.jar">
- <sha256 value="4f5c1cc6432244cd16e36aa0e02b74bce34a81ff95a13d63d50951ec4ce3f4bd" origin="Generated by Gradle"/>
+ <component group="org.junit.jupiter" name="junit-jupiter" version="5.10.0">
+ <artifact name="junit-jupiter-5.10.0.jar">
+ <sha256 value="8e4bde23ee28fc443975654a7b28c410a3b78d6be96b78c99ab73695ec344f7c" origin="Generated by Gradle"/>
</artifact>
+ <artifact name="junit-jupiter-5.10.0.module">
+ <sha256 value="0570e0832a5465a82f04a2b8f761f2bb1e30fafe282d2a30987015fcb0507603" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="org.junit.jupiter" name="junit-jupiter" version="5.8.2">
<artifact name="junit-jupiter-5.8.2.module">
<sha256 value="d9df47b3c7431883ab1f1f1d820c2980ebcbd753edc4c82b99bf5ec2c533ad2e" origin="Generated by Gradle"/>
</artifact>
</component>
- <component group="org.junit.jupiter" name="junit-jupiter-api" version="5.8.2">
- <artifact name="junit-jupiter-api-5.8.2.jar">
- <sha256 value="1808ee87e0f718cd6e25f3b75afc17956ac8a3edc48c7e9bab9f19f9a79e3801" origin="Generated by Gradle"/>
+ <component group="org.junit.jupiter" name="junit-jupiter-api" version="5.10.0">
+ <artifact name="junit-jupiter-api-5.10.0.jar">
+ <sha256 value="108088fd7ea46a8e65a0ce7f5d75ae3ff7865606770a078715f5a6e5709e17d8" origin="Generated by Gradle"/>
</artifact>
- <artifact name="junit-jupiter-api-5.8.2.module">
- <sha256 value="7e9af4dfff6267acddd157d9e11ba0d5dc91b332fa74bc4c65939e4517a1b770" origin="Generated by Gradle"/>
+ <artifact name="junit-jupiter-api-5.10.0.module">
+ <sha256 value="ae5661cd381e109a3c3575b3ab2ded7479e7bdd7cec4aa9f26d437897340979b" origin="Generated by Gradle"/>
</artifact>
</component>
- <component group="org.junit.jupiter" name="junit-jupiter-engine" version="5.8.2">
- <artifact name="junit-jupiter-engine-5.8.2.jar">
- <sha256 value="753b7726cdd158bb34cedb94c161e2291896f47832a1e9eda53d970020a8184e" origin="Generated by Gradle"/>
+ <component group="org.junit.jupiter" name="junit-jupiter-engine" version="5.10.0">
+ <artifact name="junit-jupiter-engine-5.10.0.jar">
+ <sha256 value="57ea48e6f795200791065bbc86b70b84cd05367c5c9f2ac8f9268e27154c88a8" origin="Generated by Gradle"/>
</artifact>
- <artifact name="junit-jupiter-engine-5.8.2.module">
- <sha256 value="a56204c716c2379970ca8e3fe2a72e3a030cd9027328d3ce1457dd10c0150e7e" origin="Generated by Gradle"/>
+ <artifact name="junit-jupiter-engine-5.10.0.module">
+ <sha256 value="6a108572905d1ed19c02dcd078f34c1edeb31555f5442176e01418270085626a" origin="Generated by Gradle"/>
</artifact>
</component>
- <component group="org.junit.jupiter" name="junit-jupiter-params" version="5.8.2">
- <artifact name="junit-jupiter-params-5.8.2.jar">
- <sha256 value="d1c22d6fe5483568c08c8913f34abd2303490c3480ce6c18a2ea31c65e44102a" origin="Generated by Gradle"/>
+ <component group="org.junit.jupiter" name="junit-jupiter-engine" version="5.8.0">
+ <artifact name="junit-jupiter-engine-5.8.0.module">
+ <sha256 value="cf5aa188633997c81cece9bcbbe9092471af4f290b3cb91e50318fee0ba8d1d6" origin="Generated by Gradle"/>
</artifact>
- <artifact name="junit-jupiter-params-5.8.2.module">
- <sha256 value="5023e4e3ec156ec6bd3cf655f3070cfc5a3e8aad5d51b4bbe025a792e9498d73" origin="Generated by Gradle"/>
+ </component>
+ <component group="org.junit.jupiter" name="junit-jupiter-params" version="5.10.0">
+ <artifact name="junit-jupiter-params-5.10.0.jar">
+ <sha256 value="f259a7322cce375430c2236a2dcb24d4a49d22045b723ad85af88e11704391c2" origin="Generated by Gradle"/>
+ </artifact>
+ <artifact name="junit-jupiter-params-5.10.0.module">
+ <sha256 value="196f7f4efdf9c773a7104c339f6025342b8742fcfab02f8802ba8027ed28f92e" origin="Generated by Gradle"/>
</artifact>
</component>
- <component group="org.junit.platform" name="junit-platform-commons" version="1.8.2">
- <artifact name="junit-platform-commons-1.8.2.jar">
- <sha256 value="d2e015fca7130e79af2f4608dc54415e4b10b592d77333decb4b1a274c185050" origin="Generated by Gradle"/>
+ <component group="org.junit.platform" name="junit-platform-commons" version="1.10.0">
+ <artifact name="junit-platform-commons-1.10.0.jar">
+ <sha256 value="6083db08ca11fca1e16099d0dcfede0193d80b3762b276349d80d3da536791b2" origin="Generated by Gradle"/>
</artifact>
- <artifact name="junit-platform-commons-1.8.2.module">
- <sha256 value="342847d3046fea435595692db4f05d5f039e0e1d1e204f4d5755902557082626" origin="Generated by Gradle"/>
+ <artifact name="junit-platform-commons-1.10.0.module">
+ <sha256 value="8cb60d3df81d606ea1be3e3fcae5697653b1b303e2f7a9822a7ed1264745fc27" origin="Generated by Gradle"/>
</artifact>
</component>
- <component group="org.junit.platform" name="junit-platform-engine" version="1.8.2">
- <artifact name="junit-platform-engine-1.8.2.jar">
- <sha256 value="0b7d000f8c3e8e5f7d6b819649936e7b9938314e87c8f983805218ea57567e59" origin="Generated by Gradle"/>
+ <component group="org.junit.platform" name="junit-platform-engine" version="1.10.0">
+ <artifact name="junit-platform-engine-1.10.0.jar">
+ <sha256 value="cd338efd02ee73966ea754e0c0c71e1a11f4af5db9c2003e4b6137e119155abe" origin="Generated by Gradle"/>
</artifact>
- <artifact name="junit-platform-engine-1.8.2.module">
- <sha256 value="eba77b36efdf75a67f46438333825f9e448f550d521e7249d950358580ee636b" origin="Generated by Gradle"/>
+ <artifact name="junit-platform-engine-1.10.0.module">
+ <sha256 value="76e08c83f93dd52b83e885b900920c1dc85e3686880f6653af2b22317f4dde37" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="org.junit.platform" name="junit-platform-launcher" version="1.10.0">
+ <artifact name="junit-platform-launcher-1.10.0.jar">
+ <sha256 value="8c60b661ac170701a635dfc67565efbb8c85b5c5cdd5a4a9576e3a015c7111a4" origin="Generated by Gradle"/>
+ </artifact>
+ <artifact name="junit-platform-launcher-1.10.0.module">
+ <sha256 value="f5dcb7408c4242603f99bd5cdc635c4066d18a828db85ed3700aa8dd3eaf1a69" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="org.junit.platform" name="junit-platform-runner" version="1.10.0">
+ <artifact name="junit-platform-runner-1.10.0.jar">
+ <sha256 value="8bc9c0c41bc8a5215fb7304d3b213ef1817abb2b97b0f1007191a9276a19091d" origin="Generated by Gradle"/>
+ </artifact>
+ <artifact name="junit-platform-runner-1.10.0.module">
+ <sha256 value="2629524ea1b1d4c9bfda7f90fca0961f621770da23c8523c29fab0cff3bf883c" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="org.junit.platform" name="junit-platform-runner" version="1.8.0">
+ <artifact name="junit-platform-runner-1.8.0.module">
+ <sha256 value="75c619e946e7d168ef465bfd3d8d70566bfc3bb447f1712aa33fc9570bccc817" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="org.junit.platform" name="junit-platform-suite-api" version="1.10.0">
+ <artifact name="junit-platform-suite-api-1.10.0.jar">
+ <sha256 value="29375380c304d96c93466dd2d21e7a0692381689a0a2205e3c0d1961638beaf3" origin="Generated by Gradle"/>
+ </artifact>
+ <artifact name="junit-platform-suite-api-1.10.0.module">
+ <sha256 value="df78221e56e13850a857deb0ba7573949a8a1a6ba82580a2a028534548578903" origin="Generated by Gradle"/>
+ </artifact>
+ </component>
+ <component group="org.junit.platform" name="junit-platform-suite-commons" version="1.10.0">
+ <artifact name="junit-platform-suite-commons-1.10.0.jar">
+ <sha256 value="01eb735855dc0d9d24d7219c84c4d4bf8751a126101e56948f792b27289f676b" origin="Generated by Gradle"/>
+ </artifact>
+ <artifact name="junit-platform-suite-commons-1.10.0.module">
+ <sha256 value="11652b259d60afe3511fd016f6631b2c82c66e571fb9c6460b08a43fb3292768" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.jvnet.staxex" name="stax-ex" version="1.8.1">
@@ -3983,9 +4093,12 @@
<sha256 value="02dfd0b0439a5591e35b708ed2f5474eb0948f53abf74637e959b8e4ef69bfeb" origin="Generated by Gradle"/>
</artifact>
</component>
- <component group="org.opentest4j" name="opentest4j" version="1.2.0">
- <artifact name="opentest4j-1.2.0.jar">
- <sha256 value="58812de60898d976fb81ef3b62da05c6604c18fd4a249f5044282479fc286af2" origin="Generated by Gradle"/>
+ <component group="org.opentest4j" name="opentest4j" version="1.3.0">
+ <artifact name="opentest4j-1.3.0.jar">
+ <sha256 value="48e2df636cab6563ced64dcdff8abb2355627cb236ef0bf37598682ddf742f1b" origin="Generated by Gradle"/>
+ </artifact>
+ <artifact name="opentest4j-1.3.0.module">
+ <sha256 value="48bf1d6c8b5dc94f74652bd17900f654deb714350248cf5e8fca27b9090c8e0d" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.ow2.asm" name="asm" version="9.2">
diff --git a/android/lib/billing/build.gradle.kts b/android/lib/billing/build.gradle.kts
index 8ecc14f7cd..26cc345556 100644
--- a/android/lib/billing/build.gradle.kts
+++ b/android/lib/billing/build.gradle.kts
@@ -1,5 +1,6 @@
plugins {
id(Dependencies.Plugin.androidLibraryId)
+ id(Dependencies.Plugin.junit5) version Versions.Plugin.junit5
id(Dependencies.Plugin.kotlinAndroidId)
}
@@ -55,11 +56,13 @@ dependencies {
implementation(project(Dependencies.Mullvad.paymentLib))
// Test dependencies
+ testRuntimeOnly(Dependencies.junitEngine)
+
testImplementation(project(Dependencies.Mullvad.commonTestLib))
testImplementation(Dependencies.Kotlin.test)
testImplementation(Dependencies.KotlinX.coroutinesTest)
testImplementation(Dependencies.MockK.core)
- testImplementation(Dependencies.junit)
+ testImplementation(Dependencies.junitApi)
testImplementation(Dependencies.turbine)
androidTestImplementation(project(Dependencies.Mullvad.commonTestLib))
@@ -67,6 +70,7 @@ dependencies {
androidTestImplementation(Dependencies.Kotlin.test)
androidTestImplementation(Dependencies.KotlinX.coroutinesTest)
androidTestImplementation(Dependencies.turbine)
- androidTestImplementation(Dependencies.junit)
+ androidTestImplementation(Dependencies.junitApi)
+ androidTestImplementation(Dependencies.junitEngine)
androidTestImplementation(Dependencies.AndroidX.espressoCore)
}
diff --git a/android/lib/billing/src/androidTest/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt b/android/lib/billing/src/androidTest/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt
index e6f5225740..386932681d 100644
--- a/android/lib/billing/src/androidTest/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt
+++ b/android/lib/billing/src/androidTest/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingRepositoryTest.kt
@@ -34,13 +34,13 @@ import net.mullvad.mullvadvpn.lib.billing.model.BillingException
import net.mullvad.mullvadvpn.lib.billing.model.PurchaseEvent
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.lib.common.test.assertLists
-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 BillingRepositoryTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val mockContext: Context = mockk()
private lateinit var billingRepository: BillingRepository
@@ -51,7 +51,7 @@ class BillingRepositoryTest {
private val purchaseUpdatedListenerSlot: CapturingSlot<PurchasesUpdatedListener> =
CapturingSlot()
- @Before
+ @BeforeEach
fun setUp() {
mockkStatic(BILLING_CLIENT_CLASS)
mockkStatic(BILLING_CLIENT_KOTLIN_CLASS)
@@ -66,7 +66,7 @@ class BillingRepositoryTest {
billingRepository = BillingRepository(mockContext)
}
- @After
+ @AfterEach
fun tearDown() {
unmockkAll()
}
diff --git a/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt b/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt
index fe25457e49..21e13d5da8 100644
--- a/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt
+++ b/android/lib/billing/src/test/kotlin/net/mullvad/mullvadvpn/lib/billing/BillingPaymentRepositoryTest.kt
@@ -25,12 +25,12 @@ import net.mullvad.mullvadvpn.model.PlayPurchaseInitError
import net.mullvad.mullvadvpn.model.PlayPurchaseInitResult
import net.mullvad.mullvadvpn.model.PlayPurchaseVerifyError
import net.mullvad.mullvadvpn.model.PlayPurchaseVerifyResult
-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.ExtendWith
+@ExtendWith(TestCoroutineRule::class)
class BillingPaymentRepositoryTest {
- @get:Rule val testCoroutineRule = TestCoroutineRule()
private val mockBillingRepository: BillingRepository = mockk()
private val mockPlayPurchaseRepository: PlayPurchaseRepository = mockk()
@@ -39,7 +39,7 @@ class BillingPaymentRepositoryTest {
private lateinit var paymentRepository: BillingPaymentRepository
- @Before
+ @BeforeEach
fun setUp() {
mockkStatic(PRODUCT_DETAILS_TO_PAYMENT_PRODUCT_EXT)
diff --git a/android/lib/common-test/build.gradle.kts b/android/lib/common-test/build.gradle.kts
index 3d0ef6c028..6e3fc7c02f 100644
--- a/android/lib/common-test/build.gradle.kts
+++ b/android/lib/common-test/build.gradle.kts
@@ -21,10 +21,20 @@ android {
abortOnError = true
warningsAsErrors = true
}
+
+ packaging {
+ resources {
+ pickFirsts += setOf(
+ // Fixes packaging error caused by: jetified-junit-*
+ "META-INF/LICENSE.md",
+ "META-INF/LICENSE-notice.md"
+ )
+ }
+ }
}
dependencies {
implementation(Dependencies.Kotlin.test)
implementation(Dependencies.KotlinX.coroutinesTest)
- implementation(Dependencies.junit)
+ implementation(Dependencies.junitApi)
}
diff --git a/android/lib/common-test/src/main/java/net/mullvad/mullvadvpn/lib/common/test/TestCoroutineRule.kt b/android/lib/common-test/src/main/java/net/mullvad/mullvadvpn/lib/common/test/TestCoroutineRule.kt
index d04983be26..34d6739119 100644
--- a/android/lib/common-test/src/main/java/net/mullvad/mullvadvpn/lib/common/test/TestCoroutineRule.kt
+++ b/android/lib/common-test/src/main/java/net/mullvad/mullvadvpn/lib/common/test/TestCoroutineRule.kt
@@ -6,22 +6,20 @@ import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
-import org.junit.rules.TestWatcher
-import org.junit.runner.Description
+import org.junit.jupiter.api.extension.AfterEachCallback
+import org.junit.jupiter.api.extension.BeforeEachCallback
+import org.junit.jupiter.api.extension.ExtensionContext
@OptIn(ExperimentalCoroutinesApi::class)
class TestCoroutineRule(val testDispatcher: TestDispatcher = UnconfinedTestDispatcher()) :
- TestWatcher() {
+ BeforeEachCallback, AfterEachCallback {
- override fun starting(description: Description) {
- super.starting(description)
+ override fun beforeEach(var1: ExtensionContext?) {
Dispatchers.setMain(testDispatcher)
}
- override fun finished(description: Description) {
- super.finished(description)
+ override fun afterEach(var1: ExtensionContext?) {
Dispatchers.resetMain()
- // Replacement for cleanupTestCoroutines()
testDispatcher.scheduler.runCurrent()
}
}
diff --git a/android/scripts/run-instrumented-tests.sh b/android/scripts/run-instrumented-tests.sh
index 5c6ace121b..3d25480854 100755
--- a/android/scripts/run-instrumented-tests.sh
+++ b/android/scripts/run-instrumented-tests.sh
@@ -122,11 +122,13 @@ if [[ "$USE_ORCHESTRATOR" == "true" ]]; then
am instrument -r -w \
-e targetInstrumentation $TEST_PACKAGE/androidx.test.runner.AndroidJUnitRunner \
-e clearPackageData true \
+ -e runnerBuilder de.mannodermaus.junit5.AndroidJUnit5Builder \
${OPTIONAL_TEST_ARGUMENTS:-""} \
androidx.test.orchestrator/androidx.test.orchestrator.AndroidTestOrchestrator"
else
INSTRUMENTATION_COMMAND="\
am instrument -w \
+ -e runnerBuilder de.mannodermaus.junit5.AndroidJUnit5Builder \
$TEST_PACKAGE/androidx.test.runner.AndroidJUnitRunner"
fi
adb shell "$INSTRUMENTATION_COMMAND" | tee "$INSTRUMENTATION_LOG_FILE_PATH"
diff --git a/android/test/arch/build.gradle.kts b/android/test/arch/build.gradle.kts
index dff039f0e2..18503fa362 100644
--- a/android/test/arch/build.gradle.kts
+++ b/android/test/arch/build.gradle.kts
@@ -30,6 +30,6 @@ androidComponents {
dependencies {
testImplementation(Dependencies.Compose.uiToolingAndroidPreview)
testImplementation(Dependencies.AndroidX.appcompat)
- testImplementation(Dependencies.junit)
+ testImplementation(Dependencies.junitApi)
testImplementation(Dependencies.konsist)
}
diff --git a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/ArchitectureTests.kt b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/ArchitectureTests.kt
index 2a7e1e205e..4c0eac135e 100644
--- a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/ArchitectureTests.kt
+++ b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/ArchitectureTests.kt
@@ -3,7 +3,7 @@ package net.mullvad.mullvadvpn.test.arch
import com.lemonappdev.konsist.api.Konsist
import com.lemonappdev.konsist.api.architecture.KoArchitectureCreator.assertArchitecture
import com.lemonappdev.konsist.api.architecture.Layer
-import org.junit.Test
+import org.junit.jupiter.api.Test
class ArchitectureTests {
diff --git a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/GeneralTests.kt b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/GeneralTests.kt
index 60842537c3..a4049270ed 100644
--- a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/GeneralTests.kt
+++ b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/GeneralTests.kt
@@ -4,7 +4,7 @@ import com.lemonappdev.konsist.api.Konsist
import com.lemonappdev.konsist.api.ext.list.properties
import com.lemonappdev.konsist.api.verify.assert
import com.lemonappdev.konsist.api.verify.assertNot
-import org.junit.Test
+import org.junit.jupiter.api.Test
class GeneralTests {
@Test
diff --git a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/KonsistTests.kt b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/KonsistTests.kt
index f2954bdb68..a1994c4a83 100644
--- a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/KonsistTests.kt
+++ b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/KonsistTests.kt
@@ -3,7 +3,7 @@ package net.mullvad.mullvadvpn.test.arch
import com.lemonappdev.konsist.api.Konsist
import com.lemonappdev.konsist.api.ext.list.withAnnotationOf
import com.lemonappdev.konsist.api.verify.assert
-import org.junit.Test
+import org.junit.jupiter.api.Test
class KonsistTests {
@Test
diff --git a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/ViewModelTests.kt b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/ViewModelTests.kt
index 0f23e52a43..d80959af78 100644
--- a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/ViewModelTests.kt
+++ b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/ViewModelTests.kt
@@ -8,7 +8,7 @@ import com.lemonappdev.konsist.api.ext.list.properties
import com.lemonappdev.konsist.api.ext.list.withAllParentsOf
import com.lemonappdev.konsist.api.verify.assert
import com.lemonappdev.konsist.api.verify.assertNot
-import org.junit.Test
+import org.junit.jupiter.api.Test
class ViewModelTests {
@Test
diff --git a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/ClassTests.kt b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/ClassTests.kt
index 918139bf24..f3aa3a9938 100644
--- a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/ClassTests.kt
+++ b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/ClassTests.kt
@@ -2,7 +2,7 @@ package net.mullvad.mullvadvpn.test.arch.classes
import com.lemonappdev.konsist.api.Konsist
import com.lemonappdev.konsist.api.verify.assert
-import org.junit.Test
+import org.junit.jupiter.api.Test
class ClassTests {
@Test
diff --git a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/DataClassTests.kt b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/DataClassTests.kt
index cc2f7262b1..44ca7bcd49 100644
--- a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/DataClassTests.kt
+++ b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/DataClassTests.kt
@@ -4,7 +4,7 @@ import com.lemonappdev.konsist.api.Konsist
import com.lemonappdev.konsist.api.ext.list.modifierprovider.withDataModifier
import com.lemonappdev.konsist.api.ext.list.properties
import com.lemonappdev.konsist.api.verify.assertNot
-import org.junit.Test
+import org.junit.jupiter.api.Test
class DataClasses {
@Test
diff --git a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/ValueClassTests.kt b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/ValueClassTests.kt
index 6b40e051e8..9d085876fd 100644
--- a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/ValueClassTests.kt
+++ b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/classes/ValueClassTests.kt
@@ -2,9 +2,8 @@ package net.mullvad.mullvadvpn.test.arch.classes
import com.lemonappdev.konsist.api.Konsist
import com.lemonappdev.konsist.api.ext.list.modifierprovider.withValueModifier
-import com.lemonappdev.konsist.api.ext.list.properties
import com.lemonappdev.konsist.api.verify.assertTrue
-import org.junit.Test
+import org.junit.jupiter.api.Test
class ValueClassTests {
@Test
diff --git a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/compose/ComposePreviewTests.kt b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/compose/ComposePreviewTests.kt
index 5f8b1fef80..1c2df4bdd7 100644
--- a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/compose/ComposePreviewTests.kt
+++ b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/compose/ComposePreviewTests.kt
@@ -4,7 +4,7 @@ import androidx.compose.ui.tooling.preview.Preview
import com.lemonappdev.konsist.api.Konsist
import com.lemonappdev.konsist.api.ext.list.withAllAnnotationsOf
import com.lemonappdev.konsist.api.verify.assert
-import org.junit.Test
+import org.junit.jupiter.api.Test
class ComposePreviewTests {
@Test
diff --git a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/compose/ComposeTests.kt b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/compose/ComposeTests.kt
index 025f10d11f..2f7bb481fd 100644
--- a/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/compose/ComposeTests.kt
+++ b/android/test/arch/src/test/kotlin/net/mullvad/mullvadvpn/test/arch/compose/ComposeTests.kt
@@ -4,7 +4,7 @@ import androidx.compose.runtime.Composable
import com.lemonappdev.konsist.api.Konsist
import com.lemonappdev.konsist.api.ext.list.withAllAnnotationsOf
import com.lemonappdev.konsist.api.verify.assert
-import org.junit.Test
+import org.junit.jupiter.api.Test
class ComposeTests {
@Test
diff --git a/android/test/arch/src/test/resources/junit-platform.properties b/android/test/arch/src/test/resources/junit-platform.properties
new file mode 100644
index 0000000000..c5cb4a4e88
--- /dev/null
+++ b/android/test/arch/src/test/resources/junit-platform.properties
@@ -0,0 +1,6 @@
+# Enables parallel execution of Konsist tests, values found here:
+# https://docs.konsist.lemonappdev.com/advanced/additional-junit5-setup
+junit.jupiter.execution.parallel.enabled=true
+junit.jupiter.execution.parallel.mode.default=concurrent
+junit.jupiter.execution.parallel.config.strategy=dynamic
+junit.jupiter.execution.parallel.config.dynamic.factor=0.95
diff --git a/android/test/common/build.gradle.kts b/android/test/common/build.gradle.kts
index 99fcb9d2a7..df9dea41ab 100644
--- a/android/test/common/build.gradle.kts
+++ b/android/test/common/build.gradle.kts
@@ -22,6 +22,16 @@ android {
abortOnError = true
warningsAsErrors = true
}
+
+ packaging {
+ resources {
+ pickFirsts += setOf(
+ // Fixes packaging error caused by: jetified-junit-*
+ "META-INF/LICENSE.md",
+ "META-INF/LICENSE-notice.md"
+ )
+ }
+ }
}
androidComponents {
@@ -37,7 +47,7 @@ dependencies {
implementation(Dependencies.AndroidX.testRunner)
implementation(Dependencies.AndroidX.testRules)
implementation(Dependencies.AndroidX.testUiAutomator)
- implementation(Dependencies.junit)
+ implementation(Dependencies.junitEngine)
implementation(Dependencies.Kotlin.stdlib)
androidTestUtil(Dependencies.AndroidX.testOrchestrator)
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/CaptureScreenshotOnFailedTestRule.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/CaptureScreenshotOnFailedTestRule.kt
index 024522e94a..9138982a43 100644
--- a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/CaptureScreenshotOnFailedTestRule.kt
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/CaptureScreenshotOnFailedTestRule.kt
@@ -16,15 +16,15 @@ import java.io.IOException
import java.nio.file.Paths
import java.time.OffsetDateTime
import java.time.temporal.ChronoUnit
-import org.junit.rules.TestWatcher
-import org.junit.runner.Description
+import org.junit.jupiter.api.extension.ExtensionContext
+import org.junit.jupiter.api.extension.TestWatcher
-class CaptureScreenshotOnFailedTestRule(private val testTag: String) : TestWatcher() {
+class CaptureScreenshotOnFailedTestRule(private val testTag: String) : TestWatcher {
- override fun failed(e: Throwable?, description: Description) {
- Log.d(testTag, "Capturing screenshot of failed test: " + description.methodName)
+ override fun testFailed(context: ExtensionContext, cause: Throwable) {
+ Log.d(testTag, "Capturing screenshot of failed test: " + context.requiredTestMethod.name)
val timestamp = OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)
- val screenshotName = "$timestamp-${description.methodName}.jpeg"
+ val screenshotName = "$timestamp-${context.requiredTestMethod.name}.jpeg"
captureScreenshot(testTag, screenshotName)
}
diff --git a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/ForgetAllVpnAppsInSettingsTestRule.kt b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/ForgetAllVpnAppsInSettingsTestRule.kt
index eebdb291ab..0e5371fcc3 100644
--- a/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/ForgetAllVpnAppsInSettingsTestRule.kt
+++ b/android/test/common/src/main/kotlin/net/mullvad/mullvadvpn/test/common/rule/ForgetAllVpnAppsInSettingsTestRule.kt
@@ -7,11 +7,11 @@ import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import net.mullvad.mullvadvpn.test.common.extension.findObjectByCaseInsensitiveText
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
-import org.junit.rules.TestWatcher
-import org.junit.runner.Description
+import org.junit.jupiter.api.extension.BeforeTestExecutionCallback
+import org.junit.jupiter.api.extension.ExtensionContext
-class ForgetAllVpnAppsInSettingsTestRule : TestWatcher() {
- override fun starting(description: Description) {
+class ForgetAllVpnAppsInSettingsTestRule : BeforeTestExecutionCallback {
+ override fun beforeTestExecution(context: ExtensionContext) {
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
val targetContext = InstrumentationRegistry.getInstrumentation().targetContext
targetContext.startActivity(
diff --git a/android/test/e2e/build.gradle.kts b/android/test/e2e/build.gradle.kts
index 8e24974fcd..946e8effa9 100644
--- a/android/test/e2e/build.gradle.kts
+++ b/android/test/e2e/build.gradle.kts
@@ -4,6 +4,7 @@ import java.util.Properties
plugins {
id(Dependencies.Plugin.androidTestId)
id(Dependencies.Plugin.kotlinAndroidId)
+ id(Dependencies.Plugin.junit5) version Versions.Plugin.junit5
}
android {
@@ -14,6 +15,8 @@ android {
minSdk = Versions.Android.minSdkVersion
testApplicationId = "net.mullvad.mullvadvpn.test.e2e"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ testInstrumentationRunnerArguments["runnerBuilder"] =
+ "de.mannodermaus.junit5.AndroidJUnit5Builder"
targetProjectPath = ":app"
missingDimensionStrategy(FlavorDimensions.BILLING, Flavors.OSS)
@@ -62,6 +65,17 @@ android {
abortOnError = true
warningsAsErrors = true
}
+
+ packaging {
+ resources {
+ pickFirsts +=
+ setOf(
+ // Fixes packaging error caused by: jetified-junit-*
+ "META-INF/LICENSE.md",
+ "META-INF/LICENSE-notice.md"
+ )
+ }
+ }
}
configure<org.owasp.dependencycheck.gradle.extension.DependencyCheckExtension> {
@@ -83,6 +97,10 @@ dependencies {
implementation(Dependencies.AndroidX.testRules)
implementation(Dependencies.AndroidX.testUiAutomator)
implementation(Dependencies.androidVolley)
+ implementation(Dependencies.junitAndroidTestExtensions)
+ implementation(Dependencies.junitApi)
+ implementation(Dependencies.junitAndroidTestCore)
+ implementation(Dependencies.junitAndroidTestRunner)
implementation(Dependencies.Kotlin.stdlib)
androidTestUtil(Dependencies.AndroidX.testOrchestrator)
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/ConnectionTest.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/ConnectionTest.kt
index 488162b08c..bbecb037f3 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/ConnectionTest.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/ConnectionTest.kt
@@ -1,20 +1,22 @@
package net.mullvad.mullvadvpn.test.e2e
import androidx.test.uiautomator.By
-import junit.framework.Assert.assertEquals
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
import net.mullvad.mullvadvpn.test.common.rule.ForgetAllVpnAppsInSettingsTestRule
import net.mullvad.mullvadvpn.test.e2e.misc.CleanupAccountTestRule
import net.mullvad.mullvadvpn.test.e2e.misc.ConnCheckState
import net.mullvad.mullvadvpn.test.e2e.misc.SimpleMullvadHttpClient
-import org.junit.Rule
-import org.junit.Test
+import org.junit.jupiter.api.Assertions.assertEquals
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
class ConnectionTest : EndToEndTest() {
- @Rule @JvmField val cleanupAccountTestRule = CleanupAccountTestRule()
+ @RegisterExtension @JvmField val cleanupAccountTestRule = CleanupAccountTestRule()
- @Rule @JvmField val forgetAllVpnAppsInSettingsTestRule = ForgetAllVpnAppsInSettingsTestRule()
+ @RegisterExtension
+ @JvmField
+ val forgetAllVpnAppsInSettingsTestRule = ForgetAllVpnAppsInSettingsTestRule()
@Test
fun testConnectAndVerifyWithConnectionCheck() {
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/EndToEndTest.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/EndToEndTest.kt
index c9226993b8..2cf8ba712d 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/EndToEndTest.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/EndToEndTest.kt
@@ -4,35 +4,32 @@ import android.Manifest
import android.content.Context
import android.os.Build
import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.GrantPermissionRule
-import androidx.test.runner.AndroidJUnit4
import androidx.test.uiautomator.UiDevice
+import de.mannodermaus.junit5.extensions.GrantPermissionExtension
import net.mullvad.mullvadvpn.test.common.interactor.AppInteractor
import net.mullvad.mullvadvpn.test.common.rule.CaptureScreenshotOnFailedTestRule
import net.mullvad.mullvadvpn.test.e2e.constant.INVALID_TEST_ACCOUNT_TOKEN_ARGUMENT_KEY
import net.mullvad.mullvadvpn.test.e2e.constant.LOG_TAG
import net.mullvad.mullvadvpn.test.e2e.constant.VALID_TEST_ACCOUNT_TOKEN_ARGUMENT_KEY
import net.mullvad.mullvadvpn.test.e2e.extension.getRequiredArgument
-import org.junit.Before
-import org.junit.Rule
-import org.junit.runner.RunWith
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.extension.RegisterExtension
-@RunWith(AndroidJUnit4::class)
abstract class EndToEndTest {
- @Rule @JvmField val rule = CaptureScreenshotOnFailedTestRule(LOG_TAG)
+ @RegisterExtension @JvmField val rule = CaptureScreenshotOnFailedTestRule(LOG_TAG)
- @Rule
@JvmField
- val permissionRule: GrantPermissionRule? =
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
- GrantPermissionRule.grant(
+ @RegisterExtension
+ val extension =
+ (if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+ GrantPermissionExtension.grant(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
} else {
- null
- }
+ GrantPermissionExtension.grant()
+ })
lateinit var device: UiDevice
lateinit var targetContext: Context
@@ -40,7 +37,7 @@ abstract class EndToEndTest {
lateinit var validTestAccountToken: String
lateinit var invalidTestAccountToken: String
- @Before
+ @BeforeEach
fun setup() {
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
targetContext = InstrumentationRegistry.getInstrumentation().targetContext
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LaunchAppTest.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LaunchAppTest.kt
index 64f534990c..f68df92854 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LaunchAppTest.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LaunchAppTest.kt
@@ -1,10 +1,7 @@
package net.mullvad.mullvadvpn.test.e2e
-import androidx.test.runner.AndroidJUnit4
-import org.junit.Test
-import org.junit.runner.RunWith
+import org.junit.jupiter.api.Test
-@RunWith(AndroidJUnit4::class)
class LaunchAppTest : EndToEndTest() {
@Test
fun testLaunchApp() {
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LoginTest.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LoginTest.kt
index ab3ef54fb1..792c63f1a1 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LoginTest.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/LoginTest.kt
@@ -1,20 +1,17 @@
package net.mullvad.mullvadvpn.test.e2e
-import androidx.test.runner.AndroidJUnit4
import androidx.test.uiautomator.By
import net.mullvad.mullvadvpn.test.common.constant.LOGIN_FAILURE_TIMEOUT
import net.mullvad.mullvadvpn.test.common.extension.clickAgreeOnPrivacyDisclaimer
import net.mullvad.mullvadvpn.test.common.extension.clickAllowOnNotificationPermissionPromptIfApiLevel33AndAbove
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
import net.mullvad.mullvadvpn.test.e2e.misc.CleanupAccountTestRule
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.RegisterExtension
-@RunWith(AndroidJUnit4::class)
class LoginTest : EndToEndTest() {
- @Rule @JvmField val cleanupAccountTestRule = CleanupAccountTestRule()
+ @RegisterExtension @JvmField val cleanupAccountTestRule = CleanupAccountTestRule()
@Test
fun testLoginWithInvalidCredentials() {
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/WebLinkTest.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/WebLinkTest.kt
index ac3997c372..5e72305efe 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/WebLinkTest.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/WebLinkTest.kt
@@ -5,7 +5,7 @@ import net.mullvad.mullvadvpn.test.common.constant.WEB_TIMEOUT
import net.mullvad.mullvadvpn.test.common.extension.clickAgreeOnPrivacyDisclaimer
import net.mullvad.mullvadvpn.test.common.extension.clickAllowOnNotificationPermissionPromptIfApiLevel33AndAbove
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
-import org.junit.Test
+import org.junit.jupiter.api.Test
class WebLinkTest : EndToEndTest() {
@Test
diff --git a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/CleanupAccountTestRule.kt b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/CleanupAccountTestRule.kt
index 2e19cb42fe..ba42862397 100644
--- a/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/CleanupAccountTestRule.kt
+++ b/android/test/e2e/src/main/kotlin/net/mullvad/mullvadvpn/test/e2e/misc/CleanupAccountTestRule.kt
@@ -6,12 +6,13 @@ import net.mullvad.mullvadvpn.test.e2e.constant.LOG_TAG
import net.mullvad.mullvadvpn.test.e2e.constant.VALID_TEST_ACCOUNT_TOKEN_ARGUMENT_KEY
import net.mullvad.mullvadvpn.test.e2e.extension.getRequiredArgument
import net.mullvad.mullvadvpn.test.e2e.interactor.MullvadAccountInteractor
-import org.junit.rules.TestWatcher
-import org.junit.runner.Description
+import org.junit.jupiter.api.extension.BeforeEachCallback
+import org.junit.jupiter.api.extension.ExtensionContext
-class CleanupAccountTestRule : TestWatcher() {
- override fun starting(description: Description) {
- Log.d(LOG_TAG, "Cleaning up account before test: ${description.methodName}")
+class CleanupAccountTestRule : BeforeEachCallback {
+
+ override fun beforeEach(context: ExtensionContext) {
+ Log.d(LOG_TAG, "Cleaning up account before test: ${context.requiredTestMethod.name}")
val targetContext = InstrumentationRegistry.getInstrumentation().targetContext
val validTestAccountToken =
InstrumentationRegistry.getArguments()
diff --git a/android/test/firebase-test-lab.yml b/android/test/firebase-test-lab.yml
index feaefbc236..d84e64134b 100644
--- a/android/test/firebase-test-lab.yml
+++ b/android/test/firebase-test-lab.yml
@@ -12,3 +12,4 @@ default:
- {model: GoogleTvEmulator, version: 30, locale: en, orientation: landscape}
environment-variables:
clearPackageData: "true"
+ runnerBuilder: "de.mannodermaus.junit5.AndroidJUnit5Builder"
diff --git a/android/test/mockapi/build.gradle.kts b/android/test/mockapi/build.gradle.kts
index 8be38fdcbc..e5d20d3d50 100644
--- a/android/test/mockapi/build.gradle.kts
+++ b/android/test/mockapi/build.gradle.kts
@@ -1,6 +1,7 @@
plugins {
id(Dependencies.Plugin.androidTestId)
id(Dependencies.Plugin.kotlinAndroidId)
+ id(Dependencies.Plugin.junit5) version Versions.Plugin.junit5
}
android {
@@ -11,6 +12,8 @@ android {
minSdk = Versions.Android.minSdkVersion
testApplicationId = "net.mullvad.mullvadvpn.test.mockapi"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ testInstrumentationRunnerArguments["runnerBuilder"] =
+ "de.mannodermaus.junit5.AndroidJUnit5Builder"
targetProjectPath = ":app"
missingDimensionStrategy(FlavorDimensions.BILLING, Flavors.OSS)
@@ -37,6 +40,16 @@ android {
abortOnError = true
warningsAsErrors = true
}
+
+ packaging {
+ resources {
+ pickFirsts += setOf(
+ // Fixes packaging error caused by: jetified-junit-*
+ "META-INF/LICENSE.md",
+ "META-INF/LICENSE-notice.md"
+ )
+ }
+ }
}
configure<org.owasp.dependencycheck.gradle.extension.DependencyCheckExtension> {
@@ -59,6 +72,10 @@ dependencies {
implementation(Dependencies.AndroidX.testRules)
implementation(Dependencies.AndroidX.testUiAutomator)
implementation(Dependencies.jodaTime)
+ implementation(Dependencies.junitAndroidTestExtensions)
+ implementation(Dependencies.junitApi)
+ implementation(Dependencies.junitAndroidTestCore)
+ implementation(Dependencies.junitAndroidTestRunner)
implementation(Dependencies.Kotlin.stdlib)
implementation(Dependencies.mockkWebserver)
diff --git a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LoginMockApiTest.kt b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LoginMockApiTest.kt
index 7d94b37492..3f3d882835 100644
--- a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LoginMockApiTest.kt
+++ b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LoginMockApiTest.kt
@@ -1,6 +1,5 @@
package net.mullvad.mullvadvpn.test.mockapi
-import androidx.test.runner.AndroidJUnit4
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import net.mullvad.mullvadvpn.compose.test.LOGIN_TITLE_TEST_TAG
@@ -10,11 +9,9 @@ import net.mullvad.mullvadvpn.test.common.extension.clickAllowOnNotificationPerm
import net.mullvad.mullvadvpn.test.common.extension.dismissChangelogDialogIfShown
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
import net.mullvad.mullvadvpn.test.mockapi.util.currentUtcTimeWithOffsetZero
-import org.junit.Assert.assertTrue
-import org.junit.Test
-import org.junit.runner.RunWith
+import org.junit.jupiter.api.Assertions.assertTrue
+import org.junit.jupiter.api.Test
-@RunWith(AndroidJUnit4::class)
class LoginMockApiTest : MockApiTest() {
@Test
fun testLoginWithInvalidCredentials() {
diff --git a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LogoutMockApiTest.kt b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LogoutMockApiTest.kt
index e13a728296..266fe73977 100644
--- a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LogoutMockApiTest.kt
+++ b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/LogoutMockApiTest.kt
@@ -1,17 +1,14 @@
package net.mullvad.mullvadvpn.test.mockapi
-import androidx.test.runner.AndroidJUnit4
import androidx.test.uiautomator.By
-import junit.framework.TestCase.assertNotNull
import net.mullvad.mullvadvpn.test.common.extension.clickAgreeOnPrivacyDisclaimer
import net.mullvad.mullvadvpn.test.common.extension.clickAllowOnNotificationPermissionPromptIfApiLevel33AndAbove
import net.mullvad.mullvadvpn.test.common.extension.dismissChangelogDialogIfShown
import net.mullvad.mullvadvpn.test.common.extension.findObjectWithTimeout
import net.mullvad.mullvadvpn.test.mockapi.util.currentUtcTimeWithOffsetZero
-import org.junit.Test
-import org.junit.runner.RunWith
+import org.junit.jupiter.api.Assertions.assertNotNull
+import org.junit.jupiter.api.Test
-@RunWith(AndroidJUnit4::class)
class LogoutMockApiTest : MockApiTest() {
@Test
diff --git a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiTest.kt b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiTest.kt
index 702aa72db4..9ee4f52e04 100644
--- a/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiTest.kt
+++ b/android/test/mockapi/src/main/kotlin/net/mullvad/mullvadvpn/test/mockapi/MockApiTest.kt
@@ -5,29 +5,26 @@ import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.content.Context
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.rule.GrantPermissionRule
-import androidx.test.runner.AndroidJUnit4
import androidx.test.uiautomator.UiDevice
+import de.mannodermaus.junit5.extensions.GrantPermissionExtension
import java.net.InetAddress
import net.mullvad.mullvadvpn.lib.endpoint.CustomApiEndpointConfiguration
import net.mullvad.mullvadvpn.test.common.interactor.AppInteractor
import net.mullvad.mullvadvpn.test.common.rule.CaptureScreenshotOnFailedTestRule
import net.mullvad.mullvadvpn.test.mockapi.constant.LOG_TAG
import okhttp3.mockwebserver.MockWebServer
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.runner.RunWith
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.extension.RegisterExtension
-@RunWith(AndroidJUnit4::class)
abstract class MockApiTest {
- @Rule @JvmField val rule = CaptureScreenshotOnFailedTestRule(LOG_TAG)
+ @RegisterExtension @JvmField val rule = CaptureScreenshotOnFailedTestRule(LOG_TAG)
- @Rule
+ @RegisterExtension
@JvmField
- val permissionRule: GrantPermissionRule =
- GrantPermissionRule.grant(WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE)
+ val permissionRule: GrantPermissionExtension =
+ GrantPermissionExtension.grant(WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE)
protected val apiDispatcher = MockApiDispatcher()
private val mockWebServer = MockWebServer().apply { dispatcher = apiDispatcher }
@@ -37,7 +34,7 @@ abstract class MockApiTest {
lateinit var app: AppInteractor
lateinit var endpoint: CustomApiEndpointConfiguration
- @Before
+ @BeforeEach
open fun setup() {
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
targetContext = InstrumentationRegistry.getInstrumentation().targetContext
@@ -49,7 +46,7 @@ abstract class MockApiTest {
endpoint = createEndpoint(mockWebServer.port)
}
- @After
+ @AfterEach
open fun teardown() {
mockWebServer.shutdown()
}