Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into CrashHandling
Browse files Browse the repository at this point in the history
# Conflicts:
#	detox/ios/Detox/DetoxManager.h
#	detox/ios/Detox/DetoxManager.m
#	detox/ios/Detox/TestRunner.m
  • Loading branch information
LeoNatan committed Feb 7, 2018
2 parents fb9fea8 + 44589fa commit 567ccea
Show file tree
Hide file tree
Showing 16 changed files with 127 additions and 345 deletions.
8 changes: 1 addition & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,7 @@ matrix:
- NAME='Website - master'
node_js: 8
script:
- git config --global user.email "$GIT_USER@users.noreply.github.com"
- git config --global user.name "Wix"
- echo "machine github.com login $GIT_USER password $GIT_TOKEN" > ~/.netrc
- cd website && npm install && GIT_USER=$GIT_USER CURRENT_BRANCH=master npm run publish-gh-pages
branches:
only:
- master
- scripts/publish-website.sh

branches:
only:
Expand Down
246 changes: 2 additions & 244 deletions detox/ios/Detox.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

61 changes: 35 additions & 26 deletions detox/ios/Detox/DetoxManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ @interface DetoxManager() <WebSocketDelegate, TestRunnerDelegate>

@end

@implementation DetoxManager

+ (void)load
__attribute__((constructor))
static void detoxConditionalInit()
{
//This forces accessibility support in the application.
[[[NSUserDefaults alloc] initWithSuiteName:@"com.apple.Accessibility"] setBool:YES forKey:@"ApplicationAccessibilityEnabled"];
Expand All @@ -51,6 +50,8 @@ + (void)load
[[DetoxManager sharedManager] connectToServer:detoxServer withSessionId:detoxSessionId];
}

@implementation DetoxManager

