Skip to content

Commit d152869

Browse files
Add and update unit tests
1 parent ab41f41 commit d152869

File tree

3 files changed

+155
-40
lines changed

3 files changed

+155
-40
lines changed

libs/fluxc-tests/src/test/java/org/wordpress/android/fluxc/network/rest/wpcom/wc/WooNetworkTest.kt

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,42 @@ import org.mockito.kotlin.given
77
import org.mockito.kotlin.mock
88
import org.mockito.kotlin.never
99
import org.mockito.kotlin.verify
10+
import org.mockito.kotlin.whenever
1011
import org.robolectric.RobolectricTestRunner
1112
import org.wordpress.android.fluxc.model.SiteModel
1213
import org.wordpress.android.fluxc.network.rest.wpapi.WPAPINetworkError
1314
import org.wordpress.android.fluxc.network.rest.wpapi.WPAPIResponse
1415
import org.wordpress.android.fluxc.network.rest.wpapi.applicationpasswords.ApplicationPasswordsConfiguration
1516
import org.wordpress.android.fluxc.network.rest.wpapi.applicationpasswords.ApplicationPasswordsNetwork
17+
import org.wordpress.android.fluxc.network.rest.wpapi.applicationpasswords.JetpackApplicationPasswordsErrorHandler
18+
import org.wordpress.android.fluxc.network.rest.wpapi.applicationpasswords.JetpackApplicationPasswordsSupport
1619
import org.wordpress.android.fluxc.network.rest.wpcom.JetpackTunnelWPAPINetwork
17-
import org.wordpress.android.fluxc.persistence.SiteSqlUtils
1820
import org.wordpress.android.fluxc.test
1921

