Bgerstle has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/215354

Change subject: add tests for article fetcher
......................................................................

add tests for article fetcher

Bug: T101078
Change-Id: I6cf93ba8578b958ef1b96f7b9dae411d432c8798
---
M MediaWikiKit/MediaWikiKit/MWKArticle.h
M MediaWikiKit/MediaWikiKit/MWKArticle.m
M MediaWikiKit/MediaWikiKit/MWKImageList.h
M MediaWikiKit/MediaWikiKit/MWKImageList.m
M MediaWikiKit/MediaWikiKit/MWKSection.h
M MediaWikiKit/MediaWikiKit/MWKSection.m
M MediaWikiKit/MediaWikiKit/MWKSectionList.h
M MediaWikiKit/MediaWikiKit/MWKSectionList.m
M MediaWikiKit/MediaWikiKit/MWKUser.h
M MediaWikiKit/MediaWikiKit/MWKUser.m
M Wikipedia.xcodeproj/project.pbxproj
M Wikipedia/Networking/Fetchers/ArticleFetcher.h
M Wikipedia/Networking/Fetchers/ArticleFetcher.m
A WikipediaUnitTests/ArticleFetcherTests.m
14 files changed, 301 insertions(+), 31 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/apps/ios/wikipedia 
refs/changes/54/215354/1

diff --git a/MediaWikiKit/MediaWikiKit/MWKArticle.h 
b/MediaWikiKit/MediaWikiKit/MWKArticle.h
index 136b6fe..01733fc 100644
--- a/MediaWikiKit/MediaWikiKit/MWKArticle.h
+++ b/MediaWikiKit/MediaWikiKit/MWKArticle.h
@@ -75,6 +75,9 @@
  */
 - (MWKImage*)importImageData:(NSData*)data image:(MWKImage*)image;
 
+- (BOOL)isEqualToArticle:(MWKArticle*)article;
+- (BOOL)isDeeplyEqualToArticle:(MWKArticle*)article;
+
 - (void)save;
 - (void)saveWithoutSavingSectionText;
 - (void)remove;
diff --git a/MediaWikiKit/MediaWikiKit/MWKArticle.m 
b/MediaWikiKit/MediaWikiKit/MWKArticle.m
index 424da87..8fda60f 100644
--- a/MediaWikiKit/MediaWikiKit/MWKArticle.m
+++ b/MediaWikiKit/MediaWikiKit/MWKArticle.m
@@ -8,6 +8,7 @@
 
 #import "MediaWikiKit.h"
 #import <BlocksKit/BlocksKit.h>
+#import "WikipediaAppUtils.h"
 
 @interface MWKArticle ()
 
@@ -59,24 +60,32 @@
 #pragma mark - NSObject
 
 - (BOOL)isEqual:(id)object {
-    if (object == nil) {
-        return NO;
-    } else if (![object isKindOfClass:[MWKArticle class]]) {
-        return NO;
+    if (self == object) {
+        return YES;
+    } else if ([object isKindOfClass:[MWKArticle class]]) {
+        return [self isEqualToArticle:object];
     } else {
-        MWKArticle* other = object;
-        return [self.site isEqual:other.site] &&
-               (self.redirected == other.redirected || [self.redirected 
isEqual:other.redirected]) &&
-               [self.lastmodified isEqual:other.lastmodified] &&
-               [self.lastmodifiedby isEqual:other.lastmodifiedby] &&
-               self.articleId == other.articleId &&
-               self.languagecount == other.languagecount &&
-               [self.displaytitle isEqualToString:other.displaytitle] &&
-               [self.protection isEqual:other.protection] &&
-               self.editable == other.editable &&
-               (self.thumbnailURL == other.thumbnailURL || [self.thumbnailURL 
isEqualToString:other.thumbnailURL]) &&
-               (self.imageURL == other.imageURL || [self.imageURL 
isEqualToString:other.imageURL]);
+        return NO;
     }
+}
+
+- (BOOL)isEqualToArticle:(MWKArticle*)other {
+    return WMF_EQUAL(self.site, isEqualToSite:, other.site)
+           && WMF_EQUAL(self.redirected, isEqual:, other.redirected)
+           && WMF_EQUAL(self.lastmodified, isEqualToDate:, other.lastmodified)
+           && WMF_IS_EQUAL(self.lastmodifiedby, other.lastmodifiedby)
+           && WMF_EQUAL(self.displaytitle, isEqualToString:, 
other.displaytitle)
+           && WMF_EQUAL(self.protection, isEqual:, other.protection)
+           && WMF_EQUAL(self.thumbnailURL, isEqualToString:, 
other.thumbnailURL)
+           && WMF_EQUAL(self.imageURL, isEqualToString:, other.imageURL)
+           && self.articleId == other.articleId
+           && self.languagecount == other.languagecount;
+}
+
+- (BOOL)isDeeplyEqualToArticle:(MWKArticle*)article {
+    return [self isEqual:article]
+           && WMF_IS_EQUAL(self.images, article.images)
+           && WMF_IS_EQUAL(self.sections, article.sections);
 }
 
 - (NSString*)description {
@@ -282,4 +291,34 @@
     }
 }
 