+ (instancetype)sharedManager
{
static DetoxManager *sharedInstance = nil;
Expand Down Expand Up @@ -118,36 +119,44 @@ - (void)websocketDidReceiveAction:(NSString *)type withParams:(NSDictionary *)pa
}
else if([type isEqualToString:@"userNotification"])
{
NSURL* userNotificationDataURL = [NSURL fileURLWithPath:params[@"detoxUserNotificationDataURL"]];
DetoxUserNotificationDispatcher* dispatcher = [[DetoxUserNotificationDispatcher alloc] initWithUserNotificationDataURL:userNotificationDataURL];
[dispatcher dispatchOnAppDelegate:DetoxAppDelegateProxy.currentAppDelegateProxy simulateDuringLaunch:NO];
[self.webSocket sendAction:@"userNotificationDone" withParams:@{} withMessageId:messageId];
[EarlGrey detox_safeExecuteSync:^{
NSURL* userNotificationDataURL = [NSURL fileURLWithPath:params[@"detoxUserNotificationDataURL"]];
DetoxUserNotificationDispatcher* dispatcher = [[DetoxUserNotificationDispatcher alloc] initWithUserNotificationDataURL:userNotificationDataURL];
[dispatcher dispatchOnAppDelegate:DetoxAppDelegateProxy.currentAppDelegateProxy simulateDuringLaunch:NO];
[self.webSocket sendAction:@"userNotificationDone" withParams:@{} withMessageId: messageId];
}];
}
else if([type isEqualToString:@"openURL"])
{
NSURL* URLToOpen = [NSURL URLWithString:params[@"url"]];

NSParameterAssert(URLToOpen != nil);

NSString* sourceApp = params[@"sourceApp"];

NSMutableDictionary* options = [@{UIApplicationLaunchOptionsURLKey: URLToOpen} mutableCopy];
if(sourceApp != nil)
{
options[UIApplicationLaunchOptionsSourceApplicationKey] = sourceApp;
}

if([[UIApplication sharedApplication].delegate respondsToSelector:@selector(application:openURL:options:)])
{
[[UIApplication sharedApplication].delegate application:[UIApplication sharedApplication] openURL:URLToOpen options:options];
}

[self.webSocket sendAction:@"openURLDone" withParams:@{} withMessageId:messageId];
[EarlGrey detox_safeExecuteSync:^{
NSURL* URLToOpen = [NSURL URLWithString:params[@"url"]];

NSParameterAssert(URLToOpen != nil);

NSString* sourceApp = params[@"sourceApp"];

NSMutableDictionary* options = [@{UIApplicationLaunchOptionsURLKey: URLToOpen} mutableCopy];
if(sourceApp != nil)
{
options[UIApplicationLaunchOptionsSourceApplicationKey] = sourceApp;
}

if([[UIApplication sharedApplication].delegate respondsToSelector:@selector(application:openURL:options:)])
{
[[UIApplication sharedApplication].delegate application:[UIApplication sharedApplication] openURL:URLToOpen options:options];
}

[self.webSocket sendAction:@"openURLDone" withParams:@{} withMessageId: messageId];
}];
}
else if([type isEqualToString:@"shakeDevice"])
{ }
else if([type isEqualToString:@"reactNativeReload"])
{
_isReady = NO;
[ReactNativeSupport reloadApp];
[EarlGrey detox_safeExecuteSync:^{
[ReactNativeSupport reloadApp];
}];

[self _waitForRNLoadWithId:messageId];

Expand Down
1 change: 1 addition & 0 deletions detox/ios/Detox/EarlGrey+Detox.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

@interface EarlGreyImpl (Detox)

- (void)detox_safeExecuteSync:(void(^)(void))block;
- (GREYElementInteraction *)detox_selectElementWithMatcher:(id<GREYMatcher>)elementMatcher;

@end
9 changes: 9 additions & 0 deletions detox/ios/Detox/EarlGrey+Detox.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@

@implementation EarlGreyImpl (Detox)

- (void)detox_safeExecuteSync:(void(^)(void))block
{
grey_execute_async(^{
[[GREYUIThreadExecutor sharedInstance] executeSync:^{
block();
} error:NULL];
});
}

- (GREYElementInteraction *)detox_selectElementWithMatcher:(id<GREYMatcher>)elementMatcher
{
return [self selectElementWithMatcher:[GREYMatchers detoxMatcherAvoidingProblematicReactNativeElements:elementMatcher]];
Expand Down
1 change: 1 addition & 0 deletions detox/ios/Detox/EarlGreyExtensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

#import <EarlGrey/EarlGrey.h>
#import "EarlGrey+Detox.h"

/**
Expose provate Earl Grey methods
Expand Down
2 changes: 1 addition & 1 deletion detox/src/devices/IosDriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class IosDriver extends DeviceDriverBase {
}

async openURL(deviceId, params) {
this.client.openURL(params);
await this.client.openURL(params);
}

async setURLBlacklist(urlList) {
Expand Down
4 changes: 2 additions & 2 deletions detox/test/e2e/c-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('Actions', () => {
});

it('should tap on an element at point', async () => {
await element(by.id('View7990')).tapAtPoint({x:180, y:140});
await element(by.id('View7990')).tapAtPoint({ x: 180, y: 140 });
await expect(element(by.id('UniqueId819'))).toHaveText('Taps: 1');
});

Expand Down Expand Up @@ -81,7 +81,7 @@ describe('Actions', () => {
await expect(element(by.text('PullToReload Working!!!'))).toBeVisible();
});

it('should wait for long timeout', async () => {
it.only('should not wait for long timeout (>1.5s)', async () => {
await element(by.id('WhyDoAllTheTestIDsHaveTheseStrangeNames')).tap();
await expect(element(by.id('WhyDoAllTheTestIDsHaveTheseStrangeNames'))).toBeVisible();
});
Expand Down
12 changes: 12 additions & 0 deletions detox/test/ios/example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@
399B4E061ED587120098D2AC /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
39A077861E5450E700A53A07 /* RCTPushNotification.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTPushNotification.xcodeproj; path = "../node_modules/react-native/Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj"; sourceTree = "<group>"; };
39B0445B1DAED76400431EC5 /* Detox.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Detox.xcodeproj; path = ../../ios/Detox.xcodeproj; sourceTree = "<group>"; };
39FC9D23202899F90033C11A /* e2e */ = {isa = PBXFileReference; lastKnownFileType = folder; name = e2e; path = ../e2e; sourceTree = "<group>"; };
39FC9D24202899F90033C11A /* src */ = {isa = PBXFileReference; lastKnownFileType = folder; name = src; path = ../src; 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>"; };
CC17D3301D60A24300267B0C /* NativeModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeModule.h; path = example/NativeModule.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -524,6 +526,15 @@
name = Products;
sourceTree = "<group>";
};
39FC9CFD202899D10033C11A /* JS */ = {
isa = PBXGroup;
children = (
39FC9D23202899F90033C11A /* e2e */,
39FC9D24202899F90033C11A /* src */,
);
name = JS;
sourceTree = "<group>";
};
78C398B11ACF4ADC00677621 /* Products */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -565,6 +576,7 @@
isa = PBXGroup;
children = (
13B07FAE1A68108700A75B9A /* example */,
39FC9CFD202899D10033C11A /* JS */,
CCFA7DE41D11D22600E15EDF /* Frameworks */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
83CBBA001A601CBA00E9B192 /* Products */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
Expand All @@ -61,7 +60,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
disableMainThreadChecker = "YES"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
Expand Down
16 changes: 9 additions & 7 deletions detox/test/src/Screens/ActionsScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ export default class ActionsScreen extends Component {

<TouchableOpacity onPress={this.onButtonPress.bind(this, 'Tap Working')}
onLongPress={this.onButtonPress.bind(this, 'Long Press Working')}
>
>
<Text style={{ color: 'blue', marginBottom: 20, textAlign: 'center' }}>Tap Me</Text>
</TouchableOpacity>

<TouchableOpacity onPress={this.onLongTimeout.bind(this)}
>
>
<Text testID='WhyDoAllTheTestIDsHaveTheseStrangeNames' style={{ color: 'blue', marginBottom: 20, textAlign: 'center' }}>Tap Me For Long Timeout</Text>
</TouchableOpacity>

Expand All @@ -46,19 +46,19 @@ export default class ActionsScreen extends Component {
onChangeText={this.onChangeTypeText.bind(this)}
value={this.state.typeText}
testID='UniqueId937'
/>
/>

<TextInput style={{ height: 40, borderColor: 'gray', borderWidth: 1, marginBottom: 20, marginHorizontal: 20, padding: 5 }}
onChangeText={this.onChangeClearText.bind(this)}
value={this.state.clearText}
testID='UniqueId005'
/>
/>

<TextInput style={{ height: 40, borderColor: 'gray', borderWidth: 1, marginBottom: 20, marginHorizontal: 20, padding: 5 }}
onChangeText={this.onReplaceText.bind(this)}
value={this.state.replaceText}
testID='UniqueId006'
/>
/>

<View style={{ height: 100, borderColor: '#c0c0c0', borderWidth: 1, backgroundColor: '#f8f8ff', marginBottom: 20 }}>
<ScrollView testID='ScrollView161'>
Expand Down Expand Up @@ -100,9 +100,11 @@ export default class ActionsScreen extends Component {
});
}

onLongTimeout(greeting) {
onLongTimeout() {
setTimeout(() => {
greeting: 'Long Timeout Done'
this.setState({
greeting: "After Long Timeout"
});
}, 4000);
}

Expand Down
2 changes: 1 addition & 1 deletion docs/APIRef.DetoxCLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Initiating your test suite
| -h, --help | output usage information |
| -o, --runner-config \<config\> | Test runner config file, defaults to 'e2e/mocha.opts' for mocha and 'e2e/config.json' for jest |
| -l, --loglevel [value] | info, debug, verbose, silly, wss |
| -c, -configuration \<device config\> | Select a device configuration from your defined figurations,if not supplied, and there's only one configuration, detox will default to it |
| -c, -configuration \<device config\> | Select a device configuration from your defined configurations,if not supplied, and there's only one configuration, detox will default to it |
| -r, --reuse | Reuse existing installed app (do not delete and re-tall) for a faster run. |
| -u, --cleanup | Shutdown simulator when test is over, useful for CI ipts, to make sure detox exists cleanly with no residue |
| -d, --debug-synchronization \<value\> | When an action/expectation takes a significant amount time use this option to print device synchronization status. The status will be printed if the ion takes more than [value]ms to complete |
Expand Down
82 changes: 32 additions & 50 deletions docs/Guide.DebuggingInXcode.md
Original file line number Diff line number Diff line change
@@ -1,84 +1,66 @@
---
id: Guide.DebuggingInXcode
title: Debugging Apps in Xcode During a Test
---
# Debugging in Xcode During Detox Tests

> Advanced users might need to natively debug their app inside Xcode during a Detox test. This is mostly useful for invesigating weird crahses or when contributing to Detox itself.
> This is mostly useful for investigating weird crashes or when contributing to Detox itself. **This workflow isn't standard. Don't use it unless you have a good reason.**
This workflow isn't standard. Don't use it unless you have a good reason.
### Add Detox Framework to Your Project

<br>
* Go to `node_modules/detox` and extract `Detox-ios-src.tbz`
* Drag `Detox-ios-src/Detox.xcodeproj` into your Xcode project
* Go to your project settings -> **General** and add **Detox.framework** to **Embedded Binaries**

## Step 1: Add Detox framework to your project
> NOTE: Apps should not be submitted to the App Store with the Detox framework linked. Follow this guide only to debug Detox issues in your project. Once finished, make sure to remove **Detox.framework** from your project.
Open your Xcode project and drag `Detox.framework` from `node_modules/detox/Detox.framework` to your project.
### Add launch arguments

> NOTE: Apps should not be submitted to the App Store with the Detox framework linked. Follow this guide only to debug Detox issues in your project. Once finished, make sure to remove `Detox.framework` from your project.
Under **Product** menu select **Scheme** -> **Edit Scheme** and select **Run** -> **Arguments** tab and add the following launch arguments to **Arguments Passed On Launch**:

<br>

## Step 2: Add launch arguments

Edit your project scheme and add the following arguments to **Arguments Passed On Launch**:

```
-detoxServer
ws://localhost:8099
-detoxSessionId
test
```

<br>

## Step 3: Add custom session to Detox config

Edit Detox config in `package.json` to [add a custom session](/docs/APIRef.Configuration.md#server-configuration) by adding the `session` key under the `detox` section:

```json
"detox": {
"session": {
"server": "ws://localhost:8099",
"sessionId": "test"
}
}
<project_name>
```

<br>
> NOTE: Add each line as a separate line in Xcode.
## Step 4: Add a special xcode configuration to Detox config
### Add 'None' Configuration to Detox Section

Edit Detox config in `package.json` by adding a new configuration with type `ios.none` to the `configurations` key under the `detox` section:
Edit the Detox section in `package.json` to add the following configuration:

```json
"detox": {
"configurations": {
"xcode": {
"type": "ios.none"
"ios.none": {
"binaryPath": "ios",
"type": "ios.none",
"name": "iPhone 8 Plus",
"session": {
"server": "ws://localhost:8099",
"sessionId": "<project_name>"
}
}
}
```

> NOTE: This configuration will not handle simulator and application lifecycle, they will have to be provided manually (via Xcode "Play" button or `react-native run-ios`).
> NOTE: This configuration will not handle simulator and application lifecycle, they will have to be provided manually (via running your application from Xcode).
<br>
### Run Detox Server Manually

## Step 5: Run Detox server manually

Type the following inside your project root:
Run the following command in your project root directory:

```sh
detox run-server
```

<br>
### Run Your Application

> NOTE: Before running, place breakpoints you wish to debug.
Run your application from Xcode as you normally do.

## Step 6: Run Detox tests
### Run Detox Tests

Type the following inside your project root:
Run the following command in your project root directory:

```sh
detox test --configuration xcode
detox test --configuration ios.none
```

> NOTE: Tests that expect the app to be restarted via `device.relaunchApp()` will fail.
> NOTE: Tests that call `device.relaunchApp()` may fail as this API is unavailable when using `ios.none` configuration types. Instead, use `it.only` to run specific tests and restart your app from Xcode.
2 changes: 1 addition & 1 deletion docs/Introduction.GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ The basic configuration for Detox should be in your `package.json` file under th

In the above configuration example, change `example` to your actual project name. Under the key `"binaryPath"`, `example.app` should be `<your_project_name>.app`. Under the key `"build"`, `example.xcodeproj` should be `<your_project_name>.xcodeproj` and `-scheme example` should be `-scheme <your_project_name>`.

For iOS apps in a workspace (eg: Cocoapods) use `-workspace ios/example.xcworkspace` instead of `-project`.
For iOS apps in a workspace (eg: CocoaPods) use `-workspace ios/example.xcworkspace` instead of `-project`.

Also make sure the simulator model specified under the key `"name"` (`iPhone 7` above) is actually available on your machine (it was installed by Xcode). Check this by typing `xcrun simctl list` in terminal to display all available simulators.

Expand Down
Loading

0 comments on commit 567ccea

Please sign in to comment.