Skip to content

Commit 5d56b0f

Browse files
committed
Merge remote-tracking branch 'origin/master' into release/3.1.0
2 parents 86c95f0 + 4ae1372 commit 5d56b0f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1086
-446
lines changed

Example/Leanplum-SDK.xcodeproj/project.pbxproj

Lines changed: 58 additions & 50 deletions
Large diffs are not rendered by default.
Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="whP-gf-Uak">
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="TTt-qL-hpO">
3+
<device id="retina6_1" orientation="portrait" appearance="light"/>
34
<dependencies>
4-
<deployment identifier="iOS"/>
5-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
5+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
6+
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
67
</dependencies>
78
<scenes>
89
<!--View Controller-->
@@ -14,14 +15,33 @@
1415
<viewControllerLayoutGuide type="bottom" id="Mvr-aV-6Um"/>
1516
</layoutGuides>
1617
<view key="view" contentMode="scaleToFill" id="TpU-gO-2f1">
17-
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
18+
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
1819
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
19-
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
20+
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
2021
</view>
22+
<navigationItem key="navigationItem" id="Br3-s4-Nn2"/>
2123
</viewController>
2224
<placeholder placeholderIdentifier="IBFirstResponder" id="tc2-Qw-aMS" userLabel="First Responder" sceneMemberID="firstResponder"/>
2325
</objects>
24-
<point key="canvasLocation" x="305" y="433"/>
26+
<point key="canvasLocation" x="1167" y="468"/>
27+
</scene>
28+
<!--Navigation Controller-->
29+
<scene sceneID="pu6-NT-qYk">
30+
<objects>
31+
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="TTt-qL-hpO" sceneMemberID="viewController">
32+
<toolbarItems/>
33+
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="en4-c1-HI9">
34+
<rect key="frame" x="0.0" y="44" width="414" height="44"/>
35+
<autoresizingMask key="autoresizingMask"/>
36+
</navigationBar>
37+
<nil name="viewControllers"/>
38+
<connections>
39+
<segue destination="whP-gf-Uak" kind="relationship" relationship="rootViewController" id="Epn-76-6Ns"/>
40+
</connections>
41+
</navigationController>
42+
<placeholder placeholderIdentifier="IBFirstResponder" id="dYM-eE-nJm" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
43+
</objects>
44+
<point key="canvasLocation" x="304.34782608695656" y="432.58928571428572"/>
2545
</scene>
2646
</scenes>
2747
</document>

Example/Tests/Classes/Extensions/LPRequest+Extension.m

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//
88

99
#import "LPRequest+Extension.h"
10+
#import "LPRequestSender+Categories.h"
1011

1112
@implementation LPRequest (Extension)
1213
static LPNetworkResponseBlock responseCallback;
@@ -19,6 +20,11 @@ + (void)swizzle_methods
1920
error:&error
2021
class:[LPRequest class]];
2122

23+
success &= [LPSwizzle swizzleMethod:@selector(createArgsDictionary)
24+
withMethod:@selector(swizzle_createArgsDictionary)
25+
error:&error
26+
class:[LPRequest class]];
27+
2228
if (!success || error) {
2329
NSLog(@"Failed swizzling methods for LPRequest: %@", error);
2430
}
@@ -35,6 +41,17 @@ - (void)swizzle_onResponse:(LPNetworkResponseBlock) response_
3541
}];
3642
}
3743

