1/**
2 *  This test launches the JS Expo app called `test-suite` and checks whether all the JS tests there pass.
3 *  `test-suite` runs a bunch of jasmine JS tests against the Expo SDK.
4 *  The purpose of this file is to provide a native pass/fail hook into the JS sdk tests.
5 *
6 *  To configure it, make sure this target contains a file called `EXTestEnvironment.plist`
7 *  with a key `testSuiteUrl` whose value is the url to load some version of Expo's `test-suite` app.
8 */
9
10#import "ExpoKit.h"
11#import "EXEnvironment.h"
12#import "EXKernel.h"
13#import "EXKernelLinkingManager.h"
14#import "EXRootViewController.h"
15#import "EXHomeAppManager.h"
16#import "EXTest.h"
17
18#import <React/RCTAssert.h>
19#import <React/RCTUtils.h>
20
21#import <XCTest/XCTest.h>
22
23@interface ExponentIntegrationTests : XCTestCase
24
25@property (nonatomic, strong) EXRootViewController *rootViewController;
26@property (nonatomic, strong) NSString *testSuiteUrl;
27
28@end
29
30@implementation ExponentIntegrationTests
31
32- (void)setUp
33{
34  [super setUp];
35  [self _loadConfig];
36
37  _rootViewController = (EXRootViewController *)[ExpoKit sharedInstance].rootViewController;
38  // if test environment isn't configured for a shell app, override here
39  // since clearly we're running tests
40  if ([EXEnvironment sharedEnvironment].testEnvironment == EXTestEnvironmentNone) {
41    [EXEnvironment sharedEnvironment].testEnvironment = EXTestEnvironmentLocal;
42  }
43
44  // NOTE(2018-02-20): Without giving the kernel a second to run, it never opens test-suite. With a
45  // cursory pass through the code, I didn't see the correct event to wait for. Perhaps after we
46  // implement a pure-native kernel, we'll be able to remove this shoddy delay.
47  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
48    [[EXKernel sharedInstance].serviceRegistry.linkingManager openUrl:self->_testSuiteUrl isUniversalLink:NO];
49  });
50
51}
52
53- (void)testDoesTestSuiteAppPassAllJSTests
54{
55  XCTAssert((_testSuiteUrl), @"No url configured for JS test-suite. Make sure EXTestEnvironment.plist exists and contains a url to test-suite.");
56
57  XCTestExpectation *expectation = [[XCTestExpectation alloc] initWithDescription: @"Run all JS integration tests"];
58
59  __block NSDictionary *jsTestSuiteResult = nil;
60  id<NSObject> observer = [NSNotificationCenter.defaultCenter
61                           addObserverForName:EXTestSuiteCompletedNotification
62                           object:nil
63                           queue:NSOperationQueue.currentQueue
64                           usingBlock:^(NSNotification *notification) {
65                             jsTestSuiteResult = notification.userInfo;
66                             [expectation fulfill];
67                           }];
68
69  [self waitForExpectations:@[expectation] timeout:180];
70  [NSNotificationCenter.defaultCenter removeObserver:observer];
71
72  XCTAssert((jsTestSuiteResult), @"Test suite timed out");
73  XCTAssert(([jsTestSuiteResult[@"failed"] integerValue] == 0), @"Test suite failed: %@", jsTestSuiteResult);
74}
75
76#pragma mark - internal
77
78- (void)_loadConfig
79{
80  // This plist is generated with `powertools configure-ios-test-suite-url`
81  NSString *configPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"EXTestEnvironment" ofType:@"plist"];
82  NSDictionary *testConfig = (configPath) ? [NSDictionary dictionaryWithContentsOfFile:configPath] : [NSDictionary dictionary];
83  if (testConfig) {
84    _testSuiteUrl = testConfig[@"testSuiteUrl"];
85  }
86}
87
88@end
89