Add Android SDK support
79
README.md
@ -15,16 +15,60 @@ TestFairyBridge
|
||||
* SystemConfiguration.framework
|
||||
* OpenGLES.framework
|
||||
|
||||
## Usage
|
||||
Once the native library has been added to your project, you can now enable session recording with TestFairy. You will need an iOS app token, which you can get from your [preferences](http://app.testfairy.com/settings/) page on your TestFairy account.
|
||||
## Manual installation Android
|
||||
|
||||
Next, from your JavaScript file, (index.ios.js for example), import the TestFairy bridge into your project, and invoke `begin` passing in the iOS app token. Best time to invoke `begin` is usually before you register you Application.
|
||||
```gradle
|
||||
// file: android/settings.gradle
|
||||
...
|
||||
|
||||
include ':react-native-testfairy'
|
||||
project(':react-native-testfairy').projectDir = new File(settingsDir, '../node_modules/react-native-testfairy/android')
|
||||
```
|
||||
```gradle
|
||||
// file: android/app/build.gradle
|
||||
...
|
||||
|
||||
dependencies {
|
||||
...
|
||||
compile project(path: ':react-native-testfairy')
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
// file: MainActivity.java
|
||||
...
|
||||
|
||||
import com.testfairy.react.TestFairyPackage; // import package
|
||||
|
||||
public class MainActivity extends ReactActivity {
|
||||
|
||||
/**
|
||||
* A list of packages used by the app. If the app uses additional views
|
||||
* or modules besides the default ones, add more packages here.
|
||||
*/
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new MainReactPackage(),
|
||||
new TestFairyPackage() // Add package
|
||||
);
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Usage
|
||||
Once the native library has been added to your project, you can now enable session recording with TestFairy. You will need an app token, which you can get from your [preferences](http://app.testfairy.com/settings/) page on your TestFairy account.
|
||||
|
||||
Next, from your JavaScript file, (index.ios.js for example), import the TestFairy bridge into your project, and invoke `begin` passing in the app token. Best time to invoke `begin` is usually in `componentWillMount` or right before you register your application.
|
||||
|
||||
```
|
||||
const TestFairy = require('react-native-testfairy');
|
||||
...
|
||||
TestFairy.begin('<insert ios app token here>');
|
||||
AppRegistry.registerComponent('app', () => App);
|
||||
componentWillMount: function() {
|
||||
TestFairy.begin('<insert ios app token here>');
|
||||
}
|
||||
```
|
||||
|
||||
And that's it! You can now log into your [account](http://app.testfairy.com) and view your sessions. Also, feel free to refer to the [documentation](https://github.com/testfairy/react-native-testfairy/blob/master/index.js) for other available APIs.
|
||||
@ -38,28 +82,43 @@ In order to hide views from your recorded session, you will need to pass a refer
|
||||
<Text ref="instructions">This will be hidden</Text>
|
||||
```
|
||||
|
||||
Next, in a component callback, such as `componentDidMount`, pass the reference ID back to TestFairy by invoking `hideView`. You will need to import `findNodeHandle` into your project.
|
||||
Next, in a component callback, such as `componentDidMount`, pass the reference ID back to TestFairy by invoking `hideView`.
|
||||
|
||||
```
|
||||
var { findNodeHandle } = React;
|
||||
const TestFairy = require('react-native-testfairy');
|
||||
...
|
||||
var MyComponent = React.createClass({
|
||||
...
|
||||
componentWillMount: function() {
|
||||
TestFairy.begin('<insert ios app token here>');
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
TestFairyBridge.hideView(findNodeHandle(this.refs.instructions));
|
||||
TestFairyBridge.hideView(this.refs.instructions);
|
||||
},
|
||||
...
|
||||
render: function() {
|
||||
return (<Text ref="instructions">This will be hidden</Text>);
|
||||
}
|
||||
});
|
||||
|
||||
TestFairy.begin('<insert ios app token here>');
|
||||
```
|
||||
|
||||
Now, your Views will be hidden before any video is uploaded to TestFairy.
|
||||
|
||||
## Migrating from 1.x to 2.x
|
||||
In order to migrate from 1.x to 2.x, a minor change is required in the way you hide views.
|
||||
|
||||
Remove the import of `findNodeHandle`
|
||||
```
|
||||
- var { findNodeHandle } = React;
|
||||
```
|
||||
|
||||
Pass the `ref` object directly into `TestFairy.hideView()`
|
||||
```
|
||||
- TestFairyBridge.hideView(findNodeHandle(this.refs.instructions));
|
||||
+ TestFairyBridge.hideView(this.refs.instructions);
|
||||
```
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
|
24
android/build.gradle
Normal file
@ -0,0 +1,24 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "23.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 23
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile 'com.facebook.react:react-native:0.20.1'
|
||||
compile 'testfairy:testfairy-android-sdk:1.1.0'
|
||||
}
|
7
android/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.testfairy.react">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
</manifest>
|
146
android/src/main/java/com/testfairy/react/TestFairyModule.java
Normal file
@ -0,0 +1,146 @@
|
||||
package com.testfairy.react;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import com.facebook.react.bridge.Callback;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||
import com.facebook.react.bridge.ReactMethod;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
|
||||
import com.testfairy.TestFairy;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class TestFairyModule extends ReactContextBaseJavaModule {
|
||||
|
||||
public TestFairyModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "TestFairyBridge";
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void begin(final String appKey, ReadableMap map) {
|
||||
runOnUi(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TestFairy.begin(getReactApplicationContext(), appKey);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setCorrelationId(final String correlationId) {
|
||||
runOnUi(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TestFairy.setCorrelationId(correlationId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void identify(final String identity, ReadableMap map) {
|
||||
runOnUi(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Map<String, String> traits = null;
|
||||
TestFairy.identify(identity, traits);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void takeScreenshot() {
|
||||
// TODO: Does not exist on Android
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void pause() {
|
||||
runOnUi(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TestFairy.pause();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void resume() {
|
||||
runOnUi(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TestFairy.resume();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void checkpoint(final String checkpoint) {
|
||||
runOnUi(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TestFairy.addCheckpoint(checkpoint);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void sendUserFeedback(final String feedback) {
|
||||
runOnUi(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TestFairy.sendUserFeedback(feedback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void sessionUrl(final Callback callback) {
|
||||
runOnUi(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.invoke(TestFairy.getSessionUrl());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void version(final Callback callback) {
|
||||
runOnUi(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.invoke(TestFairy.getSessionUrl());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void hideView(final int tag) {
|
||||
runOnUi(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Activity activity = getCurrentActivity();
|
||||
if (activity == null)
|
||||
return;
|
||||
|
||||
View view = activity.findViewById(tag);
|
||||
if (view == null)
|
||||
return;
|
||||
|
||||
TestFairy.hideView(view);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void runOnUi(Runnable runnable) {
|
||||
UiThreadUtil.runOnUiThread(runnable);
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.testfairy.react;
|
||||
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.bridge.JavaScriptModule;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TestFairyPackage implements ReactPackage {
|
||||
@Override
|
||||
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
||||
List<NativeModule> modules = new ArrayList<>();
|
||||
modules.add(new TestFairyModule(reactContext));
|
||||
|
||||
return modules;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<? extends JavaScriptModule>> createJSModules() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
@ -14,17 +14,21 @@
|
||||
|
||||
# Ignore react and fbjs where there are overlaps, but don't ignore
|
||||
# anything that react-native relies on
|
||||
.*/node_modules/fbjs-haste/.*/__tests__/.*
|
||||
.*/node_modules/fbjs-haste/__forks__/Map.js
|
||||
.*/node_modules/fbjs-haste/__forks__/Promise.js
|
||||
.*/node_modules/fbjs-haste/__forks__/fetch.js
|
||||
.*/node_modules/fbjs-haste/core/ExecutionEnvironment.js
|
||||
.*/node_modules/fbjs-haste/core/isEmpty.js
|
||||
.*/node_modules/fbjs-haste/crypto/crc32.js
|
||||
.*/node_modules/fbjs-haste/stubs/ErrorUtils.js
|
||||
.*/node_modules/react-haste/React.js
|
||||
.*/node_modules/react-haste/renderers/dom/ReactDOM.js
|
||||
.*/node_modules/react-haste/renderers/shared/event/eventPlugins/ResponderEventPlugin.js
|
||||
.*/node_modules/fbjs/lib/Map.js
|
||||
.*/node_modules/fbjs/lib/fetch.js
|
||||
.*/node_modules/fbjs/lib/ExecutionEnvironment.js
|
||||
.*/node_modules/fbjs/lib/ErrorUtils.js
|
||||
|
||||
# Flow has a built-in definition for the 'react' module which we prefer to use
|
||||
# over the currently-untyped source
|
||||
.*/node_modules/react/react.js
|
||||
.*/node_modules/react/lib/React.js
|
||||
.*/node_modules/react/lib/ReactDOM.js
|
||||
|
||||
.*/__mocks__/.*
|
||||
.*/__tests__/.*
|
||||
|
||||
.*/commoner/test/source/widget/share.js
|
||||
|
||||
# Ignore commoner tests
|
||||
.*/node_modules/commoner/test/.*
|
||||
@ -38,26 +42,48 @@
|
||||
# Ignore Website
|
||||
.*/website/.*
|
||||
|
||||
.*/node_modules/is-my-json-valid/test/.*\.json
|
||||
.*/node_modules/iconv-lite/encodings/tables/.*\.json
|
||||
.*/node_modules/y18n/test/.*\.json
|
||||
.*/node_modules/spdx-license-ids/spdx-license-ids.json
|
||||
.*/node_modules/spdx-exceptions/index.json
|
||||
.*/node_modules/resolve/test/subdirs/node_modules/a/b/c/x.json
|
||||
.*/node_modules/resolve/lib/core.json
|
||||
.*/node_modules/jsonparse/samplejson/.*\.json
|
||||
.*/node_modules/json5/test/.*\.json
|
||||
.*/node_modules/ua-parser-js/test/.*\.json
|
||||
.*/node_modules/builtin-modules/builtin-modules.json
|
||||
.*/node_modules/binary-extensions/binary-extensions.json
|
||||
.*/node_modules/url-regex/tlds.json
|
||||
.*/node_modules/joi/.*\.json
|
||||
.*/node_modules/isemail/.*\.json
|
||||
.*/node_modules/tr46/.*\.json
|
||||
|
||||
[include]
|
||||
|
||||
[libs]
|
||||
node_modules/react-native/Libraries/react-native/react-native-interface.js
|
||||
node_modules/react-native/flow
|
||||
flow/
|
||||
|
||||
[options]
|
||||
module.system=haste
|
||||
|
||||
esproposal.class_static_fields=enable
|
||||
esproposal.class_instance_fields=enable
|
||||
|
||||
munge_underscores=true
|
||||
|
||||
module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'
|
||||
module.name_mapper='^[./a-zA-Z0-9$_-]+\.png$' -> 'RelativeImageStub'
|
||||
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\)$' -> 'RelativeImageStub'
|
||||
|
||||
suppress_type=$FlowIssue
|
||||
suppress_type=$FlowFixMe
|
||||
suppress_type=$FixMe
|
||||
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-2]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-2]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
|
||||
[version]
|
||||
0.19.0
|
||||
0.22.0
|
||||
|
18
example/android/TestFairy.iml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id="TestFairy" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$USER_HOME$/testfairy/react-native/example/android" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="java-gradle" name="Java-Gradle">
|
||||
<configuration>
|
||||
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
|
||||
<option name="BUILDABLE" value="false" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
129
example/android/app/app.iml
Normal file
@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$USER_HOME$/testfairy/react-native/example/android" external.system.id="GRADLE" external.system.module.group="TestFairy" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
<option name="GRADLE_PROJECT_PATH" value=":app" />
|
||||
</configuration>
|
||||
</facet>
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<afterSyncTasks>
|
||||
<task>generateDebugSources</task>
|
||||
</afterSyncTasks>
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/debug" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.0.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/23.0.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/drawee/0.8.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/fbcore/0.8.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/fresco/0.8.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline-okhttp/0.8.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline/0.8.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.23.1/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/org.webkit/android-jsc/r174650/jars" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/mockable-android-23.jar" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/tmp" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" exported="" name="okhttp-ws-2.5.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="library-2.4.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="stetho-okhttp-1.2.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
|
||||
<orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
|
||||
<orderEntry type="library" exported="" name="react-native-0.23.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="recyclerview-v7-23.0.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="imagepipeline-0.8.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="android-jsc-r174650" level="project" />
|
||||
<orderEntry type="library" exported="" name="fresco-0.8.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="imagepipeline-okhttp-0.8.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="drawee-0.8.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="appcompat-v7-23.0.1" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
|
||||
<orderEntry type="module" module-name="react-native-testfairy" exported="" />
|
||||
</component>
|
||||
</module>
|
@ -1,7 +1,10 @@
|
||||
apply plugin: "com.android.application"
|
||||
|
||||
import com.android.build.OutputFile
|
||||
|
||||
/**
|
||||
* The react.gradle file registers two tasks: bundleDebugJsAndAssets and bundleReleaseJsAndAssets.
|
||||
* The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
|
||||
* and bundleReleaseJsAndAssets).
|
||||
* These basically call `react-native bundle` with the correct arguments during the Android build
|
||||
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
|
||||
* bundle directly from the development server. Below you can see all the possible configurations
|
||||
@ -21,6 +24,15 @@ apply plugin: "com.android.application"
|
||||
* // whether to bundle JS and assets in release mode
|
||||
* bundleInRelease: true,
|
||||
*
|
||||
* // whether to bundle JS and assets in another build variant (if configured).
|
||||
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
|
||||
* // The configuration property can be in the following formats
|
||||
* // 'bundleIn${productFlavor}${buildType}'
|
||||
* // 'bundleIn${buildType}'
|
||||
* // bundleInFreeDebug: true,
|
||||
* // bundleInPaidRelease: true,
|
||||
* // bundleInBeta: true,
|
||||
*
|
||||
* // the root of your project, i.e. where "package.json" lives
|
||||
* root: "../../",
|
||||
*
|
||||
@ -49,30 +61,68 @@ apply plugin: "com.android.application"
|
||||
|
||||
apply from: "react.gradle"
|
||||
|
||||
/**
|
||||
* Set this to true to create two separate APKs instead of one:
|
||||
* - An APK that only works on ARM devices
|
||||
* - An APK that only works on x86 devices
|
||||
* The advantage is the size of the APK is reduced by about 4MB.
|
||||
* Upload all the APKs to the Play Store and people will download
|
||||
* the correct one based on the CPU architecture of their device.
|
||||
*/
|
||||
def enableSeparateBuildPerCPUArchitecture = false
|
||||
|
||||
/**
|
||||
* Run Proguard to shrink the Java bytecode in release builds.
|
||||
*/
|
||||
def enableProguardInReleaseBuilds = false
|
||||
|
||||
android {
|
||||
compileSdkVersion 23
|
||||
buildToolsVersion "23.0.1"
|
||||
buildToolsVersion "23.0.2"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.testfairy"
|
||||
applicationId "com.testfairy.react.example"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 22
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
}
|
||||
}
|
||||
splits {
|
||||
abi {
|
||||
reset()
|
||||
enable enableSeparateBuildPerCPUArchitecture
|
||||
universalApk false // If true, also generate a universal APK
|
||||
include "armeabi-v7a", "x86"
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false // Set this to true to enable Proguard
|
||||
minifyEnabled enableProguardInReleaseBuilds
|
||||
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
||||
}
|
||||
}
|
||||
// applicationVariants are e.g. debug, release
|
||||
applicationVariants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
// For each separate APK per architecture, set a unique version code as described here:
|
||||
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
|
||||
def versionCodes = ["armeabi-v7a":1, "x86":2]
|
||||
def abi = output.getFilter(OutputFile.ABI)
|
||||
if (abi != null) { // null for the universal-debug, universal-release variants
|
||||
output.versionCodeOverride =
|
||||
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: "libs", include: ["*.jar"])
|
||||
compile "com.android.support:appcompat-v7:23.0.1"
|
||||
compile "com.facebook.react:react-native:0.17.+"
|
||||
compile "com.facebook.react:react-native:+" // From node_modules
|
||||
compile project(path: ':react-native-testfairy')
|
||||
}
|
||||
|
11
example/android/app/proguard-rules.pro
vendored
@ -40,9 +40,12 @@
|
||||
|
||||
-keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
|
||||
-keep class * extends com.facebook.react.bridge.NativeModule { *; }
|
||||
-keepclassmembers,includedescriptorclasses class * { native <methods>; }
|
||||
-keepclassmembers class * { @com.facebook.react.uimanager.UIProp <fields>; }
|
||||
-keepclassmembers class * { @com.facebook.react.uimanager.ReactProp <methods>; }
|
||||
-keepclassmembers class * { @com.facebook.react.uimanager.ReactPropGroup <methods>; }
|
||||
-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp <methods>; }
|
||||
-keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup <methods>; }
|
||||
|
||||
-dontwarn com.facebook.react.**
|
||||
|
||||
# okhttp
|
||||
|
||||
@ -58,3 +61,7 @@
|
||||
-dontwarn java.nio.file.*
|
||||
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
|
||||
-dontwarn okio.**
|
||||
|
||||
# stetho
|
||||
|
||||
-dontwarn com.facebook.stetho.**
|
||||
|
@ -11,77 +11,87 @@ def elvisFile(thing) {
|
||||
}
|
||||
|
||||
def reactRoot = elvisFile(config.root) ?: file("../../")
|
||||
def jsBundleDirDebug = elvisFile(config.jsBundleDirDebug) ?:
|
||||
file("$buildDir/intermediates/assets/debug")
|
||||
def jsBundleDirRelease = elvisFile(config.jsBundleDirRelease) ?:
|
||||
file("$buildDir/intermediates/assets/release")
|
||||
def resourcesDirDebug = elvisFile(config.resourcesDirDebug) ?:
|
||||
file("$buildDir/intermediates/res/merged/debug")
|
||||
def resourcesDirRelease = elvisFile(config.resourcesDirRelease) ?:
|
||||
file("$buildDir/intermediates/res/merged/release")
|
||||
def inputExcludes = config.inputExcludes ?: ["android/**", "ios/**"]
|
||||
|
||||
def jsBundleFileDebug = file("$jsBundleDirDebug/$bundleAssetName")
|
||||
def jsBundleFileRelease = file("$jsBundleDirRelease/$bundleAssetName")
|
||||
|
||||
task bundleDebugJsAndAssets(type: Exec) {
|
||||
// create dirs if they are not there (e.g. the "clean" task just ran)
|
||||
doFirst {
|
||||
jsBundleDirDebug.mkdirs()
|
||||
resourcesDirDebug.mkdirs()
|
||||
void runBefore(String dependentTaskName, Task task) {
|
||||
Task dependentTask = tasks.findByPath(dependentTaskName);
|
||||
if (dependentTask != null) {
|
||||
dependentTask.dependsOn task
|
||||
}
|
||||
|
||||
// set up inputs and outputs so gradle can cache the result
|
||||
inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
|
||||
outputs.dir jsBundleDirDebug
|
||||
outputs.dir resourcesDirDebug
|
||||
|
||||
// set up the call to the react-native cli
|
||||
workingDir reactRoot
|
||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
commandLine "cmd", "/c", "react-native", "bundle", "--platform", "android", "--dev", "true", "--entry-file",
|
||||
entryFile, "--bundle-output", jsBundleFileDebug, "--assets-dest", resourcesDirDebug
|
||||
} else {
|
||||
commandLine "react-native", "bundle", "--platform", "android", "--dev", "true", "--entry-file",
|
||||
entryFile, "--bundle-output", jsBundleFileDebug, "--assets-dest", resourcesDirDebug
|
||||
}
|
||||
|
||||
enabled config.bundleInDebug ?: false
|
||||
}
|
||||
|
||||
task bundleReleaseJsAndAssets(type: Exec) {
|
||||
// create dirs if they are not there (e.g. the "clean" task just ran)
|
||||
doFirst {
|
||||
jsBundleDirRelease.mkdirs()
|
||||
resourcesDirRelease.mkdirs()
|
||||
}
|
||||
|
||||
// set up inputs and outputs so gradle can cache the result
|
||||
inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
|
||||
outputs.dir jsBundleDirRelease
|
||||
outputs.dir resourcesDirRelease
|
||||
|
||||
// set up the call to the react-native cli
|
||||
workingDir reactRoot
|
||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
commandLine "cmd","/c", "react-native", "bundle", "--platform", "android", "--dev", "false", "--entry-file",
|
||||
entryFile, "--bundle-output", jsBundleFileRelease, "--assets-dest", resourcesDirRelease
|
||||
} else {
|
||||
commandLine "react-native", "bundle", "--platform", "android", "--dev", "false", "--entry-file",
|
||||
entryFile, "--bundle-output", jsBundleFileRelease, "--assets-dest", resourcesDirRelease
|
||||
}
|
||||
|
||||
enabled config.bundleInRelease ?: true
|
||||
}
|
||||
|
||||
gradle.projectsEvaluated {
|
||||
// hook bundleDebugJsAndAssets into the android build process
|
||||
bundleDebugJsAndAssets.dependsOn mergeDebugResources
|
||||
bundleDebugJsAndAssets.dependsOn mergeDebugAssets
|
||||
processDebugResources.dependsOn bundleDebugJsAndAssets
|
||||
// Grab all build types and product flavors
|
||||
def buildTypes = android.buildTypes.collect { type -> type.name }
|
||||
def productFlavors = android.productFlavors.collect { flavor -> flavor.name }
|
||||
|
||||
// hook bundleReleaseJsAndAssets into the android build process
|
||||
bundleReleaseJsAndAssets.dependsOn mergeReleaseResources
|
||||
bundleReleaseJsAndAssets.dependsOn mergeReleaseAssets
|
||||
processReleaseResources.dependsOn bundleReleaseJsAndAssets
|
||||
// When no product flavors defined, use empty
|
||||
if (!productFlavors) productFlavors.add('')
|
||||
|
||||
productFlavors.each { productFlavorName ->
|
||||
buildTypes.each { buildTypeName ->
|
||||
// Create variant and target names
|
||||
def targetName = "${productFlavorName.capitalize()}${buildTypeName.capitalize()}"
|
||||
def targetPath = productFlavorName ?
|
||||
"${productFlavorName}/${buildTypeName}" :
|
||||
"${buildTypeName}"
|
||||
|
||||
// React js bundle directories
|
||||
def jsBundleDirConfigName = "jsBundleDir${targetName}"
|
||||
def jsBundleDir = elvisFile(config."$jsBundleDirConfigName") ?:
|
||||
file("$buildDir/intermediates/assets/${targetPath}")
|
||||
|
||||
def resourcesDirConfigName = "resourcesDir${targetName}"
|
||||
def resourcesDir = elvisFile(config."${resourcesDirConfigName}") ?:
|
||||
file("$buildDir/intermediates/res/merged/${targetPath}")
|
||||
def jsBundleFile = file("$jsBundleDir/$bundleAssetName")
|
||||
|
||||
// Bundle task name for variant
|
||||
def bundleJsAndAssetsTaskName = "bundle${targetName}JsAndAssets"
|
||||
|
||||
def currentBundleTask = tasks.create(
|
||||
name: bundleJsAndAssetsTaskName,
|
||||
type: Exec) {
|
||||
group = "react"
|
||||
description = "bundle JS and assets for ${targetName}."
|
||||
|
||||
// Create dirs if they are not there (e.g. the "clean" task just ran)
|
||||
doFirst {
|
||||
jsBundleDir.mkdirs()
|
||||
resourcesDir.mkdirs()
|
||||
}
|
||||
|
||||
// Set up inputs and outputs so gradle can cache the result
|
||||
inputs.files fileTree(dir: reactRoot, excludes: inputExcludes)
|
||||
outputs.dir jsBundleDir
|
||||
outputs.dir resourcesDir
|
||||
|
||||
// Set up the call to the react-native cli
|
||||
workingDir reactRoot
|
||||
|
||||
// Set up dev mode
|
||||
def devEnabled = !targetName.toLowerCase().contains("release")
|
||||
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
|
||||
commandLine "cmd", "/c", "node", "node_modules/react-native/local-cli/cli.js", "bundle", "--platform", "android", "--dev", "${devEnabled}",
|
||||
"--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir
|
||||
} else {
|
||||
commandLine "node", "node_modules/react-native/local-cli/cli.js", "bundle", "--platform", "android", "--dev", "${devEnabled}",
|
||||
"--entry-file", entryFile, "--bundle-output", jsBundleFile, "--assets-dest", resourcesDir
|
||||
}
|
||||
|
||||
enabled config."bundleIn${targetName}" ||
|
||||
config."bundleIn${buildTypeName.capitalize()}" ?:
|
||||
targetName.toLowerCase().contains("release")
|
||||
}
|
||||
|
||||
// Hook bundle${productFlavor}${buildType}JsAndAssets into the android build process
|
||||
currentBundleTask.dependsOn("merge${targetName}Resources")
|
||||
currentBundleTask.dependsOn("merge${targetName}Assets")
|
||||
|
||||
runBefore("processArmeabi-v7a${targetName}Resources", currentBundleTask)
|
||||
runBefore("processX86${targetName}Resources", currentBundleTask)
|
||||
runBefore("processUniversal${targetName}Resources", currentBundleTask)
|
||||
runBefore("process${targetName}Resources", currentBundleTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.testfairy">
|
||||
package="com.testfairy.react.example">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:icon="@mipmap/launcher"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
|
@ -1,78 +0,0 @@
|
||||
package com.testfairy;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import com.facebook.react.LifecycleState;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
|
||||
import com.facebook.react.shell.MainReactPackage;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
|
||||
public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
|
||||
|
||||
private ReactInstanceManager mReactInstanceManager;
|
||||
private ReactRootView mReactRootView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mReactRootView = new ReactRootView(this);
|
||||
|
||||
mReactInstanceManager = ReactInstanceManager.builder()
|
||||
.setApplication(getApplication())
|
||||
.setBundleAssetName("index.android.bundle")
|
||||
.setJSMainModuleName("index.android")
|
||||
.addPackage(new MainReactPackage())
|
||||
.setUseDeveloperSupport(BuildConfig.DEBUG)
|
||||
.setInitialLifecycleState(LifecycleState.RESUMED)
|
||||
.build();
|
||||
|
||||
mReactRootView.startReactApplication(mReactInstanceManager, "TestFairy", null);
|
||||
|
||||
setContentView(mReactRootView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
|
||||
mReactInstanceManager.showDevOptionsDialog();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (mReactInstanceManager != null) {
|
||||
mReactInstanceManager.onBackPressed();
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeDefaultOnBackPressed() {
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (mReactInstanceManager != null) {
|
||||
mReactInstanceManager.onPause();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if (mReactInstanceManager != null) {
|
||||
mReactInstanceManager.onResume(this, this);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.testfairy.react.example;
|
||||
|
||||
import com.facebook.react.ReactActivity;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.shell.MainReactPackage;
|
||||
import com.testfairy.react.TestFairyPackage;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class MainActivity extends ReactActivity {
|
||||
|
||||
/**
|
||||
* Returns the name of the main component registered from JavaScript.
|
||||
* This is used to schedule rendering of the component.
|
||||
*/
|
||||
@Override
|
||||
protected String getMainComponentName() {
|
||||
return "TestFairy";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether dev mode should be enabled.
|
||||
* This enables e.g. the dev menu.
|
||||
*/
|
||||
@Override
|
||||
protected boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of packages used by the app. If the app uses additional views
|
||||
* or modules besides the default ones, add more packages here.
|
||||
*/
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new MainReactPackage(),
|
||||
new TestFairyPackage()
|
||||
);
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
@ -16,5 +16,9 @@ allprojects {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
maven {
|
||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||
url "$projectDir/../../node_modules/react-native/android"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
rootProject.name = 'TestFairy'
|
||||
|
||||
include ':app'
|
||||
include ':react-native-testfairy'
|
||||
project(':react-native-testfairy').projectDir = new File(settingsDir, '../node_modules/react-native-testfairy/android')
|
@ -2,24 +2,33 @@
|
||||
* Sample React Native App
|
||||
* https://github.com/facebook/react-native
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
import React, {
|
||||
AppRegistry,
|
||||
Component,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
} = React;
|
||||
View
|
||||
} from 'react-native';
|
||||
|
||||
var TestFairy = React.createClass({
|
||||
render: function() {
|
||||
const TestFairyBridge = require('react-native-testfairy');
|
||||
|
||||
class TestFairy extends Component {
|
||||
componentWillMount() {
|
||||
TestFairyBridge.begin('5b3af35e59a1e074e2d50675b1b629306cf0cfbd');
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
TestFairyBridge.hideView(this.refs.instructions);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.welcome}>
|
||||
Welcome to React Native!
|
||||
</Text>
|
||||
<Text style={styles.instructions}>
|
||||
<Text style={styles.instructions} ref="instructions">
|
||||
To get started, edit index.android.js
|
||||
</Text>
|
||||
<Text style={styles.instructions}>
|
||||
@ -28,9 +37,9 @@ var TestFairy = React.createClass({
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
|
@ -2,43 +2,45 @@
|
||||
* Sample React Native App
|
||||
* https://github.com/facebook/react-native
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var React = require('react-native');
|
||||
var {
|
||||
import React, {
|
||||
AppRegistry,
|
||||
Component,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
findNodeHandle
|
||||
} = React;
|
||||
View
|
||||
} from 'react-native';
|
||||
|
||||
const TestFairyBridge = require('react-native-testfairy');
|
||||
|
||||
var TestFairy = React.createClass({
|
||||
componentDidMount: function() {
|
||||
TestFairyBridge.hideView(findNodeHandle(this.refs.instructions));
|
||||
},
|
||||
class TestFairy extends Component {
|
||||
componentWillMount() {
|
||||
TestFairyBridge.begin('5b3af35e59a1e074e2d50675b1b629306cf0cfbd');
|
||||
}
|
||||
|
||||
render: function() {
|
||||
componentDidMount() {
|
||||
TestFairyBridge.hideView(this.refs.instructions);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.welcome}>
|
||||
Welcome to React Native!
|
||||
</Text>
|
||||
<Text style={styles.instructions} ref="instructions">
|
||||
<Text style={styles.instructions}>
|
||||
To get started, edit index.ios.js
|
||||
</Text>
|
||||
<Text style={styles.instructions}>
|
||||
<Text style={styles.instructions} ref="instructions">
|
||||
Press Cmd+R to reload,{'\n'}
|
||||
Cmd+D or shake for dev menu
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var styles = StyleSheet.create({
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
@ -57,5 +59,4 @@ var styles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
TestFairyBridge.begin('5b3af35e59a1e074e2d50675b1b629306cf0cfbd');
|
||||
AppRegistry.registerComponent('TestFairy', () => TestFairy);
|
||||
|
175
example/ios/TestFairy.h
Normal file
@ -0,0 +1,175 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface TestFairy: NSObject
|
||||
|
||||
/**
|
||||
* Initialize a TestFairy session.
|
||||
*
|
||||
* @param appToken Your key as given to you in your TestFairy account
|
||||
*/
|
||||
+ (void)begin:(NSString *)appToken;
|
||||
|
||||
/**
|
||||
* Initialize a TestFairy session with options.
|
||||
*
|
||||
* @param appToken Your key as given to you in your TestFairy account
|
||||
* @param options A dictionary of options controlling the current session
|
||||
*/
|
||||
+ (void)begin:(NSString *)appToken withOptions:(NSDictionary *)options;
|
||||
|
||||
/**
|
||||
* Change the server endpoint for use with on-premise hosting. Please
|
||||
* contact support or sales for more information. Must be called before begin
|
||||
*
|
||||
* @param serverOverride
|
||||
*/
|
||||
+ (void)setServerEndpoint:(NSString *)serverOverride;
|
||||
|
||||
/**
|
||||
* Returns SDK version (x.x.x) string
|
||||
*
|
||||
* @return version
|
||||
*/
|
||||
+ (NSString *)version;
|
||||
|
||||
/**
|
||||
* Hides a specific view from appearing in the video generated.
|
||||
*
|
||||
* @param view The specific view you wish to hide from screenshots
|
||||
*
|
||||
*/
|
||||
+ (void)hideView:(UIView *)view;
|
||||
|
||||
/**
|
||||
* Hides a specific html element from appearing in your UIWebView
|
||||
*
|
||||
* @param selector The specific selector you wish to hide from screenshots. Multiple selectors can be comma separated
|
||||
*/
|
||||
+ (void)hideWebViewElements:(NSString *)selector;
|
||||
|
||||
/**
|
||||
* Pushes the feedback view controller. Hook a button
|
||||
* to this method to allow users to provide feedback about the current
|
||||
* session. All feedback will appear in your build report page, and in
|
||||
* the recorded session page.
|
||||
*
|
||||
*/
|
||||
+ (void)pushFeedbackController;
|
||||
|
||||
/**
|
||||
* Send a feedback on behalf of the user. Call when using a in-house
|
||||
* feedback view controller with a custom design and feel. Feedback will
|
||||
* be associated with the current session.
|
||||
*
|
||||
* @param feedbackString Feedback text
|
||||
*/
|
||||
+ (void)sendUserFeedback:(NSString *)feedbackString;
|
||||
|
||||
/**
|
||||
* Proxy didUpdateLocation delegate values and these
|
||||
* locations will appear in the recorded sessions. Useful for debugging
|
||||
* actual long/lat values against what the user sees on screen.
|
||||
*
|
||||
* @param locations Array of CLLocation. The first object of the array will determine the user location
|
||||
*/
|
||||
+ (void)updateLocation:(NSArray *)locations;
|
||||
|
||||
/**
|
||||
* Marks a checkpoint in session. Use this text to tag a session
|
||||
* with a checkpoint name. Later you can filter sessions where your
|
||||
* user passed through this checkpoint, for bettering understanding
|
||||
* user experience and behavior.
|
||||
*
|
||||
* @param name The checkpoint name
|
||||
*/
|
||||
+ (void)checkpoint:(NSString *)name;
|
||||
|
||||
/**
|
||||
* Sets a correlation identifier for this session. This value can
|
||||
* be looked up via web dashboard. For example, setting correlation
|
||||
* to the value of the user-id after they logged in. Can be called
|
||||
* only once per session (subsequent calls will be ignored.)
|
||||
*
|
||||
* @param correlationId Id for the current session
|
||||
*/
|
||||
+ (void)setCorrelationId:(NSString *)correlationId;
|
||||
|
||||
/**
|
||||
* Sets a correlation identifier for this session. This value can
|
||||
* be looked up via web dashboard. For example, setting correlation
|
||||
* to the value of the user-id after they logged in. Can be called
|
||||
* only once per session (subsequent calls will be ignored.)
|
||||
*
|
||||
* @param correlationId Id for the current session
|
||||
*/
|
||||
+ (void)identify:(NSString *)correlationId;
|
||||
|
||||
/**
|
||||
* Sets a correlation identifier for this session. This value can
|
||||
* be looked up via web dashboard. For example, setting correlation
|
||||
* to the value of the user-id after they logged in. Can be called
|
||||
* only once per session (subsequent calls will be ignored.)
|
||||
*
|
||||
* @param correlationId Id for the current session
|
||||
* @param traits Attributes and custom attributes to be associated with this session
|
||||
*/
|
||||
+ (void)identify:(NSString *)correlationId traits:(NSDictionary *)traits;
|
||||
|
||||
/**
|
||||
* Pauses the current session. This method stops recoding of
|
||||
* the current session until resume has been called.
|
||||
*
|
||||
* @see resume
|
||||
*/
|
||||
+ (void)pause;
|
||||
|
||||
/**
|
||||
* Resumes the recording of the current session. This method
|
||||
* resumes a session after it was paused.
|
||||
*
|
||||
* @see pause
|
||||
*/
|
||||
+ (void)resume;
|
||||
|
||||
/**
|
||||
* Returns the address of the recorded session on testfairy's
|
||||
* developer portal. Will return nil if recording not yet started.
|
||||
*
|
||||
* @return session URL
|
||||
*/
|
||||
+ (NSString *)sessionUrl;
|
||||
|
||||
/**
|
||||
* Takes a screenshot.
|
||||
*
|
||||
*/
|
||||
+ (void)takeScreenshot;
|
||||
|
||||
/**
|
||||
* Remote logging, use TFLog as you would use printf. These logs will be sent to the server,
|
||||
* but will not appear in the console.
|
||||
*/
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void TFLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
|
||||
void TFLogv(NSString *format, va_list arg_list);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
extern NSString *const TFSDKIdentityTraitNameKey;
|
||||
extern NSString *const TFSDKIdentityTraitEmailAddressKey;
|
||||
extern NSString *const TFSDKIdentityTraitBirthdayKey;
|
||||
extern NSString *const TFSDKIdentityTraitGenderKey;
|
||||
extern NSString *const TFSDKIdentityTraitPhoneNumberKey;
|
||||
extern NSString *const TFSDKIdentityTraitWebsiteAddressKey;
|
||||
extern NSString *const TFSDKIdentityTraitAgeKey;
|
||||
extern NSString *const TFSDKIdentityTraitSignupDateKey;
|
||||
extern NSString *const TFSDKEnableCrashReporterKey;
|
||||
|
@ -21,10 +21,12 @@
|
||||
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 */; };
|
||||
42E652531C42DD9D008B8114 /* libTestFairy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42E6524E1C42DD9D008B8114 /* libTestFairy.a */; };
|
||||
42E652541C42DD9D008B8114 /* RCTTestFairyBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 42E652501C42DD9D008B8114 /* RCTTestFairyBridge.m */; };
|
||||
42E652551C42DD9D008B8114 /* upload-dsym.sh in Resources */ = {isa = PBXBuildFile; fileRef = 42E652521C42DD9D008B8114 /* upload-dsym.sh */; };
|
||||
42E652601C42DE19008B8114 /* libTestFairy.a in Resources */ = {isa = PBXBuildFile; fileRef = 42E6524E1C42DD9D008B8114 /* libTestFairy.a */; };
|
||||
42547DE11CBB43FE007BA376 /* RCTTestFairyBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 42547DDD1CBB43FE007BA376 /* RCTTestFairyBridge.m */; };
|
||||
42547DF11CBB4490007BA376 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42547DEE1CBB4490007BA376 /* AVFoundation.framework */; };
|
||||
42547DF21CBB4490007BA376 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42547DEF1CBB4490007BA376 /* CoreMedia.framework */; };
|
||||
42547DF31CBB4490007BA376 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 42547DF01CBB4490007BA376 /* SystemConfiguration.framework */; };
|
||||
42547DF71CBB451B007BA376 /* libTestFairy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42547DF41CBB451B007BA376 /* libTestFairy.a */; };
|
||||
42547DF81CBB451B007BA376 /* upload-dsym.sh in Resources */ = {isa = PBXBuildFile; fileRef = 42547DF61CBB451B007BA376 /* upload-dsym.sh */; };
|
||||
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@ -128,11 +130,14 @@
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = TestFairy/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = TestFairy/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>"; };
|
||||
42E6524E1C42DD9D008B8114 /* libTestFairy.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libTestFairy.a; sourceTree = "<group>"; };
|
||||
42E6524F1C42DD9D008B8114 /* RCTTestFairyBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTTestFairyBridge.h; sourceTree = "<group>"; };
|
||||
42E652501C42DD9D008B8114 /* RCTTestFairyBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTTestFairyBridge.m; sourceTree = "<group>"; };
|
||||
42E652511C42DD9D008B8114 /* TestFairy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestFairy.h; sourceTree = "<group>"; };
|
||||
42E652521C42DD9D008B8114 /* upload-dsym.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "upload-dsym.sh"; sourceTree = "<group>"; };
|
||||
42547DDC1CBB43FE007BA376 /* RCTTestFairyBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTTestFairyBridge.h; path = "../node_modules/react-native-testfairy/ios/RCTTestFairyBridge.h"; sourceTree = "<group>"; };
|
||||
42547DDD1CBB43FE007BA376 /* RCTTestFairyBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RCTTestFairyBridge.m; path = "../node_modules/react-native-testfairy/ios/RCTTestFairyBridge.m"; sourceTree = "<group>"; };
|
||||
42547DEE1CBB4490007BA376 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
|
||||
42547DEF1CBB4490007BA376 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
|
||||
42547DF01CBB4490007BA376 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
|
||||
42547DF41CBB451B007BA376 /* libTestFairy.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libTestFairy.a; sourceTree = "<group>"; };
|
||||
42547DF51CBB451B007BA376 /* TestFairy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestFairy.h; sourceTree = "<group>"; };
|
||||
42547DF61CBB451B007BA376 /* upload-dsym.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "upload-dsym.sh"; 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>"; };
|
||||
/* End PBXFileReference section */
|
||||
@ -149,6 +154,9 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
42547DF11CBB4490007BA376 /* AVFoundation.framework in Frameworks */,
|
||||
42547DF21CBB4490007BA376 /* CoreMedia.framework in Frameworks */,
|
||||
42547DF31CBB4490007BA376 /* SystemConfiguration.framework in Frameworks */,
|
||||
146834051AC3E58100842450 /* libReact.a in Frameworks */,
|
||||
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
|
||||
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
|
||||
@ -156,10 +164,10 @@
|
||||
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,
|
||||
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,
|
||||
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,
|
||||
42E652531C42DD9D008B8114 /* libTestFairy.a in Frameworks */,
|
||||
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
|
||||
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
|
||||
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
|
||||
42547DF71CBB451B007BA376 /* libTestFairy.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -242,6 +250,7 @@
|
||||
13B07FAE1A68108700A75B9A /* TestFairy */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
42547DED1CBB4405007BA376 /* TestFairySDK */,
|
||||
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */,
|
||||
@ -261,16 +270,16 @@
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
42E6524D1C42DD9D008B8114 /* ios */ = {
|
||||
42547DED1CBB4405007BA376 /* TestFairySDK */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
42E6524E1C42DD9D008B8114 /* libTestFairy.a */,
|
||||
42E6524F1C42DD9D008B8114 /* RCTTestFairyBridge.h */,
|
||||
42E652501C42DD9D008B8114 /* RCTTestFairyBridge.m */,
|
||||
42E652511C42DD9D008B8114 /* TestFairy.h */,
|
||||
42E652521C42DD9D008B8114 /* upload-dsym.sh */,
|
||||
42547DF41CBB451B007BA376 /* libTestFairy.a */,
|
||||
42547DF51CBB451B007BA376 /* TestFairy.h */,
|
||||
42547DF61CBB451B007BA376 /* upload-dsym.sh */,
|
||||
42547DDC1CBB43FE007BA376 /* RCTTestFairyBridge.h */,
|
||||
42547DDD1CBB43FE007BA376 /* RCTTestFairyBridge.m */,
|
||||
);
|
||||
path = ios;
|
||||
name = TestFairySDK;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
78C398B11ACF4ADC00677621 /* Products */ = {
|
||||
@ -284,7 +293,6 @@
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
42E6524D1C42DD9D008B8114 /* ios */,
|
||||
146833FF1AC3E56700842450 /* React.xcodeproj */,
|
||||
00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
|
||||
00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
|
||||
@ -310,6 +318,9 @@
|
||||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
42547DEE1CBB4490007BA376 /* AVFoundation.framework */,
|
||||
42547DEF1CBB4490007BA376 /* CoreMedia.framework */,
|
||||
42547DF01CBB4490007BA376 /* SystemConfiguration.framework */,
|
||||
13B07FAE1A68108700A75B9A /* TestFairy */,
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||
00E356EF1AD99517003FC87E /* TestFairyTests */,
|
||||
@ -528,9 +539,8 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
42E652601C42DE19008B8114 /* libTestFairy.a in Resources */,
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
42E652551C42DD9D008B8114 /* upload-dsym.sh in Resources */,
|
||||
42547DF81CBB451B007BA376 /* upload-dsym.sh in Resources */,
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -550,7 +560,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "../node_modules/react-native/packager/react-native-xcode.sh";
|
||||
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
@ -569,7 +579,7 @@
|
||||
files = (
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
42E652541C42DD9D008B8114 /* RCTTestFairyBridge.m in Sources */,
|
||||
42547DE11CBB43FE007BA376 /* RCTTestFairyBridge.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -647,9 +657,10 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/ios",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.testfairy.react.Example;
|
||||
PRODUCT_NAME = TestFairy;
|
||||
};
|
||||
name = Debug;
|
||||
@ -667,9 +678,10 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/ios",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.testfairy.react.Example;
|
||||
PRODUCT_NAME = TestFairy;
|
||||
};
|
||||
name = Release;
|
||||
|
@ -36,7 +36,9 @@
|
||||
/**
|
||||
* OPTION 2
|
||||
* Load from pre-bundled file on disk. The static bundle is automatically
|
||||
* generated by "Bundle React Native code and images" build step.
|
||||
* generated by the "Bundle React Native code and images" build step when
|
||||
* running the project on an actual device or running the project on the
|
||||
* simulator in the "Release" build configuration.
|
||||
*/
|
||||
|
||||
// jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||
|
@ -7,7 +7,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
@ -22,6 +22,13 @@
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
@ -36,13 +43,5 @@
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -1 +0,0 @@
|
||||
../../ios/
|
BIN
example/ios/libTestFairy.a
Normal file
85
example/ios/upload-dsym.sh
Normal file
@ -0,0 +1,85 @@
|
||||
#!/bin/sh
|
||||
|
||||
TESTFAIRY_ENDPOINT="http://app.testfairy.com/upload/dsym/"
|
||||
|
||||
ZIP=zip
|
||||
CURL=curl
|
||||
STAT=stat
|
||||
DATE=date
|
||||
|
||||
log() {
|
||||
NOW=$($DATE +"%Y-%m-%d %H:%M:%S")
|
||||
echo "${NOW} ${1}"
|
||||
}
|
||||
|
||||
help() {
|
||||
echo "Usage: ${0} [-f] TESTFAIRY_API_KEY [-p DSYM_PATH]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
DAEMON=1
|
||||
if [ "${1}" == "-f" ]; then
|
||||
DAEMON=0
|
||||
shift
|
||||
elif [ "${1}" == "-d" ]; then
|
||||
# backward compatible when -f was the default
|
||||
shift
|
||||
fi
|
||||
|
||||
|
||||
API_KEY="${1}"
|
||||
if [ ! "${API_KEY}" ]; then
|
||||
help
|
||||
fi
|
||||
|
||||
DSYM_PATH=${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}
|
||||
|
||||
if [ "${#}" -gt 1 ]; then
|
||||
shift
|
||||
if [ "${1}" != "-p" ]; then
|
||||
help
|
||||
fi
|
||||
|
||||
shift
|
||||
DSYM_PATH="${1}"
|
||||
fi
|
||||
|
||||
if [ "${DSYM_PATH}" == "" ] || [ "${DSYM_PATH}" == "/" ] || [ ! -d "${DSYM_PATH}" ]; then
|
||||
echo "Fatal: Can't find .dSYM folder!"
|
||||
help
|
||||
fi
|
||||
|
||||
NOW=$($DATE +%s)
|
||||
TMP_FILENAME="/tmp/${NOW}-${DWARF_DSYM_FILE_NAME}.zip"
|
||||
|
||||
# Compress the .dSYM folder into a zip file
|
||||
log "Compressing .dSYM folder ${DSYM_PATH}"
|
||||
$ZIP -qrp9 "${TMP_FILENAME}" "${DSYM_PATH}"
|
||||
FILE_SIZE=$($STAT -f "%z" "${TMP_FILENAME}")
|
||||
|
||||
foreground_upload() {
|
||||
# Upload zipped .dSYM file to TestFairy's servers
|
||||
STARTED=$($DATE +"%s")
|
||||
$CURL -s -F api_key="${API_KEY}" -F dsym=@"${1}" -o /dev/null "${TESTFAIRY_ENDPOINT}"
|
||||
ENDED=$($DATE +"%s")
|
||||
DIFF=$(expr ${ENDED} - ${STARTED})
|
||||
log "Symbols uploaded in ${DIFF} seconds"
|
||||
|
||||
# Clean up behind
|
||||
rm -f ${TMP_FILENAME}
|
||||
}
|
||||
|
||||
background_upload() {
|
||||
sh -c "$CURL -F api_key=\"${API_KEY}\" -F dsym=@\"${1}\" -s -o /dev/null \"${TESTFAIRY_ENDPOINT}\"; rm -f ${TMP_FILENAME};" /dev/null 2>&1 &
|
||||
}
|
||||
|
||||
if [ "$DAEMON" == "0" ]; then
|
||||
log "Uploading ${FILE_SIZE} bytes to dsym server in foreground"
|
||||
foreground_upload "${TMP_FILENAME}"
|
||||
else
|
||||
log "Uploading ${FILE_SIZE} bytes to dsym server in background"
|
||||
background_upload "${TMP_FILENAME}"
|
||||
fi
|
||||
|
||||
log "TestFairy .dSYM upload script ends"
|
||||
|
@ -6,7 +6,8 @@
|
||||
"start": "node node_modules/react-native/local-cli/cli.js start"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-native": "^0.17.0",
|
||||
"react": "^0.14.8",
|
||||
"react-native": "^0.23.1",
|
||||
"react-native-testfairy": "file:../"
|
||||
}
|
||||
}
|
||||
|
6
index.js
@ -1,6 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const TestFairyBridge = require("react-native").NativeModules.TestFairyBridge;
|
||||
var React = require('react-native');
|
||||
const findNodeHandle = React.findNodeHandle;
|
||||
const TestFairyBridge = React.NativeModules.TestFairyBridge;
|
||||
|
||||
class TestFairy {
|
||||
/**
|
||||
@ -94,7 +96,7 @@ class TestFairy {
|
||||
* @param view The specific view you wish to hide from screenshots
|
||||
*/
|
||||
static hideView(viewTag) {
|
||||
TestFairyBridge.hideView(viewTag);
|
||||
TestFairyBridge.hideView(findNodeHandle(viewTag));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-testfairy",
|
||||
"version": "1.6.6",
|
||||
"version": "2.0.0",
|
||||
"description": "TestFairy for React Native",
|
||||
"author": "Gil Megidish",
|
||||
"main": "./index.js",
|
||||
@ -15,7 +15,8 @@
|
||||
"react-component",
|
||||
"testfairy",
|
||||
"react-native",
|
||||
"ios"
|
||||
"ios",
|
||||
"android"
|
||||
],
|
||||
"author": "testfairy",
|
||||
"license": "Apache-2.0",
|
||||
|