Skip to content

Commit a96d68e

Browse files
authored
[LP-11409] Add method to mark Inbox message as read (#387)
* Mark Inbox message as read without running its action. * Added Unit tests for Inbox read and markAsRead
1 parent 114e501 commit a96d68e

File tree

4 files changed

+163
-2
lines changed

4 files changed

+163
-2
lines changed

Example/Tests/Classes/LPInboxTest.m

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@
2626
#import <XCTest/XCTest.h>
2727
#import <OHHTTPStubs/HTTPStubs.h>
2828
#import <OHHTTPStubs/HTTPStubsPathHelpers.h>
29+
#import <OCMock/OCMock.h>
2930
#import "LeanplumHelper.h"
3031
#import "LeanplumRequest+Categories.h"
3132
#import "LPNetworkEngine+Category.h"
3233
#import "Leanplum+Extensions.h"
3334
#import "LPFileManager.h"
3435
#import "LPActionManager.h"
35-
#import "LPConstants.h"
36+
#import "LPInbox.h"
3637

3738
@interface LPInboxTest : XCTestCase
3839

@@ -52,6 +53,8 @@ - (void)tearDown
5253
[super tearDown];
5354
// Clean up after every test.
5455
[LeanplumHelper clean_up];
56+
// Clean up saved requests.
57+
[LPEventDataManager deleteEventsWithLimit:[LPEventDataManager count]];
5558
[HTTPStubs removeAllStubs];
5659
}
5760

@@ -336,4 +339,141 @@ - (void)test_onForceContentUpdate {
336339
[[Leanplum inbox] reset];
337340
}
338341

342+
/**
343+
* Tests inbox message [markAsRead]
344+
* Message is marked as read
345+
* markNewsfeedMessageAsRead API action is called
346+
*/
347+
-(void)test_markAsRead
348+
{
349+
dispatch_semaphore_t semaphor = dispatch_semaphore_create(0);
350+
[self loadInbox:^{
351+
// Wait for callback
352+
dispatch_semaphore_signal(semaphor);
353+
}];
354+
355+
dispatch_semaphore_wait(semaphor, [LeanplumHelper default_dispatch_time]);
356+
357+
XCTAssertEqual(2, [[Leanplum inbox] unreadCount]);
358+
LPInboxMessage *msg = [[Leanplum inbox] allMessages][0];
359+
360+
semaphor = dispatch_semaphore_create(0);
361+
[LeanplumRequest validate_request:^BOOL(NSString *method, NSString *apiMethod,
362+
NSDictionary *params) {
363+
XCTAssertEqualObjects(apiMethod, @"markNewsfeedMessageAsRead");
364+
dispatch_semaphore_signal(semaphor);
365+
return YES;
366+
}];
367+
368+
[msg markAsRead];
369+
370+
XCTAssertTrue([msg isRead]);
371+
XCTAssertEqual(1, [[Leanplum inbox] unreadCount]);
372+
373+
long timedOut = dispatch_semaphore_wait(semaphor, [LeanplumHelper default_dispatch_time]);
374+
XCTAssertTrue(timedOut == 0);
375+
}
376+
377+
/**
378+
* Tests inbox message [markAsRead] does not run the message open action
379+
*/
380+
-(void)test_markAsRead_not_run_action
381+
{
382+
dispatch_semaphore_t semaphor = dispatch_semaphore_create(0);
383+
[self loadInbox:^{
384+
// Wait for callback
385+
dispatch_semaphore_signal(semaphor);
386+
}];
387+
388+
LPInboxMessage *msg = [[Leanplum inbox] allMessages][0];
389+
id mock = OCMPartialMock(msg.context);
390+
391+
OCMReject([mock runTrackedActionNamed:[OCMArg any]]);
392+
[msg markAsRead];
393+
XCTAssertTrue([msg isRead]);
394+
}
395+
396+
/**
397+
* Tests inbox message [read] does run the message open action and marks it as read
398+
*/
399+
-(void)test_read_runs_action
400+
{
401+
dispatch_semaphore_t semaphor = dispatch_semaphore_create(0);
402+
[self loadInbox:^{
403+
// Wait for callback
404+
dispatch_semaphore_signal(semaphor);
405+
}];
406+
407+
LPInboxMessage *msg = [[Leanplum inbox] allMessages][0];
408+
id mock = OCMPartialMock(msg.context);
409+
[msg read];
410+
411+
OCMVerify([mock runTrackedActionNamed:[OCMArg any]]);
412+
XCTAssertTrue([msg isRead]);
413+
}
414+
415+
/**
416+
* Tests inbox message [read]
417+
* Message is marked as read
418+
* markNewsfeedMessageAsRead API action is called
419+
* Message open action is run [context runTrackedActionNamed:]
420+
*/
421+
-(void)test_read
422+
{
423+
dispatch_semaphore_t semaphor = dispatch_semaphore_create(0);
424+
[self loadInbox:^{
425+
// Wait for callback
426+
dispatch_semaphore_signal(semaphor);
427+
}];
428+
dispatch_semaphore_wait(semaphor, [LeanplumHelper default_dispatch_time]);
429+
430+
XCTAssertEqual(2, [[Leanplum inbox] unreadCount]);
431+
LPInboxMessage *msg = [[Leanplum inbox] allMessages][0];
432+
433+
semaphor = dispatch_semaphore_create(0);
434+
[LeanplumRequest validate_request:^BOOL(NSString *method, NSString *apiMethod,
435+
NSDictionary *params) {
436+
XCTAssertEqualObjects(apiMethod, @"markNewsfeedMessageAsRead");
437+
dispatch_semaphore_signal(semaphor);
438+
return YES;
439+
}];
440+
441+
id mock = OCMPartialMock(msg.context);
442+
443+
[msg read];
444+
OCMVerify([mock runTrackedActionNamed:[OCMArg any]]);
445+
446+
XCTAssertTrue([msg isRead]);
447+
XCTAssertEqual(1, [[Leanplum inbox] unreadCount]);
448+
449+
long timedOut = dispatch_semaphore_wait(semaphor, [LeanplumHelper default_dispatch_time]);
450+
XCTAssertTrue(timedOut == 0);
451+
}
452+
453+
-(void)loadInbox:(void (^)(void))finishBlock
454+
{
455+
// Do not need to fetch images
456+
// Prefetching will trigger downloadFile requests
457+
[[Leanplum inbox] disableImagePrefetching];
458+
// Ensure errors are thrown
459+
[LeanplumHelper mockThrowErrorToThrow];
460+
461+
id<HTTPStubsDescriptor> getNewsfeedMessagesStub = [HTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
462+
return [request.URL.host isEqualToString:API_HOST];
463+
} withStubResponse:^HTTPStubsResponse * _Nonnull(NSURLRequest *request) {
464+
NSString *response_file = OHPathForFile(@"newsfeed_response.json", self.class);
465+
return [HTTPStubsResponse responseWithFileAtPath:response_file
466+
statusCode:200
467+
headers:@{@"Content-Type":@"application/json"}];
468+
}];
469+
470+
[[Leanplum inbox] onChanged:^{
471+
[HTTPStubs removeStub:getNewsfeedMessagesStub];
472+
finishBlock();
473+
}];
474+
475+
[LeanplumHelper setup_development_test];
476+
[[Leanplum inbox] downloadMessages];
477+
}
478+
339479
@end