44+
- (NSMutableDictionary *)swizzle_createArgsDictionary
45+
{
46+
NSMutableDictionary *args = [self swizzle_createArgsDictionary];
47+
if([[LPRequestSender sharedInstance] createArgsCallback] != nil) {
48+
[LPRequestSender sharedInstance].createArgsCallback(args);
49+
[LPRequestSender sharedInstance].createArgsCallback = nil;
50+
}
51+
52+
return args;
53+
}
54+
3855
+ (void)validate_onResponse:(LPNetworkResponseBlock)callback
3956
{
4057
responseCallback = callback;

Example/Tests/Classes/Extensions/LPRequestSender+Categories.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,16 @@
2828
@interface LPRequestSender(MethodSwizzling)
2929

3030
@property (assign) BOOL (^requestCallback)(NSString *method, NSString *apiMethod, NSDictionary *params);
31+
@property (assign) void (^createArgsCallback)(NSDictionary *args);
3132

3233
- (void)setRequestCallback:(BOOL (^)(NSString *, NSString *, NSDictionary *))requestCallback;
3334
- (BOOL (^)(NSString *, NSString *, NSDictionary *))requestCallback;
3435

36+
- (void)setCreateArgsCallback:(void (^)(NSDictionary *))createArgsCallback;
37+
- (void (^)(NSDictionary *))createArgsCallback;
38+
3539
+ (void)validate_request:(BOOL (^)(NSString *, NSString *, NSDictionary *))callback;
40+
+ (void)validate_request_args_dictionary:(void (^)(NSDictionary *))callback;
3641
+ (void)swizzle_methods;
3742
+ (void)reset;
3843

Example/Tests/Classes/Extensions/LPRequestSender+Categories.m

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
@implementation LPRequestSender(MethodSwizzling)
3131
@dynamic requestCallback;
32+
@dynamic createArgsCallback;
3233

3334
- (void)setRequestCallback:(BOOL (^)(NSString *, NSString *, NSDictionary *))requestCallback
3435
{
@@ -40,6 +41,16 @@ - (void)setRequestCallback:(BOOL (^)(NSString *, NSString *, NSDictionary *))req
4041
return objc_getAssociatedObject(self, _cmd);
4142
}
4243

44+
- (void)setCreateArgsCallback:(void (^)(NSDictionary *))createArgsCallback
45+
{
46+
objc_setAssociatedObject(self, @selector(createArgsCallback), createArgsCallback, OBJC_ASSOCIATION_COPY);
47+
}
48+
49+
- (void (^)(NSDictionary *))createArgsCallback
50+
{
51+
return objc_getAssociatedObject(self, _cmd);
52+
}
53+
4354
+ (void)swizzle_methods
4455
{
4556
NSError *error;
@@ -76,6 +87,11 @@ + (void)validate_request:(BOOL (^)(NSString *, NSString *, NSDictionary *)) call
7687
[LPRequestSender sharedInstance].requestCallback = callback;
7788
}
7889

90+
+ (void)validate_request_args_dictionary:(void (^)(NSDictionary *))callback
91+
{
92+
[LPRequestSender sharedInstance].createArgsCallback = callback;
93+
}
94+
7995
+ (void)reset {
8096
[LPRequestSender sharedInstance].requestCallback = nil;
8197
}

Example/Tests/Classes/Extensions/Leanplum+Extensions.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#import "LeanplumInternal.h"
2828
#import <Leanplum/LPRequestFactory.h>
2929
#import <Leanplum/LPPushNotificationsHandler.h>
30+
#import <Leanplum/LPDeferMessageManager.h>
3031

3132
@interface Leanplum(UnitTest)
3233

@@ -40,6 +41,8 @@
4041

4142
+ (void)triggerAction:(LPActionContext *)context handledBlock:(LeanplumHandledBlock)handledBlock;
4243

44+
+ (void)setDeviceIdInternal:(NSString *)deviceId;
45+
4346
@end
4447

4548
@interface LPPushNotificationsHandler(UnitTest)
@@ -63,3 +66,12 @@
6366
+ (LPRequest *)createGetForApiMethod:(NSString *)apiMethod params:(nullable NSDictionary *)params;
6467
+ (nullable LPRequest *)createPostForApiMethod:(nonnull NSString *)apiMethod params:(nullable NSDictionary *)params;
6568
@end
69+
70+
@interface LPLogManager(UnitTest)
71+
+ (void)maybeSendLog:(NSString *)message;
72+
@end
73+
74+
@interface LPDeferMessageManager(UnitTest)
75+
+ (void)triggerDeferredMessage;
76+
+ (void)reset;
77+
@end

Example/Tests/Classes/LPCountAggregatorTest.m

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#import <OCMock/OCMock.h>
2828
#import "LPCountAggregator.h"
2929
#import "LPConstants.h"
30-
#import "LPRequest.h"
3130
#import <Leanplum/LPRequestSender.h>
3231
#import <Leanplum/LPNetworkConstants.h>
3332
#import "LeanplumHelper.h"
@@ -148,8 +147,8 @@ - (void)test_sendAllCounts {
148147
id lpRequestMockVerified = [[lpRequestMock verify] ignoringNonObjectArgs];
149148

150149
id lpRequestSenderMock = OCMClassMock([LPRequestSender class]);
151-
OCMStub([lpRequestSenderMock sendEventually:lpRequestMockVerified sync:[OCMArg any]]);
152-
[lpRequestSenderMock sendEventually:lpRequestMockVerified sync:[OCMArg any]];
150+
OCMStub([lpRequestSenderMock send:lpRequestMockVerified]);
151+
[lpRequestSenderMock send:lpRequestMockVerified];
153152
[lpRequestSenderMock stopMocking];
154153
[lpRequestMock stopMocking];
155154
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
//
2+
// LPDeferMessageManagerTest.m
3+
// Leanplum-SDK_Tests
4+
//
5+
// Created by Nikola Zagorchev on 26.08.20.
6+
// Copyright © 2020 Leanplum. All rights reserved.
7+
//
8+
9+
#import <Foundation/Foundation.h>
10+
#import <XCTest/XCTest.h>
11+
#import <OCMock/OCMock.h>
12+
#import "Leanplum+Extensions.h"
13+
#import "LeanplumHelper.h"
14+
#import "LPDeferMessageManager.h"
15+
#import "Leanplum/LPAlertMessageTemplate.h"
16+
#import "Leanplum/LPAPIConfig.h"
17+
18+
@interface LPDeferMessageManagerTest : XCTestCase
19+
20+
@end
21+
22+
@interface LPSampleViewController : UIViewController
23+
@end
24+
@implementation LPSampleViewController
25+
@end
26+
27+
@implementation LPDeferMessageManagerTest
28+
29+
+ (void)setUp
30+
{
31+
[super setUp];
32+
[LeanplumHelper mockThrowErrorToThrow];
33+
// Mock LOG_LP_MESSAGE_EXCEPTION through [LPLogManager maybeSendLog:]
34+
id mockLPLogManager = OCMClassMock([LPLogManager class]);
35+
[OCMStub(ClassMethod([mockLPLogManager maybeSendLog:[OCMArg any]])) andCall:@selector(maybeSendLog:) onObject:self];
36+
}
37+
38+
/**
39+
* Throw exception if the log is coming from LOG_LP_MESSAGE_EXCEPTION
40+
*/
41+
+ (void)maybeSendLog:(NSString *)message {
42+
if ([message containsString:@"Error in message template"]) {
43+
@throw([NSException exceptionWithName:NSGenericException reason:message userInfo:nil]);
44+
}
45+
}
46+
47+
/**
48+
* Defer message for controller and Alert message
49+
*/
50+
- (void)setupDeferMessage {
51+
NSArray<Class> *arr = @[[LPSampleViewController class]];
52+
[Leanplum deferMessagesForViewControllers: arr];
53+
}
54+
55+
- (void)tearDown
56+
{
57+
[super tearDown];
58+
[Leanplum reset];
59+
[LPDeferMessageManager reset];
60+
}
61+
62+
- (void)test_defer
63+
{
64+
[self setupDeferMessage];
65+
[LPAlertMessageTemplate defineAction];
66+
67+
id templateUtils = OCMClassMock([LPMessageTemplateUtilities class]);
68+
id deferManager = OCMClassMock([LPDeferMessageManager class]);
69+
OCMStub([templateUtils topViewController]).andReturn([LPSampleViewController new]);
70+
71+
LPActionContext *context = [LPActionContext actionContextWithName:LPMT_ALERT_NAME args:@{} messageId:0];
72+
73+
OCMReject([templateUtils presentOverVisible:OCMArg.any]);
74+
75+
XCTestExpectation *expectation = [self expectationWithDescription:@"Message is not handled"];
76+
[Leanplum triggerAction:context handledBlock:^(BOOL success) {
77+
XCTAssertFalse(success);
78+
[expectation fulfill];
79+
}];
80+
81+
OCMVerify([deferManager shouldDeferMessage:OCMArg.any]);
82+
83+
[self waitForExpectationsWithTimeout:5.0 handler:^(NSError *error) {
84+
if (error) {
85+
NSLog(@"Error: %@", error);
86+
}
87+
}];
88+
}
89+
90+
- (void)test_no_defer
91+
{
92+
// Leanplum start is needed to successfully handle message View and record impression
93+
[LeanplumHelper start_development_test];
94+
95+
[LPAlertMessageTemplate defineAction];
96+
97+
id templateUtils = OCMClassMock([LPMessageTemplateUtilities class]);
98+
id deferManager = OCMClassMock([LPDeferMessageManager class]);
99+
100+
LPActionContext *context = [LPActionContext actionContextWithName:LPMT_ALERT_NAME args:@{} messageId:0];
101+
102+
XCTestExpectation *expectation = [self expectationWithDescription:@"Message is not handled"];
103+
[Leanplum triggerAction:context handledBlock:^(BOOL success) {
104+
XCTAssertTrue(success);
105+
[expectation fulfill];
106+
}];
107+
108+
OCMVerify([deferManager shouldDeferMessage:OCMArg.any]);
109+
OCMVerify([templateUtils presentOverVisible:OCMArg.any]);
110+
111+
[self waitForExpectationsWithTimeout:5.0 handler:^(NSError *error) {
112+
if (error) {
113+
NSLog(@"Error: %@", error);
114+
}
115+
}];
116+
}
117+
118+
- (void)test_defer_and_show
119+
{
120+
// Leanplum start is needed to successfully handle message View and record impression
121+
[LeanplumHelper start_development_test];
122+
123+
[self setupDeferMessage];
124+
125+
[LPAlertMessageTemplate defineAction];
126+
127+
id templateUtils = OCMClassMock([LPMessageTemplateUtilities class]);
128+
id deferManager = OCMClassMock([LPDeferMessageManager class]);
129+
id stub = OCMStub([templateUtils topViewController]);
130+
[stub andReturn:[LPSampleViewController new]];
131+
132+
LPActionContext *context = [LPActionContext actionContextWithName:LPMT_ALERT_NAME args:@{} messageId:@"123"];
133+
134+
XCTestExpectation *expectation = [self expectationWithDescription:@"Message is not handled"];
135+
[Leanplum triggerAction:context handledBlock:^(BOOL success) {
136+
XCTAssertFalse(success);
137+
[expectation fulfill];
138+
}];
139+
140+
[self waitForExpectationsWithTimeout:5.0 handler:^(NSError *error) {
141+
if (error) {
142+
NSLog(@"Error: %@", error);
143+
}
144+
}];
145+
146+
id lpMock = OCMClassMock([Leanplum class]);
147+
148+
// Change the top controller to show the deferred message
149+
UIViewController *newTopViewController = [UIViewController new];
150+
[stub andReturn:newTopViewController];
151+
[newTopViewController viewDidAppear:NO];
152+
153+
OCMVerify([deferManager triggerDeferredMessage]);
154+
OCMVerify([templateUtils presentOverVisible:OCMArg.any]);
155+
OCMVerify([lpMock triggerAction:context handledBlock:OCMArg.any]);
156+
}
157+
158+
@end

Example/Tests/Classes/LPEventDataManagerTest.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ - (void)test_response_code
147147
return YES;
148148
}];
149149

