mirror of
https://github.com/status-im/realm-js.git
synced 2025-02-02 17:53:55 +00:00
Merge pull request #199 from realm/sk-listview
Efficient React ListView for Realm collections
This commit is contained in:
commit
d9abcf0bc2
@ -6,10 +6,24 @@
|
|||||||
"ecmaFeatures": {
|
"ecmaFeatures": {
|
||||||
"jsx": true
|
"jsx": true
|
||||||
},
|
},
|
||||||
|
"globals": {
|
||||||
|
"cancelAnimationFrame": false,
|
||||||
|
"clearImmediate": false,
|
||||||
|
"clearInterval": false,
|
||||||
|
"clearTimeout": false,
|
||||||
|
"console": false,
|
||||||
|
"global": false,
|
||||||
|
"requestAnimationFrame": false,
|
||||||
|
"setImmediate": false,
|
||||||
|
"setInterval": false,
|
||||||
|
"setTimeout": false
|
||||||
|
},
|
||||||
|
"parser": "babel-eslint",
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"react"
|
"react"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"strict": 0,
|
||||||
"react/jsx-no-duplicate-props": 2,
|
"react/jsx-no-duplicate-props": 2,
|
||||||
"react/jsx-no-undef": 2,
|
"react/jsx-no-undef": 2,
|
||||||
"react/jsx-uses-react": 2,
|
"react/jsx-uses-react": 2,
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Realm = require('realm');
|
import Realm from 'realm';
|
||||||
|
|
||||||
module.exports = new Realm({
|
export default new Realm({
|
||||||
schema: [
|
schema: [
|
||||||
{
|
{
|
||||||
name: 'Todo',
|
name: 'Todo',
|
||||||
|
@ -4,14 +4,16 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('react-native');
|
import {
|
||||||
|
Navigator,
|
||||||
|
Platform,
|
||||||
|
StyleSheet
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
const { Navigator, Platform, StyleSheet } = React;
|
|
||||||
const { NavBarHeight, TotalNavHeight } = Navigator.NavigationBar.Styles.General;
|
const { NavBarHeight, TotalNavHeight } = Navigator.NavigationBar.Styles.General;
|
||||||
|
|
||||||
const iOS = (Platform.OS == 'ios');
|
const iOS = (Platform.OS == 'ios');
|
||||||
|
|
||||||
module.exports = StyleSheet.create({
|
export default StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
|
@ -4,21 +4,21 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('react-native');
|
import React, {
|
||||||
const TodoItem = require('./todo-item');
|
Component,
|
||||||
const TodoListView = require('./todo-listview');
|
|
||||||
const realm = require('./realm');
|
|
||||||
const styles = require('./styles');
|
|
||||||
|
|
||||||
const {
|
|
||||||
Navigator,
|
Navigator,
|
||||||
StatusBarIOS,
|
StatusBarIOS,
|
||||||
Text,
|
Text,
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
View,
|
View,
|
||||||
} = React;
|
} from 'react-native';
|
||||||
|
|
||||||
class TodoApp extends React.Component {
|
import TodoItem from './todo-item';
|
||||||
|
import TodoListView from './todo-listview';
|
||||||
|
import realm from './realm';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
|
export default class TodoApp extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@ -150,8 +150,11 @@ class TodoApp extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_setEditingRow(rowIndex) {
|
_setEditingRow(rowIndex) {
|
||||||
|
let listView = this.currentListView;
|
||||||
|
|
||||||
// Update the state on the currently displayed TodoList to edit this new item.
|
// Update the state on the currently displayed TodoList to edit this new item.
|
||||||
this.currentListView.setState({editingRow: rowIndex});
|
listView.setState({editingRow: rowIndex});
|
||||||
|
listView.updateDataSource();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,5 +203,3 @@ const RouteMapper = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = TodoApp;
|
|
||||||
|
@ -4,14 +4,17 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('react-native');
|
import React, {
|
||||||
const TodoListItem = require('./todo-list-item');
|
Text,
|
||||||
const realm = require('./realm');
|
TouchableWithoutFeedback,
|
||||||
const styles = require('./styles');
|
View,
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
const { Text, TouchableWithoutFeedback, View } = React;
|
import TodoListItem from './todo-list-item';
|
||||||
|
import realm from './realm';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
class TodoItem extends TodoListItem {
|
export default class TodoItem extends TodoListItem {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@ -56,5 +59,3 @@ class TodoItem extends TodoListItem {
|
|||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = TodoItem;
|
|
||||||
|
@ -4,21 +4,20 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('react-native');
|
import React, {
|
||||||
const realm = require('./realm');
|
|
||||||
const styles = require('./styles');
|
|
||||||
|
|
||||||
const {
|
|
||||||
Platform,
|
Platform,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
TouchableWithoutFeedback,
|
TouchableWithoutFeedback,
|
||||||
View,
|
View,
|
||||||
} = React;
|
} from 'react-native';
|
||||||
|
|
||||||
|
import realm from './realm';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
const iOS = (Platform.OS == 'ios');
|
const iOS = (Platform.OS == 'ios');
|
||||||
|
|
||||||
class TodoListItem extends React.Component {
|
export default class TodoListItem extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@ -123,5 +122,3 @@ class TodoListItem extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = TodoListItem;
|
|
||||||
|
@ -4,26 +4,38 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('react-native');
|
import React, {
|
||||||
const TodoListItem = require('./todo-list-item');
|
Text,
|
||||||
const realm = require('./realm');
|
View,
|
||||||
const styles = require('./styles');
|
} from 'react-native';
|
||||||
|
|
||||||
const { ListView, Text, View } = React;
|
import { ListView } from 'realm/react-native';
|
||||||
|
import TodoListItem from './todo-list-item';
|
||||||
|
import realm from './realm';
|
||||||
|
import styles from './styles';
|
||||||
|
|
||||||
class TodoListView extends React.Component {
|
export default class TodoListView extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.dataSource = new ListView.DataSource({
|
let dataSource = new ListView.DataSource({
|
||||||
sectionHeaderHasChanged: () => false,
|
rowHasChanged(a, b) {
|
||||||
rowHasChanged: (row1, row2) => row1 !== row2
|
// Always re-render TodoList items.
|
||||||
|
return a.done !== b.done || a.text !== b.text || a.items || b.items;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.state = {};
|
this.state = {
|
||||||
|
dataSource: this._cloneDataSource(dataSource, props),
|
||||||
|
};
|
||||||
|
|
||||||
this.renderRow = this.renderRow.bind(this);
|
this.renderRow = this.renderRow.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(props) {
|
||||||
|
this.updateDataSource(props);
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
let items = this.props.items;
|
let items = this.props.items;
|
||||||
let editingRow = this.state.editingRow;
|
let editingRow = this.state.editingRow;
|
||||||
@ -43,19 +55,9 @@ class TodoListView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// Clone the items into a new Array to prevent unexpected errors from changes in length.
|
|
||||||
let sections = [Array.from(this.props.items)];
|
|
||||||
let extraItems = this.props.extraItems;
|
|
||||||
|
|
||||||
if (extraItems && extraItems.length) {
|
|
||||||
sections.push(extraItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
let dataSource = this.dataSource.cloneWithRowsAndSections(sections);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<ListView style={styles.listView} dataSource={dataSource} renderRow={this.renderRow} />
|
<ListView dataSource={this.state.dataSource} renderRow={this.renderRow} />
|
||||||
<Text style={styles.instructions}>
|
<Text style={styles.instructions}>
|
||||||
Press Cmd+R to reload,{'\n'}
|
Press Cmd+R to reload,{'\n'}
|
||||||
Cmd+D for dev menu
|
Cmd+D for dev menu
|
||||||
@ -85,6 +87,24 @@ class TodoListView extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateDataSource(props=this.props) {
|
||||||
|
this.setState({
|
||||||
|
dataSource: this._cloneDataSource(this.state.dataSource, props),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_cloneDataSource(dataSource, props) {
|
||||||
|
let items = props.items;
|
||||||
|
let extraItems = props.extraItems;
|
||||||
|
let sections = [items ? items.snapshot() : []];
|
||||||
|
|
||||||
|
if (extraItems && extraItems.length) {
|
||||||
|
sections.push(extraItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataSource.cloneWithRowsAndSections(sections);
|
||||||
|
}
|
||||||
|
|
||||||
_onPressRow(item, sectionIndex, rowIndex) {
|
_onPressRow(item, sectionIndex, rowIndex) {
|
||||||
let onPressItem = this.props.onPressItem;
|
let onPressItem = this.props.onPressItem;
|
||||||
if (onPressItem) {
|
if (onPressItem) {
|
||||||
@ -100,12 +120,13 @@ class TodoListView extends React.Component {
|
|||||||
|
|
||||||
_onPressDeleteRow(item) {
|
_onPressDeleteRow(item) {
|
||||||
this._deleteItem(item);
|
this._deleteItem(item);
|
||||||
this.forceUpdate();
|
this.updateDataSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onEndEditingRow(item, rowIndex) {
|
_onEndEditingRow(item, rowIndex) {
|
||||||
this._deleteItemIfEmpty(item);
|
if (this._deleteItemIfEmpty(item)) {
|
||||||
|
this.updateDataSource();
|
||||||
|
}
|
||||||
if (this.state.editingRow == rowIndex) {
|
if (this.state.editingRow == rowIndex) {
|
||||||
this.setState({editingRow: null});
|
this.setState({editingRow: null});
|
||||||
}
|
}
|
||||||
@ -155,5 +176,3 @@ class TodoListExtraItem extends TodoListItem {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = TodoListView;
|
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
/* Copyright 2015 Realm Inc - All Rights Reserved
|
/* Copyright 2016 Realm Inc - All Rights Reserved
|
||||||
* Proprietary and Confidential
|
* Proprietary and Confidential
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('react-native');
|
import './main';
|
||||||
const TodoApp = require('./components/todo-app');
|
|
||||||
|
|
||||||
React.AppRegistry.registerComponent('ReactExample', () => TodoApp);
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
/* Copyright 2015 Realm Inc - All Rights Reserved
|
/* Copyright 2016 Realm Inc - All Rights Reserved
|
||||||
* Proprietary and Confidential
|
* Proprietary and Confidential
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const React = require('react-native');
|
// Allow our test harness to test this app.
|
||||||
const TodoApp = require('./components/todo-app');
|
import './tests';
|
||||||
|
import './main';
|
||||||
React.AppRegistry.registerComponent('ReactExample', () => TodoApp);
|
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
|
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
|
||||||
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
|
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
|
||||||
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
|
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
|
||||||
027798491BBB2F1000C96559 /* ReactExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 027798481BBB2F1000C96559 /* ReactExampleTests.m */; };
|
|
||||||
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
|
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
|
||||||
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
|
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
|
||||||
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
|
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
|
||||||
@ -24,6 +23,8 @@
|
|||||||
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
|
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
|
||||||
F6C4656F1C48DBE900E79896 /* RealmReact.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6C465551C48D4C300E79896 /* RealmReact.framework */; };
|
F6C4656F1C48DBE900E79896 /* RealmReact.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6C465551C48D4C300E79896 /* RealmReact.framework */; };
|
||||||
F6C465701C48DBF700E79896 /* RealmReact.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F6C465551C48D4C300E79896 /* RealmReact.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
F6C465701C48DBF700E79896 /* RealmReact.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F6C465551C48D4C300E79896 /* RealmReact.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
|
F6DC9DE51C519CFF00ED587E /* RealmJSTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F6DC9DE41C519CFF00ED587E /* RealmJSTests.mm */; };
|
||||||
|
F6DC9DE71C519D2300ED587E /* RealmReactTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F6DC9DE61C519D2300ED587E /* RealmReactTests.m */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -170,7 +171,6 @@
|
|||||||
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = "<group>"; };
|
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = "<group>"; };
|
||||||
0270BC9E1B7D04D700010E03 /* RealmJS.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RealmJS.xcodeproj; path = ../../../RealmJS.xcodeproj; sourceTree = "<group>"; };
|
0270BC9E1B7D04D700010E03 /* RealmJS.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RealmJS.xcodeproj; path = ../../../RealmJS.xcodeproj; sourceTree = "<group>"; };
|
||||||
027798461BBB2F1000C96559 /* ReactExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReactExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
027798461BBB2F1000C96559 /* ReactExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ReactExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
027798481BBB2F1000C96559 /* ReactExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ReactExampleTests.m; sourceTree = "<group>"; };
|
|
||||||
0277984A1BBB2F1000C96559 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
0277984A1BBB2F1000C96559 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
|
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
|
||||||
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
|
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
|
||||||
@ -184,6 +184,9 @@
|
|||||||
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
|
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
|
||||||
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
|
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
|
||||||
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
|
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
|
||||||
|
F6DC9DE31C519CFF00ED587E /* RealmJSTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RealmJSTests.h; path = ../../../../tests/ios/RealmJSTests.h; sourceTree = "<group>"; };
|
||||||
|
F6DC9DE41C519CFF00ED587E /* RealmJSTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RealmJSTests.mm; path = ../../../../tests/ios/RealmJSTests.mm; sourceTree = "<group>"; };
|
||||||
|
F6DC9DE61C519D2300ED587E /* RealmReactTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RealmReactTests.m; path = "../../../../tests/react-test-app/ios/ReactTests/RealmReactTests.m"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -258,7 +261,9 @@
|
|||||||
027798471BBB2F1000C96559 /* ReactExampleTests */ = {
|
027798471BBB2F1000C96559 /* ReactExampleTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
027798481BBB2F1000C96559 /* ReactExampleTests.m */,
|
F6DC9DE31C519CFF00ED587E /* RealmJSTests.h */,
|
||||||
|
F6DC9DE41C519CFF00ED587E /* RealmJSTests.mm */,
|
||||||
|
F6DC9DE61C519D2300ED587E /* RealmReactTests.m */,
|
||||||
0277984A1BBB2F1000C96559 /* Info.plist */,
|
0277984A1BBB2F1000C96559 /* Info.plist */,
|
||||||
);
|
);
|
||||||
path = ReactExampleTests;
|
path = ReactExampleTests;
|
||||||
@ -644,7 +649,7 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "../node_modules/react-native/packager/react-native-xcode.sh";
|
shellScript = "[ \"$PLATFORM_NAME\" = \"iphonesimulator\" ] && exit\n../node_modules/react-native/packager/react-native-xcode.sh";
|
||||||
};
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
@ -653,7 +658,8 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
027798491BBB2F1000C96559 /* ReactExampleTests.m in Sources */,
|
F6DC9DE71C519D2300ED587E /* RealmReactTests.m in Sources */,
|
||||||
|
F6DC9DE51C519CFF00ED587E /* RealmJSTests.mm in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -698,7 +704,6 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
ENABLE_TESTABILITY = YES;
|
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
INFOPLIST_FILE = ReactExampleTests/Info.plist;
|
INFOPLIST_FILE = ReactExampleTests/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
/* Copyright 2015 Realm Inc - All Rights Reserved
|
|
||||||
* Proprietary and Confidential
|
|
||||||
*/
|
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
|
||||||
#import <XCTest/XCTest.h>
|
|
||||||
|
|
||||||
#import "RCTLog.h"
|
|
||||||
#import "RCTRootView.h"
|
|
||||||
|
|
||||||
#define TIMEOUT_SECONDS 10
|
|
||||||
#define TEXT_TO_LOOK_FOR @"Todo Items"
|
|
||||||
|
|
||||||
@interface ReactExampleTests : XCTestCase
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation ReactExampleTests
|
|
||||||
|
|
||||||
- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
|
|
||||||
{
|
|
||||||
if (test(view)) {
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
for (UIView *subview in [view subviews]) {
|
|
||||||
if ([self findSubviewInView:subview matching:test]) {
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)testLaunched
|
|
||||||
{
|
|
||||||
UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
|
|
||||||
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
|
|
||||||
BOOL foundElement = NO;
|
|
||||||
|
|
||||||
__block NSString *redboxError = nil;
|
|
||||||
RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
|
|
||||||
if (level >= RCTLogLevelError) {
|
|
||||||
redboxError = message;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
|
|
||||||
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
|
||||||
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
|
||||||
|
|
||||||
foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
|
|
||||||
if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
RCTSetLogFunction(RCTDefaultLogFunction);
|
|
||||||
|
|
||||||
XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
|
|
||||||
//XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
10
examples/ReactExample/main.js
Normal file
10
examples/ReactExample/main.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/* Copyright 2016 Realm Inc - All Rights Reserved
|
||||||
|
* Proprietary and Confidential
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import { AppRegistry } from 'react-native';
|
||||||
|
import TodoApp from './components/todo-app';
|
||||||
|
|
||||||
|
AppRegistry.registerComponent('ReactExample', () => TodoApp);
|
16
examples/ReactExample/tests/example-test.js
Normal file
16
examples/ReactExample/tests/example-test.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* Copyright 2016 Realm Inc - All Rights Reserved
|
||||||
|
* Proprietary and Confidential
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getRootComponent,
|
||||||
|
assertChildExists,
|
||||||
|
} from './util';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
async testTodoAppRendered() {
|
||||||
|
assertChildExists(await getRootComponent(), 'TodoApp');
|
||||||
|
},
|
||||||
|
}
|
56
examples/ReactExample/tests/index.js
Normal file
56
examples/ReactExample/tests/index.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* Copyright 2016 Realm Inc - All Rights Reserved
|
||||||
|
* Proprietary and Confidential
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import {
|
||||||
|
NativeAppEventEmitter,
|
||||||
|
NativeModules,
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
|
import ExampleTest from './example-test';
|
||||||
|
|
||||||
|
const TESTS = {
|
||||||
|
ExampleTest,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SPECIAL_METHODS = {
|
||||||
|
beforeEach: true,
|
||||||
|
afterEach: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Listen for event to run a particular test.
|
||||||
|
NativeAppEventEmitter.addListener('realm-run-test', async ({suite, name}) => {
|
||||||
|
let testSuite = TESTS[suite];
|
||||||
|
let testMethod = testSuite && testSuite[name];
|
||||||
|
let error;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (testMethod) {
|
||||||
|
await testMethod.call(testSuite);
|
||||||
|
} else if (!testSuite || !(name in SPECIAL_METHODS)) {
|
||||||
|
throw new Error('Missing test: ' + suite + '.' + name);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
error = '' + e;
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeModules.Realm.emit('realm-test-finished', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Inform the native test harness about the test suite once it's ready.
|
||||||
|
setTimeout(() => {
|
||||||
|
NativeModules.Realm.emit('realm-test-names', getTestNames());
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
function getTestNames() {
|
||||||
|
let testNames = {};
|
||||||
|
|
||||||
|
for (let suiteName in TESTS) {
|
||||||
|
let testSuite = TESTS[suiteName];
|
||||||
|
testNames[suiteName] = Object.keys(testSuite);
|
||||||
|
}
|
||||||
|
|
||||||
|
return testNames;
|
||||||
|
}
|
59
examples/ReactExample/tests/util.js
Normal file
59
examples/ReactExample/tests/util.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/* Copyright 2016 Realm Inc - All Rights Reserved
|
||||||
|
* Proprietary and Confidential
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import React from 'react-native';
|
||||||
|
|
||||||
|
const rootComponentPromise = new Promise((resolve) => {
|
||||||
|
// Require internal module here so the promise is rejected if there is an error.
|
||||||
|
let Mount = require('react-native/Libraries/ReactNative/ReactNativeMount');
|
||||||
|
let renderComponent = Mount.renderComponent;
|
||||||
|
|
||||||
|
Mount.renderComponent = function() {
|
||||||
|
let component = renderComponent.apply(this, arguments);
|
||||||
|
|
||||||
|
resolve(component);
|
||||||
|
return component;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export function getRootComponent() {
|
||||||
|
return rootComponentPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function assertChildExists(component, name) {
|
||||||
|
if (!findChildComponent(component, name)) {
|
||||||
|
throw new Error(name + ' not rendered');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function findChildComponent(component, name) {
|
||||||
|
for (let child of traverseChildren(component)) {
|
||||||
|
if (child.type.name == name) {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* traverseChildren(component) {
|
||||||
|
let props = component.props;
|
||||||
|
|
||||||
|
// The hacky TopLevelWrapper has its props set to the root element.
|
||||||
|
if (props.props) {
|
||||||
|
props = props.props;
|
||||||
|
}
|
||||||
|
|
||||||
|
let children = props.children;
|
||||||
|
if (!children) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReactNative is missing React.Children.toArray()
|
||||||
|
for (let child of React.Children.map(children, (x) => x)) {
|
||||||
|
yield child;
|
||||||
|
yield* traverseChildren(child);
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
"env": {
|
"env": {
|
||||||
"commonjs": true,
|
"commonjs": true,
|
||||||
"browser": true,
|
"browser": true,
|
||||||
"es6": true,
|
"es6": true
|
||||||
},
|
},
|
||||||
"ecmaFeatures": {
|
"ecmaFeatures": {
|
||||||
"forOf": false
|
"forOf": false
|
||||||
|
21
react-native/.eslintrc
Normal file
21
react-native/.eslintrc
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"commonjs": true,
|
||||||
|
"es6": true
|
||||||
|
},
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"forOf": false,
|
||||||
|
"jsx": true
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"react"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"react/jsx-no-duplicate-props": 2,
|
||||||
|
"react/jsx-no-undef": 2,
|
||||||
|
"react/jsx-uses-react": 2,
|
||||||
|
"react/no-direct-mutation-state": 1,
|
||||||
|
"react/prefer-es6-class": 1,
|
||||||
|
"react/react-in-jsx-scope": 2
|
||||||
|
}
|
||||||
|
}
|
7
react-native/index.js
vendored
Normal file
7
react-native/index.js
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/* Copyright 2015 Realm Inc - All Rights Reserved
|
||||||
|
* Proprietary and Confidential
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
exports.ListView = require('./listview');
|
190
react-native/listview.js
vendored
Normal file
190
react-native/listview.js
vendored
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
/* Copyright 2015 Realm Inc - All Rights Reserved
|
||||||
|
* Proprietary and Confidential
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const React = require('react-native');
|
||||||
|
|
||||||
|
function hashObjects(array) {
|
||||||
|
let hash = Object.create(null);
|
||||||
|
for (let i = 0, len = array.length; i < len; i++) {
|
||||||
|
hash[array[i]] = true;
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ListViewDataSource extends React.ListView.DataSource {
|
||||||
|
cloneWithRowsAndSections(inputData, sectionIds, rowIds) {
|
||||||
|
let data = {};
|
||||||
|
|
||||||
|
for (let sectionId in inputData) {
|
||||||
|
let items = inputData[sectionId];
|
||||||
|
let copy;
|
||||||
|
|
||||||
|
// Realm Results and List objects have a snapshot() method.
|
||||||
|
if (typeof items.snapshot == 'function') {
|
||||||
|
copy = items.snapshot();
|
||||||
|
} else if (Array.isArray(items)) {
|
||||||
|
copy = items.slice();
|
||||||
|
} else {
|
||||||
|
copy = Object.assign({}, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
data[sectionId] = copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sectionIds) {
|
||||||
|
sectionIds = Object.keys(data);
|
||||||
|
}
|
||||||
|
if (!rowIds) {
|
||||||
|
rowIds = sectionIds.map((sectionId) => {
|
||||||
|
let items = data[sectionId];
|
||||||
|
if (typeof items.snapshot != 'function') {
|
||||||
|
return Object.keys(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Efficiently get the keys of the Realm collection, since they're never sparse.
|
||||||
|
let count = items.length;
|
||||||
|
let indexes = new Array(count);
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
indexes[i] = i;
|
||||||
|
}
|
||||||
|
return indexes;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy this object with the same parameters initially passed into the constructor.
|
||||||
|
let newSource = new this.constructor({
|
||||||
|
getRowData: this._getRowData,
|
||||||
|
getSectionHeaderData: this._getSectionHeaderData,
|
||||||
|
rowHasChanged: this._rowHasChanged,
|
||||||
|
sectionHeaderHasChanged: this._sectionHeaderHasChanged,
|
||||||
|
});
|
||||||
|
|
||||||
|
newSource._cachedRowCount = rowIds.reduce((n, a) => n + a.length, 0);
|
||||||
|
newSource._dataBlob = data;
|
||||||
|
newSource.sectionIdentities = sectionIds;
|
||||||
|
newSource.rowIdentities = rowIds;
|
||||||
|
|
||||||
|
let prevSectionIds = this.sectionIdentities;
|
||||||
|
let prevRowIds = this.rowIdentities;
|
||||||
|
let prevRowHash = {};
|
||||||
|
for (let i = 0, len = prevRowIds.length; i < len; i++) {
|
||||||
|
prevRowHash[prevSectionIds[i]] = hashObjects(prevRowIds[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// These properties allow lazily calculating if rows and section headers should update.
|
||||||
|
newSource._prevDataBlob = this._dataBlob;
|
||||||
|
newSource._prevSectionHash = hashObjects(prevSectionIds);
|
||||||
|
newSource._prevRowHash = prevRowHash;
|
||||||
|
|
||||||
|
return newSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRowData() {
|
||||||
|
// The React.ListView calls this for *every* item during each render, which is quite
|
||||||
|
// premature since this can be mildly expensive and memory inefficient since it keeps
|
||||||
|
// the result of this alive through a bound renderRow function.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getRow(sectionId, rowId) {
|
||||||
|
// This new method is provided as a convenience for those wishing to be memory efficient.
|
||||||
|
return this._getRowData(this._dataBlob, sectionId, rowId);
|
||||||
|
}
|
||||||
|
|
||||||
|
sectionHeaderShouldUpdate(sectionIndex) {
|
||||||
|
let dirtySections = this._dirtySections;
|
||||||
|
let dirty;
|
||||||
|
|
||||||
|
if ((dirty = dirtySections[sectionIndex]) != null) {
|
||||||
|
// This was already calculated before.
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sectionId = this.sectionIdentities[sectionIndex];
|
||||||
|
let sectionHeaderHasChanged = this._sectionHeaderHasChanged;
|
||||||
|
if (this._prevSectionHash[sectionId] && sectionHeaderHasChanged) {
|
||||||
|
dirty = sectionHeaderHasChanged(
|
||||||
|
this._getSectionHeaderData(this._prevDataBlob, sectionId),
|
||||||
|
this._getSectionHeaderData(this._dataBlob, sectionId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unless it's explicitly *not* dirty, then this section header should update.
|
||||||
|
return (dirtySections[sectionIndex] = dirty !== false);
|
||||||
|
}
|
||||||
|
|
||||||
|
rowShouldUpdate(sectionIndex, rowIndex) {
|
||||||
|
let dirtyRows = this._dirtyRows[sectionIndex];
|
||||||
|
let dirty;
|
||||||
|
|
||||||
|
if (!dirtyRows) {
|
||||||
|
dirtyRows = this._dirtyRows[sectionIndex] = [];
|
||||||
|
} else if ((dirty = dirtyRows[rowIndex]) != null) {
|
||||||
|
// This was already calculated before.
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sectionId = this.sectionIdentities[sectionIndex];
|
||||||
|
if (this._prevSectionHash[sectionId]) {
|
||||||
|
let rowId = this.rowIdentities[sectionIndex][rowIndex];
|
||||||
|
if (this._prevRowHash[sectionId][rowId]) {
|
||||||
|
let prevItem = this._getRowData(this._prevDataBlob, sectionId, rowId);
|
||||||
|
if (prevItem) {
|
||||||
|
let item = this._getRowData(this._dataBlob, sectionId, rowId);
|
||||||
|
if (item) {
|
||||||
|
dirty = this._rowHasChanged(prevItem, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unless it's explicitly *not* dirty, then this row should update.
|
||||||
|
return (dirtyRows[rowIndex] = dirty !== false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ListView extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.renderRow = this.renderRow.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<React.ListView {...this.props} ref="listView" renderRow={this.renderRow} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderRow(_, sectionId, rowId, ...args) {
|
||||||
|
let props = this.props;
|
||||||
|
let item = props.dataSource.getRow(sectionId, rowId);
|
||||||
|
|
||||||
|
// The item could be null because our data is a snapshot and it was deleted.
|
||||||
|
return item ? props.renderRow(item, sectionId, rowId, ...args) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInnerViewNode() {
|
||||||
|
return this.refs.listView.getInnerViewNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollTo(...args) {
|
||||||
|
this.refs.listView.scrollTo(...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
setNativeProps(props) {
|
||||||
|
this.refs.listView.setNativeProps(props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView.propTypes = {
|
||||||
|
dataSource: React.PropTypes.instanceOf(ListViewDataSource).isRequired,
|
||||||
|
renderRow: React.PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
ListView.DataSource = ListViewDataSource;
|
||||||
|
|
||||||
|
module.exports = ListView;
|
@ -97,10 +97,11 @@ case "$TARGET" in
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
npm update react-native
|
npm update react-native
|
||||||
|
open_chrome
|
||||||
start_packager
|
start_packager
|
||||||
|
|
||||||
pushd ios
|
pushd ios
|
||||||
xcodebuild -scheme ReactExample -configuration "$CONFIGURATION" -sdk iphonesimulator build $DESTINATION
|
xcodebuild -scheme ReactExample -configuration "$CONFIGURATION" -sdk iphonesimulator $DESTINATION build test
|
||||||
;;
|
;;
|
||||||
"react-tests-android")
|
"react-tests-android")
|
||||||
if [[ $CONFIGURATION == 'Debug' ]]; then
|
if [[ $CONFIGURATION == 'Debug' ]]; then
|
||||||
|
@ -15,13 +15,10 @@ using namespace realm;
|
|||||||
|
|
||||||
JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) {
|
JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) {
|
||||||
try {
|
try {
|
||||||
// index subscripting
|
|
||||||
List *list = RJSGetInternal<List *>(object);
|
List *list = RJSGetInternal<List *>(object);
|
||||||
size_t size = list->size();
|
|
||||||
|
|
||||||
std::string indexStr = RJSStringForJSString(propertyName);
|
std::string indexStr = RJSStringForJSString(propertyName);
|
||||||
if (indexStr == "length") {
|
if (indexStr == "length") {
|
||||||
return JSValueMakeNumber(ctx, size);
|
return JSValueMakeNumber(ctx, list->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
return RJSObjectCreate(ctx, Object(list->realm(), list->get_object_schema(), list->get(RJSValidatedPositiveIndex(indexStr))));
|
return RJSObjectCreate(ctx, Object(list->realm(), list->get_object_schema(), list->get(RJSValidatedPositiveIndex(indexStr))));
|
||||||
|
@ -13,13 +13,10 @@ using namespace realm;
|
|||||||
|
|
||||||
JSValueRef ResultsGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) {
|
JSValueRef ResultsGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException) {
|
||||||
try {
|
try {
|
||||||
// index subscripting
|
|
||||||
Results *results = RJSGetInternal<Results *>(object);
|
Results *results = RJSGetInternal<Results *>(object);
|
||||||
size_t size = results->size();
|
|
||||||
|
|
||||||
std::string indexStr = RJSStringForJSString(propertyName);
|
std::string indexStr = RJSStringForJSString(propertyName);
|
||||||
if (indexStr == "length") {
|
if (indexStr == "length") {
|
||||||
return JSValueMakeNumber(ctx, size);
|
return JSValueMakeNumber(ctx, results->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto row = results->get(RJSValidatedPositiveIndex(indexStr));
|
auto row = results->get(RJSValidatedPositiveIndex(indexStr));
|
||||||
|
@ -33,8 +33,7 @@ static NSString * const RJSModuleLoaderErrorDomain = @"RJSModuleLoaderErrorDomai
|
|||||||
self.globalModules[name] = [JSValue valueWithObject:object inContext:self.context];
|
self.globalModules[name] = [JSValue valueWithObject:object inContext:self.context];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (JSValue *)loadModule:(NSString *)name relativeToURL:(NSURL *)baseURL error:(NSError **)error
|
- (JSValue *)loadModule:(NSString *)name relativeToURL:(NSURL *)baseURL error:(NSError **)error {
|
||||||
{
|
|
||||||
if (![name hasPrefix:@"./"] && ![name hasPrefix:@"../"]) {
|
if (![name hasPrefix:@"./"] && ![name hasPrefix:@"../"]) {
|
||||||
return [self loadGlobalModule:name relativeToURL:baseURL error:error];
|
return [self loadGlobalModule:name relativeToURL:baseURL error:error];
|
||||||
}
|
}
|
||||||
|
@ -26,23 +26,15 @@
|
|||||||
[moduleLoader addGlobalModuleObject:realmConstructor forName:@"realm"];
|
[moduleLoader addGlobalModuleObject:realmConstructor forName:@"realm"];
|
||||||
|
|
||||||
NSError *error;
|
NSError *error;
|
||||||
JSValue *testObjects = [moduleLoader loadModuleFromURL:scriptURL error:&error];
|
JSValue *testObject = [moduleLoader loadModuleFromURL:scriptURL error:&error];
|
||||||
|
NSAssert(testObject, @"%@", error);
|
||||||
|
|
||||||
if (!testObjects) {
|
NSDictionary *testCaseNames = [[testObject invokeMethod:@"getTestNames" withArguments:nil] toDictionary];
|
||||||
NSLog(@"%@", error);
|
NSAssert(testCaseNames.count, @"No test names were provided by the JS");
|
||||||
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 (XCTestSuite *testSuite in [self testSuitesFromDictionary:testCaseNames]) {
|
||||||
for (RealmJSCoreTests *test in testSuite.tests) {
|
for (RealmJSCoreTests *test in testSuite.tests) {
|
||||||
test.testObject = testObjects[testSuite.name];
|
test.testObject = testObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
[suite addTest:testSuite];
|
[suite addTest:testSuite];
|
||||||
@ -57,15 +49,10 @@
|
|||||||
|
|
||||||
- (void)invokeMethod:(NSString *)method {
|
- (void)invokeMethod:(NSString *)method {
|
||||||
JSValue *testObject = self.testObject;
|
JSValue *testObject = self.testObject;
|
||||||
|
|
||||||
if (![testObject hasProperty:method]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSContext *context = testObject.context;
|
JSContext *context = testObject.context;
|
||||||
context.exception = nil;
|
context.exception = nil;
|
||||||
|
|
||||||
[testObject invokeMethod:method withArguments:nil];
|
[testObject invokeMethod:@"runTest" withArguments:@[NSStringFromClass(self.class), method]];
|
||||||
|
|
||||||
JSValue *exception = context.exception;
|
JSValue *exception = context.exception;
|
||||||
if (exception) {
|
if (exception) {
|
||||||
|
@ -10,12 +10,17 @@
|
|||||||
|
|
||||||
+ (NSArray *)testSuitesFromDictionary:(NSDictionary *)testCaseNames {
|
+ (NSArray *)testSuitesFromDictionary:(NSDictionary *)testCaseNames {
|
||||||
NSMutableArray *testSuites = [[NSMutableArray alloc] init];
|
NSMutableArray *testSuites = [[NSMutableArray alloc] init];
|
||||||
|
NSSet *specialNames = [NSSet setWithObjects:@"beforeEach", @"afterEach", nil];
|
||||||
|
|
||||||
for (NSString *suiteName in testCaseNames) {
|
for (NSString *suiteName in testCaseNames) {
|
||||||
XCTestSuite *testSuite = [[XCTestSuite alloc] initWithName:suiteName];
|
XCTestSuite *testSuite = [[XCTestSuite alloc] initWithName:suiteName];
|
||||||
Class testClass = objc_allocateClassPair(self, suiteName.UTF8String, 0);
|
Class testClass = objc_allocateClassPair(self, suiteName.UTF8String, 0);
|
||||||
|
|
||||||
for (NSString *testName in testCaseNames[suiteName]) {
|
for (NSString *testName in testCaseNames[suiteName]) {
|
||||||
|
if ([specialNames containsObject:testName]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
XCTestCase *testCase = [[testClass alloc] initWithTestName:testName];
|
XCTestCase *testCase = [[testClass alloc] initWithTestName:testName];
|
||||||
[testSuite addTest:testCase];
|
[testSuite addTest:testCase];
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,6 @@ exports.extend = function(object) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Object.defineProperties(prototype, {
|
Object.defineProperties(prototype, {
|
||||||
// TODO: Remove once missing undefined check is fixed inside RCTContextExecutor.
|
|
||||||
beforeEach: {
|
|
||||||
value: function() {}
|
|
||||||
},
|
|
||||||
|
|
||||||
afterEach: {
|
afterEach: {
|
||||||
value: function() {
|
value: function() {
|
||||||
Realm.clearTestState();
|
Realm.clearTestState();
|
||||||
|
@ -4,37 +4,46 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
exports.ListTests = require('./list-tests');
|
var TESTS = {
|
||||||
exports.ObjectTests = require('./object-tests');
|
ListTests: require('./list-tests'),
|
||||||
exports.RealmTests = require('./realm-tests');
|
ObjectTests: require('./object-tests'),
|
||||||
exports.ResultsTests = require('./results-tests');
|
RealmTests: require('./realm-tests'),
|
||||||
exports.QueryTests = require('./query-tests');
|
ResultsTests: require('./results-tests'),
|
||||||
|
QueryTests: require('./query-tests'),
|
||||||
|
};
|
||||||
|
|
||||||
var SPECIAL_METHODS = {
|
var SPECIAL_METHODS = {
|
||||||
beforeEach: true,
|
beforeEach: true,
|
||||||
afterEach: true,
|
afterEach: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only the test suites should be iterable members of exports.
|
exports.getTestNames = function() {
|
||||||
Object.defineProperties(exports, {
|
var testNames = {};
|
||||||
getTestNames: {
|
|
||||||
value: function() {
|
|
||||||
var testNames = {};
|
|
||||||
|
|
||||||
for (var suiteName in exports) {
|
for (var suiteName in TESTS) {
|
||||||
var testSuite = exports[suiteName];
|
var testSuite = TESTS[suiteName];
|
||||||
|
|
||||||
testNames[suiteName] = Object.keys(testSuite).filter(function(testName) {
|
testNames[suiteName] = Object.keys(testSuite).filter(function(testName) {
|
||||||
return !(testName in SPECIAL_METHODS) && typeof testSuite[testName] == 'function';
|
return !(testName in SPECIAL_METHODS) && typeof testSuite[testName] == 'function';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return testNames;
|
return testNames;
|
||||||
}
|
};
|
||||||
},
|
|
||||||
runTest: {
|
exports.registerTests = function(tests) {
|
||||||
value: function(suiteName, testName) {
|
for (var suiteName in tests) {
|
||||||
exports[suiteName][testName]();
|
TESTS[suiteName] = tests[suiteName];
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
});
|
|
||||||
|
exports.runTest = function(suiteName, testName) {
|
||||||
|
var testSuite = TESTS[suiteName];
|
||||||
|
var testMethod = testSuite && testSuite[testName];
|
||||||
|
|
||||||
|
if (testMethod) {
|
||||||
|
testMethod.call(testSuite);
|
||||||
|
} else if (!testSuite || !(testName in SPECIAL_METHODS)) {
|
||||||
|
throw new Error('Missing test: ' + suiteName + '.' + testName);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -1,52 +1,49 @@
|
|||||||
/**
|
/* Copyright 2016 Realm Inc - All Rights Reserved
|
||||||
* Sample React Native App
|
* Proprietary and Confidential
|
||||||
* https://github.com/facebook/react-native
|
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
var React = require('react-native');
|
|
||||||
var {
|
const React = require('react-native');
|
||||||
AppRegistry,
|
const Realm = require('realm');
|
||||||
StyleSheet,
|
const RealmTests = require('realm-tests');
|
||||||
Image,
|
const builder = require('xmlbuilder');
|
||||||
Text,
|
const RNFS = require('react-native-fs');
|
||||||
View,
|
|
||||||
TouchableNativeFeedback,
|
const {
|
||||||
|
AppRegistry,
|
||||||
|
StyleSheet,
|
||||||
|
Image,
|
||||||
|
Text,
|
||||||
|
View,
|
||||||
|
TouchableNativeFeedback,
|
||||||
} = React;
|
} = React;
|
||||||
|
|
||||||
var Realm = require('realm');
|
RealmTests.registerTests({
|
||||||
var RealmTests = require('realm-tests');
|
ListViewTest: require('./tests/listview-test'),
|
||||||
var builder = require('xmlbuilder');
|
});
|
||||||
var RNFS = require('react-native-fs');
|
|
||||||
|
|
||||||
function runTests() {
|
function runTests() {
|
||||||
var rootXml = builder.create('testsuites');
|
let rootXml = builder.create('testsuites');
|
||||||
let testNames = RealmTests.getTestNames();
|
let testNames = RealmTests.getTestNames();
|
||||||
|
|
||||||
for (let suiteName in testNames) {
|
for (let suiteName in testNames) {
|
||||||
var itemTestsuite = rootXml.ele('testsuite');
|
let itemTestsuite = rootXml.ele('testsuite');
|
||||||
let nbrTests = 0;
|
let nbrTests = 0;
|
||||||
let nbrFailures = 0;
|
let nbrFailures = 0;
|
||||||
|
|
||||||
let testSuite = RealmTests[suiteName];
|
|
||||||
|
|
||||||
console.log('Starting suite ' + suiteName);
|
console.log('Starting suite ' + suiteName);
|
||||||
|
|
||||||
var suiteTestNames = testNames[suiteName];
|
testNames[suiteName].forEach((testName) => {
|
||||||
for (var index in suiteTestNames) {
|
|
||||||
nbrTests++;
|
nbrTests++;
|
||||||
var testName = suiteTestNames[index];
|
|
||||||
|
|
||||||
var itemTest = itemTestsuite.ele('testcase');
|
let itemTest = itemTestsuite.ele('testcase');
|
||||||
itemTest.att('name', testName);
|
itemTest.att('name', testName);
|
||||||
|
|
||||||
console.log('Starting ' + testName);
|
console.log('Starting ' + testName);
|
||||||
|
RealmTests.runTest(suiteName, 'beforeEach');
|
||||||
if (testSuite.beforeEach) {
|
|
||||||
testSuite.beforeEach();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
testSuite[testName]();
|
RealmTests.runTest(suiteName, testName);
|
||||||
console.log('+ ' + testName);
|
console.log('+ ' + testName);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
@ -57,11 +54,9 @@ function runTests() {
|
|||||||
nbrFailures++;
|
nbrFailures++;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
if (testSuite.afterEach) {
|
RealmTests.runTest(suiteName, 'afterEach');
|
||||||
testSuite.afterEach();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
// update Junit XML report
|
// update Junit XML report
|
||||||
itemTestsuite.att('name', suiteName);
|
itemTestsuite.att('name', suiteName);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright 2015 Realm Inc - All Rights Reserved
|
/* Copyright 2016 Realm Inc - All Rights Reserved
|
||||||
* Proprietary and Confidential
|
* Proprietary and Confidential
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -6,70 +6,21 @@
|
|||||||
|
|
||||||
const React = require('react-native');
|
const React = require('react-native');
|
||||||
const Realm = require('realm');
|
const Realm = require('realm');
|
||||||
const RealmTests = require('realm-tests');
|
const tests = require('./tests');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
AppRegistry,
|
AppRegistry,
|
||||||
NativeAppEventEmitter,
|
|
||||||
NativeModules,
|
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Text,
|
Text,
|
||||||
TouchableHighlight,
|
TouchableHighlight,
|
||||||
View,
|
View,
|
||||||
} = React;
|
} = React;
|
||||||
|
|
||||||
// Listen for event to run a particular test.
|
|
||||||
NativeAppEventEmitter.addListener('realm-run-test', (test) => {
|
|
||||||
let error;
|
|
||||||
try {
|
|
||||||
RealmTests.runTest(test.suite, test.name);
|
|
||||||
} catch (e) {
|
|
||||||
error = '' + e;
|
|
||||||
}
|
|
||||||
|
|
||||||
NativeModules.Realm.emit('realm-test-finished', error);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Inform the native test harness about the test suite once it's ready.
|
|
||||||
setTimeout(() => {
|
|
||||||
NativeModules.Realm.emit('realm-test-names', RealmTests.getTestNames());
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
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.message);
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (testSuite.afterEach) {
|
|
||||||
testSuite.afterEach();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ReactTests extends React.Component {
|
class ReactTests extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Text style={styles.button} onPress={runTests}>
|
<Text style={styles.button} onPress={tests.runTests}>
|
||||||
Tap to Run Tests
|
Tap to Run Tests
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={styles.instructions}>
|
<Text style={styles.instructions}>
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* 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 */; };
|
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
|
||||||
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
|
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
|
||||||
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
|
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
|
||||||
@ -158,7 +157,6 @@
|
|||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
|
|
||||||
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = "<group>"; };
|
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = "../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj"; sourceTree = "<group>"; };
|
||||||
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = "<group>"; };
|
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = "../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj"; sourceTree = "<group>"; };
|
||||||
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = "<group>"; };
|
00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = "<group>"; };
|
||||||
@ -172,12 +170,12 @@
|
|||||||
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
|
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
|
||||||
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
|
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
|
||||||
13B07F961A680F5B00A75B9A /* ReactTests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReactTests.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
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 = "<group>"; };
|
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = ReactTests/AppDelegate.m; sourceTree = "<group>"; };
|
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||||
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = ReactTests/Images.xcassets; sourceTree = "<group>"; };
|
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = ReactTests/Info.plist; sourceTree = "<group>"; };
|
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ReactTests/main.m; sourceTree = "<group>"; };
|
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||||
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
|
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = "<group>"; };
|
||||||
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
|
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
|
||||||
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
|
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
|
||||||
@ -283,7 +281,6 @@
|
|||||||
13B07FAE1A68108700A75B9A /* ReactTests */ = {
|
13B07FAE1A68108700A75B9A /* ReactTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
|
|
||||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||||
13B07FB01A68108700A75B9A /* AppDelegate.m */,
|
13B07FB01A68108700A75B9A /* AppDelegate.m */,
|
||||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||||
@ -291,7 +288,7 @@
|
|||||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
|
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
|
||||||
13B07FB71A68108700A75B9A /* main.m */,
|
13B07FB71A68108700A75B9A /* main.m */,
|
||||||
);
|
);
|
||||||
name = ReactTests;
|
path = ReactTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
146834001AC3E56700842450 /* Products */ = {
|
146834001AC3E56700842450 /* Products */ = {
|
||||||
@ -382,10 +379,11 @@
|
|||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactTestApp" */;
|
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "ReactTestApp" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
F65C4BCA1BC72C5A000A1793 /* ShellScript */,
|
F65C4BCA1BC72C5A000A1793 /* Install Realm Node Modules */,
|
||||||
13B07F871A680F5B00A75B9A /* Sources */,
|
13B07F871A680F5B00A75B9A /* Sources */,
|
||||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||||
|
F6EDE5BF1C49007200B1085F /* Bundle React Native code and images */,
|
||||||
F6F405C61BCE565100A1E24F /* Embed Frameworks */,
|
F6F405C61BCE565100A1E24F /* Embed Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
@ -404,7 +402,7 @@
|
|||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0710;
|
LastUpgradeCheck = 0710;
|
||||||
ORGANIZATIONNAME = Facebook;
|
ORGANIZATIONNAME = Realm;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
00E356ED1AD99517003FC87E = {
|
00E356ED1AD99517003FC87E = {
|
||||||
CreatedOnToolsVersion = 6.2;
|
CreatedOnToolsVersion = 6.2;
|
||||||
@ -597,7 +595,6 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
008F07F31AC5B25A0029DE68 /* main.jsbundle in Resources */,
|
|
||||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
|
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
|
||||||
);
|
);
|
||||||
@ -606,19 +603,34 @@
|
|||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
F65C4BCA1BC72C5A000A1793 /* ShellScript */ = {
|
F65C4BCA1BC72C5A000A1793 /* Install Realm Node Modules */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
);
|
);
|
||||||
|
name = "Install Realm Node Modules";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "[ -s \"${HOME}/.nvm/nvm.sh\" ] && . \"${HOME}/.nvm/nvm.sh\" \nrm -rf ../node_modules/realm ../node_modules/realm-tests\nnpm install realm realm-tests\ncp ../../../src/object-store/parser/queryTests.json ../node_modules/realm-tests/query-tests.json\n";
|
shellScript = "[ -s \"${HOME}/.nvm/nvm.sh\" ] && . \"${HOME}/.nvm/nvm.sh\" \nrm -rf ../node_modules/realm ../node_modules/realm-tests\nnpm install realm realm-tests\ncp ../../../src/object-store/parser/queryTests.json ../node_modules/realm-tests/query-tests.json\n";
|
||||||
};
|
};
|
||||||
|
F6EDE5BF1C49007200B1085F /* Bundle React Native code and images */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "Bundle React Native code and images";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "[ \"$PLATFORM_NAME\" = \"iphonesimulator\" ] && exit\n../node_modules/react-native/packager/react-native-xcode.sh";
|
||||||
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
@ -657,7 +669,6 @@
|
|||||||
13B07FB21A68108700A75B9A /* Base */,
|
13B07FB21A68108700A75B9A /* Base */,
|
||||||
);
|
);
|
||||||
name = LaunchScreen.xib;
|
name = LaunchScreen.xib;
|
||||||
path = ReactTests;
|
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
/* End PBXVariantGroup section */
|
/* End PBXVariantGroup section */
|
||||||
@ -679,9 +690,7 @@
|
|||||||
"$(SRCROOT)/../node_modules/react-native/React/Modules",
|
"$(SRCROOT)/../node_modules/react-native/React/Modules",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = ../../ios/Info.plist;
|
INFOPLIST_FILE = ../../ios/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 8.2;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
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)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReactTests.app/ReactTests";
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReactTests.app/ReactTests";
|
||||||
};
|
};
|
||||||
@ -700,9 +709,7 @@
|
|||||||
"$(SRCROOT)/../node_modules/react-native/React/Modules",
|
"$(SRCROOT)/../node_modules/react-native/React/Modules",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = ../../ios/Info.plist;
|
INFOPLIST_FILE = ../../ios/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 8.2;
|
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
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)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReactTests.app/ReactTests";
|
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ReactTests.app/ReactTests";
|
||||||
};
|
};
|
||||||
@ -715,7 +722,6 @@
|
|||||||
INFOPLIST_FILE = ReactTests/Info.plist;
|
INFOPLIST_FILE = ReactTests/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
OTHER_LDFLAGS = "-ObjC";
|
OTHER_LDFLAGS = "-ObjC";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
|
||||||
PRODUCT_NAME = ReactTests;
|
PRODUCT_NAME = ReactTests;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
@ -727,7 +733,6 @@
|
|||||||
INFOPLIST_FILE = ReactTests/Info.plist;
|
INFOPLIST_FILE = ReactTests/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
OTHER_LDFLAGS = "-ObjC";
|
OTHER_LDFLAGS = "-ObjC";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
|
||||||
PRODUCT_NAME = ReactTests;
|
PRODUCT_NAME = ReactTests;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
@ -776,6 +781,7 @@
|
|||||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
@ -816,6 +822,7 @@
|
|||||||
);
|
);
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "io.realm.$(PRODUCT_NAME:rfc1034identifier)";
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
};
|
};
|
||||||
|
@ -32,9 +32,8 @@ static NSString * const RCTDevMenuKey = @"RCTDevMenu";
|
|||||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||||
NSURL *jsCodeLocation;
|
NSURL *jsCodeLocation;
|
||||||
|
|
||||||
|
#if TARGET_OS_SIMULATOR
|
||||||
/**
|
/**
|
||||||
* Loading JavaScript code - uncomment the one you want.
|
|
||||||
*
|
|
||||||
* OPTION 1
|
* OPTION 1
|
||||||
* Load from development server. Start the server from the repository root:
|
* Load from development server. Start the server from the repository root:
|
||||||
*
|
*
|
||||||
@ -46,19 +45,21 @@ static NSString * const RCTDevMenuKey = @"RCTDevMenu";
|
|||||||
* on the same Wi-Fi network.
|
* on the same Wi-Fi network.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios"];
|
#if DEBUG
|
||||||
|
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];
|
||||||
|
#else
|
||||||
|
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=false"];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
/**
|
/**
|
||||||
* OPTION 2
|
* OPTION 2
|
||||||
* Load from pre-bundled file on disk. To re-generate the static bundle
|
* Load from pre-bundled file on disk. The static bundle is automatically
|
||||||
* from the root of your project directory, run
|
* generated by "Bundle React Native code and images" build step.
|
||||||
*
|
|
||||||
* $ react-native bundle --minify
|
|
||||||
*
|
|
||||||
* see http://facebook.github.io/react-native/docs/runningondevice.html
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||||
|
#endif
|
||||||
|
|
||||||
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
|
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
|
||||||
moduleName:@"ReactTests"
|
moduleName:@"ReactTests"
|
||||||
|
@ -7,6 +7,8 @@
|
|||||||
#import "RCTBridge.h"
|
#import "RCTBridge.h"
|
||||||
#import "RCTDevMenu.h"
|
#import "RCTDevMenu.h"
|
||||||
#import "RCTEventDispatcher.h"
|
#import "RCTEventDispatcher.h"
|
||||||
|
#import "RCTJavaScriptLoader.h"
|
||||||
|
#import "RCTLog.h"
|
||||||
|
|
||||||
@import RealmReact;
|
@import RealmReact;
|
||||||
|
|
||||||
@ -29,6 +31,10 @@ extern NSMutableArray *RCTGetModuleClasses(void);
|
|||||||
+ (void)load {
|
+ (void)load {
|
||||||
NSMutableArray *moduleClasses = RCTGetModuleClasses();
|
NSMutableArray *moduleClasses = RCTGetModuleClasses();
|
||||||
[moduleClasses removeObject:[RCTDevMenu class]];
|
[moduleClasses removeObject:[RCTDevMenu class]];
|
||||||
|
|
||||||
|
RCTAddLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
|
||||||
|
NSAssert(level < RCTLogLevelError, RCTFormatLog(nil, level, fileName, lineNumber, message));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (Class)executorClass {
|
+ (Class)executorClass {
|
||||||
@ -84,10 +90,7 @@ extern NSMutableArray *RCTGetModuleClasses(void);
|
|||||||
}
|
}
|
||||||
|
|
||||||
NSDictionary *testCaseNames = [self waitForEvent:@"realm-test-names"];
|
NSDictionary *testCaseNames = [self waitForEvent:@"realm-test-names"];
|
||||||
if (!testCaseNames.count) {
|
NSAssert(testCaseNames.count, @"No test names were provided by the JS");
|
||||||
NSLog(@"ERROR: No test names were provided by the JS");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
NSString *nameSuffix = [self classNameSuffix];
|
NSString *nameSuffix = [self classNameSuffix];
|
||||||
if (nameSuffix.length) {
|
if (nameSuffix.length) {
|
||||||
@ -115,25 +118,37 @@ extern NSMutableArray *RCTGetModuleClasses(void);
|
|||||||
notification = note;
|
notification = note;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[self waitForCondition:&condition];
|
@try {
|
||||||
[nc removeObserver:token];
|
[self waitForCondition:&condition description:notificationName];
|
||||||
|
} @finally {
|
||||||
|
[nc removeObserver:token];
|
||||||
|
}
|
||||||
|
|
||||||
return notification;
|
return notification;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)waitForCondition:(BOOL *)condition {
|
+ (void)waitForCondition:(BOOL *)condition description:(NSString *)description {
|
||||||
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
|
||||||
|
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:30.0];
|
||||||
|
|
||||||
while (!*condition) {
|
while (!*condition) {
|
||||||
|
if ([timeout timeIntervalSinceNow] < 0) {
|
||||||
|
@throw [NSException exceptionWithName:@"ConditionTimeout"
|
||||||
|
reason:[NSString stringWithFormat:@"Timed out waiting for: %@", description]
|
||||||
|
userInfo:nil];
|
||||||
|
}
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
|
[runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||||
|
[runLoop runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||||
|
[NSThread sleepForTimeInterval:0.01]; // Bad things may happen without some sleep.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (id)waitForEvent:(NSString *)eventName {
|
+ (id)waitForEvent:(NSString *)eventName {
|
||||||
__weak RealmReact *realmModule = [[self currentBridge] moduleForClass:[RealmReact class]];
|
__weak RealmReact *realmModule = [[self currentBridge] moduleForClass:[RealmReact class]];
|
||||||
assert(realmModule);
|
NSAssert(realmModule, @"RealmReact module not found");
|
||||||
|
|
||||||
__block BOOL condition = NO;
|
__block BOOL condition = NO;
|
||||||
__block id result;
|
__block id result;
|
||||||
@ -148,10 +163,28 @@ extern NSMutableArray *RCTGetModuleClasses(void);
|
|||||||
|
|
||||||
[realmModule addListenerForEvent:eventName handler:handler];
|
[realmModule addListenerForEvent:eventName handler:handler];
|
||||||
|
|
||||||
[self waitForCondition:&condition];
|
[self waitForCondition:&condition description:eventName];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)invokeTest {
|
||||||
|
RCTLogFunction logFunction = RCTGetLogFunction();
|
||||||
|
|
||||||
|
// Fail when React Native logs an error.
|
||||||
|
RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
|
||||||
|
RCTDefaultLogFunction(level, source, fileName, lineNumber, message);
|
||||||
|
|
||||||
|
if (level >= RCTLogLevelError) {
|
||||||
|
NSString *type = (source == RCTLogSourceJavaScript) ? @"JS" : @"Native";
|
||||||
|
XCTFail(@"%@ Error: %@", type, RCTFormatLog(nil, level, fileName, lineNumber, message));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
[super invokeTest];
|
||||||
|
|
||||||
|
RCTSetLogFunction(logFunction);
|
||||||
|
}
|
||||||
|
|
||||||
- (void)invokeMethod:(NSString *)method {
|
- (void)invokeMethod:(NSString *)method {
|
||||||
NSString *module = NSStringFromClass(self.class);
|
NSString *module = NSStringFromClass(self.class);
|
||||||
NSString *suffix = [self.class classNameSuffix];
|
NSString *suffix = [self.class classNameSuffix];
|
||||||
@ -163,7 +196,13 @@ extern NSMutableArray *RCTGetModuleClasses(void);
|
|||||||
RCTBridge *bridge = [self.class currentBridge];
|
RCTBridge *bridge = [self.class currentBridge];
|
||||||
[bridge.eventDispatcher sendAppEventWithName:@"realm-run-test" body:@{@"suite": module, @"name": method}];
|
[bridge.eventDispatcher sendAppEventWithName:@"realm-run-test" body:@{@"suite": module, @"name": method}];
|
||||||
|
|
||||||
id error = [self.class waitForEvent:@"realm-test-finished"];
|
id error;
|
||||||
|
@try {
|
||||||
|
error = [self.class waitForEvent:@"realm-test-finished"];
|
||||||
|
} @catch (id exception) {
|
||||||
|
error = exception;
|
||||||
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
[self recordFailureWithDescription:[error description] inFile:@(__FILE__) atLine:__LINE__ expected:YES];
|
[self recordFailureWithDescription:[error description] inFile:@(__FILE__) atLine:__LINE__ expected:YES];
|
||||||
}
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
// 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');
|
|
65
tests/react-test-app/tests/index.js
vendored
Normal file
65
tests/react-test-app/tests/index.js
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/* Copyright 2016 Realm Inc - All Rights Reserved
|
||||||
|
* Proprietary and Confidential
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const React = require('react-native');
|
||||||
|
const Realm = require('realm');
|
||||||
|
const RealmTests = require('realm-tests');
|
||||||
|
|
||||||
|
RealmTests.registerTests({
|
||||||
|
ListViewTest: require('./listview-test'),
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
NativeAppEventEmitter,
|
||||||
|
NativeModules,
|
||||||
|
} = React;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
runTests,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Listen for event to run a particular test.
|
||||||
|
NativeAppEventEmitter.addListener('realm-run-test', (test) => {
|
||||||
|
let error;
|
||||||
|
try {
|
||||||
|
RealmTests.runTest(test.suite, test.name);
|
||||||
|
} catch (e) {
|
||||||
|
error = '' + e;
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeModules.Realm.emit('realm-test-finished', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Inform the native test harness about the test suite once it's ready.
|
||||||
|
setTimeout(() => {
|
||||||
|
NativeModules.Realm.emit('realm-test-names', RealmTests.getTestNames());
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
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]) {
|
||||||
|
RealmTests.runTest(suiteName, 'beforeEach');
|
||||||
|
|
||||||
|
try {
|
||||||
|
RealmTests.runTest(suiteName, testName);
|
||||||
|
console.log('+ ' + testName);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.warn('- ' + testName);
|
||||||
|
console.warn(e.message);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
RealmTests.runTest(suiteName, 'afterEach');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
88
tests/react-test-app/tests/listview-test.js
vendored
Normal file
88
tests/react-test-app/tests/listview-test.js
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* Copyright 2016 Realm Inc - All Rights Reserved
|
||||||
|
* Proprietary and Confidential
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Realm = require('realm');
|
||||||
|
const { ListView } = require('realm/react-native');
|
||||||
|
const { assertEqual, assertTrue } = require('realm-tests/asserts');
|
||||||
|
|
||||||
|
const OBJECT_SCHEMA = {
|
||||||
|
name: 'UniqueObject',
|
||||||
|
primaryKey: 'id',
|
||||||
|
properties: {
|
||||||
|
id: 'int',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function createRealm() {
|
||||||
|
let realm = new Realm({schema: [OBJECT_SCHEMA]});
|
||||||
|
|
||||||
|
realm.write(() => {
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
realm.create('UniqueObject', {id: i});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDataSource() {
|
||||||
|
return new ListView.DataSource({
|
||||||
|
rowHasChanged: (a, b) => a.id !== b.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
afterEach() {
|
||||||
|
Realm.clearTestState();
|
||||||
|
},
|
||||||
|
|
||||||
|
testDataSource() {
|
||||||
|
let realm = createRealm();
|
||||||
|
let objects = realm.objects('UniqueObject');
|
||||||
|
objects.sortByProperty('id');
|
||||||
|
|
||||||
|
let dataSource = createDataSource().cloneWithRows(objects);
|
||||||
|
let count = objects.length;
|
||||||
|
|
||||||
|
// Make sure the section header should update.
|
||||||
|
assertTrue(dataSource.sectionHeaderShouldUpdate(0));
|
||||||
|
|
||||||
|
// All rows should need to update.
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
assertTrue(dataSource.rowShouldUpdate(0, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone data source with no changes and make sure no rows need to update.
|
||||||
|
dataSource = dataSource.cloneWithRows(objects);
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
assertTrue(!dataSource.rowShouldUpdate(0, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the second object and make sure current data source is unchanged.
|
||||||
|
realm.write(() => realm.delete(objects[1]));
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
assertTrue(!dataSource.rowShouldUpdate(0, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getting the row data for the second row should return null.
|
||||||
|
assertEqual(dataSource.getRow('s1', 1), null);
|
||||||
|
|
||||||
|
// Clone data source and make sure all rows after the first one need to update.
|
||||||
|
dataSource = dataSource.cloneWithRows(objects);
|
||||||
|
for (let i = 0; i < count - 1; i++) {
|
||||||
|
let changed = dataSource.rowShouldUpdate(0, i);
|
||||||
|
assertTrue(i == 0 ? !changed : changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an object at the ened and make sure only the last row needs to update.
|
||||||
|
realm.write(() => realm.create('UniqueObject', {id: count}));
|
||||||
|
dataSource = dataSource.cloneWithRows(objects);
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
let changed = dataSource.rowShouldUpdate(0, i);
|
||||||
|
assertTrue(i < count - 1 ? !changed : changed);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user