Skip to content

Commit

Permalink
Merge branch 'android-api-access-method'
Browse files Browse the repository at this point in the history
  • Loading branch information
Pururun committed Jun 14, 2024
2 parents 6fb4623 + cef76db commit 4c999e3
Show file tree
Hide file tree
Showing 101 changed files with 5,238 additions and 111 deletions.
3 changes: 3 additions & 0 deletions android/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ Line wrap the file at 100 chars. Th
* **Security**: in case of vulnerabilities.

## [Unreleased]
### Added
- Add the ability to customize how the app talks to the api.

### Changed
- Migrate underlaying communication wtih daemon to gRPC. This also implies major changes and
improvements throughout the app.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package net.mullvad.mullvadvpn.compose.data

import net.mullvad.mullvadvpn.lib.model.ApiAccessMethod
import net.mullvad.mullvadvpn.lib.model.ApiAccessMethodId
import net.mullvad.mullvadvpn.lib.model.ApiAccessMethodName
import net.mullvad.mullvadvpn.lib.model.ApiAccessMethodSetting
import net.mullvad.mullvadvpn.lib.model.Cipher
import net.mullvad.mullvadvpn.lib.model.Port

private const val UUID1 = "12345678-1234-5678-1234-567812345678"
private const val UUID2 = "12345678-1234-5678-1234-567812345679"

val DIRECT_ACCESS_METHOD =
ApiAccessMethodSetting(
id = ApiAccessMethodId.fromString(UUID1),
name = ApiAccessMethodName.fromString("Direct"),
enabled = true,
apiAccessMethod = ApiAccessMethod.Direct
)

