1// Copyright 2021-present 650 Industries. All rights reserved. 2 3#import <XCTest/XCTest.h> 4 5#import <objc/runtime.h> 6#import <EXDevLauncher/EXDevLauncher.h> 7#import <EXDevLauncher/EXDevLauncherController.h> 8 9@import EXManifests; 10 11@interface EXDevLauncherController (EXDevLauncherModuleTests) 12 13- (EXManifestsManifest * _Nullable)mockAppManifest; 14- (NSURL *)mockAppManifestURL; 15 16@end 17 18@implementation EXDevLauncherController (EXDevLauncherModuleTests) 19 20- (EXManifestsManifest * _Nullable)mockAppManifest 21{ 22 return [EXManifestsManifestFactory manifestForManifestJSON:@{ 23 @"name": @"testproject", 24 @"slug": @"testproject", 25 @"version": @"1.0.0", 26 @"sdkVersion": @"42.0.0", 27 @"bundleUrl": @"http://test.io/bundle.js" 28 }]; 29} 30 31- (NSURL *)mockAppManifestURL 32{ 33 return [NSURL URLWithString:@"https://exp.host/@test/test?query=param"]; 34} 35 36@end 37 38@interface EXDevLauncherModuleTests : XCTestCase 39 40@end 41 42@implementation EXDevLauncherModuleTests 43 44// https://nshipster.com/method-swizzling/ 45- (void)swizzleMethodForClass:(Class)class 46 originalSelector:(SEL)originalSelector 47 swizzledSelector:(SEL)swizzledSelector 48{ 49 Method originalMethod = class_getInstanceMethod(class, originalSelector); 50 Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); 51 52 BOOL didAddMethod = 53 class_addMethod(class, 54 originalSelector, 55 method_getImplementation(swizzledMethod), 56 method_getTypeEncoding(swizzledMethod)); 57 58 if (didAddMethod) { 59 class_replaceMethod(class, 60 swizzledSelector, 61 method_getImplementation(originalMethod), 62 method_getTypeEncoding(originalMethod)); 63 } else { 64 method_exchangeImplementations(originalMethod, swizzledMethod); 65 } 66} 67 68- (void)testConstantsToExportManifest 69{ 70 [self swizzleMethodForClass:[EXDevLauncherController class] 71 originalSelector:@selector(appManifest) 72 swizzledSelector:@selector(mockAppManifest)]; 73 74 EXDevLauncher *module = [EXDevLauncher new]; 75 NSDictionary *constants = [module constantsToExport]; 76 77 NSDictionary *expected = @{ 78 @"name": @"testproject", 79 @"slug": @"testproject", 80 @"version": @"1.0.0", 81 @"sdkVersion": @"42.0.0", 82 @"bundleUrl": @"http://test.io/bundle.js" 83 }; 84 NSDictionary *actual = [NSJSONSerialization JSONObjectWithData:[constants[@"manifestString"] dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:NULL]; 85 XCTAssertEqualObjects(expected, actual); 86 87 // clean up 88 [self swizzleMethodForClass:[EXDevLauncherController class] 89 originalSelector:@selector(appManifest) 90 swizzledSelector:@selector(mockAppManifest)]; 91} 92 93- (void)testConstantsToExportManifestURL 94{ 95 // used by snack 96 97 [self swizzleMethodForClass:[EXDevLauncherController class] 98 originalSelector:@selector(appManifestURL) 99 swizzledSelector:@selector(mockAppManifestURL)]; 100 101 EXDevLauncher *module = [EXDevLauncher new]; 102 NSDictionary *constants = [module constantsToExport]; 103 XCTAssertEqualObjects(@"https://exp.host/@test/test?query=param", constants[@"manifestURL"]); 104 105 // clean up 106 [self swizzleMethodForClass:[EXDevLauncherController class] 107 originalSelector:@selector(appManifestURL) 108 swizzledSelector:@selector(mockAppManifestURL)]; 109} 110 111@end 112