diff --git a/ReactNative/RealmReact.h b/ReactNative/RealmReact.h index fa334b79..6a0b086c 100644 --- a/ReactNative/RealmReact.h +++ b/ReactNative/RealmReact.h @@ -17,6 +17,10 @@ //////////////////////////////////////////////////////////////////////////// @import Foundation; +@import JavaScriptCore; + +extern JSGlobalContextRef RealmReactGetJSGlobalContextForExecutor(id executor, bool create); @interface RealmReact : NSObject + @end diff --git a/ReactNative/RealmReact.m b/ReactNative/RealmReact.m index 57992ea8..b780b73e 100644 --- a/ReactNative/RealmReact.m +++ b/ReactNative/RealmReact.m @@ -21,7 +21,6 @@ @import GCDWebServers; @import RealmJS; -@import JavaScriptCore; @import ObjectiveC; @import Darwin; @@ -30,6 +29,28 @@ - (JSGlobalContextRef)ctx; @end +JSGlobalContextRef RealmReactGetJSGlobalContextForExecutor(id executor, bool create) { + Ivar contextIvar = class_getInstanceVariable([executor class], "_context"); + if (!contextIvar) { + return NULL; + } + + id rctJSContext = contextIvar ? object_getIvar(executor, contextIvar) : nil; + if (!rctJSContext && create) { + Class RCTJavaScriptContext = NSClassFromString(@"RCTJavaScriptContext"); + if (RCTJavaScriptContext) { + JSGlobalContextRef ctx = JSGlobalContextCreate(NULL); + rctJSContext = [[RCTJavaScriptContext alloc] initWithJSContext:ctx]; + object_setIvar(executor, contextIvar, rctJSContext); + } + else { + NSLog(@"Failed to load RCTJavaScriptContext class"); + } + } + + return [rctJSContext ctx]; +} + @interface RealmReact () @end @@ -55,12 +76,17 @@ - (void)setBridge:(RCTBridge *)bridge { _bridge = bridge; - Ivar executorIvar = class_getInstanceVariable([bridge class], "_javaScriptExecutor"); - id contextExecutor = object_getIvar(bridge, executorIvar); - Ivar contextIvar = class_getInstanceVariable([contextExecutor class], "_context"); + static GCDWebServer *s_webServer; + if (s_webServer) { + [s_webServer stop]; + [s_webServer removeAllHandlers]; + s_webServer = nil; + } // The executor could be a RCTWebSocketExecutor, in which case it won't have a JS context. - if (!contextIvar) { + Ivar executorIvar = class_getInstanceVariable([bridge class], "_javaScriptExecutor"); + id executor = object_getIvar(bridge, executorIvar); + if ([executor isMemberOfClass:NSClassFromString(@"RCTWebSocketExecutor")]) { [GCDWebServer setLogLevel:3]; GCDWebServer *webServer = [[GCDWebServer alloc] init]; RJSRPCServer *rpcServer = [[RJSRPCServer alloc] init]; @@ -72,39 +98,28 @@ NSError *error; NSData *data = [(GCDWebServerDataRequest *)request data]; NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; - if (error) { - NSLog(@"%@", error); - return [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_UnprocessableEntity underlyingError:error message:@"Invalid RPC request"]; + GCDWebServerResponse *response; + + if (error || ![json isKindOfClass:[NSDictionary class]]) { + NSLog(@"Invalid RPC request - %@", error ?: json); + response = [GCDWebServerErrorResponse responseWithClientError:kGCDWebServerHTTPStatusCode_UnprocessableEntity underlyingError:error message:@"Invalid RPC request"]; } - - GCDWebServerDataResponse *response = [GCDWebServerDataResponse responseWithJSONObject:[rpcServer performRequest:request.path args:json]]; + else { + response = [GCDWebServerDataResponse responseWithJSONObject:[rpcServer performRequest:request.path args:json]]; + } + [response setValue:@"http://localhost:8081" forAdditionalHeader:@"Access-Control-Allow-Origin"]; return response; - }]; + }]; [webServer startWithPort:8082 bonjourName:nil]; + + s_webServer = webServer; return; } - [contextExecutor executeBlockOnJavaScriptQueue:^{ - id rctJSContext = object_getIvar(contextExecutor, contextIvar); - JSGlobalContextRef ctx; - - if (rctJSContext) { - ctx = [rctJSContext ctx]; - } - else { - Class RCTJavaScriptContext = NSClassFromString(@"RCTJavaScriptContext"); - - if (RCTJavaScriptContext) { - ctx = JSGlobalContextCreate(NULL); - object_setIvar(contextExecutor, contextIvar, [[RCTJavaScriptContext alloc] initWithJSContext:ctx]); - } - else { - NSLog(@"Failed to load RCTJavaScriptContext class"); - } - } - + [executor executeBlockOnJavaScriptQueue:^{ + JSGlobalContextRef ctx = RealmReactGetJSGlobalContextForExecutor(executor, true); [RealmJS initializeContext:ctx]; }]; } diff --git a/RealmJS.xcodeproj/project.pbxproj b/RealmJS.xcodeproj/project.pbxproj index 5796f13b..e3322e7e 100644 --- a/RealmJS.xcodeproj/project.pbxproj +++ b/RealmJS.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 02258FB31BC6E2D00075F13A /* RealmRPC.h in Headers */ = {isa = PBXBuildFile; fileRef = 02258FB11BC6E2D00075F13A /* RealmRPC.h */; settings = {ATTRIBUTES = (Public, ); }; }; 02258FB41BC6E2D00075F13A /* RealmRPC.mm in Sources */ = {isa = PBXBuildFile; fileRef = 02258FB21BC6E2D00075F13A /* RealmRPC.mm */; }; + 02409DC21BCF11D6005F3B3E /* RealmJSCoreTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 02409DC11BCF11D6005F3B3E /* RealmJSCoreTests.m */; settings = {ASSET_TAGS = (); }; }; 02601F031BA0F0C4007C91FF /* external_commit_helper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02601F011BA0F0C4007C91FF /* external_commit_helper.cpp */; }; 02601F041BA0F0C4007C91FF /* external_commit_helper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 02601F021BA0F0C4007C91FF /* external_commit_helper.hpp */; }; 02601F081BA0F0CD007C91FF /* index_set.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02601F051BA0F0CD007C91FF /* index_set.cpp */; }; @@ -46,8 +47,8 @@ 0270BC821B7D020100010E03 /* RealmJSTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC7B1B7D020100010E03 /* RealmJSTests.mm */; }; 0270BC831B7D020100010E03 /* RealmTests.js in Resources */ = {isa = PBXBuildFile; fileRef = 0270BC7C1B7D020100010E03 /* RealmTests.js */; }; 0270BC841B7D020100010E03 /* ResultsTests.js in Resources */ = {isa = PBXBuildFile; fileRef = 0270BC7D1B7D020100010E03 /* ResultsTests.js */; }; - 0270BC851B7D020100010E03 /* TestCase.js in Resources */ = {isa = PBXBuildFile; fileRef = 0270BC7E1B7D020100010E03 /* TestCase.js */; }; - 0270BC861B7D020100010E03 /* TestObjects.js in Resources */ = {isa = PBXBuildFile; fileRef = 0270BC7F1B7D020100010E03 /* TestObjects.js */; }; + 0270BC851B7D020100010E03 /* asserts.js in Resources */ = {isa = PBXBuildFile; fileRef = 0270BC7E1B7D020100010E03 /* asserts.js */; }; + 0270BC861B7D020100010E03 /* schemas.js in Resources */ = {isa = PBXBuildFile; fileRef = 0270BC7F1B7D020100010E03 /* schemas.js */; }; 0270BC871B7D023200010E03 /* RealmJS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CB11AE99CEC009B348C /* RealmJS.framework */; }; 0270BCD11B7D067300010E03 /* RealmReact.m in Sources */ = {isa = PBXBuildFile; fileRef = 0270BCD01B7D067300010E03 /* RealmReact.m */; }; 02B29A311B7CF86D008A7E6B /* RealmJS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CB11AE99CEC009B348C /* RealmJS.framework */; }; @@ -58,8 +59,12 @@ 02D8D1F71B601984006DB49D /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CCD1AE99D4D009B348C /* JavaScriptCore.framework */; }; F636F6C81BCDB3570023F35C /* RealmReact.h in Headers */ = {isa = PBXBuildFile; fileRef = 0270BCCF1B7D067300010E03 /* RealmReact.h */; settings = {ATTRIBUTES = (Public, ); }; }; F64426C51BCDB1E200A81210 /* RealmJS.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 02B58CB11AE99CEC009B348C /* RealmJS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + F64E1EF11BC3510E00E0E150 /* util.js in Resources */ = {isa = PBXBuildFile; fileRef = F64E1EF01BC3510E00E0E150 /* util.js */; settings = {ASSET_TAGS = (); }; }; F67191381BCE231100AD0939 /* GCDWebServers.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 02A3C7941BC4317A00B1A7BE /* GCDWebServers.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + F68A278C1BC2722A0063D40A /* RJSModuleLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = F68A278B1BC2722A0063D40A /* RJSModuleLoader.m */; settings = {ASSET_TAGS = (); }; }; + F68A278E1BC30F0A0063D40A /* index.js in Resources */ = {isa = PBXBuildFile; fileRef = F68A278D1BC30F0A0063D40A /* index.js */; settings = {ASSET_TAGS = (); }; }; F6B3963D1BCE2430008BDC39 /* GCDWebServers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 02A3C7941BC4317A00B1A7BE /* GCDWebServers.framework */; }; + F6F405F81BCF0C1A00A1E24F /* base-test.js in Resources */ = {isa = PBXBuildFile; fileRef = F6F405F71BCF0C1A00A1E24F /* base-test.js */; settings = {ASSET_TAGS = (); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -139,6 +144,7 @@ /* Begin PBXFileReference section */ 02258FB11BC6E2D00075F13A /* RealmRPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmRPC.h; path = src/RealmRPC.h; sourceTree = ""; }; 02258FB21BC6E2D00075F13A /* RealmRPC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmRPC.mm; path = src/RealmRPC.mm; sourceTree = ""; }; + 02409DC11BCF11D6005F3B3E /* RealmJSCoreTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RealmJSCoreTests.m; path = src/RealmJSCoreTests.m; sourceTree = SOURCE_ROOT; }; 02601F011BA0F0C4007C91FF /* external_commit_helper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = external_commit_helper.cpp; path = "src/object-store/apple/external_commit_helper.cpp"; sourceTree = ""; }; 02601F021BA0F0C4007C91FF /* external_commit_helper.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = external_commit_helper.hpp; path = "src/object-store/apple/external_commit_helper.hpp"; sourceTree = ""; }; 02601F051BA0F0CD007C91FF /* index_set.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = index_set.cpp; path = "src/object-store/index_set.cpp"; sourceTree = ""; }; @@ -179,8 +185,8 @@ 0270BC7B1B7D020100010E03 /* RealmJSTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmJSTests.mm; path = tests/RealmJSTests.mm; sourceTree = SOURCE_ROOT; }; 0270BC7C1B7D020100010E03 /* RealmTests.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = RealmTests.js; path = tests/RealmTests.js; sourceTree = SOURCE_ROOT; }; 0270BC7D1B7D020100010E03 /* ResultsTests.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = ResultsTests.js; path = tests/ResultsTests.js; sourceTree = SOURCE_ROOT; }; - 0270BC7E1B7D020100010E03 /* TestCase.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = TestCase.js; path = tests/TestCase.js; sourceTree = SOURCE_ROOT; }; - 0270BC7F1B7D020100010E03 /* TestObjects.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = TestObjects.js; path = tests/TestObjects.js; sourceTree = SOURCE_ROOT; }; + 0270BC7E1B7D020100010E03 /* asserts.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = asserts.js; path = tests/asserts.js; sourceTree = SOURCE_ROOT; }; + 0270BC7F1B7D020100010E03 /* schemas.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = schemas.js; path = tests/schemas.js; sourceTree = SOURCE_ROOT; }; 0270BCCF1B7D067300010E03 /* RealmReact.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmReact.h; path = ReactNative/RealmReact.h; sourceTree = ""; }; 0270BCD01B7D067300010E03 /* RealmReact.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RealmReact.m; path = ReactNative/RealmReact.m; sourceTree = ""; }; 02A3C7841BC4317A00B1A7BE /* GCDWebServer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GCDWebServer.xcodeproj; path = vendor/GCDWebServer/GCDWebServer.xcodeproj; sourceTree = ""; }; @@ -192,6 +198,11 @@ 02C0864C1BCDB27000942F9C /* list.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = list.cpp; path = "src/object-store/list.cpp"; sourceTree = ""; }; 02C0864D1BCDB27000942F9C /* list.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = list.hpp; path = "src/object-store/list.hpp"; sourceTree = ""; }; 02D456D91B7E59A500EE1299 /* ArrayTests.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = ArrayTests.js; path = tests/ArrayTests.js; sourceTree = SOURCE_ROOT; }; + F64E1EF01BC3510E00E0E150 /* util.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = util.js; path = tests/util.js; sourceTree = SOURCE_ROOT; }; + F68A278A1BC2722A0063D40A /* RJSModuleLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RJSModuleLoader.h; path = tests/RJSModuleLoader.h; sourceTree = SOURCE_ROOT; }; + F68A278B1BC2722A0063D40A /* RJSModuleLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RJSModuleLoader.m; path = tests/RJSModuleLoader.m; sourceTree = SOURCE_ROOT; }; + F68A278D1BC30F0A0063D40A /* index.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = index.js; path = tests/index.js; sourceTree = SOURCE_ROOT; }; + F6F405F71BCF0C1A00A1E24F /* base-test.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = "base-test.js"; path = "tests/base-test.js"; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -315,15 +326,21 @@ 02B58CC01AE99CEC009B348C /* RealmJSTests */ = { isa = PBXGroup; children = ( - 02D456D91B7E59A500EE1299 /* ArrayTests.js */, 0270BC781B7D020100010E03 /* Info.plist */, + F68A278D1BC30F0A0063D40A /* index.js */, + 0270BC7E1B7D020100010E03 /* asserts.js */, + F6F405F71BCF0C1A00A1E24F /* base-test.js */, + 0270BC7F1B7D020100010E03 /* schemas.js */, + F64E1EF01BC3510E00E0E150 /* util.js */, + 02D456D91B7E59A500EE1299 /* ArrayTests.js */, 0270BC791B7D020100010E03 /* ObjectTests.js */, - 0270BC7A1B7D020100010E03 /* RealmJSTests.h */, - 0270BC7B1B7D020100010E03 /* RealmJSTests.mm */, 0270BC7C1B7D020100010E03 /* RealmTests.js */, 0270BC7D1B7D020100010E03 /* ResultsTests.js */, - 0270BC7F1B7D020100010E03 /* TestObjects.js */, - 0270BC7E1B7D020100010E03 /* TestCase.js */, + 0270BC7A1B7D020100010E03 /* RealmJSTests.h */, + 0270BC7B1B7D020100010E03 /* RealmJSTests.mm */, + 02409DC11BCF11D6005F3B3E /* RealmJSCoreTests.m */, + F68A278A1BC2722A0063D40A /* RJSModuleLoader.h */, + F68A278B1BC2722A0063D40A /* RJSModuleLoader.m */, ); path = RealmJSTests; sourceTree = ""; @@ -530,10 +547,13 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0270BC851B7D020100010E03 /* TestCase.js in Resources */, + F64E1EF11BC3510E00E0E150 /* util.js in Resources */, + 0270BC851B7D020100010E03 /* asserts.js in Resources */, 0270BC811B7D020100010E03 /* ObjectTests.js in Resources */, 02D456DA1B7E59A500EE1299 /* ArrayTests.js in Resources */, - 0270BC861B7D020100010E03 /* TestObjects.js in Resources */, + 0270BC861B7D020100010E03 /* schemas.js in Resources */, + F6F405F81BCF0C1A00A1E24F /* base-test.js in Resources */, + F68A278E1BC30F0A0063D40A /* index.js in Resources */, 0270BC831B7D020100010E03 /* RealmTests.js in Resources */, 0270BC841B7D020100010E03 /* ResultsTests.js in Resources */, ); @@ -595,7 +615,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F68A278C1BC2722A0063D40A /* RJSModuleLoader.m in Sources */, 0270BC821B7D020100010E03 /* RealmJSTests.mm in Sources */, + 02409DC21BCF11D6005F3B3E /* RealmJSCoreTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -640,6 +662,7 @@ "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/examples/ReactExample/node_modules/react-native/React/", + "$(SRCROOT)/tests/ReactTests/node_modules/react-native/React/", ); INFOPLIST_FILE = src/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -672,6 +695,7 @@ "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/examples/ReactExample/node_modules/react-native/React/", + "$(SRCROOT)/tests/ReactTests/node_modules/react-native/React/", ); INFOPLIST_FILE = src/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -704,6 +728,7 @@ "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/examples/ReactExample/node_modules/react-native/React/", + "$(SRCROOT)/tests/ReactTests/node_modules/react-native/React/", ); INFOPLIST_FILE = src/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -750,7 +775,6 @@ GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( REALM_HAVE_CONFIG, - REALM_DEBUG, __ASSERTMACROS__, ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; @@ -830,7 +854,6 @@ GCC_PREPROCESSOR_DEFINITIONS = ( REALM_HAVE_CONFIG, "DEBUG=1", - REALM_DEBUG, __ASSERTMACROS__, ); HEADER_SEARCH_PATHS = ( @@ -847,8 +870,8 @@ "-isystem", core/include, ); - OTHER_LDFLAGS = "-lrealm-ios-dbg"; - OTHER_LIBTOOLFLAGS = "-lrealm-ios-dbg"; + OTHER_LDFLAGS = "-lrealm-ios"; + OTHER_LIBTOOLFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -881,7 +904,7 @@ core/include, ); OTHER_LDFLAGS = "-lrealm-ios"; - OTHER_LIBTOOLFLAGS = "-lrealm-ios"; + OTHER_LIBTOOLFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -964,7 +987,6 @@ GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( REALM_HAVE_CONFIG, - REALM_DEBUG, __ASSERTMACROS__, ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; @@ -998,7 +1020,6 @@ GCC_PREPROCESSOR_DEFINITIONS = ( REALM_HAVE_CONFIG, "DEBUG=1", - REALM_DEBUG, __ASSERTMACROS__, ); HEADER_SEARCH_PATHS = ( @@ -1015,8 +1036,8 @@ "-isystem", core/include, ); - OTHER_LDFLAGS = "-lrealm-ios-dbg"; - OTHER_LIBTOOLFLAGS = "-lrealm-ios-dbg"; + OTHER_LDFLAGS = "-lrealm-ios"; + OTHER_LIBTOOLFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; diff --git a/RealmJS.xcodeproj/xcshareddata/xcschemes/RealmReact.xcscheme b/RealmJS.xcodeproj/xcshareddata/xcschemes/RealmReact.xcscheme index 2699e2b9..0ba909fd 100644 --- a/RealmJS.xcodeproj/xcshareddata/xcschemes/RealmReact.xcscheme +++ b/RealmJS.xcodeproj/xcshareddata/xcschemes/RealmReact.xcscheme @@ -28,7 +28,31 @@ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + + + + + + + + + diff --git a/lib/realm.js b/lib/realm.js index 45cd8de6..ca56e2f6 100644 --- a/lib/realm.js +++ b/lib/realm.js @@ -30,7 +30,7 @@ class Realm { } } - let realmId = this[realmKey] = rpc.createRealm(config); + let realmId = this[realmKey] = rpc.createRealm(Array.from(arguments)); objects.registerConstructors(realmId, constructors); } @@ -83,4 +83,10 @@ class Realm { Object.defineProperty(Realm, 'Types', {value: types}); +Object.defineProperty(Realm, 'clearTestState', { + value: function() { + rpc.clearTestState(); + } +}); + module.exports = Realm; diff --git a/lib/rpc.js b/lib/rpc.js index d0fb1185..7bf4f65f 100644 --- a/lib/rpc.js +++ b/lib/rpc.js @@ -37,12 +37,18 @@ exports.beginTransaction = beginTransaction; exports.cancelTransaction = cancelTransaction; exports.commitTransaction = commitTransaction; +exports.clearTestState = clearTestState; + function registerTypeConverter(type, handler) { typeConverters[type] = handler; } -function createRealm(config) { - return sendRequest('create_realm', config); +function createRealm(args) { + if (args) { + args = args.map((arg) => serialize(null, arg)); + } + + return sendRequest('create_realm', {arguments: args}); } function callRealmMethod(realmId, name, args) { @@ -70,7 +76,7 @@ function getListItem(realmId, listId, index) { } function setListItem(realmId, listId, index, value) { - sendRequest('set_list_item', {realmId, listId, index, value}); + sendRequest('set_list_item', {realmId, listId, index, value: serialize(realmId, value)}); } function getListSize(realmId, listId) { @@ -107,6 +113,10 @@ function commitTransaction(realmId) { sendRequest('commit_transaction', {realmId}); } +function clearTestState() { + sendRequest('clear_test_state'); +} + function serialize(realmId, value) { if (!value || typeof value != 'object') { return {value: value}; @@ -149,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/RJSList.cpp b/src/RJSList.cpp index dfb35bb5..66978780 100644 --- a/src/RJSList.cpp +++ b/src/RJSList.cpp @@ -224,6 +224,6 @@ const JSStaticFunction RJSListFuncs[] = { }; JSClassRef RJSListClass() { - static JSClassRef s_listClass = RJSCreateWrapperClass("RealmList", ListGetProperty, ListSetProperty, RJSListFuncs, NULL, ListPropertyNames); + static JSClassRef s_listClass = RJSCreateWrapperClass("RealmList", ListGetProperty, ListSetProperty, RJSListFuncs, ListPropertyNames); return s_listClass; } diff --git a/src/RJSList.hpp b/src/RJSList.hpp index 6dbe9dd0..aaa07571 100644 --- a/src/RJSList.hpp +++ b/src/RJSList.hpp @@ -25,3 +25,4 @@ JSClassRef RJSListClass(); JSObjectRef RJSListCreate(JSContextRef ctx, realm::List &list); JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException); +bool ListSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* jsException); \ No newline at end of file diff --git a/src/RJSObject.mm b/src/RJSObject.mm index 1d088469..b56c2801 100644 --- a/src/RJSObject.mm +++ b/src/RJSObject.mm @@ -58,7 +58,7 @@ void ObjectPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAcc } JSClassRef RJSObjectClass() { - static JSClassRef s_objectClass = RJSCreateWrapperClass("RealmObject", ObjectGetProperty, ObjectSetProperty, NULL, NULL, ObjectPropertyNames); + static JSClassRef s_objectClass = RJSCreateWrapperClass("RealmObject", ObjectGetProperty, ObjectSetProperty, NULL, ObjectPropertyNames); return s_objectClass; } diff --git a/src/RJSResults.mm b/src/RJSResults.mm index 7cdad982..594d48de 100644 --- a/src/RJSResults.mm +++ b/src/RJSResults.mm @@ -124,6 +124,6 @@ JSClassRef RJSResultsClass() { {"sortByProperty", SortByProperty, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete}, {NULL, NULL}, }; - static JSClassRef s_objectClass = RJSCreateWrapperClass("Results", ResultsGetProperty, NULL, resultsFuncs, NULL, ResultsPropertyNames); + static JSClassRef s_objectClass = RJSCreateWrapperClass("Results", ResultsGetProperty, NULL, resultsFuncs, ResultsPropertyNames); return s_objectClass; } diff --git a/src/RJSSchema.hpp b/src/RJSSchema.hpp index 8faa8f5a..418725d4 100644 --- a/src/RJSSchema.hpp +++ b/src/RJSSchema.hpp @@ -31,3 +31,4 @@ realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject); JSValueRef RJSPrototypeForClassName(const std::string &className); realm::ObjectDefaults &RJSDefaultsForClassName(const std::string &className); +void RJSSchemaClearState(JSContextRef ctx); diff --git a/src/RJSSchema.mm b/src/RJSSchema.mm index ef9fdb12..4b00eb96 100644 --- a/src/RJSSchema.mm +++ b/src/RJSSchema.mm @@ -55,6 +55,20 @@ JSValueRef RJSPrototypeForClassName(const std::string &className) { return s_prototypes[className]; } +void RJSSchemaClearState(JSContextRef ctx) { + for (auto prototype : s_prototypes) { + JSValueUnprotect(ctx, prototype.second); + } + s_prototypes.clear(); + + for (auto defaults : s_defaults) { + for (auto value : defaults.second) { + JSValueUnprotect(ctx, value.second); + } + } + s_defaults.clear(); +} + static inline Property RJSParseProperty(JSContextRef ctx, JSObjectRef propertyObject) { static JSStringRef nameString = JSStringCreateWithUTF8CString("name"); static JSStringRef typeString = JSStringCreateWithUTF8CString("type"); diff --git a/src/RJSUtil.hpp b/src/RJSUtil.hpp index b53f2034..0ff3beeb 100644 --- a/src/RJSUtil.hpp +++ b/src/RJSUtil.hpp @@ -43,10 +43,11 @@ inline T RJSGetInternal(JSObjectRef jsObject) { } template -JSClassRef RJSCreateWrapperClass(const char * name, JSObjectGetPropertyCallback getter = NULL, JSObjectSetPropertyCallback setter = NULL, const JSStaticFunction *funcs = NULL, JSObjectFinalizeCallback finalize = RJSFinalize, JSObjectGetPropertyNamesCallback propertyNames = NULL) { +JSClassRef RJSCreateWrapperClass(const char * name, JSObjectGetPropertyCallback getter = NULL, JSObjectSetPropertyCallback setter = NULL, const JSStaticFunction *funcs = NULL, + JSObjectGetPropertyNamesCallback propertyNames = NULL) { JSClassDefinition classDefinition = kJSClassDefinitionEmpty; classDefinition.className = name; - classDefinition.finalize = finalize; + classDefinition.finalize = RJSFinalize; classDefinition.getProperty = getter; classDefinition.setProperty = setter; classDefinition.staticFunctions = funcs; 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 ecee3d7d..ad65e68b 100644 --- a/src/RealmJS.h +++ b/src/RealmJS.h @@ -25,4 +25,6 @@ // add realm apis to the given js context + (void)initializeContext:(JSContextRef)ctx; ++ (void)clearTestState; + @end diff --git a/src/RealmJS.mm b/src/RealmJS.mm index fe89b02a..13076b06 100644 --- a/src/RealmJS.mm +++ b/src/RealmJS.mm @@ -20,6 +20,9 @@ #import "RJSRealm.hpp" #import "RJSObject.hpp" #import "RJSUtil.hpp" +#import "RJSSchema.hpp" + +#include "shared_realm.hpp" JSValueRef RJSTypeGet(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { return RJSValueForString(ctx, RJSTypeGet(RJSStringForJSString(propertyName))); @@ -44,6 +47,21 @@ JSClassRef RJSRealmTypeClass() { return JSClassCreate(&realmTypesDefinition); } +NSString *RealmFileDirectory() { +#if TARGET_OS_IPHONE + return NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; +#else + NSString *path = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)[0]; + return [path stringByAppendingPathComponent:[[[NSBundle mainBundle] executablePath] lastPathComponent]]; +#endif +} + +static JSValueRef ClearTestState(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) { + [RealmJS clearTestState]; + //RJSSchemaClearState(ctx); + return NULL; +} + @implementation RealmJS + (void)initializeContext:(JSContextRef)ctx { @@ -53,10 +71,29 @@ JSClassRef RJSRealmTypeClass() { 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); + JSStringRef clearTestStateString = JSStringCreateWithUTF8CString("clearTestState"); + JSObjectRef clearTestStateFunction = JSObjectMakeFunctionWithCallback(ctx, clearTestStateString, ClearTestState); + JSObjectSetProperty(ctx, globalRealmObject, clearTestStateString, clearTestStateFunction, attributes, &exception); + JSStringRelease(clearTestStateString); + assert(!exception); } ++ (void)clearTestState { + realm::Realm::s_global_cache.invalidate_all(); + realm::Realm::s_global_cache.clear(); + + NSFileManager *manager = [NSFileManager defaultManager]; + NSString *fileDir = RealmFileDirectory(); + for (NSString *path in [manager enumeratorAtPath:fileDir]) { + if (![manager removeItemAtPath:[fileDir stringByAppendingPathComponent:path] error:nil]) { + @throw [NSException exceptionWithName:@"removeItemAtPath error" reason:@"Failed to delete file" userInfo:nil]; + } + } +} + @end diff --git a/src/RealmJSCoreTests.m b/src/RealmJSCoreTests.m new file mode 100644 index 00000000..964aaf3b --- /dev/null +++ b/src/RealmJSCoreTests.m @@ -0,0 +1,98 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + + +#import "RealmJSTests.h" +#import "RJSModuleLoader.h" + +@interface RealmJSCoreTests : RealmJSTests + +@property (nonatomic, strong) JSValue *testObject; + +@end + +@implementation RealmJSCoreTests + ++ (XCTestSuite *)defaultTestSuite { + XCTestSuite *suite = [super defaultTestSuite]; + JSContext *context = [[JSContext alloc] init]; + RJSModuleLoader *moduleLoader = [[RJSModuleLoader alloc] initWithContext:context]; + NSURL *scriptURL = [[NSBundle bundleForClass:self] URLForResource:@"index" withExtension:@"js"]; + + [RealmJS initializeContext:context.JSGlobalContextRef]; + + // Expose the global Realm object as a global 'realm' CommonJS module. + [moduleLoader addGlobalModuleObject:context[@"Realm"] forName:@"realm"]; + + NSError *error; + JSValue *testObjects = [moduleLoader loadModuleFromURL:scriptURL error:&error]; + + if (!testObjects) { + NSLog(@"%@", error); + exit(1); + } + + NSDictionary *testCaseNames = [[testObjects invokeMethod:@"getTestNames" withArguments:nil] toDictionary]; + + if (!testCaseNames.count) { + NSLog(@"No test case names from getTestNames() JS method!"); + exit(1); + } + + for (XCTestSuite *testSuite in [self testSuitesFromDictionary:testCaseNames]) { + for (RealmJSCoreTests *test in testSuite.tests) { + test.testObject = testObjects[testSuite.name]; + } + + [suite addTest:testSuite]; + } + + return suite; +} + +- (JSContext *)context { + return self.testObject.context; +} + +- (void)invokeMethod:(NSString *)method { + JSValue *testObject = self.testObject; + + if (![testObject hasProperty:method]) { + return; + } + + JSContext *context = testObject.context; + context.exception = nil; + + [testObject invokeMethod:method withArguments:nil]; + + JSValue *exception = context.exception; + if (exception) { + JSValue *message = [exception hasProperty:@"message"] ? exception[@"message"] : exception; + NSString *source = [exception hasProperty:@"sourceURL"] ? [exception[@"sourceURL"] toString] : nil; + NSUInteger line = [exception hasProperty:@"line"] ? [exception[@"line"] toUInt32] - 1 : 0; + NSURL *sourceURL = source ? [NSURL URLWithString:source.lastPathComponent relativeToURL:[NSURL URLWithString:@(__FILE__)]] : nil; + + [self recordFailureWithDescription:message.description + inFile:sourceURL ? sourceURL.absoluteString : @(__FILE__) + atLine:sourceURL ? line : __LINE__ + expected:YES]; + } +} + +@end diff --git a/src/RealmRPC.mm b/src/RealmRPC.mm index c8a2a5a6..b6c7870f 100644 --- a/src/RealmRPC.mm +++ b/src/RealmRPC.mm @@ -41,35 +41,56 @@ using RPCRequest = std::function; std::map _objects; } +- (void)dealloc { + for (auto item : _objects) { + JSValueUnprotect(_context, item.second); + } + + JSGlobalContextRelease(_context); + _requests.clear(); +} + - (instancetype)init { self = [super init]; if (self) { _context = JSGlobalContextCreate(NULL); + + id _self = self; + __weak __typeof__(self) self = _self; + _requests["/create_realm"] = [=](NSDictionary *dict) { - // We should have a method for serializing schema rather than relying on JSValue - JSValueRef value = [[JSValue valueWithObject:dict - inContext:[JSContext contextWithJSGlobalContextRef:_context]] JSValueRef]; - JSValueRef ex = NULL; - RPCObjectID realmId = [self storeObject:RealmConstructor(_context, NULL, 1, &value, &ex)]; - if (ex) { - return @{@"error": @(RJSStringForValue(_context, ex).c_str())}; + NSArray *args = dict[@"arguments"]; + NSUInteger argCount = args.count; + JSValueRef argValues[argCount]; + + for (NSUInteger i = 0; i < argCount; i++) { + argValues[i] = [self deserializeDictionaryValue:args[i]]; } + + JSValueRef exception = NULL; + JSObjectRef realmObject = RealmConstructor(_context, NULL, argCount, argValues, &exception); + + if (exception) { + return @{@"error": @(RJSStringForValue(_context, exception).c_str())}; + } + + RPCObjectID realmId = [self storeObject:realmObject]; return @{@"result": @(realmId)}; }; _requests["/begin_transaction"] = [=](NSDictionary *dict) { RPCObjectID realmId = [dict[@"realmId"] unsignedLongValue]; RJSGetInternal(_objects[realmId])->get()->begin_transaction(); - return @{}; + return nil; }; _requests["/cancel_transaction"] = [=](NSDictionary *dict) { RPCObjectID realmId = [dict[@"realmId"] unsignedLongValue]; RJSGetInternal(_objects[realmId])->get()->cancel_transaction(); - return @{}; + return nil; }; _requests["/commit_transaction"] = [=](NSDictionary *dict) { RPCObjectID realmId = [dict[@"realmId"] unsignedLongValue]; RJSGetInternal(_objects[realmId])->get()->commit_transaction(); - return @{}; + return nil; }; _requests["/call_realm_method"] = [=](NSDictionary *dict) { NSString *name = dict[@"name"]; @@ -94,7 +115,7 @@ using RPCRequest = std::function; _requests["/set_property"] = [=](NSDictionary *dict) { JSStringRef propString = RJSStringForString([dict[@"name"] UTF8String]); RPCObjectID realmId = [dict[@"objectId"] unsignedLongValue]; - JSValueRef value = [self valueFromDictionary:dict[@"value"]]; + JSValueRef value = [self deserializeDictionaryValue:dict[@"value"]]; JSValueRef exception = NULL; ObjectSetProperty(_context, _objects[realmId], propString, value, &exception); @@ -106,7 +127,7 @@ using RPCRequest = std::function; RPCObjectID oid = [dict[@"id"] unsignedLongValue]; JSValueUnprotect(_context, _objects[oid]); _objects.erase(oid); - return @{}; + return nil; }; _requests["/get_results_size"] = [=](NSDictionary *dict) { RPCObjectID resultsId = [dict[@"resultsId"] unsignedLongValue]; @@ -163,6 +184,22 @@ using RPCRequest = std::function; return @{@"result": [self resultForJSValue:objectValue]}; }; + _requests["/set_list_item"] = [=](NSDictionary *dict) { + RPCObjectID listId = [dict[@"listId"] unsignedLongValue]; + long index = [dict[@"index"] longValue]; + + JSValueRef exception = NULL; + JSStringRef indexPropertyName = JSStringCreateWithUTF8CString(std::to_string(index).c_str()); + JSValueRef value = [self deserializeDictionaryValue:dict[@"value"]]; + ListSetProperty(_context, _objects[listId], indexPropertyName, value, &exception); + JSStringRelease(indexPropertyName); + + if (exception) { + return @{@"error": @(RJSStringForValue(_context, exception).c_str())}; + } + + return @{}; + }; _requests["/call_list_method"] = [=](NSDictionary *dict) { NSString *name = dict[@"name"]; return [self performObjectMethod:name.UTF8String @@ -170,6 +207,15 @@ using RPCRequest = std::function; args:dict[@"arguments"] objectId:[dict[@"listId"] unsignedLongValue]]; }; + _requests["/clear_test_state"] = [=](NSDictionary *dict) { + for (auto object : _objects) { + JSValueUnprotect(_context, object.second); + } + _objects.clear(); + JSGarbageCollect(_context); + [RealmJS clearTestState]; + return nil; + }; } return self; } @@ -177,6 +223,8 @@ using RPCRequest = std::function; - (NSDictionary *)performRequest:(NSString *)name args:(NSDictionary *)args { // perform all realm ops on the main thread RPCRequest action = _requests[name.UTF8String]; + assert(action); + __block id response; dispatch_sync(dispatch_get_main_queue(), ^{ try { @@ -185,26 +233,26 @@ using RPCRequest = std::function; response = @{@"error": [@"exception thrown: " stringByAppendingString:@(exception.what())]}; } }); - return response; + return response ?: @{}; } - (NSDictionary *)performObjectMethod:(const char *)name classMethods:(const JSStaticFunction [])methods args:(NSArray *)args objectId:(RPCObjectID)oid { - NSUInteger count = args.count; - JSValueRef argValues[count]; - for (NSUInteger i = 0; i < count; i++) { - argValues[i] = [self valueFromDictionary:args[i]]; + NSUInteger argCount = args.count; + JSValueRef argValues[argCount]; + for (NSUInteger i = 0; i < argCount; i++) { + argValues[i] = [self deserializeDictionaryValue:args[i]]; } size_t index = 0; while (methods[index].name) { if (!strcmp(methods[index].name, name)) { - JSValueRef ex = NULL; - JSValueRef ret = methods[index].callAsFunction(_context, NULL, _objects[oid], count, argValues, &ex); - if (ex) { - return @{@"error": @(RJSStringForValue(_context, ex).c_str())}; + JSValueRef exception = NULL; + JSValueRef ret = methods[index].callAsFunction(_context, NULL, _objects[oid], argCount, argValues, &exception); + if (exception) { + return @{@"error": @(RJSStringForValue(_context, exception).c_str())}; } return @{@"result": [self resultForJSValue:ret]}; } @@ -300,7 +348,7 @@ using RPCRequest = std::function; }; } -- (JSValueRef)valueFromDictionary:(NSDictionary *)dict { +- (JSValueRef)deserializeDictionaryValue:(NSDictionary *)dict { RPCObjectID oid = [dict[@"id"] longValue]; if (oid) { return _objects[oid]; @@ -327,7 +375,7 @@ using RPCRequest = std::function; JSValueRef jsValues[count]; for (NSUInteger i = 0; i < count; i++) { - jsValues[i] = [self valueFromDictionary:value[i]]; + jsValues[i] = [self deserializeDictionaryValue:value[i]]; } return JSObjectMakeArray(_context, count, jsValues, NULL); @@ -336,7 +384,7 @@ using RPCRequest = std::function; JSObjectRef jsObject = JSObjectMake(_context, NULL, NULL); for (NSString *key in value) { - JSValueRef jsValue = [self valueFromDictionary:value[key]]; + JSValueRef jsValue = [self deserializeDictionaryValue:value[key]]; JSStringRef jsKey = JSStringCreateWithCFString((__bridge CFStringRef)key); JSObjectSetProperty(_context, jsObject, jsKey, jsValue, 0, NULL); diff --git a/tests/ArrayTests.js b/tests/ArrayTests.js index 29cd15af..4fb02a6c 100644 --- a/tests/ArrayTests.js +++ b/tests/ArrayTests.js @@ -18,9 +18,14 @@ 'use strict'; -var ArrayTests = { +var Realm = require('realm'); +var BaseTest = require('./base-test'); +var TestCase = require('./asserts'); +var schemas = require('./schemas'); + +module.exports = BaseTest.extend({ testArrayLength: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); realm.write(function() { var obj = realm.create('LinkTypesObject', [[1], [2], [[3]]]); TestCase.assertEqual(obj.arrayCol.length, 1); @@ -38,7 +43,7 @@ var ArrayTests = { }, testArraySubscriptGetters: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var array; realm.write(function() { @@ -53,7 +58,7 @@ var ArrayTests = { }, testArraySubscriptSetters: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var array; realm.write(function() { @@ -81,7 +86,7 @@ var ArrayTests = { }, testArrayInvalidProperty: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var array; realm.write(function() { @@ -93,7 +98,7 @@ var ArrayTests = { }, testArrayEnumerate: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var obj; realm.write(function() { @@ -117,7 +122,7 @@ var ArrayTests = { }, testPush: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var array; realm.write(function() { @@ -146,7 +151,7 @@ var ArrayTests = { }, testPop: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var array; realm.write(function() { @@ -170,7 +175,7 @@ var ArrayTests = { }, testUnshift: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var array; realm.write(function() { @@ -195,7 +200,7 @@ var ArrayTests = { }, testShift: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var array; realm.write(function() { @@ -219,7 +224,7 @@ var ArrayTests = { }, testSplice: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var array; realm.write(function() { @@ -278,4 +283,4 @@ var ArrayTests = { obj.arrayCol.splice(0, 0, obj.objectCol); }, 'can only splice in a write transaction'); }, -}; +}); diff --git a/tests/ObjectTests.js b/tests/ObjectTests.js index d2ebbf1b..5d045e44 100644 --- a/tests/ObjectTests.js +++ b/tests/ObjectTests.js @@ -18,17 +18,22 @@ 'use strict'; -var ObjectTests = { +var Realm = require('realm'); +var BaseTest = require('./base-test'); +var TestCase = require('./asserts'); +var schemas = require('./schemas'); + +module.exports = BaseTest.extend({ testBasicTypesPropertyGetters: function() { var basicTypesValues = [true, 1, 1.1, 1.11, 'string', new Date(1), 'DATA']; - var realm = new Realm({schema: [BasicTypesObjectSchema]}); + var realm = new Realm({schema: [schemas.BasicTypes]}); var object = null; realm.write(function() { object = realm.create('BasicTypesObject', basicTypesValues); }); - for (var i = 0; i < BasicTypesObjectSchema.properties.length; i++) { - var prop = BasicTypesObjectSchema.properties[i]; + for (var i = 0; i < schemas.BasicTypes.properties.length; i++) { + var prop = schemas.BasicTypes.properties[i]; if (prop.type == Realm.Types.FLOAT) { TestCase.assertEqualWithTolerance(object[prop.name], basicTypesValues[i], 0.000001); } @@ -42,7 +47,7 @@ var ObjectTests = { }, testBasicTypesPropertySetters: function() { var basicTypesValues = [true, 1, 1.1, 1.11, 'string', new Date(1), 'DATA']; - var realm = new Realm({schema: [BasicTypesObjectSchema]}); + var realm = new Realm({schema: [schemas.BasicTypes]}); var obj = null; realm.write(function() { @@ -81,7 +86,7 @@ var ObjectTests = { TestCase.assertEqual(obj.boolCol, false, 'bool value changed outside transaction'); }, testLinkTypesPropertyGetters: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var obj = null; realm.write(function() { obj = realm.create('LinkTypesObject', [[1], null, [[3]]]); @@ -101,7 +106,7 @@ var ObjectTests = { TestCase.assertEqual(arrayVal[0].doubleCol, 3); }, testLinkTypesPropertySetters: function() { - var realm = new Realm({schema: [LinkTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.LinkTypes, schemas.TestObject]}); var obj = null; realm.write(function() { obj = realm.create('LinkTypesObject', [[1], null, [[3]]]); @@ -143,4 +148,4 @@ var ObjectTests = { TestCase.assertEqual(obj.arrayCol[1].doubleCol, 1); TestCase.assertEqual(obj.arrayCol[2].doubleCol, 2); }, -}; +}); diff --git a/tests/RJSModuleLoader.h b/tests/RJSModuleLoader.h new file mode 100644 index 00000000..5bdac486 --- /dev/null +++ b/tests/RJSModuleLoader.h @@ -0,0 +1,30 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +#import +#import + +@interface RJSModuleLoader : NSObject + +- (instancetype)initWithContext:(JSContext *)context; + +- (void)addGlobalModuleObject:(id)object forName:(NSString *)name; + +- (JSValue *)loadModuleFromURL:(NSURL *)url error:(NSError **)error; + +@end diff --git a/tests/RJSModuleLoader.m b/tests/RJSModuleLoader.m new file mode 100644 index 00000000..e155fa80 --- /dev/null +++ b/tests/RJSModuleLoader.m @@ -0,0 +1,183 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +#import "RJSModuleLoader.h" + +static NSString * const RJSModuleLoaderErrorDomain = @"RJSModuleLoaderErrorDomain"; + +@interface RJSModuleLoader () + +@property (nonatomic, strong) JSContext *context; +@property (nonatomic, strong) NSMutableDictionary *modules; +@property (nonatomic, strong) NSMutableDictionary *globalModules; + +@end + +@implementation RJSModuleLoader + +- (instancetype)initWithContext:(JSContext *)context { + self = [super init]; + if (!self) { + return nil; + } + + _context = context; + _modules = [[NSMutableDictionary alloc] init]; + _globalModules = [[NSMutableDictionary alloc] init]; + + return self; +} + +- (void)addGlobalModuleObject:(id)object forName:(NSString *)name { + self.globalModules[name] = [JSValue valueWithObject:object inContext:self.context]; +} + +- (JSValue *)loadModule:(NSString *)name relativeToURL:(NSURL *)baseURL error:(NSError **)error +{ + if (![name hasPrefix:@"./"] && ![name hasPrefix:@"../"]) { + return [self loadGlobalModule:name relativeToURL:baseURL error:error]; + } + + NSURL *url = [[NSURL URLWithString:name relativeToURL:baseURL] absoluteURL]; + BOOL isDirectory; + + if ([[NSFileManager defaultManager] fileExistsAtPath:url.path isDirectory:&isDirectory]) { + if (!isDirectory) { + return nil; + } + + url = [url URLByAppendingPathComponent:@"index.js"]; + } else { + url = [url URLByAppendingPathExtension:@"js"]; + } + + return [self loadModuleFromURL:url error:error]; +} + +- (JSValue *)loadModuleFromURL:(NSURL *)url error:(NSError **)error { + url = url.absoluteURL; + url = url.standardizedURL ?: url; + + NSString *path = url.path; + JSValue *exports = self.modules[path]; + if (exports) { + return exports; + } + + NSString *source = [NSString stringWithContentsOfURL:url usedEncoding:NULL error:error]; + if (!source) { + return nil; + } + + JSContext *context = self.context; + JSValue *module = [JSValue valueWithNewObjectInContext:context]; + + exports = [JSValue valueWithNewObjectInContext:context]; + module[@"exports"] = exports; + + __weak __typeof__(self) weakSelf = self; + + JSValue *require = [JSValue valueWithObject:^JSValue *(NSString *name) { + NSError *error; + JSValue *result = [weakSelf loadModule:name relativeToURL:url error:&error]; + + if (!result) { + NSString *message = [NSString stringWithFormat:@"Error requiring module '%@': %@", name, error ?: @"Not found"]; + JSContext *context = [JSContext currentContext]; + + context.exception = [JSValue valueWithNewErrorFromMessage:message inContext:context]; + return nil; + } + + return result; + } inContext:context]; + + JSStringRef jsParameterNames[] = {JSStringCreateWithUTF8CString("module"), JSStringCreateWithUTF8CString("exports"), JSStringCreateWithUTF8CString("require")}; + JSStringRef jsSource = JSStringCreateWithCFString((__bridge CFStringRef)source); + JSStringRef jsSourceURL = JSStringCreateWithCFString((__bridge CFStringRef)path); + + JSValueRef jsException; + JSObjectRef jsModuleFunction = JSObjectMakeFunction(context.JSGlobalContextRef, NULL, 3, jsParameterNames, jsSource, jsSourceURL, 1, &jsException); + + JSStringRelease(jsParameterNames[0]); + JSStringRelease(jsParameterNames[1]); + JSStringRelease(jsParameterNames[2]); + JSStringRelease(jsSource); + JSStringRelease(jsSourceURL); + + // Start with the original exports for circular dependendies and in case of an error. + self.modules[path] = exports; + + JSValue *exception; + + if (jsModuleFunction) { + JSValue *moduleFunction = [JSValue valueWithJSValueRef:jsModuleFunction inContext:context]; + [moduleFunction callWithArguments:@[module, exports, require]]; + + exception = context.exception; + } else { + exception = [JSValue valueWithJSValueRef:jsException inContext:context]; + } + + exports = module[@"exports"]; + self.modules[path] = exports; + + if (exception) { + *error = [NSError errorWithDomain:RJSModuleLoaderErrorDomain code:1 userInfo:@{ + NSLocalizedDescriptionKey: exception.description, + NSURLErrorKey: url, + @"JSException": exception, + }]; + + return nil; + } + + return exports; +} + +- (JSValue *)loadGlobalModule:(NSString *)name relativeToURL:(NSURL *)baseURL error:(NSError **)error { + JSValue *exports = self.globalModules[name]; + if (exports || !baseURL) { + return exports; + } + + NSURL *bundleResourcesURL = [[NSBundle bundleForClass:self.class] resourceURL]; + NSFileManager *fileManager = [NSFileManager defaultManager]; + + while (YES) { + NSURL *moduleURL = [NSURL URLWithString:[@"node_modules" stringByAppendingPathComponent:name] relativeToURL:baseURL]; + BOOL isDirectory; + + if ([fileManager fileExistsAtPath:moduleURL.path isDirectory:&isDirectory] && isDirectory) { + return [self loadModuleFromURL:moduleURL error:error]; + } + + // Remove last two path components (node_modules/name) and make absolute. + baseURL = moduleURL.URLByDeletingLastPathComponent.URLByDeletingLastPathComponent.absoluteURL; + if ([baseURL isEqual:bundleResourcesURL] || !baseURL.path.length) { + break; + } + + // Retry with parent directory. + baseURL = baseURL.URLByDeletingLastPathComponent; + } + + return nil; +} + +@end diff --git a/tests/ReactTests/.flowconfig b/tests/ReactTests/.flowconfig new file mode 100644 index 00000000..438e495d --- /dev/null +++ b/tests/ReactTests/.flowconfig @@ -0,0 +1,46 @@ +[ignore] + +# We fork some components by platform. +.*/*.web.js +.*/*.android.js + +# Some modules have their own node_modules with overlap +.*/node_modules/node-haste/.* + +# Ignore react-tools where there are overlaps, but don't ignore anything that +# react-native relies on +.*/node_modules/react-tools/src/React.js +.*/node_modules/react-tools/src/renderers/shared/event/EventPropagators.js +.*/node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderEventPlugin.js +.*/node_modules/react-tools/src/shared/vendor/core/ExecutionEnvironment.js + + +# Ignore commoner tests +.*/node_modules/commoner/test/.* + +# See https://github.com/facebook/flow/issues/442 +.*/react-tools/node_modules/commoner/lib/reader.js + +# Ignore jest +.*/react-native/node_modules/jest-cli/.* + +[include] + +[libs] +node_modules/react-native/Libraries/react-native/react-native-interface.js + +[options] +module.system=haste + +munge_underscores=true + +suppress_type=$FlowIssue +suppress_type=$FlowFixMe +suppress_type=$FixMe + +suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-4]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) +suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-4]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+ +suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy + +[version] +0.14.0 diff --git a/tests/ReactTests/.gitignore b/tests/ReactTests/.gitignore new file mode 100644 index 00000000..b927355d --- /dev/null +++ b/tests/ReactTests/.gitignore @@ -0,0 +1,28 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +project.xcworkspace + +# node.js +# +node_modules/ +npm-debug.log diff --git a/tests/ReactTests/.watchmanconfig b/tests/ReactTests/.watchmanconfig new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/tests/ReactTests/.watchmanconfig @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/tests/ReactTests/index.ios.js b/tests/ReactTests/index.ios.js new file mode 100644 index 00000000..d86ea883 --- /dev/null +++ b/tests/ReactTests/index.ios.js @@ -0,0 +1,88 @@ +/** + * Sample React Native App + * https://github.com/facebook/react-native + */ +'use strict'; + +var React = require('react-native'); +var Realm = require('realm'); +var RealmTests = require('realm-tests'); + +var { + AppRegistry, + StyleSheet, + Text, + TouchableHighlight, + View, +} = React; + +function runTests() { + let testNames = RealmTests.getTestNames(); + + for (let suiteName in testNames) { + let testSuite = RealmTests[suiteName]; + + console.log('Starting ' + suiteName); + + for (let testName of testNames[suiteName]) { + if (testSuite.beforeEach) { + testSuite.beforeEach(); + } + + try { + testSuite[testName](); + console.log('+ ' + testName); + } + catch (e) { + console.log('- ' + testName); + console.warn(e); + } + finally { + if (testSuite.afterEach) { + testSuite.afterEach(); + } + } + } + } +} + +var ReactTests = React.createClass({ + render() { + return ( + + + Tap to Run Tests + + + Press Cmd+R to reload,{'\n'} + Cmd+D or shake for dev menu + + + ); + } +}); + +var styles = StyleSheet.create({ + container: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: '#F5FCFF', + }, + button: { + borderColor: '#cccccc', + borderRadius: 4, + borderWidth: 1, + fontSize: 20, + textAlign: 'center', + margin: 20, + padding: 10, + }, + instructions: { + textAlign: 'center', + color: '#333333', + marginBottom: 5, + }, +}); + +AppRegistry.registerComponent('ReactTests', () => ReactTests); diff --git a/tests/ReactTests/ios/ReactTests.xcodeproj/project.pbxproj b/tests/ReactTests/ios/ReactTests.xcodeproj/project.pbxproj new file mode 100644 index 00000000..f1d66156 --- /dev/null +++ b/tests/ReactTests/ios/ReactTests.xcodeproj/project.pbxproj @@ -0,0 +1,853 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 008F07F31AC5B25A0029DE68 /* main.jsbundle in Resources */ = {isa = PBXBuildFile; fileRef = 008F07F21AC5B25A0029DE68 /* main.jsbundle */; }; + 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; + 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; + 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; + 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; + 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; + 00E356F31AD99517003FC87E /* RealmReactTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* RealmReactTests.m */; }; + 02409E1E1BCF1F2E005F3B3E /* RealmJSTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 02409E1B1BCF1F2E005F3B3E /* RealmJSTests.mm */; settings = {ASSET_TAGS = (); }; }; + 0277991C1BBF3BC600C96559 /* RealmReact.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0277991B1BBF3BB700C96559 /* RealmReact.framework */; }; + 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; + 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; + 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; + 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; + 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; + 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; + F6F405C71BCE566300A1E24F /* RealmReact.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0277991B1BBF3BB700C96559 /* RealmReact.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTActionSheet; + }; + 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTGeolocation; + }; + 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B5115D1A9E6B3D00147676; + remoteInfo = RCTImage; + }; + 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B511DB1A9E6C8500147676; + remoteInfo = RCTNetwork; + }; + 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; + remoteInfo = RCTVibration; + }; + 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 13B07F861A680F5B00A75B9A; + remoteInfo = ReactTests; + }; + 027799161BBF3BB700C96559 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 027799061BBF3BB700C96559 /* RealmJS.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 02B58CB11AE99CEC009B348C; + remoteInfo = RealmJS; + }; + 027799181BBF3BB700C96559 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 027799061BBF3BB700C96559 /* RealmJS.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 02B58CBC1AE99CEC009B348C; + remoteInfo = RealmJSTests; + }; + 0277991A1BBF3BB700C96559 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 027799061BBF3BB700C96559 /* RealmJS.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 02B29A161B7CF7C9008A7E6B; + remoteInfo = RealmReact; + }; + 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTSettings; + }; + 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3C86DF461ADF2C930047B81A; + remoteInfo = RCTWebSocket; + }; + 146834031AC3E56700842450 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; + remoteInfo = React; + }; + 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 134814201AA4EA6300B7C361; + remoteInfo = RCTLinking; + }; + 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 58B5119B1A9E6C1200147676; + remoteInfo = RCTText; + }; + F6F405B71BCE55FB00A1E24F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 027799061BBF3BB700C96559 /* RealmJS.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 02B29A151B7CF7C9008A7E6B; + remoteInfo = RealmReact; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + F6F405C61BCE565100A1E24F /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + F6F405C71BCE566300A1E24F /* RealmReact.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; }; + 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = ""; }; + 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = ""; }; + 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; + 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; + 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; + 00E356EE1AD99517003FC87E /* RealmReactTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RealmReactTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 00E356F21AD99517003FC87E /* RealmReactTests.m */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = RealmReactTests.m; sourceTree = ""; tabWidth = 4; }; + 02409E1A1BCF1F2E005F3B3E /* RealmJSTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmJSTests.h; path = ../../../RealmJSTests.h; sourceTree = ""; }; + 02409E1B1BCF1F2E005F3B3E /* RealmJSTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmJSTests.mm; path = ../../../RealmJSTests.mm; sourceTree = ""; }; + 027799061BBF3BB700C96559 /* RealmJS.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RealmJS.xcodeproj; path = ../../../RealmJS.xcodeproj; sourceTree = ""; }; + 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; + 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* ReactTests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReactTests.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = ReactTests/AppDelegate.h; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = ReactTests/AppDelegate.m; sourceTree = ""; }; + 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = ReactTests/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ReactTests/Info.plist; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ReactTests/main.m; sourceTree = ""; }; + 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; + 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; + 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 00E356EB1AD99517003FC87E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0277991C1BBF3BC600C96559 /* RealmReact.framework in Frameworks */, + 146834051AC3E58100842450 /* libReact.a in Frameworks */, + 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, + 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, + 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, + 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */, + 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, + 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */, + 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, + 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, + 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00C302A81ABCB8CE00DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302B61ABCB90400DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302BC1ABCB91800DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302D41ABCB9D200DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, + ); + name = Products; + sourceTree = ""; + }; + 00C302E01ABCB9EE00DB3ED1 /* Products */ = { + isa = PBXGroup; + children = ( + 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */, + ); + name = Products; + sourceTree = ""; + }; + 00E356EF1AD99517003FC87E /* RealmReactTests */ = { + isa = PBXGroup; + children = ( + 00E356F21AD99517003FC87E /* RealmReactTests.m */, + 02409E1A1BCF1F2E005F3B3E /* RealmJSTests.h */, + 02409E1B1BCF1F2E005F3B3E /* RealmJSTests.mm */, + 00E356F01AD99517003FC87E /* Supporting Files */, + ); + name = RealmReactTests; + path = ReactTestsTests; + sourceTree = ""; + }; + 00E356F01AD99517003FC87E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 00E356F11AD99517003FC87E /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 027799071BBF3BB700C96559 /* Products */ = { + isa = PBXGroup; + children = ( + 027799171BBF3BB700C96559 /* RealmJS.framework */, + 027799191BBF3BB700C96559 /* RealmJSTests.xctest */, + 0277991B1BBF3BB700C96559 /* RealmReact.framework */, + ); + name = Products; + sourceTree = ""; + }; + 139105B71AF99BAD00B5F7CC /* Products */ = { + isa = PBXGroup; + children = ( + 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */, + ); + name = Products; + sourceTree = ""; + }; + 139FDEE71B06529A00C62182 /* Products */ = { + isa = PBXGroup; + children = ( + 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, + ); + name = Products; + sourceTree = ""; + }; + 13B07FAE1A68108700A75B9A /* ReactTests */ = { + isa = PBXGroup; + children = ( + 008F07F21AC5B25A0029DE68 /* main.jsbundle */, + 13B07FAF1A68108700A75B9A /* AppDelegate.h */, + 13B07FB01A68108700A75B9A /* AppDelegate.m */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, + 13B07FB71A68108700A75B9A /* main.m */, + ); + name = ReactTests; + sourceTree = ""; + }; + 146834001AC3E56700842450 /* Products */ = { + isa = PBXGroup; + children = ( + 146834041AC3E56700842450 /* libReact.a */, + ); + name = Products; + sourceTree = ""; + }; + 78C398B11ACF4ADC00677621 /* Products */ = { + isa = PBXGroup; + children = ( + 78C398B91ACF4ADC00677621 /* libRCTLinking.a */, + ); + name = Products; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + 027799061BBF3BB700C96559 /* RealmJS.xcodeproj */, + 146833FF1AC3E56700842450 /* React.xcodeproj */, + 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, + 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */, + 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */, + 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */, + 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */, + 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */, + 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, + 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, + 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, + ); + name = Libraries; + sourceTree = ""; + }; + 832341B11AAA6A8300B99B32 /* Products */ = { + isa = PBXGroup; + children = ( + 832341B51AAA6A8300B99B32 /* libRCTText.a */, + ); + name = Products; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 13B07FAE1A68108700A75B9A /* ReactTests */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 00E356EF1AD99517003FC87E /* RealmReactTests */, + 83CBBA001A601CBA00E9B192 /* Products */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* ReactTests.app */, + 00E356EE1AD99517003FC87E /* RealmReactTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 00E356ED1AD99517003FC87E /* RealmReactTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "RealmReactTests" */; + buildPhases = ( + 00E356EA1AD99517003FC87E /* Sources */, + 00E356EB1AD99517003FC87E /* Frameworks */, + 00E356EC1AD99517003FC87E /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 00E356F51AD99517003FC87E /* PBXTargetDependency */, + ); + name = RealmReactTests; + productName = ReactTestsTests; + productReference = 00E356EE1AD99517003FC87E /* RealmReactTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 13B07F861A680F5B00A75B9A /* ReactTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactTests" */; + buildPhases = ( + F65C4BCA1BC72C5A000A1793 /* ShellScript */, + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + F6F405C61BCE565100A1E24F /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + F6F405B81BCE55FB00A1E24F /* PBXTargetDependency */, + ); + name = ReactTests; + productName = "Hello World"; + productReference = 13B07F961A680F5B00A75B9A /* ReactTests.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0700; + ORGANIZATIONNAME = Facebook; + TargetAttributes = { + 00E356ED1AD99517003FC87E = { + CreatedOnToolsVersion = 6.2; + TestTargetID = 13B07F861A680F5B00A75B9A; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "ReactTests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */; + ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; + }, + { + ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; + ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; + }, + { + ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */; + ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; + }, + { + ProductGroup = 78C398B11ACF4ADC00677621 /* Products */; + ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; + }, + { + ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */; + ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; + }, + { + ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */; + ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; + }, + { + ProductGroup = 832341B11AAA6A8300B99B32 /* Products */; + ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; + }, + { + ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */; + ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; + }, + { + ProductGroup = 139FDEE71B06529A00C62182 /* Products */; + ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + }, + { + ProductGroup = 146834001AC3E56700842450 /* Products */; + ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; + }, + { + ProductGroup = 027799071BBF3BB700C96559 /* Products */; + ProjectRef = 027799061BBF3BB700C96559 /* RealmJS.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* ReactTests */, + 00E356ED1AD99517003FC87E /* RealmReactTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTActionSheet.a; + remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTGeolocation.a; + remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTImage.a; + remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTNetwork.a; + remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTVibration.a; + remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 027799171BBF3BB700C96559 /* RealmJS.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = RealmJS.framework; + remoteRef = 027799161BBF3BB700C96559 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 027799191BBF3BB700C96559 /* RealmJSTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = RealmJSTests.xctest; + remoteRef = 027799181BBF3BB700C96559 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 0277991B1BBF3BB700C96559 /* RealmReact.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = RealmReact.framework; + remoteRef = 0277991A1BBF3BB700C96559 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTSettings.a; + remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTWebSocket.a; + remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 146834041AC3E56700842450 /* libReact.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libReact.a; + remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTLinking.a; + remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 832341B51AAA6A8300B99B32 /* libRCTText.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTText.a; + remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 00E356EC1AD99517003FC87E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 008F07F31AC5B25A0029DE68 /* main.jsbundle in Resources */, + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + F65C4BCA1BC72C5A000A1793 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "rm -rf ./node_modules/realm ./node_modules/realm-tests\nnpm install realm realm-tests"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 00E356EA1AD99517003FC87E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 02409E1E1BCF1F2E005F3B3E /* RealmJSTests.mm in Sources */, + 00E356F31AD99517003FC87E /* RealmReactTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, + 13B07FC11A68108700A75B9A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 13B07F861A680F5B00A75B9A /* ReactTests */; + targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; + }; + F6F405B81BCE55FB00A1E24F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = RealmReact; + targetProxy = F6F405B71BCE55FB00A1E24F /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + 13B07FB21A68108700A75B9A /* Base */, + ); + name = LaunchScreen.xib; + path = ReactTests; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 00E356F61AD99517003FC87E /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + 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"; + }; + name = Debug; + }; + 00E356F71AD99517003FC87E /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + 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"; + }; + name = Release; + }; + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + 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; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + 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; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "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; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../node_modules/react-native/React/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, + "$(SRCROOT)/../node_modules/react-native/React/**", + ); + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "RealmReactTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 00E356F61AD99517003FC87E /* Debug */, + 00E356F71AD99517003FC87E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "ReactTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/tests/ReactTests/ios/ReactTests.xcodeproj/xcshareddata/xcschemes/ReactTests.xcscheme b/tests/ReactTests/ios/ReactTests.xcodeproj/xcshareddata/xcschemes/ReactTests.xcscheme new file mode 100644 index 00000000..00978f6d --- /dev/null +++ b/tests/ReactTests/ios/ReactTests.xcodeproj/xcshareddata/xcschemes/ReactTests.xcscheme @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/ReactTests/ios/ReactTests/AppDelegate.h b/tests/ReactTests/ios/ReactTests/AppDelegate.h new file mode 100644 index 00000000..a9654d5e --- /dev/null +++ b/tests/ReactTests/ios/ReactTests/AppDelegate.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +@interface AppDelegate : UIResponder + +@property (nonatomic, strong) UIWindow *window; + +@end diff --git a/tests/ReactTests/ios/ReactTests/AppDelegate.m b/tests/ReactTests/ios/ReactTests/AppDelegate.m new file mode 100644 index 00000000..309637c4 --- /dev/null +++ b/tests/ReactTests/ios/ReactTests/AppDelegate.m @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import "AppDelegate.h" + +#import "RCTRootView.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + NSURL *jsCodeLocation; + + /** + * Loading JavaScript code - uncomment the one you want. + * + * OPTION 1 + * Load from development server. Start the server from the repository root: + * + * $ npm start + * + * To run on device, change `localhost` to the IP address of your computer + * (you can get this by typing `ifconfig` into the terminal and selecting the + * `inet` value under `en0:`) and make sure your computer and iOS device are + * on the same Wi-Fi network. + */ + + jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"]; + + /** + * OPTION 2 + * Load from pre-bundled file on disk. To re-generate the static bundle + * from the root of your project directory, run + * + * $ react-native bundle --minify + * + * see http://facebook.github.io/react-native/docs/runningondevice.html + */ + +// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; + + RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation + moduleName:@"ReactTests" + initialProperties:nil + launchOptions:launchOptions]; + + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + UIViewController *rootViewController = [[UIViewController alloc] init]; + rootViewController.view = rootView; + self.window.rootViewController = rootViewController; + [self.window makeKeyAndVisible]; + return YES; +} + +@end diff --git a/tests/ReactTests/ios/ReactTests/Base.lproj/LaunchScreen.xib b/tests/ReactTests/ios/ReactTests/Base.lproj/LaunchScreen.xib new file mode 100644 index 00000000..fff23b24 --- /dev/null +++ b/tests/ReactTests/ios/ReactTests/Base.lproj/LaunchScreen.xib @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/ReactTests/ios/ReactTests/Images.xcassets/AppIcon.appiconset/Contents.json b/tests/ReactTests/ios/ReactTests/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..118c98f7 --- /dev/null +++ b/tests/ReactTests/ios/ReactTests/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/tests/ReactTests/ios/ReactTests/Info.plist b/tests/ReactTests/ios/ReactTests/Info.plist new file mode 100644 index 00000000..682480a6 --- /dev/null +++ b/tests/ReactTests/ios/ReactTests/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSLocationWhenInUseUsageDescription + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/tests/ReactTests/ios/ReactTests/main.m b/tests/ReactTests/ios/ReactTests/main.m new file mode 100644 index 00000000..3d767fcb --- /dev/null +++ b/tests/ReactTests/ios/ReactTests/main.m @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/tests/ReactTests/ios/ReactTestsTests/Info.plist b/tests/ReactTests/ios/ReactTestsTests/Info.plist new file mode 100644 index 00000000..ba72822e --- /dev/null +++ b/tests/ReactTests/ios/ReactTestsTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/tests/ReactTests/ios/ReactTestsTests/RealmReactTests.m b/tests/ReactTests/ios/ReactTestsTests/RealmReactTests.m new file mode 100644 index 00000000..58adc9f8 --- /dev/null +++ b/tests/ReactTests/ios/ReactTestsTests/RealmReactTests.m @@ -0,0 +1,120 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +#import "RealmJSTests.h" +#import "Base/RCTJavaScriptExecutor.h" +#import "Base/RCTBridge.h" + +@import RealmReact; + +extern void JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions(JSGlobalContextRef ctx, bool includesNativeCallStack); + +static id s_currentJavaScriptExecutor; + +@interface RealmReactTests : RealmJSTests +@end + +@implementation RealmReactTests + ++ (XCTestSuite *)defaultTestSuite { + NSNotification *notification = [self waitForNotification:RCTJavaScriptDidLoadNotification]; + RCTBridge *bridge = notification.userInfo[@"bridge"]; + + if (!bridge) { + NSLog(@"No RCTBridge provided by RCTJavaScriptDidLoadNotification"); + exit(1); + } + + s_currentJavaScriptExecutor = [bridge valueForKey:@"javaScriptExecutor"]; + + // FIXME: Remove this nonsense once the crashes go away when a test fails! + JSGlobalContextRef ctx = RealmReactGetJSGlobalContextForExecutor(s_currentJavaScriptExecutor, false); + if (ctx) { + JSGlobalContextSetIncludesNativeCallStackWhenReportingExceptions(ctx, false); + } + + NSError *error; + NSDictionary *testCaseNames = [self invokeMethod:@"getTestNames" inModule:@"index" error:&error]; + + if (error || !testCaseNames.count) { + NSLog(@"Error from calling getTestNames() - %@", error ?: @"None returned"); + exit(1); + } + + XCTestSuite *suite = [super defaultTestSuite]; + + for (XCTestSuite *testSuite in [self testSuitesFromDictionary:testCaseNames]) { + [suite addTest:testSuite]; + } + + return suite; +} + ++ (NSNotification *)waitForNotification:(NSString *)notificationName { + NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + __block NSNotification *notification; + + id token = [nc addObserverForName:notificationName object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { + notification = note; + }]; + + while (!notification) { + @autoreleasepool { + [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; + } + } + + [nc removeObserver:token]; + return notification; +} + ++ (id)invokeMethod:(NSString *)method inModule:(NSString *)module error:(NSError * __strong *)outError { + module = [NSString stringWithFormat:@"realm-tests/%@.js", module]; + + dispatch_group_t group = dispatch_group_create(); + __block id result; + + dispatch_group_enter(group); + + [s_currentJavaScriptExecutor executeJSCall:module method:method arguments:@[] callback:^(id json, NSError *error) { + result = json; + + if (error && outError) { + *outError = error; + } + + dispatch_group_leave(group); + }]; + + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + + return result; +} + +- (void)invokeMethod:(NSString *)method { + NSError *error; + [self.class invokeMethod:method inModule:NSStringFromClass(self.class) error:&error]; + + if (error) { + // TODO: Parse and use localizedFailureReason info once we can source map the failure location in JS. + [self recordFailureWithDescription:error.localizedDescription inFile:@(__FILE__) atLine:__LINE__ expected:YES]; + } +} + +@end diff --git a/tests/ReactTests/ios/main.jsbundle b/tests/ReactTests/ios/main.jsbundle new file mode 100644 index 00000000..b702b30c --- /dev/null +++ b/tests/ReactTests/ios/main.jsbundle @@ -0,0 +1,8 @@ +// Offline JS +// To re-generate the offline bundle, run this from the root of your project: +// +// $ react-native bundle --minify +// +// See http://facebook.github.io/react-native/docs/runningondevice.html for more details. + +throw new Error('Offline JS file is empty. See iOS/main.jsbundle for instructions'); diff --git a/tests/ReactTests/package.json b/tests/ReactTests/package.json new file mode 100644 index 00000000..33231d56 --- /dev/null +++ b/tests/ReactTests/package.json @@ -0,0 +1,13 @@ +{ + "name": "ReactTests", + "version": "0.0.1", + "private": true, + "scripts": { + "start": "node_modules/react-native/packager/packager.sh" + }, + "dependencies": { + "react-native": "^0.11.4", + "realm": "file:../../lib", + "realm-tests": "file:.." + } +} diff --git a/tests/RealmJSTests.h b/tests/RealmJSTests.h index 907a9aea..f9f8fc85 100644 --- a/tests/RealmJSTests.h +++ b/tests/RealmJSTests.h @@ -19,13 +19,10 @@ #import #import -extern NSString *RealmPathForFile(NSString *fileName); -extern NSString *TestRealmPath(); - @interface RealmJSTests : XCTestCase -+ (NSString *)jsSuiteName; ++ (NSArray *)testSuitesFromDictionary:(NSDictionary *)testCaseNames; -@property (nonatomic, readonly) JSContext *context; +- (instancetype)initWithTestName:(NSString *)name; @end diff --git a/tests/RealmJSTests.mm b/tests/RealmJSTests.mm index 0f89a761..9811af85 100644 --- a/tests/RealmJSTests.mm +++ b/tests/RealmJSTests.mm @@ -16,87 +16,42 @@ // //////////////////////////////////////////////////////////////////////////// +#import + #import "RealmJSTests.h" -#import "RJSUtil.hpp" -#import "RJSRealm.hpp" - -#import "shared_realm.hpp" - -NSString *RealmPathForFile(NSString *fileName) { -#if TARGET_OS_IPHONE - NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; -#else - NSString *path = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)[0]; - path = [path stringByAppendingPathComponent:[[[NSBundle mainBundle] executablePath] lastPathComponent]]; -#endif - return [path stringByAppendingPathComponent:fileName]; -} - - -NSString *TestRealmPath() { - return RealmPathForFile(@"test.realm"); -} - -static void DeleteOrThrow(NSString *path) { - NSError *error; - if (![[NSFileManager defaultManager] removeItemAtPath:path error:&error]) { - if (error.code != NSFileNoSuchFileError) { - @throw [NSException exceptionWithName:@"RLMTestException" - reason:[@"Unable to delete realm: " stringByAppendingString:error.description] - userInfo:nil]; - } - } -} - -static void DeleteRealmFilesAtPath(NSString *path) { - DeleteOrThrow(path); - DeleteOrThrow([path stringByAppendingString:@".lock"]); - DeleteOrThrow([path stringByAppendingString:@".note"]); -} - -static JSClassRef s_globalClass; - -@interface RealmJSTests () - -@property (nonatomic, strong) JSContext *context; - -@end @implementation RealmJSTests -+ (void)initialize { - JSClassDefinition globalDefinition = kJSClassDefinitionEmpty; - globalDefinition.attributes = kJSClassAttributeNoAutomaticPrototype; - s_globalClass = JSClassCreate(&globalDefinition); ++ (NSArray *)testSuitesFromDictionary:(NSDictionary *)testCaseNames { + NSMutableArray *testSuites = [[NSMutableArray alloc] init]; + + for (NSString *suiteName in testCaseNames) { + XCTestSuite *testSuite = [[XCTestSuite alloc] initWithName:suiteName]; + Class testClass = objc_allocateClassPair(self, suiteName.UTF8String, 0); + + for (NSString *testName in testCaseNames[suiteName]) { + XCTestCase *testCase = [[testClass alloc] initWithTestName:testName]; + [testSuite addTest:testCase]; + } + + [testSuites addObject:testSuite]; + } + + return [testSuites copy]; +} + +- (instancetype)initWithTestName:(NSString *)name { + return [super initWithSelector:NSSelectorFromString(name)]; } - (void)setUp { [super setUp]; - NSString *defaultDir = [[NSString stringWithUTF8String:RJSDefaultPath().c_str()] stringByDeletingLastPathComponent]; - [[NSFileManager defaultManager] createDirectoryAtPath:defaultDir withIntermediateDirectories:YES attributes:nil error:nil]; - - JSGlobalContextRef ctx = JSGlobalContextCreateInGroup(NULL, s_globalClass); - self.context = [JSContext contextWithJSGlobalContextRef:ctx]; - - [RealmJS initializeContext:ctx]; - - [self evaluateScriptWithName:@"TestCase"]; - [self evaluateScriptWithName:@"TestObjects"]; - [self evaluateScriptWithName:self.class.jsSuiteName]; + [self invokeMethod:@"beforeEach"]; } - (void)tearDown { - self.context = nil; - - realm::Realm::s_global_cache.invalidate_all(); - realm::Realm::s_global_cache.clear(); - - // FIXME - find all realm files in the docs dir and delete them rather than hardcoding these - DeleteRealmFilesAtPath(RealmPathForFile(@"test.realm")); - DeleteRealmFilesAtPath(RealmPathForFile(@"test1.realm")); - DeleteRealmFilesAtPath(RealmPathForFile(@"test2.realm")); - DeleteRealmFilesAtPath(@(RJSDefaultPath().c_str())); + [self invokeMethod:@"afterEach"]; [super tearDown]; } @@ -107,155 +62,17 @@ static JSClassRef s_globalClass; } } -- (void)evaluateScriptWithName:(NSString *)name { - NSURL *url = [self.class scriptURLWithName:name]; - NSString *script = [self.class loadScriptWithURL:url]; - - [self evaluateScript:script fromURL:url]; -} - -- (void)evaluateScript:(NSString *)script fromURL:(NSURL *)url { - JSValue *exception; - [self.class evaluateScript:script fromURL:url inContext:self.context exception:&exception]; - - if (exception) { - JSValue *message = [exception hasProperty:@"message"] ? exception[@"message"] : exception; - NSString *source = [exception hasProperty:@"sourceURL"] ? [exception[@"sourceURL"] toString] : nil; - NSUInteger line = [exception hasProperty:@"line"] ? [exception[@"line"] toUInt32] : 0; - NSURL *sourceURL = source ? [NSURL URLWithString:source.lastPathComponent relativeToURL:[NSURL URLWithString:@(__FILE__)]] : nil; - const char *sourcePath = sourceURL.absoluteString.UTF8String; - - _XCTFailureHandler(self, YES, sourcePath ?: __FILE__, sourcePath ? line : __LINE__, @"JS", @"%@", message); - } -} - -+ (JSValue *)evaluateScript:(NSString *)script fromURL:(NSURL *)url inContext:(JSContext *)context exception:(JSValue **)exception { - JSStringRef jsScript = JSStringCreateWithUTF8CString(script.UTF8String); - JSStringRef jsURL = url ? JSStringCreateWithUTF8CString(url.absoluteString.UTF8String) : NULL; - JSValueRef jsException = NULL; - JSValueRef jsResult = JSEvaluateScript(context.JSGlobalContextRef, jsScript, NULL, jsURL, 1, &jsException); - - JSStringRelease(jsScript); - if (jsURL) { - JSStringRelease(jsURL); - } - - if (jsException) { - *exception = [JSValue valueWithJSValueRef:jsException inContext:context]; - return NULL; - } - - return [JSValue valueWithJSValueRef:jsResult inContext:context]; -} - -+ (NSURL *)scriptURLWithName:(NSString *)name { - NSURL *url = [[NSBundle bundleForClass:self] URLForResource:name withExtension:@"js"]; - if (!url) { - NSLog(@"JS file does not exist: %@", url); - exit(1); - } - return url; -} - -+ (NSString *)loadScriptWithURL:(NSURL *)url { - NSError *error; - NSString *script = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error]; - if (!script) { - NSLog(@"Error reading JS file (%@): %@", url, error); - exit(1); - } - return script; -} - -+ (NSString *)jsSuiteName { - return nil; -} - -+ (NSString *)jsSuiteScript { - NSString *name = [self jsSuiteName]; - return name ? [self loadScriptWithURL:[self scriptURLWithName:name]] : nil; -} - -+ (XCTestSuite *)defaultTestSuite { - XCTestSuite *suite = [super defaultTestSuite]; - NSString *suiteName = [self jsSuiteName]; - NSURL *scriptURL = suiteName ? [self scriptURLWithName:suiteName] : nil; - NSString *script = scriptURL ? [self loadScriptWithURL:scriptURL] : nil; - if (!script) { - return suite; - } - - JSContext *context = [[JSContext alloc] init]; - JSValue *exception; - - [self evaluateScript:script fromURL:scriptURL inContext:context exception:&exception]; - if (exception) { - NSLog(@"%@.js - %@", suiteName, exception); - exit(1); - } - - JSValue *suiteObject = [self evaluateScript:suiteName fromURL:nil inContext:context exception:&exception]; - if (exception) { - NSLog(@"%@.js - %@", suiteName, exception); - exit(1); - } - - if (![suiteObject isObject]) { - NSLog(@"%@.js - JS test suite is not an object: %@", suiteName, suiteObject); - exit(1); - } - - for (NSString *testName in [suiteObject toDictionary]) { - [suite addTest:[self testCaseWithSelector:NSSelectorFromString(testName)]]; - } - - return suite; -} - - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { NSMethodSignature *sig = [super methodSignatureForSelector:aSelector]; - if (sig) { - return sig; - } - return [NSMethodSignature signatureWithObjCTypes:"v@:"]; + return sig ?: [NSMethodSignature signatureWithObjCTypes:"v@:"]; } - (void)forwardInvocation:(NSInvocation *)anInvocation { - NSString *script = [NSString stringWithFormat:@"%@.%@();", [self.class jsSuiteName], NSStringFromSelector(anInvocation.selector)]; - [self evaluateScript:script fromURL:nil]; + [self invokeMethod:NSStringFromSelector(anInvocation.selector)]; +} + +- (void)invokeMethod:(NSString *)method { + [self doesNotRecognizeSelector:_cmd]; } @end - -@interface RJSResultsTests : RealmJSTests -@end -@implementation RJSResultsTests -+ (NSString *)jsSuiteName { - return @"ResultsTests"; -} -@end - -@interface RJSObjectTests : RealmJSTests -@end -@implementation RJSObjectTests -+ (NSString *)jsSuiteName { - return @"ObjectTests"; -} -@end - -@interface RJSListTests : RealmJSTests -@end -@implementation RJSListTests -+ (NSString *)jsSuiteName { - return @"ArrayTests"; -} -@end - -@interface RJSRealmTests : RealmJSTests -@end -@implementation RJSRealmTests -+ (NSString *)jsSuiteName { - return @"RealmTests"; -} -@end - diff --git a/tests/RealmTests.js b/tests/RealmTests.js index 8773f581..b75360f2 100644 --- a/tests/RealmTests.js +++ b/tests/RealmTests.js @@ -18,10 +18,16 @@ 'use strict'; -var RealmTests = { +var Realm = require('realm'); +var BaseTest = require('./base-test'); +var TestCase = require('./asserts'); +var schemas = require('./schemas'); +var util = require('./util'); + +module.exports = BaseTest.extend({ testRealmConstructorPath: function() { TestCase.assertThrows(function() { new Realm('/invalidpath'); }); - TestCase.assertThrows(function() { new Realm(TestUtil.realmPathForFile('test1.realm'), 'invalidArgument'); }); + TestCase.assertThrows(function() { new Realm(util.realmPathForFile('test1.realm'), 'invalidArgument'); }); var defaultRealm = new Realm({schema: []}); TestCase.assertEqual(defaultRealm.path, Realm.defaultPath); @@ -29,12 +35,12 @@ var RealmTests = { var defaultRealm2 = new Realm(); TestCase.assertEqual(defaultRealm2.path, Realm.defaultPath); - var testPath = TestUtil.realmPathForFile('test1.realm'); + var testPath = util.realmPathForFile('test1.realm'); var realm = new Realm({schema: [], path: testPath}); //TestCase.assertTrue(realm instanceof Realm); TestCase.assertEqual(realm.path, testPath); - var testPath2 = TestUtil.realmPathForFile('test2.realm'); + var testPath2 = util.realmPathForFile('test2.realm'); var realm2 = new Realm({schema: [], path: testPath2}); //TestCase.assertTrue(realm2 instanceof Realm); TestCase.assertEqual(realm2.path, testPath2); @@ -51,7 +57,7 @@ var RealmTests = { TestCase.assertEqual(new Realm().schemaVersion, 0); TestCase.assertEqual(new Realm({schemaVersion: 0}).schemaVersion, 0); - var testPath = TestUtil.realmPathForFile('test1.realm'); + var testPath = util.realmPathForFile('test1.realm'); var realm = new Realm({path: testPath, schema: [], schemaVersion: 1}); TestCase.assertEqual(realm.schemaVersion, 1); // FIXME - enable once Realm exposes a schema object @@ -60,10 +66,10 @@ var RealmTests = { realm.close(); // FIXME - enable once realm initialization supports schema comparison // TestCase.assertThrows(function() { - // realm = new Realm({path: testPath, schema: [TestObjectSchema], schemaVersion: 1}); + // realm = new Realm({path: testPath, schema: [schemas.TestObject], schemaVersion: 1}); // }, "schema changes require updating the schema version"); - realm = new Realm({path: testPath, schema: [TestObjectSchema], schemaVersion: 2}); + realm = new Realm({path: testPath, schema: [schemas.TestObject], schemaVersion: 2}); realm.write(function() { realm.create('TestObject', [1]); }); @@ -74,7 +80,7 @@ var RealmTests = { var defaultRealm = new Realm({schema: []}); TestCase.assertEqual(defaultRealm.path, Realm.defaultPath); - var newPath = TestUtil.realmPathForFile('default2.realm'); + var newPath = util.realmPathForFile('default2.realm'); Realm.defaultPath = newPath; defaultRealm = new Realm({schema: []}); TestCase.assertEqual(defaultRealm.path, newPath); @@ -83,7 +89,7 @@ var RealmTests = { }, testRealmCreate: function() { - var realm = new Realm({schema: [IntPrimaryObjectSchema, AllTypesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.IntPrimary, schemas.AllTypes, schemas.TestObject]}); TestCase.assertThrows(function() { realm.create('TestObject', [1]); @@ -159,25 +165,25 @@ var RealmTests = { }, testRealmCreateWithDefaults: function() { - var realm = new Realm({schema: [DefaultValuesObjectSchema, TestObjectSchema]}); + var realm = new Realm({schema: [schemas.DefaultValues, schemas.TestObject]}); realm.write(function() { var obj = realm.create('DefaultValuesObject', {}); - TestCase.assertEqual(obj.boolCol, DefaultValuesObjectSchema.properties[0].default); - TestCase.assertEqual(obj.intCol, DefaultValuesObjectSchema.properties[1].default); - TestCase.assertEqualWithTolerance(obj.floatCol, DefaultValuesObjectSchema.properties[2].default, 0.000001); - TestCase.assertEqual(obj.doubleCol, DefaultValuesObjectSchema.properties[3].default); - TestCase.assertEqual(obj.stringCol, DefaultValuesObjectSchema.properties[4].default); - TestCase.assertEqual(obj.dateCol.getTime(), DefaultValuesObjectSchema.properties[5].default.getTime()); - TestCase.assertEqual(obj.dataCol, DefaultValuesObjectSchema.properties[6].default); - TestCase.assertEqual(obj.objectCol.doubleCol, DefaultValuesObjectSchema.properties[7].default[0]); + TestCase.assertEqual(obj.boolCol, schemas.DefaultValues.properties[0].default); + TestCase.assertEqual(obj.intCol, schemas.DefaultValues.properties[1].default); + TestCase.assertEqualWithTolerance(obj.floatCol, schemas.DefaultValues.properties[2].default, 0.000001); + TestCase.assertEqual(obj.doubleCol, schemas.DefaultValues.properties[3].default); + TestCase.assertEqual(obj.stringCol, schemas.DefaultValues.properties[4].default); + TestCase.assertEqual(obj.dateCol.getTime(), schemas.DefaultValues.properties[5].default.getTime()); + TestCase.assertEqual(obj.dataCol, schemas.DefaultValues.properties[6].default); + TestCase.assertEqual(obj.objectCol.doubleCol, schemas.DefaultValues.properties[7].default[0]); TestCase.assertEqual(obj.nullObjectCol, null); - TestCase.assertEqual(obj.arrayCol.length, DefaultValuesObjectSchema.properties[9].default.length); - TestCase.assertEqual(obj.arrayCol[0].doubleCol, DefaultValuesObjectSchema.properties[9].default[0][0]); + TestCase.assertEqual(obj.arrayCol.length, schemas.DefaultValues.properties[9].default.length); + TestCase.assertEqual(obj.arrayCol[0].doubleCol, schemas.DefaultValues.properties[9].default[0][0]); }); }, testRealmDelete: function() { - var realm = new Realm({schema: [TestObjectSchema]}); + var realm = new Realm({schema: [schemas.TestObject]}); realm.write(function() { for (var i = 0; i < 10; i++) { realm.create('TestObject', [i]); @@ -213,7 +219,7 @@ var RealmTests = { }, testDeleteAll: function() { - var realm = new Realm({schema: [TestObjectSchema, IntPrimaryObjectSchema]}); + var realm = new Realm({schema: [schemas.TestObject, schemas.IntPrimary]}); realm.write(function() { realm.create('TestObject', [1]); realm.create('TestObject', [2]); @@ -235,7 +241,7 @@ var RealmTests = { }, testRealmObjects: function() { - var realm = new Realm({schema: [PersonObject]}); + var realm = new Realm({schema: [schemas.PersonObject]}); realm.write(function() { realm.create('PersonObject', ['Ari', 10]); realm.create('PersonObject', ['Tim', 11]); @@ -286,5 +292,4 @@ var RealmTests = { TestCase.assertEqual(notificationCount, 1); TestCase.assertEqual(notificationName, 'DidChangeNotification'); }, -}; - +}); diff --git a/tests/ResultsTests.js b/tests/ResultsTests.js index b0db81ad..c3180c24 100644 --- a/tests/ResultsTests.js +++ b/tests/ResultsTests.js @@ -18,9 +18,14 @@ 'use strict'; -var ResultsTests = { +var Realm = require('realm'); +var BaseTest = require('./base-test'); +var TestCase = require('./asserts'); +var schemas = require('./schemas'); + +module.exports = BaseTest.extend({ testResultsLength: function() { - var realm = new Realm({schema: [TestObjectSchema]}); + var realm = new Realm({schema: [schemas.TestObject]}); var objects = realm.objects('TestObject'); TestCase.assertEqual(objects.length, 0); @@ -31,7 +36,7 @@ var ResultsTests = { TestCase.assertEqual(objects.length, 1); }, testResultsSubscript: function() { - var realm = new Realm({schema: [PersonObject]}); + var realm = new Realm({schema: [schemas.PersonObject]}); realm.write(function() { realm.create('PersonObject', ['name1', 1]); realm.create('PersonObject', ['name2', 2]); @@ -42,21 +47,21 @@ var ResultsTests = { TestCase.assertEqual(people[1].age, 2); TestCase.assertEqual(people[2], undefined); TestCase.assertEqual(people[-1], undefined); - TestCase.assertTrue(Object.getPrototypeOf(people[0]) === PersonObject.prototype); + TestCase.assertTrue(Object.getPrototypeOf(people[0]) === schemas.PersonObject.prototype); }, testResultsInvalidProperty: function() { - var realm = new Realm({schema: [TestObjectSchema]}); + var realm = new Realm({schema: [schemas.TestObject]}); var objects = realm.objects('TestObject'); TestCase.assertEqual(undefined, objects.ablasdf); }, testResultsInvalidObjectType: function() { - var realm = new Realm({schema: [TestObjectSchema]}); + var realm = new Realm({schema: [schemas.TestObject]}); TestCase.assertThrows(function() { var objects = realm.objects('NotTestObject'); }); }, testResultsEnumerate: function() { - var realm = new Realm({schema: [TestObjectSchema]}); + var realm = new Realm({schema: [schemas.TestObject]}); var objects = realm.objects('TestObject'); for (var object in objects) { TestCase.assertTrue(false, "No objects should have been enumerated"); @@ -75,7 +80,7 @@ var ResultsTests = { TestCase.assertEqual(1, count); }, testSort: function() { - var realm = new Realm({schema: [TestObjectSchema]}); + var realm = new Realm({schema: [schemas.TestObject]}); var objects = realm.objects('TestObject'); realm.write(function() { realm.create('TestObject', [2]); @@ -99,4 +104,4 @@ var ResultsTests = { TestCase.assertEqual(objects[3].doubleCol, 1); TestCase.assertEqual(objects[4].doubleCol, 0); }, -} +}); diff --git a/tests/TestCase.js b/tests/asserts.js similarity index 92% rename from tests/TestCase.js rename to tests/asserts.js index 48761f92..7f65eea8 100644 --- a/tests/TestCase.js +++ b/tests/asserts.js @@ -18,14 +18,7 @@ 'use strict'; -var TestUtil = { - realmPathForFile: function(str) { - var path = Realm.defaultPath; - return path.substring(0, path.lastIndexOf("/") + 1) + str; - }, -}; - -var TestCase = { +module.exports = { assertEqual: function(val1, val2, errorMessage) { if (val1 !== val2) { var message = "'" + val1 + "' does not equal expected value '" + val2 + "'"; @@ -75,7 +68,7 @@ var TestCase = { throw new TestFailureError(errorMessage || 'Condition expected to be true'); }; }, -} +}; function TestFailureError(message) { var error; @@ -87,7 +80,7 @@ function TestFailureError(message) { // This regular expression will match stack trace lines provided by JavaScriptCore. // Example: someMethod@file:///path/to/file.js:10:24 - var regex = /^(?:.*?@)?([^\[\(].+?):(\d+)(?::(\d+))?/; + var regex = /^(?:.*?@)?([^\[\(].+?):(\d+)(?::(\d+))?\s*$/; // Remove the top two stack frames and use information from the third, if possible. var stack = error.stack && error.stack.split('\n'); diff --git a/tests/base-test.js b/tests/base-test.js new file mode 100644 index 00000000..b299e70e --- /dev/null +++ b/tests/base-test.js @@ -0,0 +1,41 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +'use strict'; + +var Realm = require('realm'); + +var prototype = exports.prototype = {}; + +exports.extend = function(object) { + object.__proto__ = prototype; + return object; +}; + +Object.defineProperties(prototype, { + // TODO: Remove once missing undefined check is fixed inside RCTContextExecutor. + beforeEach: { + value: function() {} + }, + + afterEach: { + value: function() { + Realm.clearTestState(); + } + } +}); diff --git a/tests/index.js b/tests/index.js new file mode 100644 index 00000000..37b7901b --- /dev/null +++ b/tests/index.js @@ -0,0 +1,45 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +'use strict'; + +exports.ArrayTests = require('./ArrayTests'); +exports.ObjectTests = require('./ObjectTests'); +exports.RealmTests = require('./RealmTests'); +exports.ResultsTests = require('./ResultsTests'); + +var SPECIAL_METHODS = { + beforeEach: true, + afterEach: true, +}; + +Object.defineProperty(exports, 'getTestNames', { + value: function() { + var testNames = {}; + + for (var suiteName in exports) { + var testSuite = exports[suiteName]; + + testNames[suiteName] = Object.keys(testSuite).filter(function(testName) { + return !(testName in SPECIAL_METHODS) && typeof testSuite[testName] == 'function'; + }); + } + + return testNames; + } +}); diff --git a/tests/package.json b/tests/package.json new file mode 100644 index 00000000..36ce6dfb --- /dev/null +++ b/tests/package.json @@ -0,0 +1,8 @@ +{ + "name": "realm-tests", + "version": "0.0.1", + "private": true, + "dependencies": { + "realm": "file:../lib" + } +} diff --git a/tests/TestObjects.js b/tests/schemas.js similarity index 94% rename from tests/TestObjects.js rename to tests/schemas.js index b905a206..407bf171 100644 --- a/tests/TestObjects.js +++ b/tests/schemas.js @@ -18,7 +18,9 @@ 'use strict'; -var TestObjectSchema = { +var Realm = require('realm'); + +exports.TestObject = { name: 'TestObject', properties: [ {name: 'doubleCol', type: Realm.Types.DOUBLE}, @@ -36,8 +38,9 @@ PersonObject.prototype.schema = { PersonObject.prototype.description = function() { return this.name + ' ' + this.age; }; +exports.PersonObject = PersonObject; -var BasicTypesObjectSchema = { +exports.BasicTypes = { name: 'BasicTypesObject', properties: [ {name: 'boolCol', type: Realm.Types.BOOL}, @@ -50,7 +53,7 @@ var BasicTypesObjectSchema = { ] }; -var LinkTypesObjectSchema = { +exports.LinkTypes = { name: 'LinkTypesObject', properties: [ {name: 'objectCol', type: 'TestObject'}, @@ -59,7 +62,7 @@ var LinkTypesObjectSchema = { ] }; -var IntPrimaryObjectSchema = { +exports.IntPrimary = { name: 'IntPrimaryObject', primaryKey: 'primaryCol', properties: [ @@ -68,7 +71,7 @@ var IntPrimaryObjectSchema = { ] }; -var AllTypesObjectSchema = { +exports.AllTypes = { name: 'AllTypesObject', primaryKey: 'primaryCol', properties: [ @@ -85,7 +88,7 @@ var AllTypesObjectSchema = { ] }; -var DefaultValuesObjectSchema = { +exports.DefaultValues = { name: 'DefaultValuesObject', properties: [ {name: 'boolCol', type: Realm.Types.BOOL, default: true}, @@ -100,4 +103,3 @@ var DefaultValuesObjectSchema = { {name: 'arrayCol', type: Realm.Types.LIST, objectType: 'TestObject', default: [[2]]}, ] }; - diff --git a/tests/util.js b/tests/util.js new file mode 100644 index 00000000..6b1b1bb7 --- /dev/null +++ b/tests/util.js @@ -0,0 +1,26 @@ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// + +'use strict'; + +var Realm = require('realm'); + +exports.realmPathForFile = function(str) { + var path = Realm.defaultPath; + return path.substring(0, path.lastIndexOf("/") + 1) + str; +};