+- (NSString*)debugDescription {
+    return [NSString stringWithFormat:@"%@ { \n"
+            "\tlastModifiedBy: %@, \n"
+            "\tlastModified: %@, \n"
+            "\tarticleId: %d, \n"
+            "\tlanguageCount: %d, \n"
+            "\tdisplayTitle: %@, \n"
+            "\tprotection: %@, \n"
+            "\teditable: %d, \n"
+            "\tthumbnailURL: %@, \n"
+            "\timageURL: %@, \n"
+            "\tsections: %@, \n"
+            "\timages: %@, \n"
+            "\tentityDescription: %@, \n"
+            "}",
+            self.description,
+            self.lastmodifiedby,
+            self.lastmodified,
+            self.articleId,
+            self.languagecount,
+            self.displaytitle,
+            self.protection,
+            self.editable,
+            self.thumbnailURL,
+            self.imageURL,
+            self.sections.debugDescription,
+            self.images.debugDescription,
+            self.entityDescription];
+}
+
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKImageList.h 
b/MediaWikiKit/MediaWikiKit/MWKImageList.h
index 9620ded..101dbc9 100644
--- a/MediaWikiKit/MediaWikiKit/MWKImageList.h
+++ b/MediaWikiKit/MediaWikiKit/MWKImageList.h
@@ -87,4 +87,6 @@
 
 - (void)save;
 
+- (BOOL)isEqualToImageList:(MWKImageList*)imageList;
+
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKImageList.m 
b/MediaWikiKit/MediaWikiKit/MWKImageList.m
index 63d5208..673eb0a 100644
--- a/MediaWikiKit/MediaWikiKit/MWKImageList.m
+++ b/MediaWikiKit/MediaWikiKit/MWKImageList.m
@@ -8,6 +8,7 @@
 
 #import "MediaWikiKit.h"
 #import "NSString+Extras.h"
+#import "WikipediaAppUtils.h"
 
 @interface MWKImageList ()
 
@@ -68,6 +69,21 @@
     }
     [byname addObject:imageURL];
     self.mutationState++;
+}
+
+- (BOOL)isEqual:(id)object {
+    if (self == object) {
+        return YES;
+    } else if ([object isKindOfClass:[MWKImageList class]]) {
+        return [self isEqualToImageList:object];
+    } else {
+        return NO;
+    }
+}
+
+- (BOOL)isEqualToImageList:(MWKImageList*)imageList {
+    return WMF_EQUAL(self.article, isEqualToArticle:, imageList.article)
+           && WMF_EQUAL(self.entries, isEqualToArray:, [imageList entries]);
 }
 
 - (NSUInteger)count {
@@ -221,4 +237,10 @@
     [self.article.dataStore saveImageList:self];
 }
 
