Skip to content

Commit

Permalink
Implement touch visualizers for Detox
Browse files Browse the repository at this point in the history
Closes wix#426
  • Loading branch information
LeoNatan committed Nov 23, 2017
1 parent fc6a1a2 commit 58df5a6
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 66 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@
path = detox/ios/EarlGrey
url = https://github.com/google/EarlGrey.git
ignore = dirty
[submodule "detox/ios/COSTouchVisualizer"]
path = detox/ios/COSTouchVisualizer
url = https://github.com/conopsys/COSTouchVisualizer
1 change: 1 addition & 0 deletions detox/ios/COSTouchVisualizer
Submodule COSTouchVisualizer added at ad729c
30 changes: 30 additions & 0 deletions detox/ios/Detox.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
3928EFBE1E475E4C00C19B6E /* user_notification_calendar_trigger.json in Resources */ = {isa = PBXBuildFile; fileRef = 3928EFBA1E475E4C00C19B6E /* user_notification_calendar_trigger.json */; };
3928EFBF1E475E4C00C19B6E /* user_notification_push_trigger.json in Resources */ = {isa = PBXBuildFile; fileRef = 3928EFBB1E475E4C00C19B6E /* user_notification_push_trigger.json */; };
3928EFC21E47673800C19B6E /* LegacyApiAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3928EFC11E47673800C19B6E /* LegacyApiAppDelegate.swift */; };
393E66ED1FC5F3F40092EE89 /* COSTouchVisualizer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 393E66E61FC5F3E90092EE89 /* COSTouchVisualizer.framework */; };
3947679C1DBF985400D72256 /* Detox.h in Headers */ = {isa = PBXBuildFile; fileRef = 3947679A1DBF985400D72256 /* Detox.h */; settings = {ATTRIBUTES = (Public, ); }; };
394767AE1DBF987E00D72256 /* DetoxManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 394767A41DBF987E00D72256 /* DetoxManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
394767AF1DBF987E00D72256 /* DetoxManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 394767A51DBF987E00D72256 /* DetoxManager.m */; };
Expand Down Expand Up @@ -85,6 +86,13 @@
remoteGlobalIDString = 394767961DBF985400D72256;
remoteInfo = Detox;
};
393E66E51FC5F3E90092EE89 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 393E66E11FC5F3E90092EE89 /* COSTouchVisualizer.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = A71946A71C7EF890003B7C4A;
remoteInfo = COSTouchVisualizer;
};
394767DB1DBF991E00D72256 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 394767D71DBF991E00D72256 /* EarlGrey.xcodeproj */;
Expand Down Expand Up @@ -182,6 +190,7 @@
3928EFBA1E475E4C00C19B6E /* user_notification_calendar_trigger.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = user_notification_calendar_trigger.json; sourceTree = "<group>"; };
3928EFBB1E475E4C00C19B6E /* user_notification_push_trigger.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = user_notification_push_trigger.json; sourceTree = "<group>"; };
3928EFC11E47673800C19B6E /* LegacyApiAppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyApiAppDelegate.swift; sourceTree = "<group>"; };
393E66E11FC5F3E90092EE89 /* COSTouchVisualizer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = COSTouchVisualizer.xcodeproj; path = COSTouchVisualizer/Classes/COSTouchVisualizer.xcodeproj; sourceTree = "<group>"; };
394767971DBF985400D72256 /* Detox.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Detox.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3947679A1DBF985400D72256 /* Detox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Detox.h; sourceTree = "<group>"; };
3947679B1DBF985400D72256 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -239,6 +248,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
393E66ED1FC5F3F40092EE89 /* COSTouchVisualizer.framework in Frameworks */,
394767F71DBF994500D72256 /* EarlGrey.framework in Frameworks */,
394767F61DBF994200D72256 /* SocketRocket.framework in Frameworks */,
);
Expand Down Expand Up @@ -284,6 +294,14 @@
name = UserNotificationTestInputs;
sourceTree = "<group>";
};
393E66E21FC5F3E90092EE89 /* Products */ = {
isa = PBXGroup;
children = (
393E66E61FC5F3E90092EE89 /* COSTouchVisualizer.framework */,
);
name = Products;
sourceTree = "<group>";
};
3947678D1DBF985400D72256 = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -371,6 +389,7 @@
394767D61DBF990F00D72256 /* Frameworks */ = {
isa = PBXGroup;
children = (
393E66E11FC5F3E90092EE89 /* COSTouchVisualizer.xcodeproj */,
394767DD1DBF992400D72256 /* SocketRocket.xcodeproj */,
394767D71DBF991E00D72256 /* EarlGrey.xcodeproj */,
);
Expand Down Expand Up @@ -509,6 +528,10 @@
productRefGroup = 394767981DBF985400D72256 /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 393E66E21FC5F3E90092EE89 /* Products */;
ProjectRef = 393E66E11FC5F3E90092EE89 /* COSTouchVisualizer.xcodeproj */;
},
{
ProductGroup = 394767D81DBF991E00D72256 /* Products */;
ProjectRef = 394767D71DBF991E00D72256 /* EarlGrey.xcodeproj */;
Expand All @@ -528,6 +551,13 @@
/* End PBXProject section */

/* Begin PBXReferenceProxy section */
393E66E61FC5F3E90092EE89 /* COSTouchVisualizer.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = COSTouchVisualizer.framework;
remoteRef = 393E66E51FC5F3E90092EE89 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
394767DC1DBF991E00D72256 /* EarlGrey.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
Expand Down
46 changes: 44 additions & 2 deletions detox/ios/Detox/DetoxAppDelegateProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,44 @@
@import ObjectiveC;
@import UIKit;
@import UserNotifications;
@import COSTouchVisualizer;

#import <Detox/Detox-Swift.h>

@class DetoxAppDelegateProxy;

static DetoxAppDelegateProxy* _currentAppDelegateProxy;
static COSTouchVisualizerWindow* _touchVisualizerWindow;

@interface UIWindow (DTXEventProxy) @end

@implementation UIWindow (DTXEventProxy)

+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Method m1 = class_getInstanceMethod(self, @selector(sendEvent:));
Method m2 = class_getInstanceMethod(self, @selector(__dtx_sendEvent:));
method_exchangeImplementations(m1, m2);
});
}

- (void)__dtx_sendEvent:(UIEvent *)event
{
if([self isKindOfClass:[COSTouchVisualizerWindow class]])
{
return;
}

[_touchVisualizerWindow sendEvent:event];
[self __dtx_sendEvent:event];
}

@interface DetoxAppDelegateProxy () <UIApplicationDelegate>
@end

@interface DetoxAppDelegateProxy () <UIApplicationDelegate, COSTouchVisualizerWindowDelegate> @end

@implementation DetoxAppDelegateProxy

+ (instancetype)currentAppDelegateProxy
Expand Down Expand Up @@ -63,7 +91,7 @@ + (void)load
{
Method m = class_getInstanceMethod([UIApplication class], @selector(setDelegate:));
void (*orig)(id, SEL, id<UIApplicationDelegate>) = (void*)method_getImplementation(m);
method_setImplementation(m, imp_implementationWithBlock(^ (id _self, id<UIApplicationDelegate> origDelegate) {
method_setImplementation(m, imp_implementationWithBlock(^ (id _self, id<UIApplicationDelegate, COSTouchVisualizerWindowDelegate> origDelegate) {
//Only create a dupe class if the provided instance is not already a dupe class.
if(origDelegate != nil && [origDelegate respondsToSelector:@selector(__dtx_canaryInTheCoalMine)] == NO)
{
Expand Down Expand Up @@ -92,6 +120,15 @@ - (void)__dtx_canaryInTheCoalMine {}
- (void)__dtx_applicationDidLaunchNotification:(NSNotification*)notification
{
[self.__dtx_userNotificationDispatcher dispatchOnAppDelegate:self simulateDuringLaunch:YES];

dispatch_async(dispatch_get_main_queue(), ^{
_touchVisualizerWindow = [[COSTouchVisualizerWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
_touchVisualizerWindow.windowLevel = 100000000000;
_touchVisualizerWindow.backgroundColor = [UIColor.greenColor colorWithAlphaComponent:0.0];
_touchVisualizerWindow.hidden = NO;
_touchVisualizerWindow.touchVisualizerWindowDelegate = self;
_touchVisualizerWindow.userInteractionEnabled = NO;
});
}

- (NSURL*)_userNotificationDataURL
Expand Down Expand Up @@ -189,4 +226,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
return rv;
}

- (BOOL)touchVisualizerWindowShouldAlwaysShowFingertip:(COSTouchVisualizerWindow *)window
{
return YES;
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
disableMainThreadChecker = "YES"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
Expand Down
129 changes: 65 additions & 64 deletions detox/test/package.json
Original file line number Diff line number Diff line change
@@ -1,65 +1,66 @@
{
"name": "detox-test",
"version": "0.0.1",
"private": true,
"scripts": {
"test": ":",
"packager": "react-native start",
"detox-server": "detox run-server",
"e2e:ios": "detox test --configuration ios.sim.release --debug-synchronization 10000",
"e2e:android": "detox test --configuration android.emu.release --loglevel verbose",
"build:ios": "detox build --configuration ios.sim.release",
"build:android": "detox build --configuration android.emu.release"
},
"dependencies": {
"react": "^16.0.0-beta.5",
"react-native": "^0.49.3"
},
"devDependencies": {
"detox": "^5.0.0",
"express": "^4.15.3",
"lodash": "^4.14.1",
"mocha": "^4.0.0"
},
"detox": {
"specs": "e2e",
"__session": {
"server": "ws://localhost:8099",
"sessionId": "test"
},
"configurations": {
"ios.sim.debug": {
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
"build": "set -o pipefail && xcodebuild -project ios/example.xcodeproj -scheme example_ci -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build | xcpretty",
"type": "ios.simulator",
"name": "iPhone 7 Plus"
},
"ios.sim.release": {
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app",
"build": "set -o pipefail && export CODE_SIGNING_REQUIRED=NO && export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -project ios/example.xcodeproj -scheme example_ci -configuration Release -sdk iphonesimulator -derivedDataPath ios/build | xcpretty",
"type": "ios.simulator",
"name": "iPhone 7 Plus"
},
"ios.none": {
"type": "ios.none",
"name": "iPhone 7 Plus",
"session": {
"server": "ws://localhost:8099",
"sessionId": "test"
}
},
"android.emu.debug": {
"binaryPath": "android/app/build/outputs/apk/app-debug.apk",
"build": "cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd ..",
"type": "android.emulator",
"name": "Nexus_5X_API_24"
},
"android.emu.release": {
"binaryPath": "android/app/build/outputs/apk/app-release.apk",
"build": "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..",
"type": "android.emulator",
"name": "Nexus_5X_API_26"
}
}
}
}
"name": "detox-test",
"version": "0.0.1",
"private": true,
"scripts": {
"test": ":",
"packager": "react-native start",
"detox-server": "detox run-server",
"e2e:ios": "detox test --configuration ios.sim.release --debug-synchronization 10000",
"e2e:android": "detox test --configuration android.emu.release --loglevel verbose",
"build:ios": "detox build --configuration ios.sim.release",
"build:android": "detox build --configuration android.emu.release"
},
"dependencies": {
"react": "^16.0.0-beta.5",
"react-native": "^0.49.3"
},
"devDependencies": {
"detox": "^5.0.0",
"express": "^4.15.3",
"lodash": "^4.14.1",
"mocha": "^4.0.0"
},
"detox": {
"specs": "e2e",
"__session": {
"server": "ws://localhost:8099",
"sessionId": "test"
},
"configurations": {
"ios.sim.debug": {
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
"build": "set -o pipefail && xcodebuild -project ios/example.xcodeproj -scheme example_ci -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build | xcpretty",
"type": "ios.simulator",
"name": "iPhone 7 Plus"
},
"ios.sim.release": {
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app",
"build": "set -o pipefail && export CODE_SIGNING_REQUIRED=NO && export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -project ios/example.xcodeproj -scheme example_ci -configuration Release -sdk iphonesimulator -derivedDataPath ios/build | xcpretty",
"type": "ios.simulator",
"name": "iPhone 7 Plus"
},
"ios.none": {
"binaryPath": "ios",
"type": "ios.none",
"name": "iPhone 7 Plus",
"session": {
"server": "ws://localhost:8099",
"sessionId": "test"
}
},
"android.emu.debug": {
"binaryPath": "android/app/build/outputs/apk/app-debug.apk",
"build": "cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd ..",
"type": "android.emulator",
"name": "Nexus_5X_API_24"
},
"android.emu.release": {
"binaryPath": "android/app/build/outputs/apk/app-release.apk",
"build": "cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..",
"type": "android.emulator",
"name": "Nexus_5X_API_26"
}
}
}
}

0 comments on commit 58df5a6

Please sign in to comment.