Example/Tests/Classes/Utilities/LeanplumHelper.m

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,21 @@ + (void) throwError:(NSString *) err
183183
@throw([NSException exceptionWithName:err reason:nil userInfo:nil]);
184184
}
185185

186+
+ (void) handleException:(NSException *) ex
187+
{
188+
[LeanplumHelper setLastErrorMessage:[ex name]];
189+
@throw(ex);
190+
}
191+
186192
+ (void) mockThrowErrorToThrow
187193
{
188194
id mockLeanplumClass = OCMClassMock([Leanplum class]);
189195
[OCMStub(ClassMethod([mockLeanplumClass throwError:[OCMArg any]])) andCall:@selector(throwError:) onObject:self];
196+
197+
// Cannot mock leanplumInternalError(NSException *e) since it is a function
198+
// Mocking [LPUtils handleException:e] which is used inside leanplumInternalError first
199+
id mockLPUtilsClass = OCMClassMock([LPUtils class]);
200+
[OCMStub(ClassMethod([mockLPUtilsClass handleException:[OCMArg any]])) andCall:@selector(handleException:) onObject:self];
190201
}
191202

192203
@end

Leanplum-SDK/Classes/Features/Inbox/LPInbox.m

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ - (NSDictionary *)data
179179
return nil;
180180
}
181181

182-
- (void)read
182+
- (void)markAsRead
183183
{
184184
if (![self isRead]) {
185185
[self setIsRead:YES];
@@ -196,6 +196,11 @@ - (void)read
196196
[[LPRequestSender sharedInstance] send:request];
197197
LP_END_TRY
198198
}
199+
}
200+
201+
- (void)read
202+
{
203+
[self markAsRead];
199204

200205
LP_TRY
201206
[[self context] runTrackedActionNamed:LP_VALUE_DEFAULT_PUSH_ACTION];

Leanplum-SDK/Classes/LPInbox.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ NS_SWIFT_NAME(LeanplumInbox.Message)
8383
*/
8484
@property (assign, nonatomic, readonly) BOOL isRead;
8585

86+
/**
87+
* Mark the inbox message as read without invoking its open action.
88+
*/
89+
- (void)markAsRead;
90+
8691
/**
8792
* Read the inbox message, marking it as read and invoking its open action.
8893
*/

0 commit comments

Comments
 (0)