2022
@RunWith(RobolectricTestRunner::class)
2123
class WooNetworkTest {
2224
private val testSite = SiteModel().apply {
25+
origin = SiteModel.ORIGIN_WPCOM_REST
2326
url = "https://example.com"
2427
}
2528
private val testPath = "path"
2629
private val applicationPasswordsConfiguration = FakeApplicationPasswordsConfiguration()
2730
private val applicationPasswordsNetwork: ApplicationPasswordsNetwork = mock()
2831
private val jetpackTunnelWPAPINetwork: JetpackTunnelWPAPINetwork = mock()
29-
private val siteSqlUtils: SiteSqlUtils = mock()
32+
private val jetpackApplicationPasswordsErrorHandler: JetpackApplicationPasswordsErrorHandler = mock()
33+
private val jetpackApplicationPasswordsSupport: JetpackApplicationPasswordsSupport = mock()
3034

3135
private val sut = WooNetwork(
3236
applicationPasswordsConfiguration = applicationPasswordsConfiguration,
3337
applicationPasswordsNetwork = applicationPasswordsNetwork,
3438
jetpackTunnelWPAPINetwork = jetpackTunnelWPAPINetwork,
35-
siteSqlUtils = siteSqlUtils
39+
jetpackApplicationPasswordsSupport = jetpackApplicationPasswordsSupport,
40+
jetpackApplicationPasswordsErrorHandler = jetpackApplicationPasswordsErrorHandler
3641
)
3742

3843
@Test
3944
fun `given Jetpack site supports app passwords, when making request, then use app passwords network`() = test {
40-
testSite.origin = SiteModel.ORIGIN_WPCOM_REST
41-
testSite.applicationPasswordsAuthorizeUrl = "authorize_url"
45+
whenever(jetpackApplicationPasswordsSupport.supportsAppPasswords(testSite)).thenReturn(true)
4246
val sampleResponse = SampleResponse("value")
4347
givenAppPasswordsResponse(WPAPIResponse.Success(SampleResponse("value"), emptyList()))
4448

@@ -59,8 +63,7 @@ class WooNetworkTest {
5963
@Test
6064
fun `given jetpack site that supports app passwords, when request fails, then fall back to jetpack tunnel`() =
6165
test {
62-
testSite.origin = SiteModel.ORIGIN_WPCOM_REST
63-
testSite.applicationPasswordsAuthorizeUrl = "authorize_url"
66+
whenever(jetpackApplicationPasswordsSupport.supportsAppPasswords(testSite)).thenReturn(true)
6467
givenAppPasswordsResponse(
6568
WPAPIResponse.Error(
6669
WPAPINetworkError(
@@ -84,8 +87,7 @@ class WooNetworkTest {
8487
@Test
8588
fun `given jetpack site that does not support app passwords, when making request, then use jetpack tunnel`() =
8689
test {
87-
testSite.origin = SiteModel.ORIGIN_WPCOM_REST
88-
testSite.applicationPasswordsAuthorizeUrl = null
90+
whenever(jetpackApplicationPasswordsSupport.supportsAppPasswords(testSite)).thenReturn(false)
8991
val sampleResponse = SampleResponse("value")
9092
givenJetpackTunnelResponse(WPAPIResponse.Success(sampleResponse, emptyList()))
9193

@@ -101,8 +103,7 @@ class WooNetworkTest {
101103
@Test
102104
fun `when app passwords are disabled for jetpack access, then always use jetpack tunnel`() = test {
103105
applicationPasswordsConfiguration.isEnabledForJetpackAccessValue = false
104-
testSite.origin = SiteModel.ORIGIN_WPCOM_REST
105-
testSite.applicationPasswordsAuthorizeUrl = "authorize_url"
106+
whenever(jetpackApplicationPasswordsSupport.supportsAppPasswords(testSite)).thenReturn(true)
106107
val sampleResponse = SampleResponse("value")
107108
givenJetpackTunnelResponse(WPAPIResponse.Success(sampleResponse, emptyList()))
108109

@@ -121,33 +122,21 @@ class WooNetworkTest {
121122
}
122123

123124
@Test
124-
fun `when detecting that a site doesn't support app passwords, then update cached site with correct status`() =
125-
test {
126-
testSite.origin = SiteModel.ORIGIN_WPCOM_REST
127-
testSite.applicationPasswordsAuthorizeUrl = "authorize_url"
128-
givenAppPasswordsResponse(
129-
WPAPIResponse.Error(
130-
WPAPINetworkError(
131-
mock(),
132-
errorCode = ApplicationPasswordsNetwork.APPLICATION_PASSWORDS_NOT_SUPPORT_ERROR_CODE
133-
)
134-
)
135-
)
136-
givenJetpackTunnelResponse(
137-
WPAPIResponse.Success(SampleResponse("value"), emptyList())
138-
)
125+
fun `when jetpack tunnel fallback succeeds after app passwords failure, then notify error handler`() = test {
126+
whenever(jetpackApplicationPasswordsSupport.supportsAppPasswords(testSite)).thenReturn(true)
127+
val appPasswordsNetworkError = WPAPINetworkError(mock(), "error")
128+
givenAppPasswordsResponse(WPAPIResponse.Error(appPasswordsNetworkError))
129+
val sampleResponse = SampleResponse("value")
130+
givenJetpackTunnelResponse(WPAPIResponse.Success(sampleResponse, emptyList()))
139131

140-
sut.executeGetGsonRequest(
141-
site = testSite,
142-
path = testPath,
143-
clazz = SampleResponse::class.java
144-
)
132+
sut.executeGetGsonRequest(
133+
site = testSite,
134+
path = testPath,
135+
clazz = SampleResponse::class.java
136+
)
145137

146-
val expectedSite = testSite.apply {
147-
applicationPasswordsAuthorizeUrl = null
148-
}
149-
verify(siteSqlUtils).insertOrUpdateSite(expectedSite)
150-
}
138+
verify(jetpackApplicationPasswordsErrorHandler).handleError(testSite, appPasswordsNetworkError)
139+
}
151140

152141
private suspend fun givenAppPasswordsResponse(response: WPAPIResponse<SampleResponse>) {
153142
given(

libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/JetpackApplicationPasswordsErrorHandler.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package org.wordpress.android.fluxc.network.rest.wpapi.applicationpasswords
22

33
import org.wordpress.android.fluxc.model.SiteModel
44
import org.wordpress.android.fluxc.network.rest.wpapi.WPAPINetworkError
5+
import org.wordpress.android.fluxc.utils.AppLogWrapper
56
import org.wordpress.android.util.AppLog
67
import javax.inject.Inject
78
import javax.inject.Singleton
89

910
@Singleton
1011
class JetpackApplicationPasswordsErrorHandler @Inject constructor(
11-
private val jetpackApplicationPasswordsSupport: JetpackApplicationPasswordsSupport
12+
private val jetpackApplicationPasswordsSupport: JetpackApplicationPasswordsSupport,
13+
private val appLogWrapper: AppLogWrapper
1214
) {
1315
private var failuresCount: MutableMap<Long, Int> = mutableMapOf()
1416

@@ -22,7 +24,7 @@ class JetpackApplicationPasswordsErrorHandler @Inject constructor(
2224
apiErrorCode == "incorrect_password" ||
2325
apiErrorCode == "application_passwords_disabled_for_user"
2426
) {
25-
AppLog.w(
27+
appLogWrapper.w(
2628
AppLog.T.API,
2729
"Disabling Jetpack Application Passwords support for site ${siteModel.siteId} " +
2830
"due to error: $httpStatusCode / $apiErrorCode"
@@ -33,10 +35,10 @@ class JetpackApplicationPasswordsErrorHandler @Inject constructor(
3335
failuresCount[siteModel.siteId] = siteFailuresCount
3436

3537
if (siteFailuresCount >= FAILURES_THRESHOLD) {
36-
AppLog.w(
38+
appLogWrapper.w(
3739
AppLog.T.API,
3840
"Disabling Jetpack Application Passwords support for site ${siteModel.siteId} " +
39-
"after $failuresCount failures"
41+
"after $siteFailuresCount failures"
4042
)
4143
jetpackApplicationPasswordsSupport.flagAsUnsupported(siteModel)
4244
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package org.wordpress.android.fluxc.network.rest.wpapi.applicationpasswords
2+
3+
import com.android.volley.NetworkResponse
4+
import com.android.volley.VolleyError
5+
import org.junit.Test
6+
import org.mockito.kotlin.mock
7+
import org.mockito.kotlin.never
8+
import org.mockito.kotlin.times
9+
import org.mockito.kotlin.verify
10+
import org.wordpress.android.fluxc.model.SiteModel
11+
import org.wordpress.android.fluxc.network.BaseRequest.BaseNetworkError
12+
import org.wordpress.android.fluxc.network.rest.wpapi.WPAPINetworkError
13+
import org.wordpress.android.fluxc.utils.AppLogWrapper
14+
15+
class JetpackApplicationPasswordsErrorHandlerTests {
16+
private val jetpackApplicationPasswordsSupport: JetpackApplicationPasswordsSupport = mock()
17+
private val appLogWrapper: AppLogWrapper = mock()
18+
private val errorHandler: JetpackApplicationPasswordsErrorHandler = JetpackApplicationPasswordsErrorHandler(
19+
jetpackApplicationPasswordsSupport = jetpackApplicationPasswordsSupport,
20+
appLogWrapper = appLogWrapper
21+
)
22+
23+
private val testSite = SiteModel().apply {
24+
siteId = 123L
25+
}
26+
27+
@Test
28+
fun `given HTTP 401 error, when handling error, then flag site as unsupported`() {
29+
// Given
30+
val volleyError = VolleyError(NetworkResponse(401, null, true, 0, emptyList()))
31+
val baseError = BaseNetworkError(volleyError)
32+
val networkError = WPAPINetworkError(baseError)
33+
34+
// When
35+
errorHandler.handleError(testSite, networkError)
36+
37+
// Then
38+
verify(jetpackApplicationPasswordsSupport).flagAsUnsupported(testSite)
39+
}
40+
41+
@Test
42+
fun `given HTTP 403 error, when handling error, then flag site as unsupported`() {
43+
// Given
44+
val volleyError = VolleyError(NetworkResponse(403, null, true, 0, emptyList()))
45+
val baseError = BaseNetworkError(volleyError)
46+
val networkError = WPAPINetworkError(baseError)
47+
48+
// When
49+
errorHandler.handleError(testSite, networkError)
50+
51+
// Then
52+
verify(jetpackApplicationPasswordsSupport).flagAsUnsupported(testSite)
53+
}
54+
55+
@Test
56+
fun `given HTTP 429 error, when handling error, then flag site as unsupported`() {
57+
// Given
58+
val volleyError = VolleyError(NetworkResponse(429, null, true, 0, emptyList()))
59+
val baseError = BaseNetworkError(volleyError)
60+
val networkError = WPAPINetworkError(baseError)
61+
62+
// When
63+
errorHandler.handleError(testSite, networkError)
64+
65+
// Then
66+
verify(jetpackApplicationPasswordsSupport).flagAsUnsupported(testSite)
67+
}
68+
69+
@Test
70+
fun `given incorrect_password error code, when handling error, then flag site as unsupported`() {
71+
// Given
72+
val baseError = BaseNetworkError(mock<VolleyError>())
73+
val networkError = WPAPINetworkError(baseError, "incorrect_password")
74+
75+
// When
76+
errorHandler.handleError(testSite, networkError)
77+
78+
// Then
79+
verify(jetpackApplicationPasswordsSupport).flagAsUnsupported(testSite)
80+
}
81+
82+
@Test
83+
fun `given application_passwords_disabled_for_user error code, when handling error, then flag site as unsupported`() {
84+
// Given
85+
val baseError = BaseNetworkError(mock<VolleyError>())
86+
val networkError = WPAPINetworkError(baseError, "application_passwords_disabled_for_user")
87+
88+
// When
89+
errorHandler.handleError(testSite, networkError)
90+
91+
// Then
92+
verify(jetpackApplicationPasswordsSupport).flagAsUnsupported(testSite)
93+
}
94+
95+
@Test
96+
fun `given generic error, when handling error once, then do not flag site as unsupported`() {
97+
// Given
98+
val volleyError = VolleyError(NetworkResponse(500, null, true, 0, emptyList()))
99+
val baseError = BaseNetworkError(volleyError)
100+
val networkError = WPAPINetworkError(baseError, "generic_error")
101+
102+
// When
103+
errorHandler.handleError(testSite, networkError)
104+
105+
// Then
106+
verify(jetpackApplicationPasswordsSupport, never()).flagAsUnsupported(testSite)
107+
}
108+
109+
@Test
110+
fun `given generic error, when handling error 10 times, then flag site as unsupported`() {
111+
// Given
112+
val volleyError = VolleyError(NetworkResponse(500, null, true, 0, emptyList()))
113+
val baseError = BaseNetworkError(volleyError)
114+
val networkError = WPAPINetworkError(baseError, "generic_error")
115+
116+
// When
117+
repeat(10) {
118+
errorHandler.handleError(testSite, networkError)
119+
}
120+
121+
// Then
122+
verify(jetpackApplicationPasswordsSupport, times(1)).flagAsUnsupported(testSite)
123+
}
124+
}

0 commit comments

Comments
 (0)