150-
LPRequest *request = [LPRequestFactory createPostForApiMethod:@"sample3" params:nil];
151-
[[LPRequestSender sharedInstance] sendNow:request];
150+
LPRequest *request = [[LPRequestFactory createPostForApiMethod:@"sample3" params:nil] andRequestType:Immediate];
151+
[[LPRequestSender sharedInstance] send:request];
152152
long timedOut =dispatch_semaphore_wait(semaphore, [LeanplumHelper default_dispatch_time]);
153153
XCTAssertTrue(timedOut == 0);
154154
events = [LPEventDataManager eventsWithLimit:10000];
@@ -248,13 +248,13 @@ - (void)test_response_index
248248
// Queue up the events and test if the callback is in the correct index.
249249
XCTestExpectation *responseExpectation =
250250
[self expectationWithDescription:@"responseExpectation"];
251-
LPRequest *request = [LPRequestFactory createPostForApiMethod:@"test2" params:nil];
251+
LPRequest *request = [[LPRequestFactory createPostForApiMethod:@"test2" params:nil] andRequestType:Immediate];
252252
[request onResponse:^(id<LPNetworkOperationProtocol> operation, id json) {
253253
// Make sure the response is the first one.
254254
XCTAssertTrue([json[@"index"] intValue] == 1);
255255
[responseExpectation fulfill];
256256
}];
257-
[[LPRequestSender sharedInstance] sendNow:request];
257+
[[LPRequestSender sharedInstance] send:request];
258258
[[LPOperationQueue serialQueue] waitUntilAllOperationsAreFinished];
259259

260260

0 commit comments

Comments
 (0)