Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions WordPress/Classes/Services/ReaderTopicService.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ extern NSString * const ReaderTopicFreshlyPressedPathCommponent;
@end

@interface ReaderTopicService (Tests)
- (void)mergeFollowedSites:(NSArray *)sites withSuccess:(void (^)(void))success;
- (void)mergeMenuTopics:(NSArray *)topics withSuccess:(void (^)(void))success;
- (NSString *)formatTitle:(NSString *)str;
@end
42 changes: 34 additions & 8 deletions WordPress/Classes/Services/ReaderTopicService.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,7 @@ - (void)fetchFollowedSitesWithSuccess:(void(^)(void))success failure:(void(^)(NS
{
ReaderTopicServiceRemote *service = [[ReaderTopicServiceRemote alloc] initWithWordPressComRestApi:[self apiForRequest]];
[service fetchFollowedSitesWithSuccess:^(NSArray *sites) {
for (RemoteReaderSiteInfo *siteInfo in sites) {
[self siteTopicForRemoteSiteInfo:siteInfo];
}
[[ContextManager sharedInstance] saveContext:self.managedObjectContext withCompletionBlock:^{
if (success) {
success();
}
}];
[self mergeFollowedSites:sites withSuccess:success];
} failure:^(NSError *error) {
if (failure) {
failure(error);
Expand Down Expand Up @@ -925,6 +918,39 @@ - (NSString *)formatTitle:(NSString *)str
return [title capitalizedStringWithLocale:[NSLocale currentLocale]];
}

/**
Saves the specified `ReaderSiteTopics`. Any `ReaderSiteTopics` not included in the passed
array are marked as being unfollowed in Core Data.

@param topics An array of `ReaderSiteTopics` to save.
*/
- (void)mergeFollowedSites:(NSArray *)sites withSuccess:(void (^)(void))success
{
[self.managedObjectContext performBlock:^{
NSArray *currentSiteTopics = [self allSiteTopics];
NSMutableArray *remoteFeedIds = [NSMutableArray array];

for (RemoteReaderSiteInfo *siteInfo in sites) {
[remoteFeedIds addObject:siteInfo.feedID];
[self siteTopicForRemoteSiteInfo:siteInfo];
}

for (ReaderSiteTopic *siteTopic in currentSiteTopics) {
// If a site fetched from Core Data isn't included in the list of sites
// fetched from remote, that means it's no longer being followed.
if (![remoteFeedIds containsObject:siteTopic.feedID]) {
siteTopic.following = NO;
}
}

[[ContextManager sharedInstance] saveContext:self.managedObjectContext withCompletionBlock:^{
if (success) {
success();
}
}];
}];
}

/**
Saves the specified `ReaderAbstractTopics`. Any `ReaderAbstractTopics` not included in the passed
array are removed from Core Data.
Expand Down
61 changes: 61 additions & 0 deletions WordPress/WordPressTest/ReaderTopicServiceTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,25 @@ final class ReaderTopicSwiftTest: XCTestCase {
}
}

func remoteSiteInfoForTests() -> [RemoteReaderSiteInfo] {
let foo = RemoteReaderSiteInfo()
foo.feedID = 1
foo.isFollowing = true
foo.postsEndpoint = "/sites/foo"

let bar = RemoteReaderSiteInfo()
bar.feedID = 2
bar.isFollowing = true
bar.postsEndpoint = "/sites/bar"

let baz = RemoteReaderSiteInfo()
baz.feedID = 3
baz.isFollowing = true
baz.postsEndpoint = "/sites/baz"

return [foo, bar, baz]
}

func remoteTopicsForTests() -> [RemoteReaderTopic] {
let foo = RemoteReaderTopic()
foo.topicID = 1
Expand Down Expand Up @@ -138,6 +157,48 @@ final class ReaderTopicSwiftTest: XCTestCase {

// MARK: Tests

/**
Ensure that followed sites a user unfollows from are set to unfollowed in core data when merging
results from the REST API.
*/
func testUnfollowedSiteIsUnfollowedDuringSync() {
// Arrange: Setup
let remoteSites = remoteSiteInfoForTests()
let service = ReaderTopicService(managedObjectContext: context!)
let foo = remoteSites.first as RemoteReaderSiteInfo?

// Act: Save sites
var expect = expectation(description: "sites saved expectation")
service.mergeFollowedSites(remoteSites, withSuccess: { () -> Void in
expect.fulfill()
})
waitForExpectations(timeout: expectationTimeout, handler: nil)

// Assert: Sites exist in the context
let request = NSFetchRequest<NSFetchRequestResult>(entityName: ReaderSiteTopic.classNameWithoutNamespaces())
request.predicate = NSPredicate(format: "following = YES")
var count = try! context!.count(for: request)
XCTAssertEqual(count, remoteSites.count, "Number of sites in context did not match expectations")

// Act: Merge new set of sites
expect = expectation(description: "sites saved expectation")
service.mergeFollowedSites([foo!], withSuccess: { () -> Void in
expect.fulfill()
})
waitForExpectations(timeout: expectationTimeout, handler: nil)

// Assert: Unfollowed sites were unfollowed when merged
count = try! context!.count(for: request)
XCTAssertEqual(count, 1, "Number of sites in context did not match expectations")
do {
let results = try context!.fetch(request)
let site = results.first as! ReaderSiteTopic
XCTAssertEqual(site.feedID, foo?.feedID, "The site returned was not the one expected.")
} catch let error as NSError {
XCTAssertNil(error, "Error executing fetch request.")
}
}

/**
Ensure that topics a user unsubscribes from are removed from core data when merging
results from the REST API.
Expand Down