Skip to content

Commit 2377535

Browse files
committed
Fix remarks
1 parent 54879de commit 2377535

File tree

14 files changed

+296
-120
lines changed

14 files changed

+296
-120
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
package net.mullvad.mullvadvpn.compose.screen
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.compose.ui.test.ExperimentalTestApi
5+
import androidx.compose.ui.test.onNodeWithTag
6+
import androidx.compose.ui.test.onNodeWithText
7+
import androidx.compose.ui.test.performClick
8+
import io.mockk.MockKAnnotations
9+
import io.mockk.mockk
10+
import io.mockk.verify
11+
import net.mullvad.mullvadvpn.compose.createEdgeToEdgeComposeExtension
12+
import net.mullvad.mullvadvpn.compose.setContentWithTheme
13+
import net.mullvad.mullvadvpn.compose.test.SERVER_IP_OVERRIDES_IMPORT_BY_FILE_TEST_TAG
14+
import net.mullvad.mullvadvpn.compose.test.SERVER_IP_OVERRIDES_IMPORT_BY_TEXT_TEST_TAG
15+
import net.mullvad.mullvadvpn.compose.test.SERVER_IP_OVERRIDE_IMPORT_TEST_TAG
16+
import net.mullvad.mullvadvpn.compose.test.SERVER_IP_OVERRIDE_INFO_TEST_TAG
17+
import net.mullvad.mullvadvpn.compose.test.SERVER_IP_OVERRIDE_MORE_VERT_TEST_TAG
18+
import net.mullvad.mullvadvpn.compose.test.SERVER_IP_OVERRIDE_RESET_OVERRIDES_TEST_TAG
19+
import net.mullvad.mullvadvpn.viewmodel.ServerIpOverridesViewState
20+
import org.junit.jupiter.api.BeforeEach
21+
import org.junit.jupiter.api.Test
22+
import org.junit.jupiter.api.extension.RegisterExtension
23+
24+
@ExperimentalTestApi
25+
class ServerIpOverridesScreenTest {
26+
@JvmField @RegisterExtension val composeExtension = createEdgeToEdgeComposeExtension()
27+
28+
@BeforeEach
29+
fun setup() {
30+
MockKAnnotations.init(this)
31+
}
32+
33+
@Composable
34+
private fun Screen(
35+
state: ServerIpOverridesViewState,
36+
onBackClick: () -> Unit = {},
37+
onInfoClick: () -> Unit = {},
38+
onResetOverridesClick: () -> Unit = {},
39+
onImportByFile: () -> Unit = {},
40+
onImportByText: () -> Unit = {},
41+
) {
42+
ServerIpOverridesScreen(
43+
state = state,
44+
onBackClick = onBackClick,
45+
onInfoClick = onInfoClick,
46+
onResetOverridesClick = onResetOverridesClick,
47+
onImportByFile = onImportByFile,
48+
onImportByText = onImportByText
49+
)
50+
}
51+
52+
@Test
53+
fun testOverridesInactive() =
54+
composeExtension.use {
55+
// Arrange
56+
setContentWithTheme { Screen(state = ServerIpOverridesViewState(false)) }
57+
58+
// Assert
59+
onNodeWithText("Overrides inactive").assertExists()
60+
}
61+
62+
@Test
63+
fun testOverridesActive() =
64+
composeExtension.use {
65+
// Arrange
66+
setContentWithTheme { Screen(state = ServerIpOverridesViewState(true)) }
67+
68+
// Assert
69+
onNodeWithText("Overrides active").assertExists()
70+
}
71+
72+
@Test
73+
fun testOverridesActiveShowsWarningOnImport() =
74+
composeExtension.use {
75+
// Arrange
76+
setContentWithTheme { Screen(state = ServerIpOverridesViewState(true)) }
77+
78+
// Act
79+
onNodeWithTag(testTag = SERVER_IP_OVERRIDE_IMPORT_TEST_TAG).performClick()
80+
81+
// Assert
82+
onNodeWithText(
83+
"Importing new overrides might replace some previously imported overrides."
84+
)
85+
.assertExists()
86+
}
87+
88+
@Test
89+
fun testInfoClick() =
90+
composeExtension.use {
91+
// Arrange
92+
val clickHandler: () -> Unit = mockk(relaxed = true)
93+
setContentWithTheme {
94+
Screen(state = ServerIpOverridesViewState(false), onInfoClick = clickHandler)
95+
}
96+
97+
// Act
98+
onNodeWithTag(SERVER_IP_OVERRIDE_INFO_TEST_TAG).performClick()
99+
100+
// Assert
101+
verify { clickHandler() }
102+
}
103+
104+
@Test
105+
fun testResetClick() =
106+
composeExtension.use {
107+
// Arrange
108+
val clickHandler: () -> Unit = mockk(relaxed = true)
109+
setContentWithTheme {
110+
Screen(
111+
state = ServerIpOverridesViewState(false),
112+
onResetOverridesClick = clickHandler
113+
)
114+
}
115+
116+
// Act
117+
onNodeWithTag(SERVER_IP_OVERRIDE_MORE_VERT_TEST_TAG).performClick()
118+
onNodeWithTag(SERVER_IP_OVERRIDE_RESET_OVERRIDES_TEST_TAG).performClick()
119+
120+
// Assert
121+
verify { clickHandler() }
122+
}
123+
124+
@Test
125+
fun testImportByFile() =
126+
composeExtension.use {
127+
// Arrange
128+
val clickHandler: () -> Unit = mockk(relaxed = true)
129+
setContentWithTheme {
130+
Screen(state = ServerIpOverridesViewState(false), onImportByFile = clickHandler)
131+
}
132+
133+
// Act
134+
onNodeWithTag(SERVER_IP_OVERRIDE_IMPORT_TEST_TAG).performClick()
135+
onNodeWithTag(SERVER_IP_OVERRIDES_IMPORT_BY_FILE_TEST_TAG).performClick()
136+
137+
// Assert
138+
verify { clickHandler() }
139+
}
140+
141+
@Test
142+
fun testImportByText() =
143+
composeExtension.use {
144+
// Arrange
145+
val clickHandler: () -> Unit = mockk(relaxed = true)
146+
setContentWithTheme {
147+
Screen(state = ServerIpOverridesViewState(false), onImportByText = clickHandler)
148+
}
149+
150+
// Act
151+
onNodeWithTag(SERVER_IP_OVERRIDE_IMPORT_TEST_TAG).performClick()
152+
onNodeWithTag(SERVER_IP_OVERRIDES_IMPORT_BY_TEXT_TEST_TAG).performClick()
153+
154+
// Assert
155+
verify { clickHandler() }
156+
}
157+
}

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/InfoIconButton.kt