val CUSTOM_ACCESS_METHOD =
ApiAccessMethodSetting(
id = ApiAccessMethodId.fromString(UUID2),
name = ApiAccessMethodName.fromString("ShadowSocks"),
enabled = true,
apiAccessMethod =
ApiAccessMethod.CustomProxy.Shadowsocks(
ip = "1.1.1.1",
port = Port(123),
password = "Password",
cipher = Cipher.RC4
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package net.mullvad.mullvadvpn.compose.dialog

import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import io.mockk.mockk
import io.mockk.verify
import net.mullvad.mullvadvpn.compose.createEdgeToEdgeComposeExtension
import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.compose.state.SaveApiAccessMethodUiState
import net.mullvad.mullvadvpn.compose.state.TestApiAccessMethodState
import net.mullvad.mullvadvpn.compose.test.SAVE_API_ACCESS_METHOD_CANCEL_BUTTON_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.SAVE_API_ACCESS_METHOD_LOADING_SPINNER_TEST_TAG
import net.mullvad.mullvadvpn.compose.test.SAVE_API_ACCESS_METHOD_SAVE_BUTTON_TEST_TAG
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.RegisterExtension

@OptIn(ExperimentalTestApi::class)
class SaveApiAccessMethodDialogTest {
@JvmField @RegisterExtension val composeExtension = createEdgeToEdgeComposeExtension()

@Test
fun whenTestingInProgressShouldShowSpinnerWithCancelButton() =
composeExtension.use {
// Arrange
setContentWithTheme {
SaveApiAccessMethodDialog(
state =
SaveApiAccessMethodUiState(
testingState = TestApiAccessMethodState.Testing,
isSaving = false
)
)
}

// Assert
onNodeWithTag(SAVE_API_ACCESS_METHOD_LOADING_SPINNER_TEST_TAG).assertExists()
onNodeWithTag(SAVE_API_ACCESS_METHOD_CANCEL_BUTTON_TEST_TAG).assertExists()
}

@Test
fun whenTestingFailedShouldShowSaveAndCancelButton() =
composeExtension.use {
// Arrange
setContentWithTheme {
SaveApiAccessMethodDialog(
state =
SaveApiAccessMethodUiState(
testingState = TestApiAccessMethodState.Result.Failure,
isSaving = false
)
)
}

// Assert
onNodeWithTag(SAVE_API_ACCESS_METHOD_SAVE_BUTTON_TEST_TAG).assertExists()
onNodeWithTag(SAVE_API_ACCESS_METHOD_CANCEL_BUTTON_TEST_TAG).assertExists()
}

@Test
fun whenTestingSuccessfulAndSavingShouldShowDisabledCancelButton() =
composeExtension.use {
// Arrange
setContentWithTheme {
SaveApiAccessMethodDialog(
state =
SaveApiAccessMethodUiState(
testingState = TestApiAccessMethodState.Result.Successful,
isSaving = true
)
)
}

// Assert
onNodeWithTag(SAVE_API_ACCESS_METHOD_CANCEL_BUTTON_TEST_TAG).assertExists()
onNodeWithTag(SAVE_API_ACCESS_METHOD_CANCEL_BUTTON_TEST_TAG).assertIsNotEnabled()
}

@Test
fun whenTestingInProgressAndClickingCancelShouldCallOnCancel() =
composeExtension.use {
// Arrange
val onCancelClick: () -> Unit = mockk(relaxed = true)
setContentWithTheme {
SaveApiAccessMethodDialog(
state =
SaveApiAccessMethodUiState(
testingState = TestApiAccessMethodState.Testing,
isSaving = false
),
onCancel = onCancelClick
)
}

// Act
onNodeWithTag(SAVE_API_ACCESS_METHOD_CANCEL_BUTTON_TEST_TAG).performClick()

// Assert
verify { onCancelClick() }
}

@Test
fun whenTestingFailedAndClickingSaveShouldCallOnSave() =
composeExtension.use {
// Arrange
val onSaveClick: () -> Unit = mockk(relaxed = true)
setContentWithTheme {
SaveApiAccessMethodDialog(
state =
SaveApiAccessMethodUiState(
testingState = TestApiAccessMethodState.Result.Failure,
isSaving = false
),
onSave = onSaveClick
)
}

// Act
onNodeWithTag(SAVE_API_ACCESS_METHOD_SAVE_BUTTON_TEST_TAG).performClick()

// Assert
verify { onSaveClick() }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package net.mullvad.mullvadvpn.compose.screen

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 io.mockk.mockk
import io.mockk.verify
import net.mullvad.mullvadvpn.compose.createEdgeToEdgeComposeExtension
import net.mullvad.mullvadvpn.compose.data.DIRECT_ACCESS_METHOD
import net.mullvad.mullvadvpn.compose.setContentWithTheme
import net.mullvad.mullvadvpn.compose.state.ApiAccessListUiState
import net.mullvad.mullvadvpn.compose.test.API_ACCESS_LIST_INFO_TEST_TAG
import net.mullvad.mullvadvpn.lib.model.ApiAccessMethodSetting
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.RegisterExtension

@OptIn(ExperimentalTestApi::class)
class ApiAccessListScreenTest {
@JvmField @RegisterExtension val composeExtension = createEdgeToEdgeComposeExtension()

@Test
fun shouldShowCurrentApiAccessName() =
composeExtension.use {
// Arrange
val currentApiAccessMethod = DIRECT_ACCESS_METHOD
setContentWithTheme {
ApiAccessListScreen(
state =
ApiAccessListUiState(currentApiAccessMethodSetting = currentApiAccessMethod)
)
}

// Assert
onNodeWithText("Current: ${currentApiAccessMethod.name}")
}

@Test
fun shouldShowApiAccessNameAndStatusInList() =
composeExtension.use {
// Arrange
val apiAccessMethod = DIRECT_ACCESS_METHOD
setContentWithTheme {
ApiAccessListScreen(
state = ApiAccessListUiState(apiAccessMethodSettings = listOf(apiAccessMethod))
)
}

// Assert
onNodeWithText(apiAccessMethod.name.value)
onNodeWithText("On")
}

@Test
fun whenClickingOnAddMethodShouldCallOnAddMethodClicked() =
composeExtension.use {
// Arrange
val onAddMethodClick: () -> Unit = mockk(relaxed = true)
setContentWithTheme {
ApiAccessListScreen(
state = ApiAccessListUiState(),
onAddMethodClick = onAddMethodClick
)
}

// Act
onNodeWithText("Add").performClick()

// Assert
verify { onAddMethodClick() }
}

@Test
fun whenClickingOnInfoButtonShouldCallOnApiAccessInfoClick() =
composeExtension.use {
// Arrange
val onApiAccessInfoClick: () -> Unit = mockk(relaxed = true)
setContentWithTheme {
ApiAccessListScreen(
state = ApiAccessListUiState(),
onApiAccessInfoClick = onApiAccessInfoClick
)
}

// Act
onNodeWithTag(API_ACCESS_LIST_INFO_TEST_TAG).performClick()

// Assert
verify { onApiAccessInfoClick() }
}

@Test
fun whenClickingOnApiAccessMethodShouldCallOnApiAccessMethodClickWithCorrectAccessMethod() =
composeExtension.use {
// Arrange
val apiAccessMethod = DIRECT_ACCESS_METHOD
val onApiAccessMethodClick: (ApiAccessMethodSetting) -> Unit = mockk(relaxed = true)
setContentWithTheme {
ApiAccessListScreen(
state = ApiAccessListUiState(apiAccessMethodSettings = listOf(apiAccessMethod)),
onApiAccessMethodClick = onApiAccessMethodClick
)
}

// Act
onNodeWithText(apiAccessMethod.name.value).performClick()

// Assert
verify { onApiAccessMethodClick(apiAccessMethod) }
}
}
Loading

0 comments on commit 4c999e3

Please sign in to comment.