+- (NSString*)debugDescription {
+    return [NSString stringWithFormat:@"%@ { \n"
+            "\t images: %@ \n"
+            "}", self.description, self.entries];
+}
+
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKSection.h 
b/MediaWikiKit/MediaWikiKit/MWKSection.h
index e1bcdb9..ba71f05 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSection.h
+++ b/MediaWikiKit/MediaWikiKit/MWKSection.h
@@ -38,6 +38,8 @@
 - (BOOL)     isLeadSection;
 - (MWKTitle*)sourceTitle;
 
+- (BOOL)isEqualToSection:(MWKSection*)section;
+
 - (void)save;
 
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKSection.m 
b/MediaWikiKit/MediaWikiKit/MWKSection.m
index 6c7fef3..0f60b4f 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSection.m
+++ b/MediaWikiKit/MediaWikiKit/MWKSection.m
@@ -7,6 +7,7 @@
 //
 
 #import "MediaWikiKit.h"
+#import "WikipediaAppUtils.h"
 
 @interface MWKSection ()
 
@@ -119,4 +120,29 @@
     }
 }
 
+- (BOOL)isEqual:(id)object {
+    if (self == object) {
+        return YES;
+    } else if ([object isKindOfClass:[MWKSection class]]) {
+        return [self isEqualToSection:object];
+    } else {
+        return nil;
+    }
+}
+
+- (BOOL)isEqualToSection:(MWKSection*)section {
+    return WMF_IS_EQUAL(self.article, section.article)
+           && self.sectionId == section.sectionId
+           && self.references == section.references
+           && WMF_EQUAL(self.toclevel, isEqualToNumber:, section.toclevel)
+           && WMF_EQUAL(self.level, isEqualToNumber:, section.level)
+           && WMF_EQUAL(self.line, isEqualToString:, section.line)
+           && WMF_EQUAL(self.number, isEqualToString:, section.number)
+           && WMF_EQUAL(self.index, isEqualToString:, section.index)
+           && WMF_EQUAL(self.fromtitle, isEqual:, section.fromtitle)
+           && WMF_EQUAL(self.anchor, isEqualToString:, section.anchor)
+           && WMF_EQUAL(self.text, isEqualToString:, section.text)
+           && WMF_EQUAL(self.images, isEqual:, section.images);
+}
+
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKSectionList.h 
b/MediaWikiKit/MediaWikiKit/MWKSectionList.h
index fc8e276..78744d7 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSectionList.h
+++ b/MediaWikiKit/MediaWikiKit/MWKSectionList.h
@@ -36,4 +36,6 @@
 
 - (void)save;
 
+- (BOOL)isEqualToSectionList:(MWKSectionList*)sectionList;
+
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKSectionList.m 
b/MediaWikiKit/MediaWikiKit/MWKSectionList.m
index 07f9874..ce16ea5 100644
--- a/MediaWikiKit/MediaWikiKit/MWKSectionList.m
+++ b/MediaWikiKit/MediaWikiKit/MWKSectionList.m
@@ -8,6 +8,7 @@
 
 #import "MWKSectionList_Private.h"
 #import "MediaWikiKit.h"
+#import "WikipediaAppUtils.h"
 
 @interface MWKSectionList ()
 
@@ -43,6 +44,21 @@
         [self importSectionsFromDisk];
     }
     return self;
+}
+
+- (BOOL)isEqual:(id)object {
+    if (self == object) {
+        return YES;
+    } else if ([object isKindOfClass:[MWKSectionList class]]) {
+        return [self isEqualToSectionList:object];
+    } else {
+        return NO;
+    }
+}
+
+- (BOOL)isEqualToSectionList:(MWKSectionList*)sectionList {
+    return WMF_EQUAL(self.article, isEqualToArticle:, [sectionList article])
+           && WMF_EQUAL(self.sections, isEqualToArray:, [sectionList 
sections]);
 }
 
 - (void)importSectionsFromDisk {
@@ -105,4 +121,10 @@
     }
 }
 
