expo-dev-launcher 0.7.0 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/README.md +1 -1
- package/android/build.gradle +2 -1
- package/android/src/debug/assets/expo_dev_launcher_android.bundle +396 -403
- package/android/src/debug/java/expo/modules/devlauncher/DevLauncherController.kt +10 -6
- package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherAppLoaderFactory.kt +5 -5
- package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherExpoAppLoader.kt +5 -5
- package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherLocalAppLoader.kt +3 -3
- package/android/src/debug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherPublishedAppLoader.kt +2 -6
- package/android/src/debug/java/expo/modules/devlauncher/modules/DevLauncherInternalModule.kt +6 -1
- package/android/src/debug/java/expo/modules/devlauncher/modules/DevLauncherModule.kt +1 -1
- package/android/src/main/java/expo/modules/devlauncher/launcher/DevLauncherControllerInterface.kt +2 -2
- package/android/src/main/java/expo/modules/devlauncher/launcher/configurators/DevLauncherExpoActivityConfigurator.kt +12 -11
- package/android/src/main/java/expo/modules/devlauncher/launcher/manifest/DevLauncherManifestParser.kt +4 -2
- package/android/src/main/java/expo/modules/devlauncher/launcher/manifest/DevLauncherManifestTypes.kt +11 -26
- package/android/src/main/java/expo/modules/devlauncher/launcher/menu/DevLauncherMenuDelegate.kt +3 -3
- package/android/src/release/java/expo/modules/devlauncher/DevLauncherController.kt +2 -2
- package/android/src/testDebug/java/expo/modules/devlauncher/DevLauncherControllerTest.kt +50 -0
- package/android/src/testDebug/java/expo/modules/devlauncher/launcher/DevLauncherRecentlyOpenedAppsRegistryTest.kt +43 -0
- package/android/src/testDebug/java/expo/modules/devlauncher/launcher/loaders/DevLauncherAppLoaderFactoryTest.kt +3 -3
- package/android/src/testDebug/java/expo/modules/devlauncher/modules/DevLauncherModuleTest.kt +38 -0
- package/build/DevLauncherErrorManager.js +7 -0
- package/build/DevLauncherErrorManager.js.map +1 -1
- package/expo-dev-launcher.podspec +2 -0
- package/ios/EXDevLauncher.m +8 -2
- package/ios/EXDevLauncher.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/ios/EXDevLauncher.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/ios/EXDevLauncher.xcodeproj/xcuserdata/brentvatne.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
- package/ios/EXDevLauncher.xcworkspace/xcuserdata/brentvatne.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/EXDevLauncherController.h +2 -2
- package/ios/EXDevLauncherController.m +22 -11
- package/ios/EXDevLauncherInternal.m +5 -0
- package/ios/EXDevLauncherMenuDelegate.swift +3 -3
- package/ios/Errors/EXDevLauncherRedBox.m +5 -0
- package/ios/Manifest/EXDevLauncherManifestHelper.swift +15 -12
- package/ios/Manifest/EXDevLauncherManifestParser.h +3 -3
- package/ios/Manifest/EXDevLauncherManifestParser.m +17 -5
- package/ios/Tests/EXDevLauncherManifestHelperTests.swift +28 -0
- package/ios/Tests/EXDevLauncherManifestParserTests.m +113 -0
- package/ios/Tests/EXDevLauncherModuleTests.m +39 -0
- package/ios/devvyc 2021-05-14 18-19-10/devvyc.ipa +0 -0
- package/ios/main.jsbundle +414 -420
- package/package.json +6 -6
- package/plugin/build/constants.d.ts +1 -0
- package/plugin/build/constants.js +4 -0
- package/plugin/build/utils.d.ts +2 -0
- package/plugin/build/utils.js +24 -0
- package/plugin/build/withDevLauncher.js +27 -39
- package/plugin/build/withDevLauncherAppDelegate.d.ts +1 -0
- package/plugin/build/withDevLauncherAppDelegate.js +161 -16
- package/plugin/src/constants.ts +1 -0
- package/plugin/src/utils.ts +25 -0
- package/plugin/src/withDevLauncher.ts +32 -45
- package/plugin/src/withDevLauncherAppDelegate.ts +211 -23
- package/src/DevLauncherErrorManager.ts +7 -0
- package/android/src/main/java/expo/modules/devlauncher/launcher/manifest/DevLauncherManifest.kt +0 -111
- package/ios/Manifest/EXDevLauncherManifest.swift +0 -158
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>SchemeUserState</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key>EXDevLauncher.xcscheme_^#shared#^_</key>
|
|
8
|
+
<dict>
|
|
9
|
+
<key>orderHint</key>
|
|
10
|
+
<integer>0</integer>
|
|
11
|
+
</dict>
|
|
12
|
+
</dict>
|
|
13
|
+
</dict>
|
|
14
|
+
</plist>
|
|
Binary file
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
|
|
4
4
|
#import <UIKit/UIKit.h>
|
|
5
5
|
|
|
6
|
+
#import <EXManifests/EXManifestsManifest.h>
|
|
6
7
|
#import <EXUpdatesInterface/EXUpdatesExternalInterface.h>
|
|
7
8
|
|
|
8
9
|
NS_ASSUME_NONNULL_BEGIN
|
|
9
10
|
|
|
10
11
|
@class EXDevLauncherPendingDeepLinkRegistry;
|
|
11
12
|
@class EXDevLauncherController;
|
|
12
|
-
@class EXDevLauncherManifest;
|
|
13
13
|
@class EXDevLauncherErrorManager;
|
|
14
14
|
|
|
15
15
|
@protocol EXDevLauncherControllerDelegate <NSObject>
|
|
@@ -42,7 +42,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
42
42
|
|
|
43
43
|
- (NSDictionary<UIApplicationLaunchOptionsKey, NSObject*> *)getLaunchOptions;
|
|
44
44
|
|
|
45
|
-
- (
|
|
45
|
+
- (EXManifestsManifest * _Nullable)appManifest;
|
|
46
46
|
|
|
47
47
|
- (NSURL * _Nullable)appManifestURL;
|
|
48
48
|
|
|
@@ -17,7 +17,14 @@
|
|
|
17
17
|
#import "EXDevLauncherUpdatesHelper.h"
|
|
18
18
|
#import "RCTPackagerConnection+EXDevLauncherPackagerConnectionInterceptor.h"
|
|
19
19
|
|
|
20
|
+
#if __has_include(<EXDevLauncher/EXDevLauncher-Swift.h>)
|
|
21
|
+
// For cocoapods framework, the generated swift header will be inside EXDevLauncher module
|
|
22
|
+
#import <EXDevLauncher/EXDevLauncher-Swift.h>
|
|
23
|
+
#else
|
|
20
24
|
#import <EXDevLauncher-Swift.h>
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
#import <EXManifests/EXManifestsManifestFactory.h>
|
|
21
28
|
|
|
22
29
|
@import EXDevMenuInterface;
|
|
23
30
|
|
|
@@ -41,7 +48,7 @@ NSString *fakeLauncherBundleUrl = @"embedded://EXDevLauncher/dummy";
|
|
|
41
48
|
@property (nonatomic, strong) NSURL *sourceUrl;
|
|
42
49
|
@property (nonatomic, assign) BOOL shouldPreferUpdatesInterfaceSourceUrl;
|
|
43
50
|
@property (nonatomic, strong) EXDevLauncherRecentlyOpenedAppsRegistry *recentlyOpenedAppsRegistry;
|
|
44
|
-
@property (nonatomic, strong)
|
|
51
|
+
@property (nonatomic, strong) EXManifestsManifest *manifest;
|
|
45
52
|
@property (nonatomic, strong) NSURL *manifestURL;
|
|
46
53
|
@property (nonatomic, strong) EXDevLauncherErrorManager *errorManager;
|
|
47
54
|
|
|
@@ -119,7 +126,7 @@ NSString *fakeLauncherBundleUrl = @"embedded://EXDevLauncher/dummy";
|
|
|
119
126
|
};
|
|
120
127
|
}
|
|
121
128
|
|
|
122
|
-
- (
|
|
129
|
+
- (EXManifestsManifest *)appManifest
|
|
123
130
|
{
|
|
124
131
|
return self.manifest;
|
|
125
132
|
}
|
|
@@ -147,6 +154,9 @@ NSString *fakeLauncherBundleUrl = @"embedded://EXDevLauncher/dummy";
|
|
|
147
154
|
|
|
148
155
|
if (!launchOptions[UIApplicationLaunchOptionsURLKey]) {
|
|
149
156
|
[self navigateToLauncher];
|
|
157
|
+
} else {
|
|
158
|
+
// For deeplink launch, we need the keyWindow for expo-splash-screen to setup correctly.
|
|
159
|
+
[_window makeKeyWindow];
|
|
150
160
|
}
|
|
151
161
|
}
|
|
152
162
|
|
|
@@ -277,7 +287,7 @@ NSString *fakeLauncherBundleUrl = @"embedded://EXDevLauncher/dummy";
|
|
|
277
287
|
}
|
|
278
288
|
};
|
|
279
289
|
|
|
280
|
-
void (^launchExpoApp)(NSURL *,
|
|
290
|
+
void (^launchExpoApp)(NSURL *, EXManifestsManifest *) = ^(NSURL *bundleURL, EXManifestsManifest *manifest) {
|
|
281
291
|
self->_shouldPreferUpdatesInterfaceSourceUrl = !manifest.isUsingDeveloperTool;
|
|
282
292
|
RCTDevLoadingViewSetEnabled(manifest.isUsingDeveloperTool);
|
|
283
293
|
[self.recentlyOpenedAppsRegistry appWasOpened:expoUrl.absoluteString name:manifest.name];
|
|
@@ -300,7 +310,7 @@ NSString *fakeLauncherBundleUrl = @"embedded://EXDevLauncher/dummy";
|
|
|
300
310
|
}
|
|
301
311
|
|
|
302
312
|
if (!self->_updatesInterface) {
|
|
303
|
-
[manifestParser tryToParseManifest:^(
|
|
313
|
+
[manifestParser tryToParseManifest:^(EXManifestsManifest *manifest) {
|
|
304
314
|
if (!manifest.isUsingDeveloperTool) {
|
|
305
315
|
onError([NSError errorWithDomain:@"DevelopmentClient" code:1 userInfo:@{NSLocalizedDescriptionKey: @"expo-updates is not properly installed or integrated. In order to load published projects with this development client, follow all installation and setup instructions for both the expo-dev-client and expo-updates packages."}]);
|
|
306
316
|
return;
|
|
@@ -311,7 +321,7 @@ NSString *fakeLauncherBundleUrl = @"embedded://EXDevLauncher/dummy";
|
|
|
311
321
|
}
|
|
312
322
|
|
|
313
323
|
[self->_updatesInterface fetchUpdateWithConfiguration:updatesConfiguration onManifest:^BOOL(NSDictionary *manifest) {
|
|
314
|
-
|
|
324
|
+
EXManifestsManifest *devLauncherManifest = [EXManifestsManifestFactory manifestForManifestJSON:manifest];
|
|
315
325
|
if (devLauncherManifest.isUsingDeveloperTool) {
|
|
316
326
|
// launch right away rather than continuing to load through EXUpdates
|
|
317
327
|
launchExpoApp([NSURL URLWithString:devLauncherManifest.bundleUrl], devLauncherManifest);
|
|
@@ -322,18 +332,18 @@ NSString *fakeLauncherBundleUrl = @"embedded://EXDevLauncher/dummy";
|
|
|
322
332
|
// do nothing for now
|
|
323
333
|
} success:^(NSDictionary * _Nullable manifest) {
|
|
324
334
|
if (manifest) {
|
|
325
|
-
launchExpoApp(self->_updatesInterface.launchAssetURL, [
|
|
335
|
+
launchExpoApp(self->_updatesInterface.launchAssetURL, [EXManifestsManifestFactory manifestForManifestJSON:manifest]);
|
|
326
336
|
}
|
|
327
337
|
} error:onError];
|
|
328
338
|
} onError:onError];
|
|
329
339
|
}
|
|
330
340
|
|
|
331
|
-
- (void)_initAppWithUrl:(NSURL *)appUrl bundleUrl:(NSURL *)bundleUrl manifest:(
|
|
341
|
+
- (void)_initAppWithUrl:(NSURL *)appUrl bundleUrl:(NSURL *)bundleUrl manifest:(EXManifestsManifest * _Nullable)manifest
|
|
332
342
|
{
|
|
333
343
|
self.manifest = manifest;
|
|
334
344
|
self.manifestURL = appUrl;
|
|
335
|
-
__block UIInterfaceOrientation orientation = manifest.orientation;
|
|
336
|
-
__block UIColor *backgroundColor = manifest.
|
|
345
|
+
__block UIInterfaceOrientation orientation = [EXDevLauncherManifestHelper exportManifestOrientation:manifest.orientation];
|
|
346
|
+
__block UIColor *backgroundColor = [EXDevLauncherManifestHelper hexStringToColor:manifest.iosOrRootBackgroundColor];
|
|
337
347
|
|
|
338
348
|
__weak __typeof(self) weakSelf = self;
|
|
339
349
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
@@ -350,14 +360,15 @@ NSString *fakeLauncherBundleUrl = @"embedded://EXDevLauncher/dummy";
|
|
|
350
360
|
#endif
|
|
351
361
|
|
|
352
362
|
if (@available(iOS 12, *)) {
|
|
353
|
-
[
|
|
363
|
+
UIUserInterfaceStyle userInterfaceStyle = [EXDevLauncherManifestHelper exportManifestUserInterfaceStyle:manifest.userInterfaceStyle];
|
|
364
|
+
[self _applyUserInterfaceStyle:userInterfaceStyle];
|
|
354
365
|
|
|
355
366
|
// Fix for the community react-native-appearance.
|
|
356
367
|
// RNC appearance checks the global trait collection and doesn't have another way to override the user interface.
|
|
357
368
|
// So we swap `currentTraitCollection` with one from the root view controller.
|
|
358
369
|
// Note that the root view controller will have the correct value of `userInterfaceStyle`.
|
|
359
370
|
if (@available(iOS 13.0, *)) {
|
|
360
|
-
if (
|
|
371
|
+
if (userInterfaceStyle != UIUserInterfaceStyleUnspecified) {
|
|
361
372
|
UITraitCollection.currentTraitCollection = [self.window.rootViewController.traitCollection copy];
|
|
362
373
|
}
|
|
363
374
|
}
|
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
#import "EXDevLauncherController.h"
|
|
4
4
|
#import <React/RCTBridge.h>
|
|
5
5
|
|
|
6
|
+
#if __has_include(<EXDevLauncher/EXDevLauncher-Swift.h>)
|
|
7
|
+
// For cocoapods framework, the generated swift header will be inside EXDevLauncher module
|
|
8
|
+
#import <EXDevLauncher/EXDevLauncher-Swift.h>
|
|
9
|
+
#else
|
|
6
10
|
#import <EXDevLauncher-Swift.h>
|
|
11
|
+
#endif
|
|
7
12
|
|
|
8
13
|
NSString *ON_NEW_DEEP_LINK_EVENT = @"expo.modules.devlauncher.onnewdeeplink";
|
|
9
14
|
|
|
@@ -48,10 +48,10 @@ private class AppDelegate : DevMenuDelegateProtocol {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
return [
|
|
51
|
-
"appName": manifest.name,
|
|
52
|
-
"appVersion": manifest.version,
|
|
51
|
+
"appName": manifest.name(),
|
|
52
|
+
"appVersion": manifest.version(),
|
|
53
53
|
"appIcon": NSNull(),
|
|
54
|
-
"hostUrl": manifest.bundleUrl,
|
|
54
|
+
"hostUrl": manifest.bundleUrl(),
|
|
55
55
|
]
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
#import "EXDevLauncherRedBox.h"
|
|
6
6
|
#import "EXDevLauncherController.h"
|
|
7
7
|
|
|
8
|
+
#if __has_include(<EXDevLauncher/EXDevLauncher-Swift.h>)
|
|
9
|
+
// For cocoapods framework, the generated swift header will be inside EXDevLauncher module
|
|
10
|
+
#import <EXDevLauncher/EXDevLauncher-Swift.h>
|
|
11
|
+
#else
|
|
8
12
|
#import <EXDevLauncher-Swift.h>
|
|
13
|
+
#endif
|
|
9
14
|
|
|
10
15
|
@interface EXDevLauncherRedBox ()
|
|
11
16
|
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import UIKit
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
class EXDevLauncherManifestHelper {
|
|
5
|
+
@objc
|
|
6
|
+
public class EXDevLauncherManifestHelper: NSObject {
|
|
7
7
|
private static func defaultOrientationForOrientationMask(_ orientationMask: UIInterfaceOrientationMask) -> UIInterfaceOrientation {
|
|
8
8
|
if orientationMask.contains(.portrait) {
|
|
9
9
|
return UIInterfaceOrientation.portrait
|
|
@@ -17,19 +17,21 @@ class EXDevLauncherManifestHelper {
|
|
|
17
17
|
|
|
18
18
|
return UIInterfaceOrientation.unknown
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
|
|
21
|
+
@objc
|
|
22
|
+
public static func exportManifestOrientation(_ orientation: String?) -> UIInterfaceOrientation {
|
|
22
23
|
var orientationMask = UIInterfaceOrientationMask.all
|
|
23
|
-
if orientation ==
|
|
24
|
+
if orientation == "portrait" {
|
|
24
25
|
orientationMask = .portrait
|
|
25
|
-
} else if orientation ==
|
|
26
|
+
} else if orientation == "landscape" {
|
|
26
27
|
orientationMask = .landscape
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
return defaultOrientationForOrientationMask(orientationMask)
|
|
30
31
|
}
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
|
|
33
|
+
@objc
|
|
34
|
+
public static func hexStringToColor(_ hexString: String?) -> UIColor? {
|
|
33
35
|
guard var hexString = hexString else {
|
|
34
36
|
return nil
|
|
35
37
|
}
|
|
@@ -48,13 +50,14 @@ class EXDevLauncherManifestHelper {
|
|
|
48
50
|
blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
|
|
49
51
|
alpha: 1.0)
|
|
50
52
|
}
|
|
51
|
-
|
|
53
|
+
|
|
54
|
+
@objc
|
|
52
55
|
@available(iOS 12.0, *)
|
|
53
|
-
static func exportManifestUserInterfaceStyle(_ userInterfaceStyle:
|
|
56
|
+
public static func exportManifestUserInterfaceStyle(_ userInterfaceStyle: String?) -> UIUserInterfaceStyle {
|
|
54
57
|
switch (userInterfaceStyle){
|
|
55
|
-
case
|
|
58
|
+
case "light":
|
|
56
59
|
return .light
|
|
57
|
-
case
|
|
60
|
+
case "dark":
|
|
58
61
|
return .dark
|
|
59
62
|
default:
|
|
60
63
|
return .unspecified
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
#import <EXManifests/EXManifestsManifest.h>
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
6
|
|
|
7
7
|
typedef void (^IsManifestURL)(BOOL isManifestURL);
|
|
8
|
-
typedef void (^OnManifestParsed)(
|
|
8
|
+
typedef void (^OnManifestParsed)(EXManifestsManifest *manifest);
|
|
9
9
|
typedef void (^OnManifestError)(NSError *error);
|
|
10
10
|
|
|
11
11
|
@interface EXDevLauncherManifestParser : NSObject
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
3
|
#import "EXDevLauncherManifestParser.h"
|
|
4
|
+
#if __has_include(<EXDevLauncher/EXDevLauncher-Swift.h>)
|
|
5
|
+
// For cocoapods framework, the generated swift header will be inside EXDevLauncher module
|
|
6
|
+
#import <EXDevLauncher/EXDevLauncher-Swift.h>
|
|
7
|
+
#else
|
|
4
8
|
#import <EXDevLauncher-Swift.h>
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
#import <EXManifests/EXManifestsManifestFactory.h>
|
|
5
12
|
|
|
6
13
|
typedef void (^CompletionHandler)(NSData *data, NSURLResponse *response);
|
|
7
14
|
|
|
@@ -63,13 +70,18 @@ typedef void (^CompletionHandler)(NSData *data, NSURLResponse *response);
|
|
|
63
70
|
return;
|
|
64
71
|
}
|
|
65
72
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
NSError *error;
|
|
74
|
+
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
|
|
75
|
+
if (!jsonObject) {
|
|
76
|
+
NSMutableDictionary *details = [NSMutableDictionary dictionary];
|
|
77
|
+
details[NSLocalizedDescriptionKey] = [NSString stringWithFormat:@"Couldn't parse the manifest. %@", (error ? error.localizedDescription : @"")];
|
|
78
|
+
if (error) {
|
|
79
|
+
details[NSUnderlyingErrorKey] = error;
|
|
80
|
+
}
|
|
81
|
+
onError([[NSError alloc] initWithDomain:@"DevelopmentClient" code:1 userInfo:details]);
|
|
71
82
|
return;
|
|
72
83
|
}
|
|
84
|
+
EXManifestsManifest *manifest = [EXManifestsManifestFactory manifestForManifestJSON:jsonObject];
|
|
73
85
|
onParsed(manifest);
|
|
74
86
|
}];
|
|
75
87
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Copyright 2021-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import XCTest
|
|
4
|
+
|
|
5
|
+
@testable import EXDevLauncher
|
|
6
|
+
|
|
7
|
+
class EXDevLauncherManifestHelperTests: XCTestCase {
|
|
8
|
+
func testExportManifestOrientation() {
|
|
9
|
+
XCTAssertEqual(UIInterfaceOrientation.portrait, EXDevLauncherManifestHelper.exportManifestOrientation("portrait"))
|
|
10
|
+
XCTAssertEqual(UIInterfaceOrientation.landscapeLeft, EXDevLauncherManifestHelper.exportManifestOrientation("landscape"))
|
|
11
|
+
XCTAssertEqual(UIInterfaceOrientation.portrait, EXDevLauncherManifestHelper.exportManifestOrientation("default"))
|
|
12
|
+
XCTAssertEqual(UIInterfaceOrientation.portrait, EXDevLauncherManifestHelper.exportManifestOrientation("unsupported-value"))
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
func testExportManifestUserInterfaceStyle() {
|
|
16
|
+
XCTAssertEqual(UIUserInterfaceStyle.light, EXDevLauncherManifestHelper.exportManifestUserInterfaceStyle("light"))
|
|
17
|
+
XCTAssertEqual(UIUserInterfaceStyle.dark, EXDevLauncherManifestHelper.exportManifestUserInterfaceStyle("dark"))
|
|
18
|
+
XCTAssertEqual(UIUserInterfaceStyle.unspecified, EXDevLauncherManifestHelper.exportManifestUserInterfaceStyle("automatic"))
|
|
19
|
+
XCTAssertEqual(UIUserInterfaceStyle.unspecified, EXDevLauncherManifestHelper.exportManifestUserInterfaceStyle("unsupported-value"))
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
func testHexStringToColor() {
|
|
23
|
+
XCTAssertEqual(UIColor.init(red: 192.0/255.0, green: 1.0, blue: 51.0/255.0, alpha: 1.0), EXDevLauncherManifestHelper.hexStringToColor("#c0ff33"))
|
|
24
|
+
XCTAssertEqual(UIColor.init(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0), EXDevLauncherManifestHelper.hexStringToColor("#000000"))
|
|
25
|
+
XCTAssertNil(EXDevLauncherManifestHelper.hexStringToColor("#000000FF")) // alpha values are not supported
|
|
26
|
+
XCTAssertNil(EXDevLauncherManifestHelper.hexStringToColor("000000"))
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#import <OHHTTPStubs/HTTPStubs.h>
|
|
5
5
|
|
|
6
6
|
#import <EXDevLauncher/EXDevLauncherManifestParser.h>
|
|
7
|
+
#import <EXManifests/EXManifestsManifest.h>
|
|
7
8
|
|
|
8
9
|
@interface EXDevLauncherManifestParserTests : XCTestCase
|
|
9
10
|
|
|
@@ -116,4 +117,116 @@
|
|
|
116
117
|
[self waitForExpectationsWithTimeout:5 handler:nil];
|
|
117
118
|
}
|
|
118
119
|
|
|
120
|
+
- (void)testParseManifest
|
|
121
|
+
{
|
|
122
|
+
[HTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
|
|
123
|
+
return [request.URL.host isEqualToString:@"ohhttpstubs"];
|
|
124
|
+
} withStubResponse:^HTTPStubsResponse * _Nonnull(NSURLRequest * _Nonnull request) {
|
|
125
|
+
NSString *manifestString = @"{\"name\":\"testproject\",\"slug\":\"testproject\",\"version\":\"1.0.0\",\"orientation\":\"portrait\",\"userInterfaceStyle\":\"light\",\"backgroundColor\":\"#c0ff33\",\"sdkVersion\":\"42.0.0\",\"bundleUrl\":\"http://test.io/bundle.js\"}";
|
|
126
|
+
NSData *jsonData = [manifestString dataUsingEncoding:NSUTF8StringEncoding];
|
|
127
|
+
return [HTTPStubsResponse responseWithData:jsonData statusCode:200 headers:nil];
|
|
128
|
+
}];
|
|
129
|
+
|
|
130
|
+
NSURL *url = [NSURL URLWithString:@"http://ohhttpstubs"];
|
|
131
|
+
EXDevLauncherManifestParser *parser = [[EXDevLauncherManifestParser alloc] initWithURL:url session:NSURLSession.sharedSession];
|
|
132
|
+
|
|
133
|
+
XCTestExpectation *expectation = [self expectationWithDescription:@"should parse manifest successfully"];
|
|
134
|
+
|
|
135
|
+
[parser tryToParseManifest:^(EXManifestsManifest * _Nonnull manifest) {
|
|
136
|
+
XCTAssertEqualObjects(@"testproject", manifest.name);
|
|
137
|
+
XCTAssertEqualObjects(@"testproject", manifest.slug);
|
|
138
|
+
XCTAssertEqualObjects(@"1.0.0", manifest.version);
|
|
139
|
+
XCTAssertEqualObjects(@"portrait", manifest.orientation);
|
|
140
|
+
XCTAssertEqualObjects(@"light", manifest.userInterfaceStyle);
|
|
141
|
+
XCTAssertEqualObjects(@"#c0ff33", manifest.iosOrRootBackgroundColor);
|
|
142
|
+
XCTAssertEqualObjects(@"http://test.io/bundle.js", manifest.bundleUrl);
|
|
143
|
+
XCTAssertFalse(manifest.isUsingDeveloperTool);
|
|
144
|
+
[expectation fulfill];
|
|
145
|
+
} onError:^(NSError * _Nonnull error) {
|
|
146
|
+
XCTFail(@"Response should have been successful");
|
|
147
|
+
[expectation fulfill];
|
|
148
|
+
}];
|
|
149
|
+
|
|
150
|
+
[self waitForExpectationsWithTimeout:5 handler:nil];
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
- (void)testParseManifest_PlatformSpecificValues
|
|
154
|
+
{
|
|
155
|
+
[HTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
|
|
156
|
+
return [request.URL.host isEqualToString:@"ohhttpstubs"];
|
|
157
|
+
} withStubResponse:^HTTPStubsResponse * _Nonnull(NSURLRequest * _Nonnull request) {
|
|
158
|
+
NSString *manifestString = @"{\"name\":\"testproject\",\"slug\":\"testproject\",\"version\":\"1.0.0\",\"orientation\":\"portrait\",\"userInterfaceStyle\":\"light\",\"backgroundColor\":\"#c0ff33\",\"sdkVersion\":\"42.0.0\",\"bundleUrl\":\"http://test.io/bundle.js\",\"ios\":{\"userInterfaceStyle\":\"dark\",\"backgroundColor\":\"#e41c00\"}}";
|
|
159
|
+
NSData *jsonData = [manifestString dataUsingEncoding:NSUTF8StringEncoding];
|
|
160
|
+
return [HTTPStubsResponse responseWithData:jsonData statusCode:200 headers:nil];
|
|
161
|
+
}];
|
|
162
|
+
|
|
163
|
+
NSURL *url = [NSURL URLWithString:@"http://ohhttpstubs"];
|
|
164
|
+
EXDevLauncherManifestParser *parser = [[EXDevLauncherManifestParser alloc] initWithURL:url session:NSURLSession.sharedSession];
|
|
165
|
+
|
|
166
|
+
XCTestExpectation *expectation = [self expectationWithDescription:@"should parse manifest successfully"];
|
|
167
|
+
|
|
168
|
+
[parser tryToParseManifest:^(EXManifestsManifest * _Nonnull manifest) {
|
|
169
|
+
XCTAssertEqualObjects(@"dark", manifest.userInterfaceStyle);
|
|
170
|
+
XCTAssertEqualObjects(@"#e41c00", manifest.iosOrRootBackgroundColor);
|
|
171
|
+
[expectation fulfill];
|
|
172
|
+
} onError:^(NSError * _Nonnull error) {
|
|
173
|
+
XCTFail(@"Response should have been successful");
|
|
174
|
+
[expectation fulfill];
|
|
175
|
+
}];
|
|
176
|
+
|
|
177
|
+
[self waitForExpectationsWithTimeout:5 handler:nil];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
- (void)testParseManifest_DeveloperTool
|
|
181
|
+
{
|
|
182
|
+
[HTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
|
|
183
|
+
return [request.URL.host isEqualToString:@"ohhttpstubs"];
|
|
184
|
+
} withStubResponse:^HTTPStubsResponse * _Nonnull(NSURLRequest * _Nonnull request) {
|
|
185
|
+
NSString *manifestString = @"{\"name\":\"testproject\",\"slug\":\"testproject\",\"version\":\"1.0.0\",\"orientation\":\"portrait\",\"userInterfaceStyle\": \"light\",\"backgroundColor\": \"#c0ff33\",\"sdkVersion\":\"42.0.0\",\"bundleUrl\":\"http://test.io/bundle.js\",\"developer\":{\"tool\":\"expo-cli\"}}";
|
|
186
|
+
NSData *jsonData = [manifestString dataUsingEncoding:NSUTF8StringEncoding];
|
|
187
|
+
return [HTTPStubsResponse responseWithData:jsonData statusCode:200 headers:nil];
|
|
188
|
+
}];
|
|
189
|
+
|
|
190
|
+
NSURL *url = [NSURL URLWithString:@"http://ohhttpstubs"];
|
|
191
|
+
EXDevLauncherManifestParser *parser = [[EXDevLauncherManifestParser alloc] initWithURL:url session:NSURLSession.sharedSession];
|
|
192
|
+
|
|
193
|
+
XCTestExpectation *expectation = [self expectationWithDescription:@"should parse manifest successfully"];
|
|
194
|
+
|
|
195
|
+
[parser tryToParseManifest:^(EXManifestsManifest * _Nonnull manifest) {
|
|
196
|
+
XCTAssertTrue(manifest.isUsingDeveloperTool);
|
|
197
|
+
[expectation fulfill];
|
|
198
|
+
} onError:^(NSError * _Nonnull error) {
|
|
199
|
+
XCTFail(@"Response should have been successful");
|
|
200
|
+
[expectation fulfill];
|
|
201
|
+
}];
|
|
202
|
+
|
|
203
|
+
[self waitForExpectationsWithTimeout:5 handler:nil];
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
- (void)testParseManifest_InvalidJson
|
|
207
|
+
{
|
|
208
|
+
[HTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest * _Nonnull request) {
|
|
209
|
+
return [request.URL.host isEqualToString:@"ohhttpstubs"];
|
|
210
|
+
} withStubResponse:^HTTPStubsResponse * _Nonnull(NSURLRequest * _Nonnull request) {
|
|
211
|
+
NSString *manifestString = @"{invalid json}";
|
|
212
|
+
NSData *jsonData = [manifestString dataUsingEncoding:NSUTF8StringEncoding];
|
|
213
|
+
return [HTTPStubsResponse responseWithData:jsonData statusCode:200 headers:nil];
|
|
214
|
+
}];
|
|
215
|
+
|
|
216
|
+
NSURL *url = [NSURL URLWithString:@"http://ohhttpstubs"];
|
|
217
|
+
EXDevLauncherManifestParser *parser = [[EXDevLauncherManifestParser alloc] initWithURL:url session:NSURLSession.sharedSession];
|
|
218
|
+
|
|
219
|
+
XCTestExpectation *expectation = [self expectationWithDescription:@"should fail to parse manifest"];
|
|
220
|
+
|
|
221
|
+
[parser tryToParseManifest:^(EXManifestsManifest * _Nonnull manifest) {
|
|
222
|
+
XCTFail(@"Parsing bad JSON should not have been successful");
|
|
223
|
+
[expectation fulfill];
|
|
224
|
+
} onError:^(NSError * _Nonnull error) {
|
|
225
|
+
XCTAssertNotNil(error);
|
|
226
|
+
[expectation fulfill];
|
|
227
|
+
}];
|
|
228
|
+
|
|
229
|
+
[self waitForExpectationsWithTimeout:5 handler:nil];
|
|
230
|
+
}
|
|
231
|
+
|
|
119
232
|
@end
|
|
@@ -5,15 +5,29 @@
|
|
|
5
5
|
#import <objc/runtime.h>
|
|
6
6
|
#import <EXDevLauncher/EXDevLauncher.h>
|
|
7
7
|
#import <EXDevLauncher/EXDevLauncherController.h>
|
|
8
|
+
#import <EXManifests/EXManifestsManifest.h>
|
|
9
|
+
#import <EXManifests/EXManifestsManifestFactory.h>
|
|
8
10
|
|
|
9
11
|
@interface EXDevLauncherController (EXDevLauncherModuleTests)
|
|
10
12
|
|
|
13
|
+
- (EXManifestsManifest * _Nullable)mockAppManifest;
|
|
11
14
|
- (NSURL *)mockAppManifestURL;
|
|
12
15
|
|
|
13
16
|
@end
|
|
14
17
|
|
|
15
18
|
@implementation EXDevLauncherController (EXDevLauncherModuleTests)
|
|
16
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
|
+
|
|
17
31
|
- (NSURL *)mockAppManifestURL
|
|
18
32
|
{
|
|
19
33
|
return [NSURL URLWithString:@"https://exp.host/@test/test?query=param"];
|
|
@@ -51,6 +65,31 @@
|
|
|
51
65
|
}
|
|
52
66
|
}
|
|
53
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
|
+
|
|
54
93
|
- (void)testConstantsToExportManifestURL
|
|
55
94
|
{
|
|
56
95
|
// used by snack
|
|
Binary file
|