FIRMessagingContextManagerServiceTest.m 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0 || \
  17. __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_14 || __TV_OS_VERSION_MAX_ALLOWED >= __TV_10_0 || \
  18. __WATCH_OS_VERSION_MAX_ALLOWED >= __WATCHOS_3_0 || TARGET_OS_MACCATALYST
  19. #import <UserNotifications/UserNotifications.h>
  20. #endif
  21. #import <OCMock/OCMock.h>
  22. #import <XCTest/XCTest.h>
  23. #import "FirebaseMessaging/Sources/FIRMessagingContextManagerService.h"
  24. static NSString *const kBody = @"Save 20% off!";
  25. static NSString *const kUserInfoKey1 = @"level";
  26. static NSString *const kUserInfoKey2 = @"isPayUser";
  27. static NSString *const kUserInfoValue1 = @"5";
  28. static NSString *const kUserInfoValue2 = @"Yes";
  29. static NSString *const kMessageIdentifierKey = @"gcm.message_id";
  30. static NSString *const kMessageIdentifierValue = @"1584748495200141";
  31. @interface FIRMessagingContextManagerServiceTest : XCTestCase
  32. @property(nonatomic, readwrite, strong) NSDateFormatter *dateFormatter;
  33. @property(nonatomic, readwrite, strong) NSMutableArray *scheduledLocalNotifications;
  34. @property(nonatomic, readwrite, strong)
  35. NSMutableArray<UNNotificationRequest *> *requests API_AVAILABLE(ios(10.0));
  36. @end
  37. @implementation FIRMessagingContextManagerServiceTest
  38. - (void)setUp {
  39. [super setUp];
  40. self.dateFormatter = [[NSDateFormatter alloc] init];
  41. self.dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
  42. [self.dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  43. self.scheduledLocalNotifications = [[NSMutableArray alloc] init];
  44. if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
  45. self.requests = [[NSMutableArray alloc] init];
  46. }
  47. [self mockSchedulingLocalNotifications];
  48. }
  49. - (void)tearDown {
  50. [super tearDown];
  51. }
  52. /**
  53. * Test invalid context manager message, missing lt_start string.
  54. */
  55. - (void)testInvalidContextManagerMessage_missingStartTime {
  56. NSDictionary *message = @{
  57. @"hello" : @"world",
  58. };
  59. XCTAssertFalse([FIRMessagingContextManagerService isContextManagerMessage:message]);
  60. }
  61. /**
  62. * Test valid context manager message.
  63. */
  64. - (void)testValidContextManagerMessage {
  65. NSDictionary *message = @{
  66. kFIRMessagingContextManagerLocalTimeStart : @"2015-12-12 00:00:00",
  67. @"hello" : @"world",
  68. };
  69. XCTAssertTrue([FIRMessagingContextManagerService isContextManagerMessage:message]);
  70. }
  71. /**
  72. * Context Manager message with future start date should be successfully scheduled.
  73. */
  74. - (void)testMessageWithFutureStartTime {
  75. // way into the future
  76. NSString *startTimeString = [self.dateFormatter stringFromDate:[NSDate distantFuture]];
  77. NSDictionary *message = @{
  78. kFIRMessagingContextManagerLocalTimeStart : startTimeString,
  79. kFIRMessagingContextManagerBodyKey : kBody,
  80. kMessageIdentifierKey : kMessageIdentifierValue,
  81. kUserInfoKey1 : kUserInfoValue1,
  82. kUserInfoKey2 : kUserInfoValue2
  83. };
  84. XCTAssertTrue([FIRMessagingContextManagerService handleContextManagerMessage:message]);
  85. if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
  86. XCTAssertEqual(self.requests.count, 1);
  87. UNNotificationRequest *request = self.requests.firstObject;
  88. XCTAssertEqualObjects(request.identifier, kMessageIdentifierValue);
  89. #if TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_OSX
  90. XCTAssertEqualObjects(request.content.body, kBody);
  91. XCTAssertEqualObjects(request.content.userInfo[kUserInfoKey1], kUserInfoValue1);
  92. XCTAssertEqualObjects(request.content.userInfo[kUserInfoKey2], kUserInfoValue2);
  93. #endif
  94. return;
  95. }
  96. #if TARGET_OS_IOS
  97. XCTAssertEqual(self.scheduledLocalNotifications.count, 1);
  98. #pragma clang diagnostic push
  99. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  100. UILocalNotification *notification = self.scheduledLocalNotifications.firstObject;
  101. #pragma clang diagnostic pop
  102. NSDate *date = [self.dateFormatter dateFromString:startTimeString];
  103. XCTAssertEqual([notification.fireDate compare:date], NSOrderedSame);
  104. XCTAssertEqualObjects(notification.alertBody, kBody);
  105. XCTAssertEqualObjects(notification.userInfo[kUserInfoKey1], kUserInfoValue1);
  106. XCTAssertEqualObjects(notification.userInfo[kUserInfoKey2], kUserInfoValue2);
  107. #endif
  108. }
  109. /**
  110. * Context Manager message with past end date should not be scheduled.
  111. */
  112. - (void)testMessageWithPastEndTime {
  113. #if TARGET_OS_IOS
  114. NSString *startTimeString = @"2010-01-12 12:00:00"; // way into the past
  115. NSString *endTimeString = @"2011-01-12 12:00:00"; // way into the past
  116. NSDictionary *message = @{
  117. kFIRMessagingContextManagerLocalTimeStart : startTimeString,
  118. kFIRMessagingContextManagerLocalTimeEnd : endTimeString,
  119. kFIRMessagingContextManagerBodyKey : kBody,
  120. kMessageIdentifierKey : kMessageIdentifierValue,
  121. @"hello" : @"world"
  122. };
  123. XCTAssertTrue([FIRMessagingContextManagerService handleContextManagerMessage:message]);
  124. if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
  125. XCTAssertEqual(self.requests.count, 0);
  126. return;
  127. }
  128. XCTAssertEqual(self.scheduledLocalNotifications.count, 0);
  129. #endif
  130. }
  131. /**
  132. * Context Manager message with past start and future end date should be successfully
  133. * scheduled.
  134. */
  135. - (void)testMessageWithPastStartAndFutureEndTime {
  136. #if TARGET_OS_IOS
  137. NSDate *startDate = [NSDate dateWithTimeIntervalSinceNow:-1000]; // past
  138. NSDate *endDate = [NSDate dateWithTimeIntervalSinceNow:1000]; // future
  139. NSString *startTimeString = [self.dateFormatter stringFromDate:startDate];
  140. NSString *endTimeString = [self.dateFormatter stringFromDate:endDate];
  141. NSDictionary *message = @{
  142. kFIRMessagingContextManagerLocalTimeStart : startTimeString,
  143. kFIRMessagingContextManagerLocalTimeEnd : endTimeString,
  144. kFIRMessagingContextManagerBodyKey : kBody,
  145. kMessageIdentifierKey : kMessageIdentifierValue,
  146. kUserInfoKey1 : kUserInfoValue1,
  147. kUserInfoKey2 : kUserInfoValue2
  148. };
  149. XCTAssertTrue([FIRMessagingContextManagerService handleContextManagerMessage:message]);
  150. if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
  151. XCTAssertEqual(self.requests.count, 1);
  152. UNNotificationRequest *request = self.requests.firstObject;
  153. XCTAssertEqualObjects(request.identifier, kMessageIdentifierValue);
  154. XCTAssertEqualObjects(request.content.body, kBody);
  155. XCTAssertEqualObjects(request.content.userInfo[kUserInfoKey1], kUserInfoValue1);
  156. XCTAssertEqualObjects(request.content.userInfo[kUserInfoKey2], kUserInfoValue2);
  157. return;
  158. }
  159. XCTAssertEqual(self.scheduledLocalNotifications.count, 1);
  160. #pragma clang diagnostic push
  161. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  162. UILocalNotification *notification = [self.scheduledLocalNotifications firstObject];
  163. #pragma clang diagnostic pop
  164. // schedule notification after start date
  165. XCTAssertEqual([notification.fireDate compare:startDate], NSOrderedDescending);
  166. // schedule notification after end date
  167. XCTAssertEqual([notification.fireDate compare:endDate], NSOrderedAscending);
  168. XCTAssertEqualObjects(notification.userInfo[kUserInfoKey1], kUserInfoValue1);
  169. XCTAssertEqualObjects(notification.userInfo[kUserInfoKey2], kUserInfoValue2);
  170. #endif
  171. }
  172. /**
  173. * Test correctly parsing user data in local notifications.
  174. */
  175. - (void)testTimedNotificationsUserInfo {
  176. #if TARGET_OS_IOS
  177. // way into the future
  178. NSString *startTimeString = [self.dateFormatter stringFromDate:[NSDate distantFuture]];
  179. NSDictionary *message = @{
  180. kFIRMessagingContextManagerLocalTimeStart : startTimeString,
  181. kFIRMessagingContextManagerBodyKey : kBody,
  182. kMessageIdentifierKey : kMessageIdentifierValue,
  183. kUserInfoKey1 : kUserInfoValue1,
  184. kUserInfoKey2 : kUserInfoValue2
  185. };
  186. XCTAssertTrue([FIRMessagingContextManagerService handleContextManagerMessage:message]);
  187. if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
  188. XCTAssertEqual(self.requests.count, 1);
  189. UNNotificationRequest *request = self.requests.firstObject;
  190. XCTAssertEqualObjects(request.identifier, kMessageIdentifierValue);
  191. XCTAssertEqualObjects(request.content.body, kBody);
  192. XCTAssertEqualObjects(request.content.userInfo[kUserInfoKey1], kUserInfoValue1);
  193. XCTAssertEqualObjects(request.content.userInfo[kUserInfoKey2], kUserInfoValue2);
  194. return;
  195. }
  196. XCTAssertEqual(self.scheduledLocalNotifications.count, 1);
  197. #pragma clang diagnostic push
  198. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  199. UILocalNotification *notification = [self.scheduledLocalNotifications firstObject];
  200. #pragma clang diagnostic pop
  201. XCTAssertEqualObjects(notification.userInfo[kUserInfoKey1], kUserInfoValue1);
  202. XCTAssertEqualObjects(notification.userInfo[kUserInfoKey2], kUserInfoValue2);
  203. #endif
  204. }
  205. #pragma mark - Private Helpers
  206. - (void)mockSchedulingLocalNotifications {
  207. if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
  208. id mockNotificationCenter =
  209. OCMPartialMock([UNUserNotificationCenter currentNotificationCenter]);
  210. __block UNNotificationRequest *request;
  211. [[[mockNotificationCenter stub] andDo:^(NSInvocation *invocation) {
  212. [self.requests addObject:request];
  213. }] addNotificationRequest:[OCMArg checkWithBlock:^BOOL(id obj) {
  214. if ([obj isKindOfClass:[UNNotificationRequest class]]) {
  215. request = obj;
  216. [self.requests addObject:request];
  217. return YES;
  218. }
  219. return NO;
  220. }]
  221. withCompletionHandler:^(NSError *_Nullable error){
  222. }];
  223. return;
  224. }
  225. #if TARGET_OS_IOS
  226. id mockApplication = OCMPartialMock([UIApplication sharedApplication]);
  227. #pragma clang diagnostic push
  228. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  229. __block UILocalNotification *notificationToSchedule;
  230. [[[mockApplication stub] andDo:^(NSInvocation *invocation) {
  231. // Mock scheduling a notification
  232. if (notificationToSchedule) {
  233. [self.scheduledLocalNotifications addObject:notificationToSchedule];
  234. }
  235. }] scheduleLocalNotification:[OCMArg checkWithBlock:^BOOL(id obj) {
  236. if ([obj isKindOfClass:[UILocalNotification class]]) {
  237. notificationToSchedule = obj;
  238. return YES;
  239. }
  240. return NO;
  241. }]];
  242. #pragma clang diagnostic pop
  243. #endif
  244. }
  245. @end