17
17
#import " KIOFileStore.h"
18
18
#import " KIONetwork.h"
19
19
#import " KIOUploader.h"
20
+ #import " MockNSURLSession.h"
20
21
21
22
NSString * kDefaultProjectID = @" id" ;
22
23
NSString * kDefaultWriteKey = @" wk" ;
@@ -44,7 +45,9 @@ @interface KeenClient (testability)
44
45
@property (nonatomic , strong ) NSString *writeKey;
45
46
@property (nonatomic , strong ) NSString *readKey;
46
47
47
- @property (nonatomic ) KIONetwork* network;
48
+ @property (nonatomic ) KIONetwork *network;
49
+
50
+ @property (nonatomic ) KIODBStore *store;
48
51
49
52
// If we're running tests.
50
53
@property (nonatomic ) BOOL isRunningTests;
@@ -502,21 +505,8 @@ - (id)mockUrlSessionWithResponse:(NSHTTPURLResponse*)response
502
505
andResponseData : (NSData *)responseData
503
506
andRequestValidator : (BOOL (^)(id requestObject))requestValidator {
504
507
// Mock the NSURLSession to be used for the request
505
- id urlSessionMock = [OCMockObject partialMockForObject: [[NSURLSession alloc ] init ]];
506
-
507
- // Set up fake response data and request validation
508
- if (nil != requestValidator) {
509
- // Set up validation of the request
510
- [[urlSessionMock expect ] dataTaskWithRequest: [OCMArg checkWithBlock: requestValidator]
511
- completionHandler: [OCMArg invokeBlockWithArgs: responseData, response, [NSNull null ], nil ]];
512
- } else {
513
- // We won't check that the request contained anything specific
514
- [[urlSessionMock stub ] dataTaskWithRequest: [OCMArg any ]
515
- completionHandler: [OCMArg invokeBlockWithArgs: responseData, response, [NSNull null ], nil ]];
516
-
517
- }
518
-
519
- return urlSessionMock;
508
+ // If a validator is provided, it will check the actual request made
509
+ return [[MockNSURLSession alloc ] initWithValidator: requestValidator data: responseData response: response error: nil ];
520
510
}
521
511
522
512
- (id )createClientWithResponseData : (id )data
@@ -583,7 +573,7 @@ - (void)addSimpleEventAndUploadWithMock:(id)mock andFinishedBlock:(void (^)())fi
583
573
584
574
-(void )testUploadWithNoEvents {
585
575
XCTestExpectation* uploadFinishedBlockCalled = [self expectationWithDescription: @" Upload should finish." ];
586
-
576
+
587
577
id mock = [self createClientWithResponseData: nil andStatusCode: HTTPCode200OK];
588
578
589
579
[mock uploadWithFinishedBlock: ^{
@@ -883,6 +873,46 @@ - (void)testUploadMultipleEventsSameCollectionSuccess {
883
873
}];
884
874
}
885
875
876
+ - (void )testUploadEventDoesntDuplicateWithMultipleCallsToUpload {
877
+ NSDictionary *eventResult = [self buildResultWithSuccess: YES andErrorCode: nil andDescription: nil ];
878
+ NSDictionary *result =
879
+ [NSDictionary dictionaryWithObject: [NSArray arrayWithObjects: eventResult, nil ] forKey: @" foo" ];
880
+
881
+ __block NSInteger requestCount = 0 ;
882
+ __block NSInteger uploadCallCount = 0 ;
883
+ const NSInteger totalUploadCallCount = 10 ;
884
+ KeenClient* client = [self createClientWithResponseData: result andStatusCode: HTTPCode200OK andNetworkConnected: @YES andRequestValidator: ^BOOL (id obj) {
885
+ requestCount++;
886
+ return @YES ;
887
+ }];
888
+
889
+ // add an event
890
+ [client addEvent: [NSDictionary dictionaryWithObject: @" apple" forKey: @" a" ] toEventCollection: @" foo" error: nil ];
891
+
892
+ NSUInteger pendingEvents = [client.store getTotalEventCountWithProjectID: kDefaultProjectID ];
893
+ XCTAssertEqual (pendingEvents, 1 , @" There should be an event awaiting upload." );
894
+
895
+ // and "upload" it
896
+ XCTestExpectation *responseArrived = [self expectationWithDescription: @" response of async request has arrived" ];
897
+ for (int i = 0 ; i < totalUploadCallCount; ++i) {
898
+ [client uploadWithFinishedBlock: ^{
899
+ uploadCallCount++;
900
+ if (uploadCallCount == totalUploadCallCount) {
901
+ [responseArrived fulfill ];
902
+ }
903
+ }];
904
+ }
905
+
906
+ [self waitForExpectationsWithTimeout: _asyncTimeInterval
907
+ handler: ^(NSError *_Nullable error) {
908
+ // make sure the events were deleted locally
909
+ XCTAssertTrue ([client.store getTotalEventCountWithProjectID: nil ] == 0 ,
910
+ @" There should be no files after a successful upload." );
911
+ }];
912
+
913
+ XCTAssertEqual (requestCount, 1 , @" Only one request should have been made" );
914
+ }
915
+
886
916
- (void )testUploadMultipleEventsSameCollectionSuccessInstanceClient {
887
917
NSDictionary *result1 = [self buildResultWithSuccess: YES
888
918
andErrorCode: nil
@@ -1492,7 +1522,7 @@ - (void)testUploadMultipleTimes {
1492
1522
XCTestExpectation* uploadFinishedBlockCalled1 = [self expectationWithDescription: @" Upload 1 should run to completion." ];
1493
1523
XCTestExpectation* uploadFinishedBlockCalled2 = [self expectationWithDescription: @" Upload 2 should run to completion." ];
1494
1524
XCTestExpectation* uploadFinishedBlockCalled3 = [self expectationWithDescription: @" Upload 3 should run to completion." ];
1495
-
1525
+
1496
1526
KeenClient *client = [KeenClient sharedClientWithProjectID: kDefaultProjectID andWriteKey: kDefaultWriteKey andReadKey: kDefaultReadKey ];
1497
1527
client.isRunningTests = YES ;
1498
1528
@@ -1505,7 +1535,7 @@ - (void)testUploadMultipleTimes {
1505
1535
[client uploadWithFinishedBlock: ^ {
1506
1536
[uploadFinishedBlockCalled3 fulfill ];
1507
1537
}];
1508
-
1538
+
1509
1539
[self waitForExpectationsWithTimeout: _asyncTimeInterval handler: nil ];
1510
1540
}
1511
1541
@@ -1526,7 +1556,7 @@ - (void)testUploadMultipleTimesInstanceClient {
1526
1556
[client uploadWithFinishedBlock: ^ {
1527
1557
[uploadFinishedBlockCalled3 fulfill ];
1528
1558
}];
1529
-
1559
+
1530
1560
[self waitForExpectationsWithTimeout: _asyncTimeInterval handler: nil ];
1531
1561
}
1532
1562
@@ -1946,90 +1976,93 @@ - (void)validateSdkVersionHeaderFieldForRequest:(id)requestObject {
1946
1976
}
1947
1977
1948
1978
- (void )testSdkTrackingHeadersOnUpload {
1979
+ XCTestExpectation *requestValidated = [self expectationWithDescription: @" request was validated" ];
1949
1980
// mock an empty response from the server
1950
-
1951
- KeenClient* client = [self createClientWithRequestValidator: ^BOOL (id obj) {
1981
+ KeenClient *client = [self createClientWithRequestValidator: ^BOOL (id obj) {
1952
1982
[self validateSdkVersionHeaderFieldForRequest: obj];
1983
+ [requestValidated fulfill ];
1953
1984
return @YES ;
1954
1985
}];
1955
1986
1956
- // Get the mock url session. We'll check the request it gets passed by sendEvents for the version header
1957
- id urlSessionMock = client.network .urlSession ;
1958
-
1959
1987
// add an event
1960
1988
[client addEvent: [NSDictionary dictionaryWithObject: @" apple" forKey: @" a" ] toEventCollection: @" foo" error: nil ];
1961
1989
1962
- XCTestExpectation* responseArrived = [self expectationWithDescription: @" response of async request has arrived" ];
1990
+ XCTestExpectation * responseArrived = [self expectationWithDescription: @" response of async request has arrived" ];
1963
1991
// and "upload" it
1964
1992
[client uploadWithFinishedBlock: ^{
1965
- // Check for the sdk version header
1966
- [urlSessionMock verify ];
1967
-
1968
1993
[responseArrived fulfill ];
1969
1994
}];
1970
1995
1971
- [self waitForExpectationsWithTimeout: _asyncTimeInterval handler: ^(NSError * _Nullable error) {
1972
- XCTAssertNil (error, @" Test should complete within expected interval." );
1973
- }];
1996
+ [self waitForExpectationsWithTimeout: _asyncTimeInterval
1997
+ handler: ^(NSError *_Nullable error) {
1998
+ XCTAssertNil (error, @" Test should complete within expected interval." );
1999
+ }];
1974
2000
}
1975
2001
1976
2002
- (void )testSdkTrackingHeadersOnQuery {
1977
- KeenClient* client = [self createClientWithResponseData: @{@" result" : @10 }
1978
- andStatusCode: HTTPCode200OK
1979
- andNetworkConnected: @YES
1980
- andRequestValidator: ^BOOL (id obj) {
1981
- [self validateSdkVersionHeaderFieldForRequest: obj];
1982
- return @YES ;
1983
- }];
1984
-
1985
- // Get the mock url session. We'll check the request it gets passed by sendEvents for the version header
1986
- id urlSessionMock = client.network .urlSession ;
1987
-
1988
- KIOQuery *query = [[KIOQuery alloc ] initWithQuery: @" count" andPropertiesDictionary: @{@" event_collection" : @" event_collection" }];
2003
+ XCTestExpectation *requestValidated = [self expectationWithDescription: @" request was validated" ];
2004
+ KeenClient *client = [self createClientWithResponseData: @{
2005
+ @" result" : @10
2006
+ }
2007
+ andStatusCode: HTTPCode200OK
2008
+ andNetworkConnected: @YES
2009
+ andRequestValidator: ^BOOL (id obj) {
2010
+ [self validateSdkVersionHeaderFieldForRequest: obj];
2011
+ [requestValidated fulfill ];
2012
+ return @YES ;
2013
+ }];
1989
2014
1990
- XCTestExpectation* responseArrived = [ self expectationWithDescription: @" response of async request has arrived " ];
1991
- [client runQuery: query completionHandler: ^( NSData *queryResponseData, NSURLResponse *response, NSError *error) {
1992
- // Check for the sdk version header
1993
- [urlSessionMock verify ];
2015
+ KIOQuery *query =
2016
+ [[KIOQuery alloc ] initWithQuery: @" count " andPropertiesDictionary: @ {
2017
+ @" event_collection " : @" event_collection "
2018
+ } ];
1994
2019
1995
- [responseArrived fulfill ];
1996
- }];
2020
+ XCTestExpectation *responseArrived = [self expectationWithDescription: @" response of async request has arrived" ];
2021
+ [client runAsyncQuery: query
2022
+ block: ^(NSData *queryResponseData, NSURLResponse *response, NSError *error) {
2023
+ [responseArrived fulfill ];
2024
+ }];
1997
2025
1998
- [self waitForExpectationsWithTimeout: _asyncTimeInterval handler: ^(NSError * _Nullable error) {
1999
- XCTAssertNil (error, @" Test should complete within expected interval." );
2000
- }];
2026
+ [self waitForExpectationsWithTimeout: _asyncTimeInterval
2027
+ handler: ^(NSError *_Nullable error) {
2028
+ XCTAssertNil (error, @" Test should complete within expected interval." );
2029
+ }];
2001
2030
}
2002
2031
2003
2032
- (void )testSdkTrackingHeadersOnMultiAnalysis {
2004
- KeenClient* client = [self createClientWithResponseData: @{@" result" : @{@" query1" : @10 , @" query2" : @1 }}
2005
- andStatusCode: HTTPCode200OK
2006
- andNetworkConnected: @YES
2007
- andRequestValidator: ^BOOL (id obj) {
2008
- [self validateSdkVersionHeaderFieldForRequest: obj];
2009
- return @YES ;
2010
- }];
2011
-
2012
- // Get the mock url session. We'll check the request it gets passed by sendEvents for the version header
2013
- id urlSessionMock = client.network .urlSession ;
2014
-
2015
- KIOQuery* countQuery = [[KIOQuery alloc ] initWithQuery: @" count"
2016
- andPropertiesDictionary: @{@" event_collection" : @" event_collection" }];
2017
-
2018
- KIOQuery* averageQuery = [[KIOQuery alloc ] initWithQuery: @" count_unique"
2019
- andPropertiesDictionary: @{@" event_collection" : @" event_collection" , @" target_property" : @" something" }];
2020
-
2021
- XCTestExpectation* responseArrived = [self expectationWithDescription: @" response of async request has arrived" ];
2022
- [client runMultiAnalysisWithQueries: @[countQuery, averageQuery]
2023
- completionHandler: ^(NSData * queryResponseData, NSURLResponse * response, NSError * error) {
2024
- // Check for the sdk version header
2025
- [urlSessionMock verify ];
2033
+ XCTestExpectation *requestValidated = [self expectationWithDescription: @" request was validated" ];
2034
+ KeenClient *client = [self createClientWithResponseData: @{
2035
+ @" result" : @{@" query1" : @10 , @" query2" : @1 }
2036
+ }
2037
+ andStatusCode: HTTPCode200OK
2038
+ andNetworkConnected: @YES
2039
+ andRequestValidator: ^BOOL (id obj) {
2040
+ [self validateSdkVersionHeaderFieldForRequest: obj];
2041
+ [requestValidated fulfill ];
2042
+ return @YES ;
2043
+ }];
2026
2044
2027
- [responseArrived fulfill ];
2028
- }];
2045
+ KIOQuery *countQuery =
2046
+ [[KIOQuery alloc ] initWithQuery: @" count" andPropertiesDictionary: @{
2047
+ @" event_collection" : @" event_collection"
2048
+ }];
2029
2049
2030
- [self waitForExpectationsWithTimeout: _asyncTimeInterval handler: ^(NSError * _Nullable error) {
2031
- XCTAssertNil (error, @" Test should complete within expected interval." );
2032
- }];
2050
+ KIOQuery *averageQuery = [[KIOQuery alloc ] initWithQuery: @" count_unique"
2051
+ andPropertiesDictionary: @{
2052
+ @" event_collection" : @" event_collection" ,
2053
+ @" target_property" : @" something"
2054
+ }];
2055
+
2056
+ XCTestExpectation *responseArrived = [self expectationWithDescription: @" response of async request has arrived" ];
2057
+ [client runAsyncMultiAnalysisWithQueries: @[countQuery, averageQuery]
2058
+ block: ^(NSData *queryResponseData, NSURLResponse *response, NSError *error) {
2059
+ [responseArrived fulfill ];
2060
+ }];
2061
+
2062
+ [self waitForExpectationsWithTimeout: _asyncTimeInterval
2063
+ handler: ^(NSError *_Nullable error) {
2064
+ XCTAssertNil (error, @" Test should complete within expected interval." );
2065
+ }];
2033
2066
}
2034
2067
2035
2068
# pragma mark - test filesystem utility methods
0 commit comments