Skip to content

Commit 907ab00

Browse files
committed
tests
1 parent a8535d6 commit 907ab00

File tree

1 file changed

+254
-0
lines changed

1 file changed

+254
-0
lines changed
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
package org.wordpress.android.ui.newstats.repository
2+
3+
import kotlinx.coroutines.ExperimentalCoroutinesApi
4+
import org.assertj.core.api.Assertions.assertThat
5+
import org.junit.Before
6+
import org.junit.Test
7+
import org.mockito.Mock
8+
import org.mockito.kotlin.any
9+
import org.mockito.kotlin.eq
10+
import org.mockito.kotlin.times
11+
import org.mockito.kotlin.verify
12+
import org.mockito.kotlin.whenever
13+
import org.wordpress.android.BaseUnitTest
14+
import org.wordpress.android.fluxc.utils.AppLogWrapper
15+
import org.wordpress.android.ui.newstats.StatsPeriod
16+
import org.wordpress.android.ui.newstats.datasource.CountryViewItem
17+
import org.wordpress.android.ui.newstats.datasource.CountryViewsData
18+
import org.wordpress.android.ui.newstats.datasource.CountryViewsDataResult
19+
import org.wordpress.android.ui.newstats.datasource.StatsDataSource
20+
21+
@ExperimentalCoroutinesApi
22+
class StatsRepositoryCountryViewsTest : BaseUnitTest() {
23+
@Mock
24+
private lateinit var statsDataSource: StatsDataSource
25+
26+
@Mock
27+
private lateinit var appLogWrapper: AppLogWrapper
28+
29+
private lateinit var repository: StatsRepository
30+
31+
@Before
32+
fun setUp() {
33+
repository = StatsRepository(
34+
statsDataSource = statsDataSource,
35+
appLogWrapper = appLogWrapper,
36+
ioDispatcher = testDispatcher()
37+
)
38+
}
39+
40+
@Test
41+
fun `given successful response, when fetchCountryViews, then success result is returned`() = test {
42+
whenever(statsDataSource.fetchCountryViews(any(), any(), any()))
43+
.thenReturn(CountryViewsDataResult.Success(createCountryViewsData()))
44+
45+
val result = repository.fetchCountryViews(TEST_SITE_ID, StatsPeriod.Last7Days)
46+
47+
assertThat(result).isInstanceOf(CountryViewsResult.Success::class.java)
48+
val success = result as CountryViewsResult.Success
49+
assertThat(success.countries).hasSize(2)
50+
assertThat(success.countries[0].countryCode).isEqualTo(TEST_COUNTRY_CODE_1)
51+
assertThat(success.countries[0].countryName).isEqualTo(TEST_COUNTRY_NAME_1)
52+
assertThat(success.countries[0].views).isEqualTo(TEST_COUNTRY_VIEWS_1)
53+
assertThat(success.countries[1].countryCode).isEqualTo(TEST_COUNTRY_CODE_2)
54+
assertThat(success.countries[1].views).isEqualTo(TEST_COUNTRY_VIEWS_2)
55+
}
56+
57+
@Test
58+
fun `given successful response, when fetchCountryViews, then totalViews is sum of country views`() = test {
59+
whenever(statsDataSource.fetchCountryViews(any(), any(), any()))
60+
.thenReturn(CountryViewsDataResult.Success(createCountryViewsData()))
61+
62+
val result = repository.fetchCountryViews(TEST_SITE_ID, StatsPeriod.Last7Days)
63+
64+
assertThat(result).isInstanceOf(CountryViewsResult.Success::class.java)
65+
val success = result as CountryViewsResult.Success
66+
// totalViews should be calculated from countries, not from API's summary field
67+
assertThat(success.totalViews).isEqualTo(TEST_COUNTRY_VIEWS_1 + TEST_COUNTRY_VIEWS_2)
68+
}
69+
70+
@Test
71+
fun `given API totalViews is zero, when fetchCountryViews, then totalViews is sum of country views`() = test {
72+
// Simulate API returning 0 for totalViews but having country data
73+
val countryViewsData = CountryViewsData(
74+
countries = listOf(
75+
CountryViewItem(TEST_COUNTRY_CODE_1, TEST_COUNTRY_NAME_1, TEST_COUNTRY_VIEWS_1, null),
76+
CountryViewItem(TEST_COUNTRY_CODE_2, TEST_COUNTRY_NAME_2, TEST_COUNTRY_VIEWS_2, null)
77+
),
78+
totalViews = 0L, // API returns 0
79+
otherViews = 0L
80+
)
81+
whenever(statsDataSource.fetchCountryViews(any(), any(), any()))
82+
.thenReturn(CountryViewsDataResult.Success(countryViewsData))
83+
84+
val result = repository.fetchCountryViews(TEST_SITE_ID, StatsPeriod.Last7Days)
85+
86+
assertThat(result).isInstanceOf(CountryViewsResult.Success::class.java)
87+
val success = result as CountryViewsResult.Success
88+
// totalViews should still be calculated from country views
89+
assertThat(success.totalViews).isEqualTo(TEST_COUNTRY_VIEWS_1 + TEST_COUNTRY_VIEWS_2)
90+
}
91+
92+
@Test
93+
fun `given current and previous data, when fetchCountryViews, then change is calculated correctly`() = test {
94+
val currentData = CountryViewsData(
95+
countries = listOf(
96+
CountryViewItem("US", "United States", 150, null),
97+
CountryViewItem("UK", "United Kingdom", 100, null)
98+
),
99+
totalViews = 250L,
100+
otherViews = 0L
101+
)
102+
val previousData = CountryViewsData(
103+
countries = listOf(
104+
CountryViewItem("US", "United States", 100, null),
105+
CountryViewItem("UK", "United Kingdom", 100, null)
106+
),
107+
totalViews = 200L,
108+
otherViews = 0L
109+
)
110+
111+
whenever(statsDataSource.fetchCountryViews(any(), any(), any()))
112+
.thenReturn(CountryViewsDataResult.Success(currentData))
113+
.thenReturn(CountryViewsDataResult.Success(previousData))
114+
115+
val result = repository.fetchCountryViews(TEST_SITE_ID, StatsPeriod.Last7Days)
116+
117+
assertThat(result).isInstanceOf(CountryViewsResult.Success::class.java)
118+
val success = result as CountryViewsResult.Success
119+
// Current total: 250, Previous total: 200, Change: 50
120+
assertThat(success.totalViews).isEqualTo(250)
121+
assertThat(success.totalViewsChange).isEqualTo(50)
122+
assertThat(success.totalViewsChangePercent).isEqualTo(25.0)
123+
}
124+
125+
@Test
126+
fun `given country in both periods, when fetchCountryViews, then previousViews is set correctly`() = test {
127+
val currentData = CountryViewsData(
128+
countries = listOf(CountryViewItem("US", "United States", 150, null)),
129+
totalViews = 150L,
130+
otherViews = 0L
131+
)
132+
val previousData = CountryViewsData(
133+
countries = listOf(CountryViewItem("US", "United States", 100, null)),
134+
totalViews = 100L,
135+
otherViews = 0L
136+
)
137+
138+
whenever(statsDataSource.fetchCountryViews(any(), any(), any()))
139+
.thenReturn(CountryViewsDataResult.Success(currentData))
140+
.thenReturn(CountryViewsDataResult.Success(previousData))
141+
142+
val result = repository.fetchCountryViews(TEST_SITE_ID, StatsPeriod.Last7Days)
143+
144+
assertThat(result).isInstanceOf(CountryViewsResult.Success::class.java)
145+
val success = result as CountryViewsResult.Success
146+
assertThat(success.countries[0].previousViews).isEqualTo(100)
147+
assertThat(success.countries[0].viewsChange).isEqualTo(50)
148+
assertThat(success.countries[0].viewsChangePercent).isEqualTo(50.0)
149+
}
150+
151+
@Test
152+
fun `given new country not in previous period, when fetchCountryViews, then previousViews is zero`() = test {
153+
val currentData = CountryViewsData(
154+
countries = listOf(CountryViewItem("US", "United States", 100, null)),
155+
totalViews = 100L,
156+
otherViews = 0L
157+
)
158+
val previousData = CountryViewsData(
159+
countries = emptyList(),
160+
totalViews = 0L,
161+
otherViews = 0L
162+
)
163+
164+
whenever(statsDataSource.fetchCountryViews(any(), any(), any()))
165+
.thenReturn(CountryViewsDataResult.Success(currentData))
166+
.thenReturn(CountryViewsDataResult.Success(previousData))
167+
168+
val result = repository.fetchCountryViews(TEST_SITE_ID, StatsPeriod.Last7Days)
169+
170+
assertThat(result).isInstanceOf(CountryViewsResult.Success::class.java)
171+
val success = result as CountryViewsResult.Success
172+
assertThat(success.countries[0].previousViews).isEqualTo(0)
173+
assertThat(success.countries[0].viewsChange).isEqualTo(100)
174+
assertThat(success.countries[0].viewsChangePercent).isEqualTo(100.0)
175+
}
176+
177+
@Test
178+
fun `given previous fetch fails, when fetchCountryViews, then previousViews defaults to zero`() = test {
179+
val currentData = CountryViewsData(
180+
countries = listOf(CountryViewItem("US", "United States", 100, null)),
181+
totalViews = 100L,
182+
otherViews = 0L
183+
)
184+
185+
whenever(statsDataSource.fetchCountryViews(any(), any(), any()))
186+
.thenReturn(CountryViewsDataResult.Success(currentData))
187+
.thenReturn(CountryViewsDataResult.Error("Network error"))
188+
189+
val result = repository.fetchCountryViews(TEST_SITE_ID, StatsPeriod.Last7Days)
190+
191+
assertThat(result).isInstanceOf(CountryViewsResult.Success::class.java)
192+
val success = result as CountryViewsResult.Success
193+
assertThat(success.countries[0].previousViews).isEqualTo(0)
194+
assertThat(success.totalViewsChange).isEqualTo(100)
195+
assertThat(success.totalViewsChangePercent).isEqualTo(100.0)
196+
}
197+
198+
@Test
199+
fun `given error response, when fetchCountryViews, then error result is returned`() = test {
200+
whenever(statsDataSource.fetchCountryViews(any(), any(), any()))
201+
.thenReturn(CountryViewsDataResult.Error(ERROR_MESSAGE))
202+
203+
val result = repository.fetchCountryViews(TEST_SITE_ID, StatsPeriod.Last7Days)
204+
205+
assertThat(result).isInstanceOf(CountryViewsResult.Error::class.java)
206+
assertThat((result as CountryViewsResult.Error).message).isEqualTo(ERROR_MESSAGE)
207+
}
208+
209+
@Test
210+
fun `when fetchCountryViews is called, then data source is called twice for comparison`() = test {
211+
whenever(statsDataSource.fetchCountryViews(any(), any(), any()))
212+
.thenReturn(CountryViewsDataResult.Success(createCountryViewsData()))
213+
214+
repository.fetchCountryViews(TEST_SITE_ID, StatsPeriod.Last7Days)
215+
216+
// Verify data source is called twice (current and previous period)
217+
verify(statsDataSource, times(2)).fetchCountryViews(
218+
siteId = eq(TEST_SITE_ID),
219+
dateRange = any(),
220+
max = any()
221+
)
222+
}
223+
224+
private fun createCountryViewsData() = CountryViewsData(
225+
countries = listOf(
226+
CountryViewItem(
227+
countryCode = TEST_COUNTRY_CODE_1,
228+
countryName = TEST_COUNTRY_NAME_1,
229+
views = TEST_COUNTRY_VIEWS_1,
230+
flagIconUrl = null
231+
),
232+
CountryViewItem(
233+
countryCode = TEST_COUNTRY_CODE_2,
234+
countryName = TEST_COUNTRY_NAME_2,
235+
views = TEST_COUNTRY_VIEWS_2,
236+
flagIconUrl = null
237+
)
238+
),
239+
totalViews = TEST_COUNTRY_VIEWS_1 + TEST_COUNTRY_VIEWS_2,
240+
otherViews = 0L
241+
)
242+
243+
companion object {
244+
private const val TEST_SITE_ID = 123L
245+
private const val ERROR_MESSAGE = "Test error message"
246+
247+
private const val TEST_COUNTRY_CODE_1 = "US"
248+
private const val TEST_COUNTRY_CODE_2 = "UK"
249+
private const val TEST_COUNTRY_NAME_1 = "United States"
250+
private const val TEST_COUNTRY_NAME_2 = "United Kingdom"
251+
private const val TEST_COUNTRY_VIEWS_1 = 500L
252+
private const val TEST_COUNTRY_VIEWS_2 = 300L
253+
}
254+
}

0 commit comments

Comments
 (0)