|
2 | 2 |
|
3 | 3 | package ee.ria.DigiDoc.viewmodel |
4 | 4 |
|
| 5 | +import android.app.Activity |
5 | 6 | import android.net.Uri |
6 | | -import kotlinx.coroutines.ExperimentalCoroutinesApi |
7 | | -import kotlinx.coroutines.test.runTest |
8 | | -import org.junit.Assert.assertEquals |
9 | | -import org.junit.Assert.assertNull |
| 7 | +import androidx.arch.core.executor.testing.InstantTaskExecutorRule |
| 8 | +import ee.ria.DigiDoc.webEid.WebEidAuthService |
| 9 | +import ee.ria.DigiDoc.webEid.domain.model.WebEidAuthRequest |
| 10 | +import kotlinx.coroutines.flow.MutableStateFlow |
| 11 | +import org.json.JSONObject |
10 | 12 | import org.junit.Before |
| 13 | +import org.junit.Rule |
11 | 14 | import org.junit.Test |
12 | | - |
13 | | -@OptIn(ExperimentalCoroutinesApi::class) |
| 15 | +import org.junit.runner.RunWith |
| 16 | +import org.mockito.Mock |
| 17 | +import org.mockito.Mockito.never |
| 18 | +import org.mockito.Mockito.`when` |
| 19 | +import org.mockito.MockitoAnnotations |
| 20 | +import org.mockito.junit.MockitoJUnitRunner |
| 21 | +import org.mockito.kotlin.any |
| 22 | +import org.mockito.kotlin.verify |
| 23 | + |
| 24 | +@RunWith(MockitoJUnitRunner::class) |
14 | 25 | class WebEidViewModelTest { |
| 26 | + @get:Rule |
| 27 | + val instantExecutorRule = InstantTaskExecutorRule() |
| 28 | + |
| 29 | + @Mock |
| 30 | + private lateinit var authService: WebEidAuthService |
| 31 | + |
| 32 | + @Mock |
| 33 | + private lateinit var activity: Activity |
15 | 34 |
|
16 | 35 | private lateinit var viewModel: WebEidViewModel |
17 | 36 |
|
18 | 37 | @Before |
19 | | - fun setUp() { |
20 | | - viewModel = WebEidViewModel() |
21 | | - } |
| 38 | + fun setup() { |
| 39 | + MockitoAnnotations.openMocks(this) |
22 | 40 |
|
23 | | - @Test |
24 | | - fun handleAuth_validUri_setsAuthPayload() = runTest { |
25 | | - val json = """ |
26 | | - { |
27 | | - "challenge": "abc123", |
28 | | - "login_uri": "https://example.com/auth/login", |
29 | | - "get_signing_certificate": true |
30 | | - } |
31 | | - """.trimIndent() |
32 | | - |
33 | | - val encoded = java.util.Base64.getEncoder().encodeToString(json.toByteArray()) |
34 | | - val uri = Uri.parse("web-eid-mobile://auth#$encoded") |
| 41 | + `when`(authService.authRequest).thenReturn(MutableStateFlow(null)) |
| 42 | + `when`(authService.signRequest).thenReturn(MutableStateFlow(null)) |
| 43 | + `when`(authService.errorState).thenReturn(MutableStateFlow(null)) |
| 44 | + `when`(authService.redirectUri).thenReturn(MutableStateFlow(null)) |
35 | 45 |
|
36 | | - viewModel.handleAuth(uri) |
37 | | - |
38 | | - val result = viewModel.authPayload.value |
39 | | - assertEquals("abc123", result?.challenge) |
40 | | - assertEquals("https://example.com/auth/login", result?.loginUri) |
41 | | - assertEquals(true, result?.getSigningCertificate) |
| 46 | + viewModel = WebEidViewModel(authService) |
42 | 47 | } |
43 | 48 |
|
44 | 49 | @Test |
45 | | - fun handleAuth_missingFragment_setsNullPayload() = runTest { |
46 | | - val uri = Uri.parse("web-eid-mobile://auth") |
47 | | - |
| 50 | + fun handleAuth_callsParseAuthUri() { |
| 51 | + val uri = Uri.parse("web-eid-mobile://auth#dummyData") |
48 | 52 | viewModel.handleAuth(uri) |
49 | | - |
50 | | - assertNull(viewModel.authPayload.value) |
| 53 | + verify(authService).parseAuthUri(uri) |
51 | 54 | } |
52 | 55 |
|
53 | 56 | @Test |
54 | | - fun handleAuth_invalidBase64_setsNullPayload() = runTest { |
55 | | - val uri = Uri.parse("web-eid-mobile://auth#invalid-base64!!") |
| 57 | + fun handleSign_callsParseSignUri() { |
| 58 | + val uri = Uri.parse("web-eid-mobile://sign#dummyData") |
| 59 | + viewModel.handleSign(uri) |
| 60 | + verify(authService).parseSignUri(uri) |
| 61 | + } |
56 | 62 |
|
57 | | - viewModel.handleAuth(uri) |
| 63 | + @Test |
| 64 | + fun reset_callsResetValues() { |
| 65 | + viewModel.reset() |
| 66 | + verify(authService).resetValues() |
| 67 | + } |
58 | 68 |
|
59 | | - assertNull(viewModel.authPayload.value) |
| 69 | + @Test |
| 70 | + fun redirectUri_isExposedFromAuthService() { |
| 71 | + val redirectFlow = MutableStateFlow("https://example.com#encodedPayload") |
| 72 | + `when`(authService.redirectUri).thenReturn(redirectFlow) |
| 73 | + val vm = WebEidViewModel(authService) |
| 74 | + assert(vm.redirectUri.value == "https://example.com#encodedPayload") |
60 | 75 | } |
61 | 76 |
|
62 | 77 | @Test |
63 | | - fun handleAuth_missingOptionalField_defaultsToFalse() = runTest { |
64 | | - val json = """ |
65 | | - { |
66 | | - "challenge": "xyz456", |
67 | | - "login_uri": "https://rp.example.com/login" |
68 | | - } |
69 | | - """.trimIndent() |
| 78 | + fun redirectUri_updatesWhenServiceUpdates() { |
| 79 | + val redirectFlow = MutableStateFlow<String?>(null) |
| 80 | + `when`(authService.redirectUri).thenReturn(redirectFlow) |
| 81 | + val vm = WebEidViewModel(authService) |
| 82 | + redirectFlow.value = "https://example.com#updatedPayload" |
| 83 | + assert(vm.redirectUri.value == "https://example.com#updatedPayload") |
| 84 | + } |
70 | 85 |
|
71 | | - val encoded = java.util.Base64.getEncoder().encodeToString(json.toByteArray()) |
72 | | - val uri = Uri.parse("web-eid-mobile://auth#$encoded") |
| 86 | + @Test |
| 87 | + fun handleWebEidAuthResult_callsBuildAuthToken_whenPayloadValid() { |
| 88 | + val cert = byteArrayOf(1, 2, 3) |
| 89 | + val signature = byteArrayOf(4, 5, 6) |
| 90 | + val challenge = "test-challenge" |
| 91 | + val loginUri = "https://example.com/login" |
| 92 | + val getSigningCertificate = true |
| 93 | + val origin = "https://example.com" |
| 94 | + |
| 95 | + val authRequest = |
| 96 | + WebEidAuthRequest( |
| 97 | + challenge = challenge, |
| 98 | + loginUri = loginUri, |
| 99 | + getSigningCertificate = getSigningCertificate, |
| 100 | + origin = origin, |
| 101 | + ) |
| 102 | + `when`(authService.authRequest).thenReturn(MutableStateFlow(authRequest)) |
| 103 | + |
| 104 | + val token = JSONObject().put("mock", "token") |
| 105 | + `when`(authService.buildAuthToken(cert, signature, challenge)).thenReturn(token) |
| 106 | + |
| 107 | + viewModel = WebEidViewModel(authService) |
| 108 | + |
| 109 | + viewModel.handleWebEidAuthResult(cert, signature, activity) |
| 110 | + |
| 111 | + verify(authService).buildAuthToken(cert, signature, challenge) |
| 112 | + verify(activity).startActivity(any()) |
| 113 | + verify(activity).finish() |
| 114 | + } |
73 | 115 |
|
74 | | - viewModel.handleAuth(uri) |
| 116 | + @Test |
| 117 | + fun handleWebEidAuthResult_doesNothing_whenChallengeMissing() { |
| 118 | + val cert = byteArrayOf(1) |
| 119 | + val signature = byteArrayOf(2) |
| 120 | + |
| 121 | + val authRequest = |
| 122 | + WebEidAuthRequest( |
| 123 | + challenge = "", |
| 124 | + loginUri = "https://example.com", |
| 125 | + getSigningCertificate = true, |
| 126 | + origin = "https://example.com", |
| 127 | + ) |
| 128 | + `when`(authService.authRequest).thenReturn(MutableStateFlow(authRequest)) |
| 129 | + |
| 130 | + viewModel = WebEidViewModel(authService) |
| 131 | + viewModel.handleWebEidAuthResult(cert, signature, activity) |
| 132 | + |
| 133 | + verify(authService, never()).buildAuthToken(any(), any(), any()) |
| 134 | + verify(activity, never()).startActivity(any()) |
| 135 | + } |
75 | 136 |
|
76 | | - val result = viewModel.authPayload.value |
77 | | - assertEquals("xyz456", result?.challenge) |
78 | | - assertEquals("https://rp.example.com/login", result?.loginUri) |
79 | | - assertEquals(false, result?.getSigningCertificate) |
| 137 | + @Test |
| 138 | + fun handleWebEidAuthResult_doesNothing_whenLoginUriMissing() { |
| 139 | + val cert = byteArrayOf(1) |
| 140 | + val signature = byteArrayOf(2) |
| 141 | + |
| 142 | + val authRequest = |
| 143 | + WebEidAuthRequest( |
| 144 | + challenge = "abc", |
| 145 | + loginUri = "", |
| 146 | + getSigningCertificate = true, |
| 147 | + origin = "https://example.com", |
| 148 | + ) |
| 149 | + `when`(authService.authRequest).thenReturn(MutableStateFlow(authRequest)) |
| 150 | + |
| 151 | + viewModel = WebEidViewModel(authService) |
| 152 | + viewModel.handleWebEidAuthResult(cert, signature, activity) |
| 153 | + |
| 154 | + verify(authService, never()).buildAuthToken(any(), any(), any()) |
| 155 | + verify(activity, never()).startActivity(any()) |
80 | 156 | } |
81 | 157 | } |
0 commit comments