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(); -};