+- (NSString*)debugDescription {
+    return [NSString stringWithFormat:@"%@ { \n"
+            "\t sections: %@ \n"
+            "}", [self description], self.sections];
+}
+
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKUser.h 
b/MediaWikiKit/MediaWikiKit/MWKUser.h
index 7e6cc99..8fcb467 100644
--- a/MediaWikiKit/MediaWikiKit/MWKUser.h
+++ b/MediaWikiKit/MediaWikiKit/MWKUser.h
@@ -20,4 +20,6 @@
 
 - (instancetype)initWithSite:(MWKSite*)site data:(id)data;
 
+- (BOOL)isEqualToUser:(MWKUser*)user;
+
 @end
diff --git a/MediaWikiKit/MediaWikiKit/MWKUser.m 
b/MediaWikiKit/MediaWikiKit/MWKUser.m
index 04e27ab..a42d897 100644
--- a/MediaWikiKit/MediaWikiKit/MWKUser.m
+++ b/MediaWikiKit/MediaWikiKit/MWKUser.m
@@ -7,6 +7,7 @@
 //
 
 #import "MediaWikiKit.h"
+#import "WikipediaAppUtils.h"
 
 @interface MWKUser ()
 
@@ -51,21 +52,20 @@
 }
 
 - (BOOL)isEqual:(id)object {
-    if (object == nil) {
-        return NO;
-    } else if (![object isKindOfClass:[MWKUser class]]) {
-        return NO;
+    if (self == object) {
+        return YES;
+    } else if ([object isKindOfClass:[MWKUser class]]) {
+        return [self isEqualToUser:object];
     } else {
-        MWKUser* other = object;
-        if (self.anonymous && other.anonymous) {
-            // well that's all we can do for now
-            return YES;
-        } else {
-            return (self.anonymous == other.anonymous) &&
-                   [self.name isEqualToString:other.name] &&
-                   [self.gender isEqualToString:other.gender];
-        }
+        return NO;
     }
 }
 
+- (BOOL)isEqualToUser:(MWKUser*)other {
+#warning FIXME: verify functionality of comparing users or are/aren't anonymous
+    return self.anonymous == other.anonymous
+           || (WMF_EQUAL(self.name, isEqualToString:, other.name)
+               && WMF_EQUAL(self.gender, isEqualToString:, other.gender));
+}
+
 @end
diff --git a/Wikipedia.xcodeproj/project.pbxproj 
b/Wikipedia.xcodeproj/project.pbxproj
index af6fb6a..fd8b58f 100644
--- a/Wikipedia.xcodeproj/project.pbxproj
+++ b/Wikipedia.xcodeproj/project.pbxproj
@@ -220,6 +220,7 @@
                BC49B3641AEECFD8009F55BE /* ArticleLoadingTests.m in Sources */ 
= {isa = PBXBuildFile; fileRef = BC49B3631AEECFD8009F55BE /* 
ArticleLoadingTests.m */; };
                BC50C37F1A83C784006DC7AF /* WMFNetworkUtilities.m in Sources */ 
= {isa = PBXBuildFile; fileRef = BC50C37E1A83C784006DC7AF /* 
WMFNetworkUtilities.m */; };
                BC50C3871A83CBDA006DC7AF /* MWKImageInfoResponseSerializer.m in 
Sources */ = {isa = PBXBuildFile; fileRef = BC50C3861A83CBDA006DC7AF /* 
MWKImageInfoResponseSerializer.m */; };
+               BC5FE5751B1DFF5400273BC0 /* ArticleFetcherTests.m in Sources */ 
= {isa = PBXBuildFile; fileRef = BC5FE5741B1DFF5400273BC0 /* 
ArticleFetcherTests.m */; };
                BC69C3141AB0C1FF0090B039 /* WMFImageInfoController.m in Sources 
*/ = {isa = PBXBuildFile; fileRef = BC69C3131AB0C1FF0090B039 /* 
WMFImageInfoController.m */; };
                BC7DFCD61AA4E5FE000035C3 /* WMFImageURLParsing.m in Sources */ 
= {isa = PBXBuildFile; fileRef = BC7DFCD51AA4E5FE000035C3 /* 
WMFImageURLParsing.m */; };
                BC86B9361A92966B00B4C039 /* 
AFHTTPRequestOperationManager+UniqueRequests.m in Sources */ = {isa = 
PBXBuildFile; fileRef = BC86B9351A92966B00B4C039 /* 
AFHTTPRequestOperationManager+UniqueRequests.m */; };
@@ -749,6 +750,7 @@
                BC50C3821A83C88F006DC7AF /* WMFJoinedPropertyParametersTests.m 
*/ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = 
sourcecode.c.objc; path = WMFJoinedPropertyParametersTests.m; sourceTree = 
"<group>"; };
                BC50C3851A83CBDA006DC7AF /* MWKImageInfoResponseSerializer.h */ 
