From 7a79ac8803d4304d2804424edbbcd29b6d64a0de Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Thu, 15 Oct 2015 03:12:28 -0700 Subject: [PATCH] Make Xcode tests run in React environment The deleteTestFiles() function is now added to the Realm object, so that it's easy for the RPC module to handle this as well. We can only do this in testing environments in the future. --- ReactNative/RealmReact.h | 2 +- ReactNative/RealmReact.m | 1 - lib/realm.js | 6 +++++ lib/rpc.js | 8 ++++++- src/RJSUtil.mm | 5 ++-- src/RealmJS.h | 2 +- src/RealmJS.mm | 18 +++++++++----- src/RealmRPC.mm | 4 ++++ tests/ReactTests/index.ios.js | 5 ---- .../ios/ReactTests.xcodeproj/project.pbxproj | 17 +++++-------- .../xcschemes/ReactTests.xcscheme | 2 +- tests/ReactTests/ios/ReactTests/Info.plist | 17 +++++++------ .../ReactTests/ios/ReactTestsTests/Info.plist | 2 +- .../ios/ReactTestsTests/RealmReactTests.m | 24 +++++++++---------- tests/RealmJSTests.h | 3 --- tests/base-test.js | 9 +++++-- tests/index.js | 4 ---- tests/util.js | 6 ----- 18 files changed, 69 insertions(+), 66 deletions(-) diff --git a/ReactNative/RealmReact.h b/ReactNative/RealmReact.h index 91874a16..481b9fa2 100644 --- a/ReactNative/RealmReact.h +++ b/ReactNative/RealmReact.h @@ -20,7 +20,7 @@ @interface RealmReact : NSObject -@property (nonatomic) id executor; +@property (nonatomic, readonly) id executor; + (id)executor; diff --git a/ReactNative/RealmReact.m b/ReactNative/RealmReact.m index c05526a6..286fc017 100644 --- a/ReactNative/RealmReact.m +++ b/ReactNative/RealmReact.m @@ -37,7 +37,6 @@ static id s_executor; @implementation RealmReact -@dynamic executor; @synthesize bridge = _bridge; + (void)load { diff --git a/lib/realm.js b/lib/realm.js index 80a461b2..3110ec0a 100644 --- a/lib/realm.js +++ b/lib/realm.js @@ -83,4 +83,10 @@ class Realm { Object.defineProperty(Realm, 'Types', {value: types}); +Object.defineProperty(Realm, 'deleteTestFiles', { + value: function() { + rpc.deleteTestFiles(); + } +}); + module.exports = Realm; diff --git a/lib/rpc.js b/lib/rpc.js index f9af5650..89c13ab6 100644 --- a/lib/rpc.js +++ b/lib/rpc.js @@ -37,6 +37,8 @@ exports.beginTransaction = beginTransaction; exports.cancelTransaction = cancelTransaction; exports.commitTransaction = commitTransaction; +exports.deleteTestFiles = deleteTestFiles; + function registerTypeConverter(type, handler) { typeConverters[type] = handler; } @@ -111,6 +113,10 @@ function commitTransaction(realmId) { sendRequest('commit_transaction', {realmId}); } +function deleteTestFiles() { + sendRequest('delete_test_files'); +} + function serialize(realmId, value) { if (!value || typeof value != 'object') { return {value: value}; @@ -153,7 +159,7 @@ function deserialize(realmId, info) { } function sendRequest(command, data) { - let body = JSON.stringify(data); + let body = JSON.stringify(data || {}); let request = new XMLHttpRequest(); let url = 'http://' + DEVICE_HOST + '/' + command; diff --git a/src/RJSUtil.mm b/src/RJSUtil.mm index b8603dd8..e64dd061 100644 --- a/src/RJSUtil.mm +++ b/src/RJSUtil.mm @@ -20,10 +20,11 @@ using namespace realm; -JSObjectRef RJSRegisterGlobalClass(JSContextRef ctx, JSObjectRef globalObject, JSClassRef classRef, const char * name, JSValueRef *exception) { +JSObjectRef RJSRegisterGlobalClass(JSContextRef ctx, JSObjectRef globalObject, JSClassRef classRef, const char *name, JSValueRef *exception) { JSObjectRef classObject = JSObjectMake(ctx, classRef, NULL); JSStringRef nameString = JSStringCreateWithUTF8CString(name); - JSObjectSetProperty(ctx, globalObject, nameString, classObject, kJSPropertyAttributeNone, exception); + JSPropertyAttributes attributes = kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete; + JSObjectSetProperty(ctx, globalObject, nameString, classObject, attributes, exception); JSStringRelease(nameString); return classObject; } diff --git a/src/RealmJS.h b/src/RealmJS.h index 54e1476e..f10133ff 100644 --- a/src/RealmJS.h +++ b/src/RealmJS.h @@ -25,6 +25,6 @@ // add realm apis to the given js context + (void)initializeContext:(JSContextRef)ctx; -+ (void)cleanupTestRealms; ++ (void)deleteTestFiles; @end diff --git a/src/RealmJS.mm b/src/RealmJS.mm index 6bbf9366..246d11d6 100644 --- a/src/RealmJS.mm +++ b/src/RealmJS.mm @@ -46,7 +46,6 @@ JSClassRef RJSRealmTypeClass() { return JSClassCreate(&realmTypesDefinition); } - NSString *RealmPathForFile(NSString *fileName) { #if TARGET_OS_IPHONE NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; @@ -74,6 +73,11 @@ static void DeleteRealmFilesAtPath(NSString *path) { DeleteOrThrow([path stringByAppendingString:@".note"]); } +static JSValueRef DeleteTestFiles(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) { + [RealmJS deleteTestFiles]; + return NULL; +} + @implementation RealmJS + (void)initializeContext:(JSContextRef)ctx { @@ -83,17 +87,19 @@ static void DeleteRealmFilesAtPath(NSString *path) { JSObjectRef globalRealmObject = RJSRegisterGlobalClass(ctx, globalObject, RJSRealmConstructorClass(), "Realm", &exception); JSObjectRef typesObject = JSObjectMake(ctx, RJSRealmTypeClass(), NULL); JSStringRef typeString = JSStringCreateWithUTF8CString("Types"); - JSObjectSetProperty(ctx, globalRealmObject, typeString, typesObject, kJSPropertyAttributeNone, &exception); + JSPropertyAttributes attributes = kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete; + JSObjectSetProperty(ctx, globalRealmObject, typeString, typesObject, attributes, &exception); JSStringRelease(typeString); - [JSContext contextWithJSGlobalContextRef:JSContextGetGlobalContext(ctx)][@"cleanupTestRealms"] = ^{ - [RealmJS cleanupTestRealms]; - }; + JSStringRef deleteTestFilesString = JSStringCreateWithUTF8CString("deleteTestFiles"); + JSObjectRef deleteTestFilesFunction = JSObjectMakeFunctionWithCallback(ctx, deleteTestFilesString, DeleteTestFiles); + JSObjectSetProperty(ctx, globalRealmObject, deleteTestFilesString, deleteTestFilesFunction, attributes, &exception); + JSStringRelease(deleteTestFilesString); assert(!exception); } -+ (void)cleanupTestRealms { ++ (void)deleteTestFiles { realm::Realm::s_global_cache.invalidate_all(); realm::Realm::s_global_cache.clear(); diff --git a/src/RealmRPC.mm b/src/RealmRPC.mm index 7f2fdf9a..531e5f06 100644 --- a/src/RealmRPC.mm +++ b/src/RealmRPC.mm @@ -179,6 +179,10 @@ using RPCRequest = std::function; args:dict[@"arguments"] objectId:[dict[@"listId"] unsignedLongValue]]; }; + _requests["/delete_test_files"] = [=](NSDictionary *dict) { + [RealmJS deleteTestFiles]; + return nil; + }; } return self; } diff --git a/tests/ReactTests/index.ios.js b/tests/ReactTests/index.ios.js index 1396ab32..39316ad2 100644 --- a/tests/ReactTests/index.ios.js +++ b/tests/ReactTests/index.ios.js @@ -21,10 +21,6 @@ function runTests() { for (let suiteName in RealmTests) { let testSuite = RealmTests[suiteName]; - if (typeof testSuite != 'object') { - continue; - } - console.log('Starting suite:', suiteName); for (let testName in testSuite) { @@ -32,7 +28,6 @@ function runTests() { continue; } - if (testSuite.beforeEach) { testSuite.beforeEach(); } diff --git a/tests/ReactTests/ios/ReactTests.xcodeproj/project.pbxproj b/tests/ReactTests/ios/ReactTests.xcodeproj/project.pbxproj index 7cb351fc..b979c4e1 100644 --- a/tests/ReactTests/ios/ReactTests.xcodeproj/project.pbxproj +++ b/tests/ReactTests/ios/ReactTests.xcodeproj/project.pbxproj @@ -448,7 +448,7 @@ 83CBB9F71A601CBA00E9B192 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0610; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = Facebook; TargetAttributes = { 00E356ED1AD99517003FC87E = { @@ -724,6 +724,7 @@ INFOPLIST_FILE = ReactTestsTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReactTests.app/ReactTests"; }; @@ -741,6 +742,7 @@ INFOPLIST_FILE = ReactTestsTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.2; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReactTests.app/ReactTests"; }; @@ -750,14 +752,10 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../node_modules/react-native/React/**", - ); INFOPLIST_FILE = ReactTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = ReactTests; }; name = Debug; @@ -766,14 +764,10 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, - "$(SRCROOT)/../node_modules/react-native/React/**", - ); INFOPLIST_FILE = ReactTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = ReactTests; }; name = Release; @@ -798,6 +792,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; diff --git a/tests/ReactTests/ios/ReactTests.xcodeproj/xcshareddata/xcschemes/ReactTests.xcscheme b/tests/ReactTests/ios/ReactTests.xcodeproj/xcshareddata/xcschemes/ReactTests.xcscheme index 74ba8c85..00978f6d 100644 --- a/tests/ReactTests/ios/ReactTests.xcodeproj/xcshareddata/xcschemes/ReactTests.xcscheme +++ b/tests/ReactTests/ios/ReactTests.xcodeproj/xcshareddata/xcschemes/ReactTests.xcscheme @@ -1,6 +1,6 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -22,6 +22,13 @@ 1 LSRequiresIPhoneOS + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSLocationWhenInUseUsageDescription + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities @@ -36,13 +43,5 @@ UIViewControllerBasedStatusBarAppearance - NSLocationWhenInUseUsageDescription - - NSAppTransportSecurity - - - NSAllowsArbitraryLoads - - diff --git a/tests/ReactTests/ios/ReactTestsTests/Info.plist b/tests/ReactTests/ios/ReactTestsTests/Info.plist index 886825cc..ba72822e 100644 --- a/tests/ReactTests/ios/ReactTestsTests/Info.plist +++ b/tests/ReactTests/ios/ReactTestsTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/tests/ReactTests/ios/ReactTestsTests/RealmReactTests.m b/tests/ReactTests/ios/ReactTestsTests/RealmReactTests.m index 01899f69..306ee4d0 100644 --- a/tests/ReactTests/ios/ReactTestsTests/RealmReactTests.m +++ b/tests/ReactTests/ios/ReactTestsTests/RealmReactTests.m @@ -8,8 +8,8 @@ */ #import "RealmJSTests.h" -#import "../../node_modules/react-native/React/Base/RCTJavaScriptExecutor.h" -#import "../../node_modules/react-native/React/Base/RCTBridge.h" +#import "Base/RCTJavaScriptExecutor.h" +#import "Base/RCTBridge.h" @import RealmReact; @@ -26,24 +26,24 @@ - (void)invokeMethod:(NSString *)method { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - [self expectationForNotification:RCTJavaScriptDidLoadNotification object:nil handler:^BOOL(NSNotification * _Nonnull notification) { - return YES; - }]; - [self waitForExpectationsWithTimeout:10000000 handler:^(NSError * _Nullable error) { + [self expectationForNotification:RCTJavaScriptDidLoadNotification object:nil handler:^(NSNotification *notification) { + return YES; }]; + [self waitForExpectationsWithTimeout:10000000 handler:NULL]; }); dispatch_group_t group = dispatch_group_create(); dispatch_group_enter(group); id executor = [RealmReact executor]; - [executor executeBlockOnJavaScriptQueue:^{ - [executor executeJSCall:@"realm-tests" method:@"executeTest" arguments:@[NSStringFromClass(self.class), method] callback:^(id json, NSError *error) { - XCTAssertNil(error, @"%@", [error description]); - dispatch_group_leave(group); - }]; - dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + NSString *module = [NSString stringWithFormat:@"realm-tests/%@.js", NSStringFromClass(self.class)]; + + [executor executeJSCall:module method:method arguments:@[] callback:^(id json, NSError *error) { + XCTAssertNil(error, @"%@", [error description]); + dispatch_group_leave(group); }]; + + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); } @end diff --git a/tests/RealmJSTests.h b/tests/RealmJSTests.h index 4ff55c4f..6498d9b0 100644 --- a/tests/RealmJSTests.h +++ b/tests/RealmJSTests.h @@ -19,9 +19,6 @@ #import #import -extern NSString *RealmPathForFile(NSString *fileName); -extern NSString *TestRealmPath(); - @interface RealmJSTests : XCTestCase @end diff --git a/tests/base-test.js b/tests/base-test.js index a7ad8aaa..99e382d9 100644 --- a/tests/base-test.js +++ b/tests/base-test.js @@ -18,7 +18,7 @@ 'use strict'; -var util = require('./util'); +var Realm = require('realm'); var prototype = exports.prototype = {}; @@ -28,9 +28,14 @@ exports.extend = function(object) { }; Object.defineProperties(prototype, { + // TODO: Remove once missing undefined check is fixed inside RCTContextExecutor. + beforeEach: { + value: function() {} + }, + afterEach: { value: function() { - util.cleanupTestRealms(); + Realm.deleteTestFiles(); } } }); diff --git a/tests/index.js b/tests/index.js index 9ea35ae3..eb2c08e9 100644 --- a/tests/index.js +++ b/tests/index.js @@ -23,7 +23,3 @@ exports.ObjectTests = require('./ObjectTests'); exports.RealmTests = require('./RealmTests'); exports.ResultsTests = require('./ResultsTests'); -exports.executeTest = function(suiteName, testName) { - var suite = exports[suiteName]; - suite[textName](); -}; diff --git a/tests/util.js b/tests/util.js index 3008d62a..6b1b1bb7 100644 --- a/tests/util.js +++ b/tests/util.js @@ -20,13 +20,7 @@ var Realm = require('realm'); -var global = (typeof global != 'undefined') ? global : this; - exports.realmPathForFile = function(str) { var path = Realm.defaultPath; return path.substring(0, path.lastIndexOf("/") + 1) + str; }; - -exports.cleanupTestRealms = function() { - global.cleanupTestRealms(); -};