appium-webdriveragent 4.4.3 → 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PrivateHeaders/XCTest/XCUICoordinate.h +2 -0
- package/PrivateHeaders/XCTest/XCUIDevice.h +2 -0
- package/PrivateHeaders/XCTest/XCUIElement.h +2 -0
- package/README.md +1 -0
- package/Scripts/build-webdriveragent.js +1 -1
- package/Scripts/fetch-prebuilt-wda.js +1 -1
- package/WebDriverAgent.xcodeproj/project.xcworkspace/xcuserdata/elf.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/WebDriverAgent.xcodeproj/xcuserdata/elf.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +91 -0
- package/WebDriverAgent.xcodeproj/xcuserdata/elf.xcuserdatad/xcschemes/xcschememanagement.plist +59 -0
- package/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.h +13 -13
- package/WebDriverAgentLib/Categories/XCUIElement+FBForceTouch.m +34 -45
- package/WebDriverAgentLib/Commands/FBElementCommands.m +47 -40
- package/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +22 -5
- package/WebDriverAgentRunner-Runner.app.zip +0 -0
- package/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m +1 -29
- package/WebDriverAgentTests/IntegrationTests/FBElementScreenshotTests.m +1 -16
- package/WebDriverAgentTests/IntegrationTests/FBForceTouchTests.m +16 -5
- package/WebDriverAgentTests/IntegrationTests/FBPasteboardTests.m +8 -2
- package/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m +35 -4
- package/WebDriverAgentTests/IntegrationTests/XCUIDeviceHelperTests.m +17 -6
- package/build/index.js +1 -1
- package/build/lib/check-dependencies.js +2 -2
- package/build/lib/constants.js +1 -1
- package/build/lib/logger.js +2 -2
- package/build/lib/no-session-proxy.js +3 -3
- package/build/lib/utils.js +2 -2
- package/build/lib/webdriveragent.js +4 -4
- package/build/lib/xcodebuild.js +2 -2
- package/lib/check-dependencies.js +1 -1
- package/lib/logger.js +1 -1
- package/lib/no-session-proxy.js +1 -1
- package/lib/utils.js +1 -1
- package/lib/webdriveragent.js +2 -2
- package/lib/xcodebuild.js +1 -1
- package/package.json +5 -3
|
@@ -43,6 +43,8 @@
|
|
|
43
43
|
- (id)_highestNonWindowAncestorOfElement:(id)arg1 notSharedWithElement:(id)arg2;
|
|
44
44
|
- (id)_pointsInFrame:(CGRect)arg1 numberOfTouches:(unsigned long long)arg2;
|
|
45
45
|
- (CGPoint)_hitPointByAttemptingToScrollToVisibleSnapshot:(id)arg1;
|
|
46
|
+
// Since 11.3
|
|
47
|
+
- (void)pressWithPressure:(double)arg1 duration:(double)arg2;
|
|
46
48
|
- (void)forcePress;
|
|
47
49
|
- (void)tapWithNumberOfTaps:(unsigned long long)arg1 numberOfTouches:(unsigned long long)arg2;
|
|
48
50
|
- (void)twoFingerTap;
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const os = require('os');
|
|
3
3
|
const { asyncify } = require('asyncbox');
|
|
4
|
-
const { logger, fs, mkdirp, zip } = require('
|
|
4
|
+
const { logger, fs, mkdirp, zip } = require('appium/support');
|
|
5
5
|
const { exec } = require('teen_process');
|
|
6
6
|
const xcode = require('appium-xcode');
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const axios = require('axios');
|
|
3
3
|
const { asyncify } = require('asyncbox');
|
|
4
|
-
const { logger, fs, mkdirp, net } = require('
|
|
4
|
+
const { logger, fs, mkdirp, net } = require('appium/support');
|
|
5
5
|
const _ = require('lodash');
|
|
6
6
|
const B = require('bluebird');
|
|
7
7
|
|
|
Binary file
|
package/WebDriverAgent.xcodeproj/xcuserdata/elf.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<Bucket
|
|
3
|
+
uuid = "2F0174F2-ED3F-4D11-9A17-7C590053D796"
|
|
4
|
+
type = "1"
|
|
5
|
+
version = "2.0">
|
|
6
|
+
<Breakpoints>
|
|
7
|
+
<BreakpointProxy
|
|
8
|
+
BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
|
|
9
|
+
<BreakpointContent
|
|
10
|
+
uuid = "471ECA8C-2C53-4C59-88DB-1C1CB3D61601"
|
|
11
|
+
shouldBeEnabled = "No"
|
|
12
|
+
ignoreCount = "0"
|
|
13
|
+
continueAfterRunningActions = "No"
|
|
14
|
+
breakpointStackSelectionBehavior = "1"
|
|
15
|
+
scope = "1"
|
|
16
|
+
stopOnStyle = "0">
|
|
17
|
+
</BreakpointContent>
|
|
18
|
+
</BreakpointProxy>
|
|
19
|
+
<BreakpointProxy
|
|
20
|
+
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
|
21
|
+
<BreakpointContent
|
|
22
|
+
uuid = "C2E06865-6A52-4686-9771-279AF13ABF8A"
|
|
23
|
+
shouldBeEnabled = "Yes"
|
|
24
|
+
ignoreCount = "0"
|
|
25
|
+
continueAfterRunningActions = "No"
|
|
26
|
+
filePath = "WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m"
|
|
27
|
+
timestampString = "0"
|
|
28
|
+
startingColumnNumber = "9223372036854775807"
|
|
29
|
+
endingColumnNumber = "9223372036854775807"
|
|
30
|
+
startingLineNumber = "264"
|
|
31
|
+
endingLineNumber = "264">
|
|
32
|
+
</BreakpointContent>
|
|
33
|
+
</BreakpointProxy>
|
|
34
|
+
<BreakpointProxy
|
|
35
|
+
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
|
36
|
+
<BreakpointContent
|
|
37
|
+
uuid = "54216FE6-E240-47F1-88D3-D450CF0AF44E"
|
|
38
|
+
shouldBeEnabled = "Yes"
|
|
39
|
+
ignoreCount = "0"
|
|
40
|
+
continueAfterRunningActions = "No"
|
|
41
|
+
filePath = "WebDriverAgentLib/Categories/XCUIElement+FBResolve.m"
|
|
42
|
+
startingColumnNumber = "9223372036854775807"
|
|
43
|
+
endingColumnNumber = "9223372036854775807"
|
|
44
|
+
startingLineNumber = "37"
|
|
45
|
+
endingLineNumber = "37"
|
|
46
|
+
landmarkName = "-fb_stableInstance"
|
|
47
|
+
landmarkType = "7">
|
|
48
|
+
<Locations>
|
|
49
|
+
<Location
|
|
50
|
+
uuid = "54216FE6-E240-47F1-88D3-D450CF0AF44E - b09f4ce1ce926e6"
|
|
51
|
+
shouldBeEnabled = "Yes"
|
|
52
|
+
ignoreCount = "0"
|
|
53
|
+
continueAfterRunningActions = "No"
|
|
54
|
+
symbolName = "-[XCUIElement(FBResolve) fb_stableInstance]"
|
|
55
|
+
moduleName = "WebDriverAgentLib"
|
|
56
|
+
usesParentBreakpointCondition = "Yes"
|
|
57
|
+
urlString = "file:///Users/elf/code/WebDriverAgent/WebDriverAgentLib/Categories/XCUIElement+FBResolve.m"
|
|
58
|
+
startingColumnNumber = "9223372036854775807"
|
|
59
|
+
endingColumnNumber = "9223372036854775807"
|
|
60
|
+
startingLineNumber = "37"
|
|
61
|
+
endingLineNumber = "37"
|
|
62
|
+
offsetFromSymbolStart = "19">
|
|
63
|
+
</Location>
|
|
64
|
+
<Location
|
|
65
|
+
shouldBeEnabled = "Yes"
|
|
66
|
+
ignoreCount = "0"
|
|
67
|
+
continueAfterRunningActions = "No"
|
|
68
|
+
usesParentBreakpointCondition = "Yes"
|
|
69
|
+
offsetFromSymbolStart = "0">
|
|
70
|
+
</Location>
|
|
71
|
+
</Locations>
|
|
72
|
+
</BreakpointContent>
|
|
73
|
+
</BreakpointProxy>
|
|
74
|
+
<BreakpointProxy
|
|
75
|
+
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
|
76
|
+
<BreakpointContent
|
|
77
|
+
uuid = "D3009B57-42BC-4905-99BC-70232544FAFB"
|
|
78
|
+
shouldBeEnabled = "Yes"
|
|
79
|
+
ignoreCount = "0"
|
|
80
|
+
continueAfterRunningActions = "No"
|
|
81
|
+
filePath = "WebDriverAgentTests/IntegrationTests/FBAlertTests.m"
|
|
82
|
+
startingColumnNumber = "5"
|
|
83
|
+
endingColumnNumber = "64"
|
|
84
|
+
startingLineNumber = "32"
|
|
85
|
+
endingLineNumber = "32"
|
|
86
|
+
landmarkName = "-setUp"
|
|
87
|
+
landmarkType = "7">
|
|
88
|
+
</BreakpointContent>
|
|
89
|
+
</BreakpointProxy>
|
|
90
|
+
</Breakpoints>
|
|
91
|
+
</Bucket>
|
package/WebDriverAgent.xcodeproj/xcuserdata/elf.xcuserdatad/xcschemes/xcschememanagement.plist
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>SchemeUserState</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key>IntegrationApp.xcscheme_^#shared#^_</key>
|
|
8
|
+
<dict>
|
|
9
|
+
<key>orderHint</key>
|
|
10
|
+
<integer>0</integer>
|
|
11
|
+
</dict>
|
|
12
|
+
<key>IntegrationTests_1.xcscheme_^#shared#^_</key>
|
|
13
|
+
<dict>
|
|
14
|
+
<key>orderHint</key>
|
|
15
|
+
<integer>1</integer>
|
|
16
|
+
</dict>
|
|
17
|
+
<key>IntegrationTests_2.xcscheme_^#shared#^_</key>
|
|
18
|
+
<dict>
|
|
19
|
+
<key>orderHint</key>
|
|
20
|
+
<integer>2</integer>
|
|
21
|
+
</dict>
|
|
22
|
+
<key>IntegrationTests_3.xcscheme_^#shared#^_</key>
|
|
23
|
+
<dict>
|
|
24
|
+
<key>orderHint</key>
|
|
25
|
+
<integer>3</integer>
|
|
26
|
+
</dict>
|
|
27
|
+
<key>WebDriverAgentLib copy.xcscheme_^#shared#^_</key>
|
|
28
|
+
<dict>
|
|
29
|
+
<key>orderHint</key>
|
|
30
|
+
<integer>9</integer>
|
|
31
|
+
</dict>
|
|
32
|
+
<key>WebDriverAgentLib.xcscheme_^#shared#^_</key>
|
|
33
|
+
<dict>
|
|
34
|
+
<key>orderHint</key>
|
|
35
|
+
<integer>4</integer>
|
|
36
|
+
</dict>
|
|
37
|
+
<key>WebDriverAgentLib_tvOS.xcscheme_^#shared#^_</key>
|
|
38
|
+
<dict>
|
|
39
|
+
<key>orderHint</key>
|
|
40
|
+
<integer>5</integer>
|
|
41
|
+
</dict>
|
|
42
|
+
<key>WebDriverAgentRunner-nodebug.xcscheme_^#shared#^_</key>
|
|
43
|
+
<dict>
|
|
44
|
+
<key>orderHint</key>
|
|
45
|
+
<integer>7</integer>
|
|
46
|
+
</dict>
|
|
47
|
+
<key>WebDriverAgentRunner.xcscheme_^#shared#^_</key>
|
|
48
|
+
<dict>
|
|
49
|
+
<key>orderHint</key>
|
|
50
|
+
<integer>6</integer>
|
|
51
|
+
</dict>
|
|
52
|
+
<key>WebDriverAgentRunner_tvOS.xcscheme_^#shared#^_</key>
|
|
53
|
+
<dict>
|
|
54
|
+
<key>orderHint</key>
|
|
55
|
+
<integer>8</integer>
|
|
56
|
+
</dict>
|
|
57
|
+
</dict>
|
|
58
|
+
</dict>
|
|
59
|
+
</plist>
|
|
@@ -11,29 +11,29 @@
|
|
|
11
11
|
|
|
12
12
|
NS_ASSUME_NONNULL_BEGIN
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
#if !TARGET_OS_TV
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
Waits for element to become stable (not move) and performs sync force touch on element
|
|
18
|
-
|
|
19
|
-
@param error If there is an error, upon return contains an NSError object that describes the problem.
|
|
20
|
-
@param pressure The pressure of the force touch – valid values are [0, touch.maximumPossibleForce]
|
|
21
|
-
@param duration The duration of the gesture in float seconds
|
|
22
|
-
@return YES if the operation succeeds, otherwise NO.
|
|
23
|
-
*/
|
|
24
|
-
- (BOOL)fb_forceTouchWithPressure:(double)pressure duration:(double)duration error:(NSError **)error;
|
|
16
|
+
@interface XCUIElement (FBForceTouch)
|
|
25
17
|
|
|
26
18
|
/**
|
|
27
|
-
|
|
19
|
+
Performs force touch on element
|
|
28
20
|
|
|
29
|
-
@param relativeCoordinate hit point coordinate relative to the current element position
|
|
21
|
+
@param relativeCoordinate hit point coordinate relative to the current element position.
|
|
22
|
+
nil value means to use the default element hit point
|
|
30
23
|
@param pressure The pressure of the force touch – valid values are [0, touch.maximumPossibleForce]
|
|
24
|
+
nil value would use the default pressure value
|
|
31
25
|
@param duration The duration of the gesture in float seconds
|
|
26
|
+
nil value would use the default duration value
|
|
32
27
|
@param error If there is an error, upon return contains an NSError object that describes the problem.
|
|
33
28
|
@return YES if the operation succeeds, otherwise NO.
|
|
34
29
|
*/
|
|
35
|
-
- (BOOL)fb_forceTouchCoordinate:(
|
|
30
|
+
- (BOOL)fb_forceTouchCoordinate:(nullable NSValue *)relativeCoordinate
|
|
31
|
+
pressure:(nullable NSNumber *)pressure
|
|
32
|
+
duration:(nullable NSNumber *)duration
|
|
33
|
+
error:(NSError **)error;
|
|
36
34
|
|
|
37
35
|
@end
|
|
38
36
|
|
|
37
|
+
#endif
|
|
38
|
+
|
|
39
39
|
NS_ASSUME_NONNULL_END
|
|
@@ -9,56 +9,45 @@
|
|
|
9
9
|
|
|
10
10
|
#import "XCUIElement+FBForceTouch.h"
|
|
11
11
|
|
|
12
|
-
#
|
|
12
|
+
#if !TARGET_OS_TV
|
|
13
|
+
|
|
14
|
+
#import "FBErrorBuilder.h"
|
|
15
|
+
#import "XCUICoordinate.h"
|
|
16
|
+
#import "XCUIDevice.h"
|
|
13
17
|
|
|
14
18
|
@implementation XCUIElement (FBForceTouch)
|
|
15
19
|
|
|
16
|
-
- (BOOL)
|
|
20
|
+
- (BOOL)fb_forceTouchCoordinate:(NSValue *)relativeCoordinate
|
|
21
|
+
pressure:(NSNumber *)pressure
|
|
22
|
+
duration:(NSNumber *)duration
|
|
23
|
+
error:(NSError **)error
|
|
17
24
|
{
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@"pressure": @(pressure)
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
@{
|
|
27
|
-
@"action": @"wait",
|
|
28
|
-
@"options": @{
|
|
29
|
-
@"ms": @(duration * 1000)
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
@{
|
|
33
|
-
@"action": @"release"
|
|
34
|
-
}
|
|
35
|
-
];
|
|
36
|
-
return [self.application fb_performAppiumTouchActions:gesture elementCache:nil error:error];
|
|
37
|
-
}
|
|
25
|
+
if (![XCUIDevice sharedDevice].supportsPressureInteraction) {
|
|
26
|
+
return [[[FBErrorBuilder builder]
|
|
27
|
+
withDescriptionFormat:@"Force press is not supported on this device"]
|
|
28
|
+
buildError:error];
|
|
29
|
+
}
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
@{
|
|
58
|
-
@"action": @"release"
|
|
59
|
-
}
|
|
60
|
-
];
|
|
61
|
-
return [self.application fb_performAppiumTouchActions:gesture elementCache:nil error:error];
|
|
31
|
+
if (nil == relativeCoordinate) {
|
|
32
|
+
if (nil == pressure || nil == duration) {
|
|
33
|
+
[self forcePress];
|
|
34
|
+
} else {
|
|
35
|
+
[self pressWithPressure:[pressure doubleValue] duration:[duration doubleValue]];
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
CGSize size = self.frame.size;
|
|
39
|
+
CGVector offset = CGVectorMake(size.width > 0 ? relativeCoordinate.CGPointValue.x / size.width : 0,
|
|
40
|
+
size.height > 0 ? relativeCoordinate.CGPointValue.y / size.height : 0);
|
|
41
|
+
XCUICoordinate *hitPoint = [self coordinateWithNormalizedOffset:offset];
|
|
42
|
+
if (nil == pressure || nil == duration) {
|
|
43
|
+
[hitPoint forcePress];
|
|
44
|
+
} else {
|
|
45
|
+
[hitPoint pressWithPressure:[pressure doubleValue] duration:[duration doubleValue]];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return YES;
|
|
62
49
|
}
|
|
63
50
|
|
|
64
51
|
@end
|
|
52
|
+
|
|
53
|
+
#endif
|
|
@@ -85,14 +85,15 @@
|
|
|
85
85
|
[[FBRoute POST:@"/wda/element/:uuid/touchAndHold"] respondWithTarget:self action:@selector(handleTouchAndHold:)],
|
|
86
86
|
[[FBRoute POST:@"/wda/element/:uuid/scroll"] respondWithTarget:self action:@selector(handleScroll:)],
|
|
87
87
|
[[FBRoute POST:@"/wda/element/:uuid/dragfromtoforduration"] respondWithTarget:self action:@selector(handleDrag:)],
|
|
88
|
+
[[FBRoute POST:@"/wda/element/:uuid/forceTouch"] respondWithTarget:self action:@selector(handleForceTouch:)],
|
|
88
89
|
[[FBRoute POST:@"/wda/dragfromtoforduration"] respondWithTarget:self action:@selector(handleDragCoordinate:)],
|
|
89
90
|
[[FBRoute POST:@"/wda/tap/:uuid"] respondWithTarget:self action:@selector(handleTap:)],
|
|
90
91
|
[[FBRoute POST:@"/wda/touchAndHold"] respondWithTarget:self action:@selector(handleTouchAndHoldCoordinate:)],
|
|
91
92
|
[[FBRoute POST:@"/wda/doubleTap"] respondWithTarget:self action:@selector(handleDoubleTapCoordinate:)],
|
|
92
93
|
[[FBRoute POST:@"/wda/pickerwheel/:uuid/select"] respondWithTarget:self action:@selector(handleWheelSelect:)],
|
|
94
|
+
[[FBRoute POST:@"/wda/forceTouch"] respondWithTarget:self action:@selector(handleForceTouch:)],
|
|
93
95
|
#endif
|
|
94
96
|
[[FBRoute POST:@"/wda/keys"] respondWithTarget:self action:@selector(handleKeys:)],
|
|
95
|
-
[[FBRoute POST:@"/wda/element/:uuid/forceTouch"] respondWithTarget:self action:@selector(handleForceTouch:)],
|
|
96
97
|
];
|
|
97
98
|
}
|
|
98
99
|
|
|
@@ -291,7 +292,8 @@
|
|
|
291
292
|
+ (id<FBResponsePayload>)handleDoubleTapCoordinate:(FBRouteRequest *)request
|
|
292
293
|
{
|
|
293
294
|
CGPoint doubleTapPoint = CGPointMake((CGFloat)[request.arguments[@"x"] doubleValue], (CGFloat)[request.arguments[@"y"] doubleValue]);
|
|
294
|
-
XCUICoordinate *doubleTapCoordinate = [self.class gestureCoordinateWithCoordinate:doubleTapPoint
|
|
295
|
+
XCUICoordinate *doubleTapCoordinate = [self.class gestureCoordinateWithCoordinate:doubleTapPoint
|
|
296
|
+
application:request.session.activeApplication];
|
|
295
297
|
[doubleTapCoordinate doubleTap];
|
|
296
298
|
return FBResponseWithOK();
|
|
297
299
|
}
|
|
@@ -328,7 +330,8 @@
|
|
|
328
330
|
+ (id<FBResponsePayload>)handleTouchAndHoldCoordinate:(FBRouteRequest *)request
|
|
329
331
|
{
|
|
330
332
|
CGPoint touchPoint = CGPointMake((CGFloat)[request.arguments[@"x"] doubleValue], (CGFloat)[request.arguments[@"y"] doubleValue]);
|
|
331
|
-
XCUICoordinate *pressCoordinate = [self.class gestureCoordinateWithCoordinate:touchPoint
|
|
333
|
+
XCUICoordinate *pressCoordinate = [self.class gestureCoordinateWithCoordinate:touchPoint
|
|
334
|
+
application:request.session.activeApplication];
|
|
332
335
|
[pressCoordinate pressForDuration:[request.arguments[@"duration"] doubleValue]];
|
|
333
336
|
return FBResponseWithOK();
|
|
334
337
|
}
|
|
@@ -386,8 +389,10 @@
|
|
|
386
389
|
CGPoint startPoint = CGPointMake((CGFloat)[request.arguments[@"fromX"] doubleValue], (CGFloat)[request.arguments[@"fromY"] doubleValue]);
|
|
387
390
|
CGPoint endPoint = CGPointMake((CGFloat)[request.arguments[@"toX"] doubleValue], (CGFloat)[request.arguments[@"toY"] doubleValue]);
|
|
388
391
|
NSTimeInterval duration = [request.arguments[@"duration"] doubleValue];
|
|
389
|
-
XCUICoordinate *endCoordinate = [self.class gestureCoordinateWithCoordinate:endPoint
|
|
390
|
-
|
|
392
|
+
XCUICoordinate *endCoordinate = [self.class gestureCoordinateWithCoordinate:endPoint
|
|
393
|
+
application:session.activeApplication];
|
|
394
|
+
XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithCoordinate:startPoint
|
|
395
|
+
application:session.activeApplication];
|
|
391
396
|
[startCoordinate pressForDuration:duration thenDragToCoordinate:endCoordinate];
|
|
392
397
|
return FBResponseWithOK();
|
|
393
398
|
}
|
|
@@ -401,9 +406,10 @@
|
|
|
401
406
|
CGPoint startPoint = CGPointMake((CGFloat)(frame.origin.x + [request.arguments[@"fromX"] doubleValue]), (CGFloat)(frame.origin.y + [request.arguments[@"fromY"] doubleValue]));
|
|
402
407
|
CGPoint endPoint = CGPointMake((CGFloat)(frame.origin.x + [request.arguments[@"toX"] doubleValue]), (CGFloat)(frame.origin.y + [request.arguments[@"toY"] doubleValue]));
|
|
403
408
|
NSTimeInterval duration = [request.arguments[@"duration"] doubleValue];
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithCoordinate:startPoint
|
|
409
|
+
XCUICoordinate *endCoordinate = [self.class gestureCoordinateWithCoordinate:endPoint
|
|
410
|
+
application:session.activeApplication];
|
|
411
|
+
XCUICoordinate *startCoordinate = [self.class gestureCoordinateWithCoordinate:startPoint
|
|
412
|
+
application:session.activeApplication];
|
|
407
413
|
[startCoordinate pressForDuration:duration thenDragToCoordinate:endCoordinate];
|
|
408
414
|
return FBResponseWithOK();
|
|
409
415
|
}
|
|
@@ -439,8 +445,7 @@
|
|
|
439
445
|
}
|
|
440
446
|
} else {
|
|
441
447
|
XCUICoordinate *tapCoordinate = [self.class gestureCoordinateWithCoordinate:tapPoint
|
|
442
|
-
application:request.session.activeApplication
|
|
443
|
-
shouldApplyOrientationWorkaround:isSDKVersionLessThan(@"11.0")];
|
|
448
|
+
application:request.session.activeApplication];
|
|
444
449
|
[tapCoordinate tap];
|
|
445
450
|
}
|
|
446
451
|
return FBResponseWithOK();
|
|
@@ -465,27 +470,34 @@
|
|
|
465
470
|
[element rotate:rotation withVelocity:velocity];
|
|
466
471
|
return FBResponseWithOK();
|
|
467
472
|
}
|
|
468
|
-
#endif
|
|
469
473
|
|
|
470
474
|
+ (id<FBResponsePayload>)handleForceTouch:(FBRouteRequest *)request
|
|
471
475
|
{
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
double duration = [request.arguments[@"duration"] doubleValue];
|
|
476
|
-
NSError *error;
|
|
477
|
-
if (nil != request.arguments[@"x"] && nil != request.arguments[@"y"]) {
|
|
478
|
-
CGPoint forceTouchPoint = CGPointMake((CGFloat)[request.arguments[@"x"] doubleValue], (CGFloat)[request.arguments[@"y"] doubleValue]);
|
|
479
|
-
if (![element fb_forceTouchCoordinate:forceTouchPoint pressure:pressure duration:duration error:&error]) {
|
|
480
|
-
return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description traceback:nil]);
|
|
481
|
-
}
|
|
476
|
+
XCUIElement *element = nil;
|
|
477
|
+
if (nil == request.parameters[@"uuid"]) {
|
|
478
|
+
element = [FBApplication fb_activeApplication];
|
|
482
479
|
} else {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
}
|
|
480
|
+
FBElementCache *elementCache = request.session.elementCache;
|
|
481
|
+
element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
|
|
486
482
|
}
|
|
487
|
-
|
|
483
|
+
NSNumber *pressure = request.arguments[@"pressure"];
|
|
484
|
+
NSNumber *duration = request.arguments[@"duration"];
|
|
485
|
+
NSNumber *x = request.arguments[@"x"];
|
|
486
|
+
NSNumber *y = request.arguments[@"y"];
|
|
487
|
+
NSValue *hitPoint = (nil == x || nil == y)
|
|
488
|
+
? nil
|
|
489
|
+
: [NSValue valueWithCGPoint:CGPointMake((CGFloat)[x doubleValue], (CGFloat)[y doubleValue])];
|
|
490
|
+
NSError *error;
|
|
491
|
+
BOOL didSucceed = [element fb_forceTouchCoordinate:hitPoint
|
|
492
|
+
pressure:pressure
|
|
493
|
+
duration:duration
|
|
494
|
+
error:&error];
|
|
495
|
+
return didSucceed
|
|
496
|
+
? FBResponseWithOK()
|
|
497
|
+
: FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description
|
|
498
|
+
traceback:nil]);
|
|
488
499
|
}
|
|
500
|
+
#endif
|
|
489
501
|
|
|
490
502
|
+ (id<FBResponsePayload>)handleKeys:(FBRouteRequest *)request
|
|
491
503
|
{
|
|
@@ -574,7 +586,8 @@ static const CGFloat DEFAULT_OFFSET = (CGFloat)0.2;
|
|
|
574
586
|
return FBResponseWithStatus([FBCommandStatus elementNotVisibleErrorWithMessage:@"Can't scroll to element that does not exist" traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
|
|
575
587
|
}
|
|
576
588
|
if (![element fb_scrollToVisibleWithError:&error]) {
|
|
577
|
-
return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description
|
|
589
|
+
return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description
|
|
590
|
+
traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
|
|
578
591
|
}
|
|
579
592
|
return FBResponseWithOK();
|
|
580
593
|
}
|
|
@@ -584,21 +597,12 @@ static const CGFloat DEFAULT_OFFSET = (CGFloat)0.2;
|
|
|
584
597
|
|
|
585
598
|
@param coordinate absolute screen coordinates
|
|
586
599
|
@param application the instance of current application under test
|
|
587
|
-
@shouldApplyOrientationWorkaround whether to apply orientation workaround. This is to
|
|
588
|
-
handle XCTest bug where it does not translate screen coordinates for elements if
|
|
589
|
-
screen orientation is different from the default one (which is portrait).
|
|
590
|
-
Different iOS version have different behavior, for example iOS 9.3 returns correct
|
|
591
|
-
coordinates for elements in landscape, but iOS 10.0+ returns inverted coordinates as if
|
|
592
|
-
the current screen orientation would be portrait.
|
|
593
600
|
@return translated gesture coordinates ready to be passed to XCUICoordinate methods
|
|
594
601
|
*/
|
|
595
|
-
+ (XCUICoordinate *)gestureCoordinateWithCoordinate:(CGPoint)coordinate
|
|
602
|
+
+ (XCUICoordinate *)gestureCoordinateWithCoordinate:(CGPoint)coordinate
|
|
603
|
+
application:(XCUIApplication *)application
|
|
596
604
|
{
|
|
597
605
|
CGPoint point = coordinate;
|
|
598
|
-
if (shouldApplyOrientationWorkaround) {
|
|
599
|
-
point = FBInvertPointForApplication(coordinate, application.frame.size, application.interfaceOrientation);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
606
|
/**
|
|
603
607
|
If SDK >= 11, the tap coordinate based on application is not correct when
|
|
604
608
|
the application orientation is landscape and
|
|
@@ -632,10 +636,13 @@ static const CGFloat DEFAULT_OFFSET = (CGFloat)0.2;
|
|
|
632
636
|
@param element the element in the current application under test
|
|
633
637
|
@return translated gesture coordinates ready to be passed to XCUICoordinate methods
|
|
634
638
|
*/
|
|
635
|
-
+ (XCUICoordinate *)gestureCoordinateWithCoordinate:(CGPoint)coordinate
|
|
639
|
+
+ (XCUICoordinate *)gestureCoordinateWithCoordinate:(CGPoint)coordinate
|
|
640
|
+
element:(XCUIElement *)element
|
|
636
641
|
{
|
|
637
|
-
XCUICoordinate *appCoordinate = [[XCUICoordinate alloc] initWithElement:element
|
|
638
|
-
|
|
642
|
+
XCUICoordinate *appCoordinate = [[XCUICoordinate alloc] initWithElement:element
|
|
643
|
+
normalizedOffset:CGVectorMake(0, 0)];
|
|
644
|
+
return [[XCUICoordinate alloc] initWithCoordinate:appCoordinate
|
|
645
|
+
pointsOffset:CGVectorMake(coordinate.x, coordinate.y)];
|
|
639
646
|
}
|
|
640
647
|
#endif
|
|
641
648
|
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
#import "FBXCTestDaemonsProxy.h"
|
|
22
22
|
#import "XCElementSnapshot+FBHelpers.h"
|
|
23
23
|
#import "XCUIApplication+FBHelpers.h"
|
|
24
|
+
#import "XCUIDevice.h"
|
|
24
25
|
#import "XCUIElement+FBCaching.h"
|
|
25
26
|
#import "XCUIElement+FBIsVisible.h"
|
|
26
27
|
#import "XCUIElement+FBUtilities.h"
|
|
@@ -218,12 +219,28 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
|
|
|
218
219
|
return @[];
|
|
219
220
|
}
|
|
220
221
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
222
|
+
if (nil == self.pressure) {
|
|
223
|
+
XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition
|
|
224
|
+
offset:FBMillisToSeconds(self.offset)];
|
|
225
|
+
return @[result];
|
|
225
226
|
}
|
|
226
|
-
|
|
227
|
+
|
|
228
|
+
if (nil == eventPath) {
|
|
229
|
+
NSString *description = [NSString stringWithFormat:@"'%@' action with pressure must be preceeded with at least one '%@' action without this option", self.class.actionName, self.class.actionName];
|
|
230
|
+
if (error) {
|
|
231
|
+
*error = [[FBErrorBuilder.builder withDescription:description] build];
|
|
232
|
+
}
|
|
233
|
+
return nil;
|
|
234
|
+
}
|
|
235
|
+
if (![XCUIDevice sharedDevice].supportsPressureInteraction) {
|
|
236
|
+
if (error) {
|
|
237
|
+
*error = [[FBErrorBuilder.builder withDescription:@"This device does not support force press interactions"] build];
|
|
238
|
+
}
|
|
239
|
+
return nil;
|
|
240
|
+
}
|
|
241
|
+
[eventPath pressDownWithPressure:self.pressure.doubleValue
|
|
242
|
+
atOffset:FBMillisToSeconds(self.offset)];
|
|
243
|
+
return @[];
|
|
227
244
|
}
|
|
228
245
|
|
|
229
246
|
@end
|
|
Binary file
|
|
@@ -214,6 +214,7 @@
|
|
|
214
214
|
[self verifyGesture:gesture orientation:UIDeviceOrientationLandscapeLeft];
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
// TODO: UIDeviceOrientationLandscapeRight is not so good in iOS 16? (Especially simulators)
|
|
217
218
|
- (void)testPress
|
|
218
219
|
{
|
|
219
220
|
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
|
|
@@ -284,35 +285,6 @@
|
|
|
284
285
|
[self verifyGesture:gesture orientation:orientation];
|
|
285
286
|
}
|
|
286
287
|
|
|
287
|
-
- (void)testForcePress
|
|
288
|
-
{
|
|
289
|
-
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
|
|
290
|
-
// Does not work on iOS 15.
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
NSArray<NSDictionary<NSString *, id> *> *gesture =
|
|
294
|
-
@[@{
|
|
295
|
-
@"action": @"press",
|
|
296
|
-
@"options": @{
|
|
297
|
-
@"ELEMENT": self.testedApplication.buttons[FBShowAlertForceTouchButtonName],
|
|
298
|
-
@"x": @1,
|
|
299
|
-
@"y": @1,
|
|
300
|
-
@"pressure": @1
|
|
301
|
-
}
|
|
302
|
-
},
|
|
303
|
-
@{
|
|
304
|
-
@"action": @"wait",
|
|
305
|
-
@"options": @{
|
|
306
|
-
@"ms": @300
|
|
307
|
-
}
|
|
308
|
-
},
|
|
309
|
-
@{
|
|
310
|
-
@"action": @"release"
|
|
311
|
-
}
|
|
312
|
-
];
|
|
313
|
-
[self verifyGesture:gesture orientation:UIDeviceOrientationPortrait];
|
|
314
|
-
}
|
|
315
|
-
|
|
316
288
|
@end
|
|
317
289
|
|
|
318
290
|
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
#import <XCTest/XCTest.h>
|
|
11
11
|
|
|
12
|
+
#import "FBMacros.h"
|
|
12
13
|
#import "FBIntegrationTestCase.h"
|
|
13
14
|
#import "XCUIDevice+FBRotation.h"
|
|
14
15
|
#import "XCUIElement+FBUtilities.h"
|
|
@@ -41,27 +42,11 @@
|
|
|
41
42
|
XCUIElement *button = self.testedApplication.buttons[FBShowAlertButtonName];
|
|
42
43
|
NSError *error = nil;
|
|
43
44
|
NSData *screenshotData = [button fb_screenshotWithError:&error];
|
|
44
|
-
if (nil == screenshotData && [error.description containsString:@"available since Xcode9"]) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
45
|
XCTAssertNotNil(screenshotData);
|
|
48
46
|
XCTAssertNil(error);
|
|
49
47
|
UIImage *image = [UIImage imageWithData:screenshotData];
|
|
50
48
|
XCTAssertNotNil(image);
|
|
51
49
|
XCTAssertTrue(image.size.width > image.size.height);
|
|
52
|
-
|
|
53
|
-
XCUIScreen *mainScreen = XCUIScreen.mainScreen;
|
|
54
|
-
// Note about iPadOS 15.0 environment.
|
|
55
|
-
// The 'button.screenshot.image' (by XCTest) had a white image while 'image' had
|
|
56
|
-
// expected FBShowAlertButtonName area image by WebDriverAgent.
|
|
57
|
-
// It seems the native XCTest element screenshot has an issue on iPadOS.
|
|
58
|
-
UIImage *buttonScreenshot = button.screenshot.image;
|
|
59
|
-
XCTAssertEqualWithAccuracy(buttonScreenshot.size.height * mainScreen.scale,
|
|
60
|
-
image.size.height,
|
|
61
|
-
FLT_EPSILON);
|
|
62
|
-
XCTAssertEqualWithAccuracy(buttonScreenshot.size.width * mainScreen.scale,
|
|
63
|
-
image.size.width,
|
|
64
|
-
FLT_EPSILON);
|
|
65
50
|
}
|
|
66
51
|
|
|
67
52
|
@end
|