= {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = 
sourcecode.c.h; name = MWKImageInfoResponseSerializer.h; path = 
Serializers/MWKImageInfoResponseSerializer.h; sourceTree = "<group>"; };
                BC50C3861A83CBDA006DC7AF /* MWKImageInfoResponseSerializer.m */ 
= {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = 
sourcecode.c.objc; name = MWKImageInfoResponseSerializer.m; path = 
Serializers/MWKImageInfoResponseSerializer.m; sourceTree = "<group>"; };
+               BC5FE5741B1DFF5400273BC0 /* ArticleFetcherTests.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= ArticleFetcherTests.m; sourceTree = "<group>"; };
                BC69C3121AB0C1FF0090B039 /* WMFImageInfoController.h */ = {isa 
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name 
= WMFImageInfoController.h; path = "Image Gallery/WMFImageInfoController.h"; 
sourceTree = "<group>"; };
                BC69C3131AB0C1FF0090B039 /* WMFImageInfoController.m */ = {isa 
= PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; 
name = WMFImageInfoController.m; path = "Image 
Gallery/WMFImageInfoController.m"; sourceTree = "<group>"; };
                BC6FEAE01A9B7EFD00A1D890 /* WMFCodingStyle.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= WMFCodingStyle.m; sourceTree = "<group>"; };
@@ -2075,6 +2077,7 @@
                                BC49B3631AEECFD8009F55BE /* 
ArticleLoadingTests.m */,
                                BC92A7721AFA88D3003C4212 /* 
MWKSection+WMFSharingTests.m */,
                                BCAFC5CF1AFD5E7D004615BA /* 
MWKArticle+WMFSharingTests.m */,
+                               BC5FE5741B1DFF5400273BC0 /* 
ArticleFetcherTests.m */,
                        );
                        name = Tests;
                        path = WikipediaUnitTests;
