@@ -37,6 +37,7 @@ @interface FIRIAMMessageContentDataForTesting : NSObject <FIRIAMMessageContentDa
37
37
@property (nonatomic , nullable ) NSURL *imageURL;
38
38
@property (nonatomic , nullable ) NSURL *landscapeImageURL;
39
39
@property BOOL errorEncountered;
40
+ @property BOOL loadImagesAsynchronously;
40
41
41
42
- (instancetype )initWithMessageTitle : (NSString *)title
42
43
messageBody : (NSString *)body
@@ -46,7 +47,8 @@ - (instancetype)initWithMessageTitle:(NSString *)title
46
47
secondaryActionURL : (nullable NSURL *)secondaryActionURL
47
48
imageURL : (nullable NSURL *)imageURL
48
49
landscapeImageURL : (nullable NSURL *)landscapeImageURL
49
- hasImageError : (BOOL )hasImageError ;
50
+ hasImageError : (BOOL )hasImageError
51
+ loadImagesAsynchronously : (BOOL )loadImagesAsynchronously ;
50
52
@end
51
53
52
54
@implementation FIRIAMMessageContentDataForTesting
@@ -58,7 +60,8 @@ - (instancetype)initWithMessageTitle:(NSString *)title
58
60
secondaryActionURL : (nullable NSURL *)secondaryActionURL
59
61
imageURL : (nullable NSURL *)imageURL
60
62
landscapeImageURL : (nullable NSURL *)landscapeImageURL
61
- hasImageError : (BOOL )hasImageError {
63
+ hasImageError : (BOOL )hasImageError
64
+ loadImagesAsynchronously : (BOOL )loadImagesAsynchronously {
62
65
if (self = [super init ]) {
63
66
_titleText = title;
64
67
_bodyText = body;
@@ -69,6 +72,7 @@ - (instancetype)initWithMessageTitle:(NSString *)title
69
72
_actionURL = actionURL;
70
73
_secondaryActionURL = secondaryActionURL;
71
74
_errorEncountered = hasImageError;
75
+ _loadImagesAsynchronously = loadImagesAsynchronously;
72
76
}
73
77
return self;
74
78
}
@@ -77,14 +81,38 @@ - (void)loadImageDataWithBlock:(void (^)(NSData *_Nullable imageData,
77
81
NSData *_Nullable landscapeImageData,
78
82
NSError *_Nullable error))block {
79
83
if (self.errorEncountered ) {
80
- block (nil , nil , [NSError errorWithDomain: @" image error" code: 0 userInfo: nil ]);
84
+ NSError *error = [NSError errorWithDomain: @" image error" code: 0 userInfo: nil ];
85
+
86
+ if (_loadImagesAsynchronously) {
87
+ [self performOnMainQueueAfterDelay: 0.01
88
+ block: ^{
89
+ block (nil , nil , error);
90
+ }];
91
+ } else {
92
+ block (nil , nil , error);
93
+ }
81
94
} else {
82
95
NSData *imageData = [@" image data" dataUsingEncoding: NSUTF8StringEncoding];
83
96
NSData *landscapeImageData = [@" landscape image data" dataUsingEncoding: NSUTF8StringEncoding];
84
97
85
- block (imageData, landscapeImageData, nil );
98
+ if (_loadImagesAsynchronously) {
99
+ [self performOnMainQueueAfterDelay: 0.01
100
+ block: ^{
101
+ block (imageData, landscapeImageData, nil );
102
+ }];
103
+ } else {
104
+ block (imageData, landscapeImageData, nil );
105
+ }
86
106
}
87
107
}
108
+
109
+ - (void )performOnMainQueueAfterDelay : (NSTimeInterval )delay block : (void (^)(void ))block {
110
+ dispatch_after (dispatch_time (DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), dispatch_get_main_queue (),
111
+ ^{
112
+ block ();
113
+ });
114
+ }
115
+
88
116
@end
89
117
90
118
// Defines how the message display component triggers the delegate in unit testing.
@@ -207,8 +235,8 @@ @interface FIRIAMDisplayExecutorTests : XCTestCase
207
235
208
236
@property id <FIRInAppMessagingDisplay> mockMessageDisplayComponent;
209
237
210
- // four pre -defined messages
211
- @property FIRIAMMessageDefinition *m1, *m2, *m3, *m4, *m5;
238
+ // Pre -defined messages
239
+ @property FIRIAMMessageDefinition *m1, *m2, *m3, *m4, *m5, *m6 ;
212
240
@end
213
241
214
242
@implementation FIRIAMDisplayExecutorTests
@@ -222,7 +250,7 @@ - (void)setupMessageTexture {
222
250
FIRIAMDisplayTriggerDefinition *contextualTriggerDefinition =
223
251
[[FIRIAMDisplayTriggerDefinition alloc ] initWithFirebaseAnalyticEvent: @" test_event" ];
224
252
225
- // m2, m4, and m5 will be of app open trigger
253
+ // m2, m4, m5, and m6 will be of app open trigger
226
254
FIRIAMDisplayTriggerDefinition *appOpentriggerDefinition =
227
255
[[FIRIAMDisplayTriggerDefinition alloc ] initForAppForegroundTrigger ];
228
256
@@ -235,7 +263,8 @@ - (void)setupMessageTexture {
235
263
secondaryActionURL: nil
236
264
imageURL: [NSURL URLWithString: @" https://google.com/image" ]
237
265
landscapeImageURL: nil
238
- hasImageError: NO ];
266
+ hasImageError: NO
267
+ loadImagesAsynchronously: NO ];
239
268
240
269
FIRIAMRenderingEffectSetting *renderSetting1 =
241
270
[FIRIAMRenderingEffectSetting getDefaultRenderingEffectSetting ];
@@ -261,7 +290,8 @@ - (void)setupMessageTexture {
261
290
secondaryActionURL: nil
262
291
imageURL: [NSURL URLWithString: @" https://unsplash.it/300/400" ]
263
292
landscapeImageURL: nil
264
- hasImageError: NO ];
293
+ hasImageError: NO
294
+ loadImagesAsynchronously: NO ];
265
295
266
296
FIRIAMRenderingEffectSetting *renderSetting2 =
267
297
[FIRIAMRenderingEffectSetting getDefaultRenderingEffectSetting ];
@@ -287,7 +317,8 @@ - (void)setupMessageTexture {
287
317
secondaryActionURL: nil
288
318
imageURL: [NSURL URLWithString: @" https://google.com/image" ]
289
319
landscapeImageURL: nil
290
- hasImageError: NO ];
320
+ hasImageError: NO
321
+ loadImagesAsynchronously: NO ];
291
322
292
323
FIRIAMRenderingEffectSetting *renderSetting3 =
293
324
[FIRIAMRenderingEffectSetting getDefaultRenderingEffectSetting ];
@@ -313,7 +344,8 @@ - (void)setupMessageTexture {
313
344
secondaryActionURL: nil
314
345
imageURL: [NSURL URLWithString: @" https://google.com/image" ]
315
346
landscapeImageURL: nil
316
- hasImageError: NO ];
347
+ hasImageError: NO
348
+ loadImagesAsynchronously: NO ];
317
349
318
350
FIRIAMRenderingEffectSetting *renderSetting4 =
319
351
[FIRIAMRenderingEffectSetting getDefaultRenderingEffectSetting ];
@@ -353,7 +385,8 @@ - (void)setupMessageTexture {
353
385
secondaryActionURL: nil
354
386
imageURL: [NSURL URLWithString: @" https://google.com/image" ]
355
387
landscapeImageURL: nil
356
- hasImageError: NO ];
388
+ hasImageError: NO
389
+ loadImagesAsynchronously: NO ];
357
390
358
391
FIRIAMRenderingEffectSetting *renderSetting5 =
359
392
[FIRIAMRenderingEffectSetting getDefaultRenderingEffectSetting ];
@@ -372,6 +405,33 @@ - (void)setupMessageTexture {
372
405
appData: nil
373
406
experimentPayload: nil
374
407
isTestMessage: NO ];
408
+
409
+ FIRIAMMessageContentDataForTesting *m6ContentData = [[FIRIAMMessageContentDataForTesting alloc ]
410
+ initWithMessageTitle: @" m6 title"
411
+ messageBody: @" message body"
412
+ actionButtonText: nil
413
+ secondaryActionButtonText: nil
414
+ actionURL: [NSURL URLWithString: @" http://google.com" ]
415
+ secondaryActionURL: nil
416
+ imageURL: [NSURL URLWithString: @" https://google.com/image" ]
417
+ landscapeImageURL: nil
418
+ hasImageError: NO
419
+ loadImagesAsynchronously: YES ];
420
+
421
+ FIRIAMRenderingEffectSetting *renderSetting6 =
422
+ [FIRIAMRenderingEffectSetting getDefaultRenderingEffectSetting ];
423
+ renderSetting6.viewMode = FIRIAMRenderAsBannerView;
424
+
425
+ FIRIAMMessageRenderData *renderData6 =
426
+ [[FIRIAMMessageRenderData alloc ] initWithMessageID: @" m6"
427
+ messageName: @" name"
428
+ contentData: m6ContentData
429
+ renderingEffect: renderSetting6];
430
+
431
+ self.m6 = [[FIRIAMMessageDefinition alloc ] initWithRenderData: renderData6
432
+ startTime: activeStartTime
433
+ endTime: activeEndTime
434
+ triggerDefinition: @[ appOpentriggerDefinition ]];
375
435
}
376
436
377
437
NSTimeInterval DISPLAY_MIN_INTERVALS = 1 ;
@@ -888,6 +948,36 @@ - (void)testNoRenderingIfMessageDisplayIsSuppressed {
888
948
XCTAssertEqual (1 , remainingMsgCount2);
889
949
}
890
950
951
+ - (void )testNoRenderingIfMessageDisplayIsSuppressedDuringImageLoading {
952
+ // This setup allows next message to be displayed from display interval perspective.
953
+ OCMStub ([self .mockTimeFetcher currentTimestampInSeconds ])
954
+ .andReturn (DISPLAY_MIN_INTERVALS * 60 + 100 );
955
+
956
+ [self .clientMessageCache setMessageData: @[ self .m6 ]];
957
+
958
+ FIRIAMMessageDisplayForTesting *display = [[FIRIAMMessageDisplayForTesting alloc ]
959
+ initWithDelegateInteraction: FIRInAppMessagingDelegateInteractionClick];
960
+ self.displayExecutor .messageDisplayComponent = display;
961
+ [self .displayExecutor checkAndDisplayNextAppForegroundMessage ];
962
+ self.displayExecutor .suppressMessageDisplay = YES ;
963
+
964
+ XCTestExpectation *expectation = [[XCTestExpectation alloc ] init ];
965
+
966
+ dispatch_after (dispatch_time (DISPATCH_TIME_NOW, 0.05 * NSEC_PER_SEC), dispatch_get_main_queue (),
967
+ ^{
968
+ // no message display has happened
969
+ XCTAssertNil (display.message );
970
+
971
+ NSInteger remainingMsgCount = [self .clientMessageCache allRegularMessages ].count ;
972
+ // no message is removed from the cache
973
+ XCTAssertEqual (1 , remainingMsgCount);
974
+
975
+ [expectation fulfill ];
976
+ });
977
+
978
+ [self waitForExpectations: @[ expectation ] timeout: 0.1 ];
979
+ }
980
+
891
981
// No contextual message rendering if suppress message display flag is turned on
892
982
- (void )testNoContextualMsgRenderingIfMessageDisplayIsSuppressed {
893
983
// This setup allows next message to be displayed from display interval perspective.
0 commit comments