+9-3
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,22 @@ import androidx.compose.material3.IconButton
55
import androidx.compose.material3.MaterialTheme
66
import androidx.compose.runtime.Composable
77
import androidx.compose.ui.Modifier
8+
import androidx.compose.ui.graphics.Color
89
import androidx.compose.ui.res.painterResource
910
import net.mullvad.mullvadvpn.R
1011

1112
@Composable
12-
fun InfoIconButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
13+
fun InfoIconButton(
14+
onClick: () -> Unit,
15+
modifier: Modifier = Modifier,
16+
contentDescription: String? = null,
17+
iconTint: Color = MaterialTheme.colorScheme.onPrimary
18+
) {
1319
IconButton(modifier = modifier, onClick = onClick) {
1420
Icon(
1521
painter = painterResource(id = R.drawable.icon_info),
16-
contentDescription = null,
17-
tint = MaterialTheme.colorScheme.onPrimary
22+
contentDescription = contentDescription,
23+
tint = iconTint
1824
)
1925
}
2026
}

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/IconCell.kt

+5-3
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,14 @@ private fun PreviewIconCell() {
2525
@Composable
2626
fun IconCell(
2727
iconId: Int?,
28-
contentDescription: String? = null,
2928
title: String,
29+
modifier: Modifier = Modifier,
30+
contentDescription: String? = null,
3031
titleStyle: TextStyle = MaterialTheme.typography.labelLarge,
3132
titleColor: Color = MaterialTheme.colorScheme.onPrimary,
3233
onClick: () -> Unit = {},
3334
background: Color = MaterialTheme.colorScheme.primary,
34-
enabled: Boolean = true,
35+
enabled: Boolean = true
3536
) {
3637
BaseCell(
3738
headlineContent = {
@@ -49,6 +50,7 @@ fun IconCell(
4950
},
5051
onCellClicked = onClick,
5152
background = background,
52-
isRowEnabled = enabled
53+
isRowEnabled = enabled,
54+
modifier = modifier
5355
)
5456
}

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/ServerIpOverridesCell.kt

+34-45
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,12 @@ package net.mullvad.mullvadvpn.compose.cell
22

33
import androidx.compose.foundation.background
44
import androidx.compose.foundation.layout.Box
5-
import androidx.compose.foundation.layout.IntrinsicSize
6-
import androidx.compose.foundation.layout.Row
7-
import androidx.compose.foundation.layout.fillMaxWidth
8-
import androidx.compose.foundation.layout.height
95
import androidx.compose.foundation.layout.padding
106
import androidx.compose.foundation.layout.size
11-
import androidx.compose.foundation.layout.wrapContentHeight
127
import androidx.compose.foundation.shape.CircleShape
138
import androidx.compose.material3.MaterialTheme
149
import androidx.compose.material3.Text
1510
import androidx.compose.runtime.Composable
16-
import androidx.compose.ui.Alignment
1711
import androidx.compose.ui.Modifier
1812
import androidx.compose.ui.draw.alpha
1913
import androidx.compose.ui.graphics.Color
@@ -39,43 +33,38 @@ fun ServerIpOverridesCell(
3933
activeColor: Color = MaterialTheme.colorScheme.selected,
4034
inactiveColor: Color = MaterialTheme.colorScheme.error,
4135
) {
42-
Row(
43-
modifier =
44-
modifier
45-
.wrapContentHeight()
46-
.height(IntrinsicSize.Min)
47-
.background(MaterialTheme.colorScheme.primary)
48-
.padding(horizontal = Dimens.sideMargin)
49-
.fillMaxWidth(),
50-
verticalAlignment = Alignment.CenterVertically
51-
) {
52-
Box(
53-
modifier =
54-
Modifier.size(Dimens.relayCircleSize)
55-
.background(
56-
color =
57-
when {
58-
active -> activeColor
59-
else -> inactiveColor
60-
},
61-
shape = CircleShape
62-
)
63-
)
64-
Text(
65-
text =
66-
if (active) stringResource(id = R.string.server_ip_overrides_active)
67-
else stringResource(id = R.string.server_ip_overrides_inactive),
68-
color = MaterialTheme.colorScheme.onPrimary,
69-
modifier =
70-
Modifier.weight(1f)
71-
.alpha(
72-
if (active) {
73-
AlphaVisible
74-
} else {
75-
AlphaInactive
76-
}
77-
)
78-
.padding(horizontal = Dimens.smallPadding, vertical = Dimens.mediumPadding)
79-
)
80-
}
36+
BaseCell(
37+
iconView = {
38+
Box(
39+
modifier =
40+
Modifier.size(Dimens.relayCircleSize)
41+
.background(
42+
color =
43+
when {
44+
active -> activeColor
45+
else -> inactiveColor
46+
},
47+
shape = CircleShape
48+
)
49+
)
50+
},
51+
headlineContent = {
52+
Text(
53+
text =
54+
if (active) stringResource(id = R.string.server_ip_overrides_active)
55+
else stringResource(id = R.string.server_ip_overrides_inactive),
56+
color = MaterialTheme.colorScheme.onPrimary,
57+
modifier =
58+
Modifier.weight(1f)
59+
.alpha(
60+
if (active) {
61+
AlphaVisible
62+
} else {
63+
AlphaInactive
64+
}
65+
)
66+
.padding(horizontal = Dimens.smallPadding, vertical = Dimens.mediumPadding)
67+
)
68+
}
69+
)
8170
}

android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/ResetServerIpOverridesConfirmationDialog.kt

+14-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package net.mullvad.mullvadvpn.compose.dialog
22

3-
import androidx.compose.foundation.layout.Arrangement
4-
import androidx.compose.foundation.layout.Column
53
import androidx.compose.foundation.layout.fillMaxWidth
64
import androidx.compose.material3.AlertDialog
75
import androidx.compose.material3.MaterialTheme
@@ -18,7 +16,6 @@ import net.mullvad.mullvadvpn.R
1816
import net.mullvad.mullvadvpn.compose.button.NegativeButton
1917
import net.mullvad.mullvadvpn.compose.button.PrimaryButton
2018
import net.mullvad.mullvadvpn.lib.theme.AppTheme
21-
import net.mullvad.mullvadvpn.lib.theme.Dimens
2219

2320
@Preview
2421
@Composable
@@ -34,30 +31,29 @@ fun ResetServerIpOverridesConfirmationDialog(
3431
AlertDialog(
3532
containerColor = MaterialTheme.colorScheme.background,
3633
confirmButton = {
37-
Column(verticalArrangement = Arrangement.spacedBy(Dimens.buttonSpacing)) {
38-
NegativeButton(
39-
modifier = Modifier.fillMaxWidth(),
40-
text = stringResource(id = R.string.server_ip_overrides_reset_reset_button),
41-
onClick = { resultNavigator.navigateBack(result = true) }
42-
)
43-
44-
PrimaryButton(
45-
modifier = Modifier.fillMaxWidth(),
46-
text = stringResource(R.string.cancel),
47-
onClick = resultNavigator::navigateBack
48-
)
49-
}
34+
NegativeButton(
35+
modifier = Modifier.fillMaxWidth(),
36+
text = stringResource(id = R.string.server_ip_overrides_reset_reset_button),
37+
onClick = { resultNavigator.navigateBack(result = true) }
38+
)
39+
},
40+
dismissButton = {
41+
PrimaryButton(
42+
modifier = Modifier.fillMaxWidth(),
43+
text = stringResource(R.string.cancel),
44+
onClick = resultNavigator::navigateBack
45+
)
5046
},
5147
title = {
5248
Text(
5349
text = stringResource(id = R.string.server_ip_overrides_reset_title),
54-
color = MaterialTheme.colorScheme.onPrimary
50+
color = MaterialTheme.colorScheme.onBackground
5551
)
5652
},
5753
text = {
5854
Text(
5955
text = stringResource(id = R.string.server_ip_overrides_reset_body),
60-
color = MaterialTheme.colorScheme.onPrimary,
56+
color = MaterialTheme.colorScheme.onBackground,
6157
style = MaterialTheme.typography.bodySmall,
6258
)
6359
},

0 commit comments

Comments
 (0)