@@ -2975,6 +2978,7 @@
                                BCD41E001B11D1B200231BB1 /* 
XCTestCase+MWKFixtures.m in Sources */,
                                BC0FED631AAA0263002488D7 /* MWKTestCase.m in 
Sources */,
                                BC92A7731AFA88D3003C4212 /* 
MWKSection+WMFSharingTests.m in Sources */,
+                               BC5FE5751B1DFF5400273BC0 /* 
ArticleFetcherTests.m in Sources */,
                                BCAFC5ED1B02490A004615BA /* 
WMFRandomFileUtilities.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
diff --git a/Wikipedia/Networking/Fetchers/ArticleFetcher.h 
b/Wikipedia/Networking/Fetchers/ArticleFetcher.h
index 43d75f0..941a4ef 100644
--- a/Wikipedia/Networking/Fetchers/ArticleFetcher.h
+++ b/Wikipedia/Networking/Fetchers/ArticleFetcher.h
@@ -4,7 +4,7 @@
 #import <Foundation/Foundation.h>
 #import "FetcherBase.h"
 
-@class Article, AFHTTPRequestOperationManager, ArticleFetcher;
+@class Article, AFHTTPRequestOperationManager, ArticleFetcher, MWKArticle;
 
 @protocol ArticleFetcherDelegate <FetchFinishedDelegate>
 
diff --git a/Wikipedia/Networking/Fetchers/ArticleFetcher.m 
b/Wikipedia/Networking/Fetchers/ArticleFetcher.m
index 320b68a..99708de 100644
--- a/Wikipedia/Networking/Fetchers/ArticleFetcher.m
+++ b/Wikipedia/Networking/Fetchers/ArticleFetcher.m
@@ -111,7 +111,7 @@
 
             dispatch_async(dispatch_get_main_queue(), ^{
                 [self finishWithError:nil
-                          fetchedData:nil];
+                          fetchedData:self.article];
             });
         });
     } failure:^(AFHTTPRequestOperation* operation, NSError* error) {
diff --git a/WikipediaUnitTests/ArticleFetcherTests.m 
b/WikipediaUnitTests/ArticleFetcherTests.m
new file mode 100644
index 0000000..a24eb14
--- /dev/null
+++ b/WikipediaUnitTests/ArticleFetcherTests.m
@@ -0,0 +1,146 @@
+//
+//  ArticleFetcherTests.m
+//  Wikipedia
+//
+//  Created by Brian Gerstle on 6/2/15.
+//  Copyright (c) 2015 Wikimedia Foundation. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import <XCTest/XCTest.h>
+#import "ArticleFetcher.h"
+#import <AFNetworking/AFHTTPRequestOperationManager.h>
+#import "MWKDataStore+TemporaryDataStore.h"
+#import "MWKArticle.h"
+#import "MWKSite.h"
+#import "MWKTitle.h"
+#import "WMFTestFixtureUtilities.h"
+#import "SessionSingleton.h"
+#import "WMFAsyncTestCase.h"
+
+#define MOCKITO_SHORTHAND 1
+#import <OCMockito/OCMockito.h>
+
+#define HC_SHORTHAND 1
+#import <OCHamcrest/OCHamcrest.h>
+
+@interface ArticleFetcherTests : XCTestCase
+    <ArticleFetcherDelegate>
+@property (strong, nonatomic) MWKDataStore* tempDataStore;
+@property (strong, nonatomic) AFHTTPRequestOperationManager* 
mockRequestManager;
+@property (strong, nonatomic) ArticleFetcher* articleFetcher;
+@property (strong, nonatomic) void (^ fetchFinished)(id, id, FetchFinalStatus, 
NSError*);
+@end
+
+@implementation ArticleFetcherTests
+
+- (void)setUp {
+    [super setUp];
+    self.mockRequestManager = mock([AFHTTPRequestOperationManager class]);
+    self.tempDataStore      = [MWKDataStore temporaryDataStore];
+}
+
+- (void)tearDown {
+    [self.tempDataStore removeFolderAtBasePath];
+    self.fetchFinished = nil;
+    [super tearDown];
+}
+
+- (void)testSuccessfulFetchWritesArticleToDataStore {
+    MWKTitle* dummyTitle     = [[MWKSite siteWithDomain:@"wikipedia.org" 
language:@"en"] titleWithString:@"Foo"];
+    MWKArticle* dummyArticle = [self.tempDataStore 
articleWithTitle:dummyTitle];
+
+    MKTArgumentCaptor* successCaptor = [self 
mockSuccessfulFetchOfArticle:dummyArticle
+                                                              
withManager:self.mockRequestManager];
+
+    XCTestExpectation* responseExpectation = [self 
expectationWithDescription:@"articleResponse"];
+
+    self.fetchFinished = ^(id sender, id fetchedData, FetchFinalStatus status, 
NSError* err) {
+        assertThat(@(status), is(@(FETCH_FINAL_STATUS_SUCCEEDED)));
+        assertThat(err, is(nilValue()));
+        MWKArticle* savedArticle = [self.tempDataStore 
articleWithTitle:dummyTitle];
+        assertThat(fetchedData, is(equalTo(savedArticle)));
+        assertThat(@([fetchedData isDeeplyEqualToArticle:savedArticle]), 
isTrue());
+        [responseExpectation fulfill];
+    };
+
+    [self invokeCapturedSuccessBlock:successCaptor 
withDataFromFixture:@"Obama"];
+
+    // this is slow, so needs a longer timeout
+    [self waitForExpectationsWithTimeout:1.0 handler:nil];
+}
+
+- (void)testFetchingArticleIsIdempotent {
+    MWKTitle* dummyTitle     = [[MWKSite siteWithDomain:@"wikipedia.org" 
language:@"en"] titleWithString:@"Foo"];
+    MWKArticle* dummyArticle = [self.tempDataStore 
articleWithTitle:dummyTitle];
+
+    dispatch_block_t fetch = ^{
+        XCTestExpectation* responseExpectation = [self 
expectationWithDescription:@"articleResponse"];
+
+        AFHTTPRequestOperationManager* manager = 
mock([AFHTTPRequestOperationManager class]);
+        MKTArgumentCaptor* successBlockCaptor  = [self 
mockSuccessfulFetchOfArticle:dummyArticle
+                                                                        
withManager:manager];
+
+        self.fetchFinished = ^(id sender, id fetchedData, FetchFinalStatus 
status, NSError* err) {
+            [responseExpectation fulfill];
+        };
+
+        [self invokeCapturedSuccessBlock:successBlockCaptor 
withDataFromFixture:@"Obama"];
+
+        // this is slow, so needs a longer timeout
+        [self waitForExpectationsWithTimeout:1.0 handler:nil];
+    };
+
+    fetch();
+
+    MWKArticle* firstFetchResult = [self.tempDataStore 
articleWithTitle:dummyTitle];
+
+
+    fetch();
+
+    MWKArticle* secondFetchResult = [self.tempDataStore 
articleWithTitle:dummyTitle];
+
+    assertThat(secondFetchResult, is(equalTo(firstFetchResult)));
+    assertThat(@([secondFetchResult isDeeplyEqualToArticle:firstFetchResult]),
+               describedAs(@"Expected data store to remain the same after 
fetching the same article twice: \n"
+                           "firstResult: %0 \n"
+                           "secondResult: %1",
+                           isTrue(),
+                           [firstFetchResult debugDescription],
+                           [secondFetchResult debugDescription], nil));
+}
+
+- (MKTArgumentCaptor*)mockSuccessfulFetchOfArticle:(MWKArticle*)article
+                                       
withManager:(AFHTTPRequestOperationManager*)manager {
+    (void)[[ArticleFetcher alloc] initAndFetchSectionsForArticle:article
+                                                     withManager:manager
+                                              thenNotifyDelegate:self];
+
+    MKTArgumentCaptor* successCaptor = [MKTArgumentCaptor new];
+    [MKTVerify(manager)
+     GET:[[[SessionSingleton sharedInstance] 
urlForLanguage:article.title.site.language] absoluteString]
+     parameters:anything()
+        success:[successCaptor capture]
+        failure:anything()];
+
+    return successCaptor;
+}
+
+- (void)invokeCapturedSuccessBlock:(MKTArgumentCaptor*)captor 
withDataFromFixture:(NSString*)fixture {
+    void (^ successBlock)(AFHTTPRequestOperation*, id response) = [captor 
value];
+    NSData* jsonData = [[self wmf_bundle] wmf_dataFromContentsOfFile:fixture 
ofType:@"json"];
+    successBlock(nil, jsonData);
+}
+
+#pragma mark - FetchFinishedDelegate
+
+- (void)fetchFinished:(id)sender
+          fetchedData:(id)fetchedData
+               status:(FetchFinalStatus)status
+                error:(NSError*)error {
+    if (self.fetchFinished) {
+        self.fetchFinished(sender, fetchedData, status, error);
+    }
+}
+
+@end

-- 
To view, visit https://gerrit.wikimedia.org/r/215354
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6cf93ba8578b958ef1b96f7b9dae411d432c8798
Gerrit-PatchSet: 1
Gerrit-Project: apps/ios/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Bgerstle <bgers...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to