Skip to content

Commit c2a51c2

Browse files
authored
Reader: Update fetch followed sites to take additional parameters (#753)
2 parents 69532b7 + 35cad56 commit c2a51c2

File tree

7 files changed

+306
-107
lines changed

7 files changed

+306
-107
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ _None._
7272
### Internal Changes
7373

7474
- Add WP.com theme type information. [#750]
75+
- Add `page` and `number` parameters to fetchFollowedSites in `ReaderTopicServiceRemote` [#753]
7576

7677
## 14.0.1
7778

Sources/WordPressKit/Services/ReaderTopicServiceRemote.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,26 @@ extern NSString * const WordPressComReaderEndpointURL;
1919
failure:(void (^)(NSError *error))failure;
2020

2121
/**
22-
Get a list of the sites the user follows.
22+
Get a list of the sites the user follows with the default API parameters.
2323
2424
@param success block called on a successful fetch.
2525
@param failure block called if there is any error. `error` can be any underlying network error.
2626
*/
2727
- (void)fetchFollowedSitesWithSuccess:(void(^)(NSArray *sites))success
28-
failure:(void(^)(NSError *error))failure;
28+
failure:(void(^)(NSError *error))failure DEPRECATED_MSG_ATTRIBUTE("Use fetchFollowedSitesForPage:number:success:failure: instead.");
29+
30+
/**
31+
Get a list of the sites the user follows with the specified API parameters.
32+
33+
@param page The page number to fetch.
34+
@param number The number of sites to fetch per page.
35+
@param success block called on a successful fetch.
36+
@param failure block called if there is any error. `error` can be any underlying network error.
37+
*/
38+
- (void)fetchFollowedSitesForPage:(NSUInteger)page
39+
number:(NSUInteger)number
40+
success:(void(^)(NSNumber *totalSites, NSArray<RemoteReaderSiteInfo *> *sites))success
41+
failure:(void(^)(NSError *error))failure;
2942

3043
/**
3144
Unfollows the topic with the specified slug.

Sources/WordPressKit/Services/ReaderTopicServiceRemote.m

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,21 @@ - (void)fetchReaderMenuWithSuccess:(void (^)(NSArray *topics))success failure:(v
6161

6262
- (void)fetchFollowedSitesWithSuccess:(void(^)(NSArray *sites))success failure:(void(^)(NSError *error))failure
6363
{
64-
NSString *path = @"read/following/mine?meta=site,feed";
64+
void (^wrappedSuccess)(NSNumber *, NSArray<RemoteReaderSiteInfo *> *) = ^(NSNumber *totalSites, NSArray<RemoteReaderSiteInfo *> *sites) {
65+
if (success) {
66+
success(sites);
67+
}
68+
};
69+
70+
[self fetchFollowedSitesForPage:0 number:0 success:wrappedSuccess failure:failure];
71+
}
72+
73+
- (void)fetchFollowedSitesForPage:(NSUInteger)page
74+
number:(NSUInteger)number
75+
success:(void(^)(NSNumber *totalSites, NSArray<RemoteReaderSiteInfo *> *sites))success
76+
failure:(void(^)(NSError *error))failure
77+
{
78+
NSString *path = [self pathForFollowedSitesWithPage:page number:number];
6579
NSString *requestUrl = [self pathForEndpoint:path
6680
withVersion:ServiceRemoteWordPressComRESTApiVersion_1_2];
6781

@@ -70,14 +84,14 @@ - (void)fetchFollowedSitesWithSuccess:(void(^)(NSArray *sites))success failure:(
7084
return;
7185
}
7286
NSDictionary *response = (NSDictionary *)responseObject;
87+
NSNumber *totalSites = [response numberForKey:@"total_subscriptions"];
7388
NSArray *subscriptions = [response arrayForKey:@"subscriptions"];
7489
NSMutableArray *sites = [NSMutableArray array];
7590
for (NSDictionary *dict in subscriptions) {
7691
RemoteReaderSiteInfo *siteInfo = [self siteInfoFromFollowedSiteDictionary:dict];
7792
[sites addObject:siteInfo];
7893
}
79-
success(sites);
80-
94+
success(totalSites, sites);
8195
} failure:^(NSError *error, NSHTTPURLResponse *httpResponse) {
8296
if (failure) {
8397
failure(error);
@@ -300,4 +314,17 @@ - (RemoteReaderTopic *)normalizeMenuTopicDictionary:(NSDictionary *)topicDict su
300314
return topic;
301315
}
302316

317+
- (NSString *)pathForFollowedSitesWithPage:(NSUInteger)page number:(NSUInteger)number
318+
{
319+
NSString *path = @"read/following/mine?meta=site,feed";
320+
if (page > 0) {
321+
path = [path stringByAppendingFormat:@"&page=%lu", (unsigned long)page];
322+
}
323+
if (number > 0) {
324+
path = [path stringByAppendingFormat:@"&number=%lu", (unsigned long)number];
325+
}
326+
327+
return path;
328+
}
329+
303330
@end
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
{
2+
"subscriptions": [
3+
{
4+
"ID": "764146175",
5+
"blog_ID": "3584907",
6+
"feed_ID": "25823",
7+
"URL": "http://en.blog.wordpress.com",
8+
"date_subscribed": "2024-03-05T20:48:52+00:00",
9+
"delivery_methods": {
10+
"email": {
11+
"send_posts": true,
12+
"send_comments": false,
13+
"post_delivery_frequency": "instantly",
14+
"date_subscribed": "2024-03-05 20:48:53"
15+
},
16+
"notification": {
17+
"send_posts": false
18+
}
19+
},
20+
"name": "WordPress.com News",
21+
"organization_id": 0,
22+
"unseen_count": 0,
23+
"last_updated": "2024-03-07T15:00:00+00:00",
24+
"site_icon": "https://secure.gravatar.com/blavatar/4d5d4c4006d86ff465780ec0d2671c0231c8536cc2fa8167aca8a4dd76811795",
25+
"is_owner": false,
26+
"meta": {
27+
"links": {
28+
"site": "https://public-api.wordpress.com/rest/v1.2/read/sites/3584907",
29+
"feed": "https://public-api.wordpress.com/rest/v1.1/read/feed/25823"
30+
},
31+
"data": {
32+
"site": {
33+
"ID": 3584907,
34+
"name": "WordPress.com News",
35+
"description": "The latest news on WordPress.com and the WordPress community.",
36+
"URL": "http://en.blog.wordpress.com",
37+
"jetpack": false,
38+
"jetpack_connection": false,
39+
"post_count": 1728,
40+
"subscribers_count": 104372237,
41+
"lang": "en",
42+
"icon": {
43+
"img": "https://secure.gravatar.com/blavatar/4d5d4c4006d86ff465780ec0d2671c0231c8536cc2fa8167aca8a4dd76811795",
44+
"ico": "https://secure.gravatar.com/blavatar/4d5d4c4006d86ff465780ec0d2671c0231c8536cc2fa8167aca8a4dd76811795"
45+
},
46+
"logo": {
47+
"id": 0,
48+
"sizes": [],
49+
"url": ""
50+
},
51+
"visible": true,
52+
"is_private": false,
53+
"is_coming_soon": false,
54+
"is_following": true,
55+
"organization_id": 0,
56+
"meta": {
57+
"links": {
58+
"self": "https://public-api.wordpress.com/rest/v1.2/sites/3584907",
59+
"help": "https://public-api.wordpress.com/rest/v1.2/sites/3584907/help",
60+
"posts": "https://public-api.wordpress.com/rest/v1.2/sites/3584907/posts/",
61+
"comments": "https://public-api.wordpress.com/rest/v1.1/sites/3584907/comments/",
62+
"xmlrpc": "https://en.blog.wordpress.com/xmlrpc.php"
63+
}
64+
},
65+
"launch_status": false,
66+
"site_migration": null,
67+
"is_fse_active": false,
68+
"is_fse_eligible": false,
69+
"is_core_site_editor_enabled": false,
70+
"is_wpcom_atomic": false,
71+
"is_wpcom_staging_site": false,
72+
"capabilities": {
73+
"edit_pages": false,
74+
"edit_posts": false,
75+
"edit_others_posts": false,
76+
"edit_theme_options": false,
77+
"list_users": false,
78+
"manage_categories": false,
79+
"manage_options": false,
80+
"publish_posts": false,
81+
"upload_files": false,
82+
"view_stats": false
83+
},
84+
"is_multi_author": true,
85+
"feed_ID": 25823,
86+
"feed_URL": "http://en.blog.wordpress.com",
87+
"header_image": false,
88+
"owner": {
89+
"ID": 26957695,
90+
"login": "a8cuser",
91+
"name": "Automattic",
92+
"first_name": "Automattic",
93+
"last_name": "",
94+
"nice_name": "a8cuser",
95+
"URL": "",
96+
"avatar_URL": "https://1.gravatar.com/avatar/48e997e4a437d5002ae4c1eff741b37c2f4e1cad14d45f173ae78c25a0c41a38?s=96&d=retro",
97+
"profile_URL": "https://gravatar.com/a8cuser",
98+
"ip_address": false,
99+
"site_visible": true,
100+
"has_avatar": true
101+
},
102+
"subscription": {
103+
"delivery_methods": {
104+
"email": {
105+
"send_posts": true,
106+
"send_comments": false,
107+
"post_delivery_frequency": "instantly",
108+
"date_subscribed": "2024-03-05 20:48:53"
109+
},
110+
"notification": {
111+
"send_posts": false
112+
}
113+
}
114+
},
115+
"is_blocked": false,
116+
"unseen_count": 0
117+
},
118+
"feed": {
119+
"blog_ID": "3584907",
120+
"feed_ID": "25823",
121+
"name": "WordPress.com News",
122+
"URL": "http://en.blog.wordpress.com/",
123+
"feed_URL": "http://en.blog.wordpress.com",
124+
"subscribers_count": 104372237,
125+
"is_following": true,
126+
"last_update": "2024-03-07T15:00:00+00:00",
127+
"last_checked": "2024-03-07T17:08:35+00:00",
128+
"marked_for_refresh": false,
129+
"next_refresh_time": null,
130+
"organization_id": 0,
131+
"unseen_count": 0,
132+
"meta": {
133+
"links": {
134+
"self": "https://public-api.wordpress.com/rest/v1.1/read/feed/25823",
135+
"site": "https://public-api.wordpress.com/rest/v1.1/read/sites/3584907"
136+
}
137+
},
138+
"image": "http://0.gravatar.com/blavatar/4d5d4c4006d86ff465780ec0d2671c0231c8536cc2fa8167aca8a4dd76811795?s=96&amp;d=http%3A%2F%2Fs0.wp.com%2Fi%2Fbuttonw-com.png",
139+
"description": "The latest news on WordPress.com and the WordPress community.",
140+
"subscription_id": 764146175
141+
}
142+
}
143+
},
144+
"is_wpforteams_site": false,
145+
"is_paid_subscription": false,
146+
"is_rss": false,
147+
"is_gift": false
148+
}
149+
],
150+
"page": 1,
151+
"number": 1,
152+
"total_subscriptions": 1
153+
}

Tests/WordPressKitTests/Tests/ReaderTopicServiceRemoteTests.m

Lines changed: 0 additions & 70 deletions
This file was deleted.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import XCTest
2+
@testable import WordPressKit
3+
4+
class ReaderTopicServiceRemoteTests: RemoteTestCase, RESTTestable {
5+
6+
let mockApi = MockWordPressComRestApi()
7+
lazy var subject: ReaderTopicServiceRemote = {
8+
ReaderTopicServiceRemote(wordPressComRestApi: mockApi)
9+
}()
10+
11+
func testFollowedSitesDefaultParameters() {
12+
let expectedParameter = "meta=site,feed"
13+
14+
subject.fetchFollowedSites(forPage: 0, number: 0, success: { _, _ in }, failure: { _ in })
15+
16+
XCTAssertTrue(mockApi.URLStringPassedIn?.contains(expectedParameter) ?? false)
17+
}
18+
19+
func testFollowedSitesPageParameter() {
20+
let expectedParameter = "page=5"
21+
22+
subject.fetchFollowedSites(forPage: 5, number: 0, success: { _, _ in }, failure: { _ in })
23+
24+
XCTAssertTrue(mockApi.URLStringPassedIn?.contains(expectedParameter) ?? false)
25+
}
26+
27+
func testFollowedSitesNumberParameter() {
28+
let expectedParameter = "number=7"
29+
30+
subject.fetchFollowedSites(forPage: 0, number: 7, success: { _, _ in }, failure: { _ in })
31+
32+
XCTAssertTrue(mockApi.URLStringPassedIn?.contains(expectedParameter) ?? false)
33+
}
34+
35+
func testFollowedSitesSuccess() async throws {
36+
let subject = ReaderTopicServiceRemote(wordPressComRestApi: getRestApi())
37+
stubRemoteResponse("read/following/mine", filename: "reader-following-mine.json", contentType: .ApplicationJSON)
38+
39+
let (totalSites, sites) = try await fetchFollowedSites(service: subject, page: 1, number: 1)
40+
41+
XCTAssertEqual(totalSites, 1)
42+
XCTAssertEqual(sites?.count, 1)
43+
}
44+
45+
func testFollowedSitesFailure() async throws {
46+
let subject = ReaderTopicServiceRemote(wordPressComRestApi: getRestApi())
47+
stubRemoteResponse("read/following/mine", filename: "reader-following-mine.json", contentType: .ApplicationJSON, status: 500)
48+
49+
do {
50+
try await fetchFollowedSites(service: subject, page: 1, number: 1)
51+
XCTFail("Expected the call to throw")
52+
} catch {
53+
XCTAssertNotNil(error)
54+
}
55+
}
56+
57+
// MARK: - Helpers
58+
59+
@discardableResult
60+
private func fetchFollowedSites(service: ReaderTopicServiceRemote, page: UInt, number: UInt) async throws -> (NSNumber?, [RemoteReaderSiteInfo]?) {
61+
return try await withUnsafeThrowingContinuation { continuation in
62+
service.fetchFollowedSites(
63+
forPage: 1,
64+
number: 1,
65+
success: { continuation.resume(returning: ($0, $1))},
66+
failure: { continuation.resume(throwing: $0!) }
67+
)
68+
}
69+
}
70+
71+
}

0 commit comments

Comments
 (0)