Skip to content

Commit 801cd5d

Browse files
authored
CMM-770 request categories using wordpress rs (#22226)
* Creatign the taxonomy client * Fetching tags from the new endpoint * detekt * Adding tests * Removing debug code * Adding a function for categories * typo * Handling categories correctly * Adding tests * Typos * minor renaming
1 parent e42c789 commit 801cd5d

File tree

3 files changed

+162
-33
lines changed

3 files changed

+162
-33
lines changed

libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/taxonomy/TaxonomyRsApiRestClient.kt

Lines changed: 75 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@ import org.wordpress.android.fluxc.model.TermModel
99
import org.wordpress.android.fluxc.model.TermsModel
1010
import org.wordpress.android.fluxc.module.FLUXC_SCOPE
1111
import org.wordpress.android.fluxc.network.rest.wpapi.rs.WpApiClientProvider
12+
import org.wordpress.android.fluxc.store.TaxonomyStore
13+
import org.wordpress.android.fluxc.store.TaxonomyStore.DEFAULT_TAXONOMY_TAG
1214
import org.wordpress.android.fluxc.store.TaxonomyStore.FetchTermsResponsePayload
1315
import org.wordpress.android.fluxc.store.TaxonomyStore.TaxonomyError
1416
import org.wordpress.android.fluxc.store.TaxonomyStore.TaxonomyErrorType
1517
import org.wordpress.android.fluxc.utils.AppLogWrapper
1618
import org.wordpress.android.util.AppLog
1719
import rs.wordpress.api.kotlin.WpRequestResult
20+
import uniffi.wp_api.CategoryListParams
1821
import uniffi.wp_api.TagListParams
19-
import uniffi.wp_api.TagWithEditContext
2022
import javax.inject.Inject
2123
import javax.inject.Named
2224
import javax.inject.Singleton
@@ -28,59 +30,106 @@ class TaxonomyRsApiRestClient @Inject constructor(
2830
private val appLogWrapper: AppLogWrapper,
2931
private val wpApiClientProvider: WpApiClientProvider,
3032
) {
31-
fun fetchPostTags(site: SiteModel, taxonomyName: String) {
33+
fun fetchPostCategories(site: SiteModel) {
3234
scope.launch {
3335
val client = wpApiClientProvider.getWpApiClient(site)
3436

35-
val mediaResponse = client.request { requestBuilder ->
37+
val categoriesResponse = client.request { requestBuilder ->
38+
requestBuilder.categories().listWithEditContext(
39+
CategoryListParams()
40+
)
41+
}
42+
43+
val termsResponsePayload = when (categoriesResponse) {
44+
is WpRequestResult.Success -> {
45+
appLogWrapper.d(AppLog.T.POSTS, "Fetched categories list: ${categoriesResponse.response.data.size}")
46+
createTermsResponsePayload(
47+
categoriesResponse.response.data.map { category ->
48+
TermModel(
49+
category.id.toInt(),
50+
site.id,
51+
category.id,
52+
TaxonomyStore.DEFAULT_TAXONOMY_CATEGORY,
53+
category.name,
54+
category.slug,
55+
category.description,
56+
0,
57+
category.count.toInt()
58+
)
59+
},
60+
site,
61+
TaxonomyStore.DEFAULT_TAXONOMY_CATEGORY
62+
)
63+
}
64+
65+
else -> {
66+
appLogWrapper.e(AppLog.T.POSTS, "Fetch categories list failed: $categoriesResponse")
67+
FetchTermsResponsePayload(
68+
TaxonomyError(TaxonomyErrorType.GENERIC_ERROR, ""),
69+
TaxonomyStore.DEFAULT_TAXONOMY_CATEGORY
70+
)
71+
}
72+
}
73+
notifyTermsFetched(termsResponsePayload)
74+
}
75+
}
76+
77+
fun fetchPostTags(site: SiteModel) {
78+
scope.launch {
79+
val client = wpApiClientProvider.getWpApiClient(site)
80+
81+
val tagsResponse = client.request { requestBuilder ->
3682
requestBuilder.tags().listWithEditContext(
3783
TagListParams()
3884
)
3985
}
4086

41-
val termsResponsePayload = when (mediaResponse) {
87+
val termsResponsePayload = when (tagsResponse) {
4288
is WpRequestResult.Success -> {
43-
appLogWrapper.d(AppLog.T.POSTS, "Fetched tags list: ${mediaResponse.response.data.size}")
44-
mediaResponse.response.data.toFetchTermsResponsePayload(site, taxonomyName)
89+
appLogWrapper.d(AppLog.T.POSTS, "Fetched tags list: ${tagsResponse.response.data.size}")
90+
createTermsResponsePayload(
91+
tagsResponse.response.data.map { tag ->
92+
TermModel(
93+
tag.id.toInt(),
94+
site.id,
95+
tag.id,
96+
DEFAULT_TAXONOMY_TAG,
97+
tag.name,
98+
tag.slug,
99+
tag.description,
100+
0,
101+
tag.count.toInt()
102+
)
103+
},
104+
site,
105+
DEFAULT_TAXONOMY_TAG
106+
)
45107
}
46108

47109
else -> {
48-
appLogWrapper.e(AppLog.T.POSTS, "Fetch tags list failed: $mediaResponse")
110+
appLogWrapper.e(AppLog.T.POSTS, "Fetch tags list failed: $tagsResponse")
49111
FetchTermsResponsePayload(
50112
TaxonomyError(TaxonomyErrorType.GENERIC_ERROR, ""),
51-
taxonomyName
113+
DEFAULT_TAXONOMY_TAG
52114
)
53115
}
54116
}
55-
notifyTagsFetched(termsResponsePayload)
117+
notifyTermsFetched(termsResponsePayload)
56118
}
57119
}
58120

59-
private fun notifyTagsFetched(
121+
private fun notifyTermsFetched(
60122
payload: FetchTermsResponsePayload,
61123
) {
62124
dispatcher.dispatch(TaxonomyActionBuilder.newFetchedTermsAction(payload))
63125
}
64126

65-
private fun List<TagWithEditContext>.toFetchTermsResponsePayload(
127+
private fun createTermsResponsePayload(
128+
terms: List<TermModel>,
66129
site: SiteModel,
67130
taxonomyName: String
68131
): FetchTermsResponsePayload = FetchTermsResponsePayload(
69-
TermsModel(
70-
this.map {
71-
TermModel(
72-
it.id.toInt(),
73-
site.id,
74-
it.id,
75-
taxonomyName,
76-
it.name,
77-
it.slug,
78-
it.description,
79-
0,
80-
it.count.toInt()
81-
)
82-
}
83-
),
132+
TermsModel(terms),
84133
site,
85134
taxonomyName
86135
)

libs/fluxc/src/main/java/org/wordpress/android/fluxc/store/TaxonomyStore.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,11 @@ private void fetchTerm(@NonNull RemoteTermPayload payload) {
328328
}
329329

330330
private void fetchTerms(@NonNull SiteModel site, @NonNull String taxonomyName) {
331-
if (site.isUsingSelfHostedRestApi() && DEFAULT_TAXONOMY_TAG.equals(taxonomyName)) {
332-
mTaxonomyRsApiRestClient.fetchPostTags(site, taxonomyName);
331+
boolean isUsingApplicationPassword = site.isUsingSelfHostedRestApi();
332+
if (isUsingApplicationPassword && DEFAULT_TAXONOMY_CATEGORY.equals(taxonomyName)) {
333+
mTaxonomyRsApiRestClient.fetchPostCategories(site);
334+
} else if (isUsingApplicationPassword && DEFAULT_TAXONOMY_TAG.equals(taxonomyName)) {
335+
mTaxonomyRsApiRestClient.fetchPostTags(site);
333336
} else if (site.isUsingWpComRestApi()) {
334337
mTaxonomyRestClient.fetchTerms(site, taxonomyName);
335338
} else {

libs/fluxc/src/test/java/org/wordpress/android/fluxc/network/rest/wpapi/taxonomy/TaxonomyRsApiRestClientTest.kt

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ import org.wordpress.android.fluxc.store.TaxonomyStore.TaxonomyErrorType
2929
import org.wordpress.android.fluxc.utils.AppLogWrapper
3030
import rs.wordpress.api.kotlin.WpApiClient
3131
import rs.wordpress.api.kotlin.WpRequestResult
32+
import uniffi.wp_api.CategoryWithEditContext
33+
import uniffi.wp_api.CategoriesRequestListWithEditContextResponse
3234
import uniffi.wp_api.TagWithEditContext
3335
import uniffi.wp_api.TagsRequestListWithEditContextResponse
3436
import uniffi.wp_api.TaxonomyType
@@ -54,7 +56,8 @@ class TaxonomyRsApiRestClientTest {
5456
url = "https://test.wordpress.com"
5557
}
5658

57-
private val testTaxonomyName = "post_tag"
59+
private val testTagTaxonomyName = "post_tag"
60+
private val testCategoryTaxonomyName = "category"
5861

5962
@Before
6063
fun setUp() {
@@ -84,7 +87,7 @@ class TaxonomyRsApiRestClientTest {
8487

8588
whenever(wpApiClient.request<Any>(any())).thenReturn(errorResponse)
8689

87-
taxonomyClient.fetchPostTags(testSite, testTaxonomyName)
90+
taxonomyClient.fetchPostTags(testSite)
8891

8992
// Verify dispatcher was called with error action
9093
val actionCaptor = ArgumentCaptor.forClass(Action::class.java)
@@ -93,7 +96,7 @@ class TaxonomyRsApiRestClientTest {
9396
val capturedAction = actionCaptor.value
9497
val payload = capturedAction.payload as FetchTermsResponsePayload
9598
assertEquals(capturedAction.type, TaxonomyAction.FETCHED_TERMS)
96-
assertEquals(testTaxonomyName, payload.taxonomy)
99+
assertEquals(testTagTaxonomyName, payload.taxonomy)
97100
assertNotNull(payload.error)
98101
assertEquals(TaxonomyErrorType.GENERIC_ERROR, payload.error?.type)
99102
}
@@ -119,7 +122,7 @@ class TaxonomyRsApiRestClientTest {
119122

120123
whenever(wpApiClient.request<TagsRequestListWithEditContextResponse>(any())).thenReturn(successResponse)
121124

122-
taxonomyClient.fetchPostTags(testSite, testTaxonomyName)
125+
taxonomyClient.fetchPostTags(testSite)
123126

124127
// Verify dispatcher was called with success action
125128
val actionCaptor = ArgumentCaptor.forClass(Action::class.java)
@@ -128,13 +131,87 @@ class TaxonomyRsApiRestClientTest {
128131
val capturedAction = actionCaptor.value
129132
val payload = capturedAction.payload as FetchTermsResponsePayload
130133
assertEquals(capturedAction.type, TaxonomyAction.FETCHED_TERMS)
131-
assertEquals(testTaxonomyName, payload.taxonomy)
134+
assertEquals(testTagTaxonomyName, payload.taxonomy)
132135
assertEquals(testSite, payload.site)
133136
assertNotNull(payload.terms)
134137
assertEquals(2, payload.terms.terms.size)
135138
assertNull(payload.error)
136139
}
137140

141+
@Test
142+
fun `fetchPostCategories with error response dispatches error action`() = runTest {
143+
// Use a concrete error type that we can create - UnknownError requires statusCode and response
144+
val errorResponse = WpRequestResult.UnknownError<Any>(
145+
statusCode = 500u,
146+
response = "Internal Server Error"
147+
)
148+
149+
whenever(wpApiClient.request<Any>(any())).thenReturn(errorResponse)
150+
151+
taxonomyClient.fetchPostCategories(testSite)
152+
153+
// Verify dispatcher was called with error action
154+
val actionCaptor = ArgumentCaptor.forClass(Action::class.java)
155+
verify(dispatcher).dispatch(actionCaptor.capture())
156+
157+
val capturedAction = actionCaptor.value
158+
val payload = capturedAction.payload as FetchTermsResponsePayload
159+
assertEquals(capturedAction.type, TaxonomyAction.FETCHED_TERMS)
160+
assertEquals(testCategoryTaxonomyName, payload.taxonomy)
161+
assertNotNull(payload.error)
162+
assertEquals(TaxonomyErrorType.GENERIC_ERROR, payload.error?.type)
163+
}
164+
165+
@Test
166+
fun `fetchPostCategories with success response dispatches success action`() = runTest {
167+
val categoryWithEditContext = listOf(
168+
createTestCategoryWithEditContext(),
169+
createTestCategoryWithEditContext()
170+
)
171+
172+
// Create the correct response structure following the MediaRSApiRestClientTest pattern
173+
val categoryResponse = CategoriesRequestListWithEditContextResponse(
174+
categoryWithEditContext,
175+
mock<WpNetworkHeaderMap>(),
176+
null,
177+
null
178+
)
179+
180+
val successResponse: WpRequestResult<CategoriesRequestListWithEditContextResponse> = WpRequestResult.Success(
181+
response = categoryResponse
182+
)
183+
184+
whenever(wpApiClient.request<CategoriesRequestListWithEditContextResponse>(any())).thenReturn(successResponse)
185+
186+
taxonomyClient.fetchPostCategories(testSite)
187+
188+
// Verify dispatcher was called with success action
189+
val actionCaptor = ArgumentCaptor.forClass(Action::class.java)
190+
verify(dispatcher).dispatch(actionCaptor.capture())
191+
192+
val capturedAction = actionCaptor.value
193+
val payload = capturedAction.payload as FetchTermsResponsePayload
194+
assertEquals(capturedAction.type, TaxonomyAction.FETCHED_TERMS)
195+
assertEquals(testCategoryTaxonomyName, payload.taxonomy)
196+
assertEquals(testSite, payload.site)
197+
assertNotNull(payload.terms)
198+
assertEquals(2, payload.terms.terms.size)
199+
assertNull(payload.error)
200+
}
201+
202+
private fun createTestCategoryWithEditContext(): CategoryWithEditContext {
203+
return CategoryWithEditContext(
204+
id = 2L,
205+
count = 3L,
206+
description = "Test category description",
207+
link = "https://example.com/category/test",
208+
name = "Test Category",
209+
slug = "test-category",
210+
taxonomy = TaxonomyType.Category,
211+
parent = 0L
212+
)
213+
}
214+
138215
private fun createTestTagWithEditContext(): TagWithEditContext {
139216
return TagWithEditContext(
140217
id = 1L,

0 commit comments

Comments
 (0)