hunk.code_window: #pragma mark - internal
   - (void)_onTestSuiteCompleted:(NSNotification *)notif
   {
     _jsTestSuiteResult = notif.userInfo;
   }
  
hunk.labels: keep keep add keep keep keep keep keep
hunk.after_edit: - (void)_onKernelJSLoaded
   {
     // if test environment isn't configured for a shell app, override here
     // since clearly we're running tests
     if ([EXShellManager sharedInstance].testEnvironment == EXTestEnvironmentNone) {
       [EXShellManager sharedInstance].testEnvironment = EXTestEnvironmentLocal;
     }
     [[EXKernel sharedInstance].serviceRegistry.linkingManager openUrl:@"exp://localhost:19002" isUniversalLink:NO];
   }
  
hunk.file_path: ios/ExponentIntegrationTests/ExponentIntegrationTests.m
hunk.type: add
file: // Copyright 2015-present 650 Industries. All rights reserved.
  
  #import "ABI14_0_0EXKernelModule.h"
  #import "ABI14_0_0EXUnversioned.h"
  
  #import <ReactABI14_0_0/ABI14_0_0RCTEventDispatcher.h>
  
  @interface ABI14_0_0EXKernelModule ()
  
  @property (nonatomic, assign) BOOL hasListeners;
  @property (nonatomic, strong) NSMutableDictionary *eventSuccessBlocks;
  @property (nonatomic, strong) NSMutableDictionary *eventFailureBlocks;
  @property (nonatomic, strong) NSArray * _Nonnull sdkVersions;
  
  @end
  
  @implementation ABI14_0_0EXKernelModule
  
  + (NSString *)moduleName { return @"ExponentKernel"; }
  
  - (instancetype)initWithVersions:(NSArray *)supportedSdkVersions
  {
    if (self = [super init]) {
      _eventSuccessBlocks = [NSMutableDictionary dictionary];
      _eventFailureBlocks = [NSMutableDictionary dictionary];
      _sdkVersions = supportedSdkVersions;
    }
    return self;
  }
  
  - (NSDictionary *)constantsToExport
  {
    return @{ @"sdkVersions": _sdkVersions };
  }
  
  #pragma mark - ABI14_0_0RCTEventEmitter methods
  
  - (NSArray<NSString *> *)supportedEvents
  {
    return @[];
  }
  
  /**
   *  Override this method to avoid the [self supportedEvents] validation
   */
  - (void)sendEventWithName:(NSString *)eventName body:(id)body
  {
    // Note that this could be a versioned bridge!
    [self.bridge enqueueJSCall:@"ABI14_0_0RCTDeviceEventEmitter.emit"
                          args:body ? @[eventName, body] : @[eventName]];
  }
  
  #pragma mark -
  
  - (void)dispatchJSEvent:(NSString *)eventName body:(NSDictionary *)eventBody onSuccess:(void (^)(NSDictionary *))success onFailure:(void (^)(NSString *))failure
  {
    NSString *qualifiedEventName = [NSString stringWithFormat:@"ExponentKernel.%@", eventName];
    NSMutableDictionary *qualifiedEventBody = (eventBody) ? [eventBody mutableCopy] : [NSMutableDictionary dictionary];
  
    if (success && failure) {
      NSString *eventId = [[NSUUID UUID] UUIDString];
      [_eventSuccessBlocks setObject:success forKey:eventId];
      [_eventFailureBlocks setObject:failure forKey:eventId];
      [qualifiedEventBody setObject:eventId forKey:@"eventId"];
    }
  
    [self sendEventWithName:qualifiedEventName body:qualifiedEventBody];
  }
  
  /**
   *  Duplicates Linking.openURL but does not validate that this is an exponent URL;
   *  in other words, we just take your word for it and never hand it off to iOS.
   *  Used by the home screen URL bar.
   */
  ABI14_0_0RCT_EXPORT_METHOD(openURL:(NSURL *)URL
                    resolve:(ABI14_0_0RCTPromiseResolveBlock)resolve
                    reject:(__unused ABI14_0_0RCTPromiseRejectBlock)reject)
  {
    if (URL) {
      [[NSNotificationCenter defaultCenter] postNotificationName:@"EXKernelOpenUrlNotification"
                                                          object:nil
                                                        userInfo:@{
                                                                   @"bridge": self.bridge,
                                                                   @"url": URL.absoluteString,
                                                                   }];
      resolve(@YES);
    } else {
      NSError *err = [NSError errorWithDomain:@"EXKernelErrorDomain" code:-1 userInfo:@{ NSLocalizedDescriptionKey: @"Cannot open a nil url" }];
      reject(@"E_INVALID_URL", err.localizedDescription, err);
    }
  }
  
  ABI14_0_0RCT_EXPORT_METHOD(addDevMenu)
  {
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_main_queue(), ^{
      if (weakSelf.delegate) {
        [weakSelf.delegate kernelModuleDidSelectDevMenu:weakSelf];
      }
    });
  }
  
  ABI14_0_0RCT_REMAP_METHOD(routeDidForeground,
                   routeDidForegroundWithType:(NSUInteger)routeType
                   params:(NSDictionary *)params)
  {
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_main_queue(), ^{
      if (weakSelf.delegate) {
        [weakSelf.delegate kernelModule:weakSelf taskDidForegroundWithType:routeType params:params];
      }
    });
  }
  
  ABI14_0_0RCT_EXPORT_METHOD(onLoaded)
  {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"EXKernelJSIsLoadedNotification" object:self];
  }
  
  ABI14_0_0RCT_REMAP_METHOD(getManifestAsync,
                   getManifestWithUrl:(NSURL *)url
                   originalUrl:(NSURL *)originalUrl
                   resolve:(ABI14_0_0RCTPromiseResolveBlock)resolve
                   reject:(ABI14_0_0RCTPromiseRejectBlock)reject)
  {
    if (_delegate) {
      [_delegate kernelModule:self didRequestManifestWithUrl:url originalUrl:originalUrl success:^(NSString *manifestString) {
        resolve(manifestString);
      } failure:^(NSError *error) {
        reject([NSString stringWithFormat:@"%ld", (long)error.code], error.localizedDescription, error);
      }];
    }
  }
  
  ABI14_0_0RCT_REMAP_METHOD(onEventSuccess,
                   eventId:(NSString *)eventId
                   body:(NSDictionary *)body)
  {
    void (^success)(NSDictionary *) = [_eventSuccessBlocks objectForKey:eventId];
    if (success) {
      success(body);
      [_eventSuccessBlocks removeObjectForKey:eventId];
      [_eventFailureBlocks removeObjectForKey:eventId];
    }
  }
  
  ABI14_0_0RCT_REMAP_METHOD(onEventFailure,
                   eventId:(NSString *)eventId
                   message:(NSString *)message)
  {
    void (^failure)(NSString *) = [_eventFailureBlocks objectForKey:eventId];
    if (failure) {
      failure(message);
      [_eventSuccessBlocks removeObjectForKey:eventId];
      [_eventFailureBlocks removeObjectForKey:eventId];
    }
  }
  
  @end
  