FIRMessagingContextManagerServiceTest.m 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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 <XCTest/XCTest.h>
  22. #import "OCMock.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. API_AVAILABLE(macos(10.14))
  32. @interface FIRMessagingContextManagerServiceTest : XCTestCase
  33. @property(nonatomic, readwrite, strong) NSDateFormatter *dateFormatter;
  34. @property(nonatomic, readwrite, strong) NSMutableArray *scheduledLocalNotifications;
  35. @property(nonatomic, readwrite, strong)
  36. NSMutableArray<UNNotificationRequest *> *requests API_AVAILABLE(ios(10.0));
  37. @end
  38. @implementation FIRMessagingContextManagerServiceTest
  39. - (void)setUp {
  40. [super setUp];
  41. self.dateFormatter = [[NSDateFormatter alloc] init];
  42. self.dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
  43. [self.dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  44. self.scheduledLocalNotifications = [[NSMutableArray alloc] init];
  45. if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
  46. self.requests = [[NSMutableArray alloc] init];
  47. }
  48. [self mockSchedulingLocalNotifications];
  49. }
  50. - (void)tearDown {
  51. [super tearDown];
  52. }
  53. /**
  54. * Test invalid context manager message, missing lt_start string.
  55. */
  56. - (void)testInvalidContextManagerMessage_missingStartTime {
  57. NSDictionary *message = @{
  58. @"hello" : @"world",
  59. };
  60. XCTAssertFalse([FIRMessagingContextManagerService isContextManagerMessage:message]);
  61. }
  62. /**
  63. * Test valid context manager message.
  64. */
  65. - (void)testValidContextManagerMessage {
  66. NSDictionary *message = @{
  67. kFIRMessagingContextManagerLocalTimeStart : @"2015-12-12 00:00:00",
  68. @"hello" : @"world",
  69. };
  70. XCTAssertTrue([FIRMessagingContextManagerService isContextManagerMessage:message]);
  71. }
  72. /**
  73. * Context Manager message with future start date should be successfully scheduled.
  74. */
  75. - (void)testMessageWithFutureStartTime {
  76. // way into the future
  77. NSString *startTimeString = [self.dateFormatter stringFromDate:[NSDate distantFuture]];
  78. NSDictionary *message = @{
  79. kFIRMessagingContextManagerLocalTimeStart : startTimeString,
  80. kFIRMessagingContextManagerBodyKey : kBody,
  81. kMessageIdentifierKey : kMessageIdentifierValue,
  82. kUserInfoKey1 : kUserInfoValue1,
  83. kUserInfoKey2 : kUserInfoValue2
  84. };
  85. XCTAssertTrue([FIRMessagingContextManagerService handleContextManagerMessage:message]);
  86. if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
  87. XCTAssertEqual(self.requests.count, 1);
  88. UNNotificationRequest *request = self.requests.firstObject;
  89. XCTAssertEqualObjects(request.identifier, kMessageIdentifierValue);
  90. #if TARGET_OS_IOS || TARGET_OS_WATCH || TARGET_OS_OSX
  91. XCTAssertEqualObjects(request.content.body, kBody);
  92. XCTAssertEqualObjects(request.content.userInfo[kUserInfoKey1], kUserInfoValue1);
  93. XCTAssertEqualObjects(request.content.userInfo[kUserInfoKey2], kUserInfoValue2);
  94. #endif
  95. return;
  96. }
  97. #if TARGET_OS_IOS
  98. XCTAssertEqual(self.scheduledLocalNotifications.count, 1);
  99. #pragma clang diagnostic push
  100. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  101. UILocalNotification *notification = self.scheduledLocalNotifications.firstObject;
  102. #pragma clang diagnostic pop
  103. NSDate *date = [self.dateFormatter dateFromString:startTimeString];
  104. XCTAssertEqual([notification.fireDate compare:date], NSOrderedSame);
  105. XCTAssertEqualObjects(notification.alertBody, kBody);
  106. XCTAssertEqualObjects(notification.userInfo[kUserInfoKey1], kUserInfoValue1);
  107. XCTAssertEqualObjects(notification.userInfo[kUserInfoKey2], kUserInfoValue2);
  108. #endif
  109. }
  110. /**
  111. * Context Manager message with past end date should not be scheduled.
  112. */
  113. - (void)testMessageWithPastEndTime {
  114. #if TARGET_OS_IOS
  115. NSString *startTimeString = @"2010-01-12 12:00:00"; // way into the past
  116. NSString *endTimeString = @"2011-01-12 12:00:00"; // way into the past
  117. NSDictionary *message = @{
  118. kFIRMessagingContextManagerLocalTimeStart : startTimeString,
  119. kFIRMessagingContextManagerLocalTimeEnd : endTimeString,
  120. kFIRMessagingContextManagerBodyKey : kBody,
  121. kMessageIdentifierKey : kMessageIdentifierValue,
  122. @"hello" : @"world"
  123. };
  124. XCTAssertTrue([FIRMessagingContextManagerService handleContextManagerMessage:message]);
  125. if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
  126. XCTAssertEqual(self.requests.count, 0);
  127. return;
  128. }
  129. XCTAssertEqual(self.scheduledLocalNotifications.count, 0);
  130. #endif
  131. }
  132. /**
  133. * Context Manager message with past start and future end date should be successfully
  134. * scheduled.
  135. */
  136. - (void)testMessageWithPastStartAndFutureEndTime {
  137. #if TARGET_OS_IOS
  138. NSDate *startDate = [NSDate dateWithTimeIntervalSinceNow:-1000]; // past
  139. NSDate *endDate = [NSDate dateWithTimeIntervalSinceNow:1000]; // future
  140. NSString *startTimeString = [self.dateFormatter stringFromDate:startDate];
  141. NSString *endTimeString = [self.dateFormatter stringFromDate:endDate];
  142. NSDictionary *message = @{
  143. kFIRMessagingContextManagerLocalTimeStart : startTimeString,
  144. kFIRMessagingContextManagerLocalTimeEnd : endTimeString,
  145. kFIRMessagingContextManagerBodyKey : kBody,
  146. kMessageIdentifierKey : kMessageIdentifierValue,
  147. kUserInfoKey1 : kUserInfoValue1,
  148. kUserInfoKey2 : kUserInfoValue2
  149. };
  150. XCTAssertTrue([FIRMessagingContextManagerService handleContextManagerMessage:message]);
  151. if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
  152. XCTAssertEqual(self.requests.count, 1);
  153. UNNotificationRequest *request = self.requests.firstObject;
  154. XCTAssertEqualObjects(request.identifier, kMessageIdentifierValue);
  155. XCTAssertEqualObjects(request.content.body, kBody);
  156. XCTAssertEqualObjects(request.content.userInfo[kUserInfoKey1], kUserInfoValue1);
  157. XCTAssertEqualObjects(request.content.userInfo[kUserInfoKey2], kUserInfoValue2);
  158. return;
  159. }
  160. XCTAssertEqual(self.scheduledLocalNotifications.count, 1);
  161. #pragma clang diagnostic push
  162. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  163. UILocalNotification *notification = [self.scheduledLocalNotifications firstObject];
  164. #pragma clang diagnostic pop
  165. // schedule notification after start date
  166. XCTAssertEqual([notification.fireDate compare:startDate], NSOrderedDescending);
  167. // schedule notification after end date
  168. XCTAssertEqual([notification.fireDate compare:endDate], NSOrderedAscending);
  169. XCTAssertEqualObjects(notification.userInfo[kUserInfoKey1], kUserInfoValue1);
  170. XCTAssertEqualObjects(notification.userInfo[kUserInfoKey2], kUserInfoValue2);
  171. #endif
  172. }
  173. /**
  174. * Test correctly parsing user data in local notifications.
  175. */
  176. - (void)testTimedNotificationsUserInfo {
  177. #if TARGET_OS_IOS
  178. // way into the future
  179. NSString *startTimeString = [self.dateFormatter stringFromDate:[NSDate distantFuture]];
  180. NSDictionary *message = @{
  181. kFIRMessagingContextManagerLocalTimeStart : startTimeString,
  182. kFIRMessagingContextManagerBodyKey : kBody,
  183. kMessageIdentifierKey : kMessageIdentifierValue,
  184. kUserInfoKey1 : kUserInfoValue1,
  185. kUserInfoKey2 : kUserInfoValue2
  186. };
  187. XCTAssertTrue([FIRMessagingContextManagerService handleContextManagerMessage:message]);
  188. if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
  189. XCTAssertEqual(self.requests.count, 1);
  190. UNNotificationRequest *request = self.requests.firstObject;
  191. XCTAssertEqualObjects(request.identifier, kMessageIdentifierValue);
  192. XCTAssertEqualObjects(request.content.body, kBody);
  193. XCTAssertEqualObjects(request.content.userInfo[kUserInfoKey1], kUserInfoValue1);
  194. XCTAssertEqualObjects(request.content.userInfo[kUserInfoKey2], kUserInfoValue2);
  195. return;
  196. }
  197. XCTAssertEqual(self.scheduledLocalNotifications.count, 1);
  198. #pragma clang diagnostic push
  199. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  200. UILocalNotification *notification = [self.scheduledLocalNotifications firstObject];
  201. #pragma clang diagnostic pop
  202. XCTAssertEqualObjects(notification.userInfo[kUserInfoKey1], kUserInfoValue1);
  203. XCTAssertEqualObjects(notification.userInfo[kUserInfoKey2], kUserInfoValue2);
  204. #endif
  205. }
  206. #pragma mark - Private Helpers
  207. - (void)mockSchedulingLocalNotifications {
  208. if (@available(macOS 10.14, iOS 10.0, watchOS 3.0, tvOS 10.0, *)) {
  209. id mockNotificationCenter =
  210. OCMPartialMock([UNUserNotificationCenter currentNotificationCenter]);
  211. __block UNNotificationRequest *request;
  212. [[[mockNotificationCenter stub] andDo:^(NSInvocation *invocation) {
  213. [self.requests addObject:request];
  214. }] addNotificationRequest:[OCMArg checkWithBlock:^BOOL(id obj) {
  215. if ([obj isKindOfClass:[UNNotificationRequest class]]) {
  216. request = obj;
  217. [self.requests addObject:request];
  218. return YES;
  219. }
  220. return NO;
  221. }]
  222. withCompletionHandler:^(NSError *_Nullable error){
  223. }];
  224. return;
  225. }
  226. #if TARGET_OS_IOS
  227. id mockApplication = OCMPartialMock([UIApplication sharedApplication]);
  228. #pragma clang diagnostic push
  229. #pragma clang diagnostic ignored "-Wdeprecated-declarations"
  230. __block UILocalNotification *notificationToSchedule;
  231. [[[mockApplication stub] andDo:^(NSInvocation *invocation) {
  232. // Mock scheduling a notification
  233. if (notificationToSchedule) {
  234. [self.scheduledLocalNotifications addObject:notificationToSchedule];
  235. }
  236. }] scheduleLocalNotification:[OCMArg checkWithBlock:^BOOL(id obj) {
  237. if ([obj isKindOfClass:[UILocalNotification class]]) {
  238. notificationToSchedule = obj;
  239. return YES;
  240. }
  241. return NO;
  242. }]];
  243. #pragma clang diagnostic pop
  244. #endif
  245. }
  246. @end