appium-webdriveragent 5.0.0 → 5.1.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.
Files changed (24) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/WebDriverAgent.xcodeproj/project.pbxproj +0 -20
  3. package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.m +0 -12
  4. package/WebDriverAgentLib/Categories/XCUIElement+FBPickerWheel.m +1 -15
  5. package/WebDriverAgentLib/Categories/XCUIElement+FBScrolling.m +7 -37
  6. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +0 -7
  7. package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.m +0 -49
  8. package/WebDriverAgentLib/Commands/FBElementCommands.m +37 -19
  9. package/WebDriverAgentLib/Utilities/FBAppiumActionsSynthesizer.m +23 -15
  10. package/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.h +4 -13
  11. package/WebDriverAgentLib/Utilities/FBBaseActionsSynthesizer.m +36 -56
  12. package/WebDriverAgentLib/Utilities/FBMathUtils.h +0 -6
  13. package/WebDriverAgentLib/Utilities/FBMathUtils.m +0 -29
  14. package/WebDriverAgentLib/Utilities/FBW3CActionsSynthesizer.m +23 -29
  15. package/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.h +0 -4
  16. package/WebDriverAgentLib/Utilities/FBXCTestDaemonsProxy.m +0 -12
  17. package/WebDriverAgentTests/IntegrationTests/FBAppiumTouchActionsIntegrationTests.m +0 -16
  18. package/WebDriverAgentTests/IntegrationTests/FBW3CTouchActionsIntegrationTests.m +0 -19
  19. package/WebDriverAgentTests/UnitTests/FBMathUtilsTests.m +0 -12
  20. package/package.json +1 -1
  21. package/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.h +0 -18
  22. package/WebDriverAgentLib/Categories/XCUICoordinate+FBFix.m +0 -46
  23. package/WebDriverAgentTests/IntegrationTests/FBElementScreenshotTests.m +0 -52
  24. package/WebDriverAgentTests/UnitTests/XCUICoordinateFix.m +0 -63
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [5.1.0](https://github.com/appium/WebDriverAgent/compare/v5.0.0...v5.1.0) (2023-05-14)
2
+
3
+
4
+ ### Features
5
+
6
+ * Add a possibility to provide a target picker value ([#699](https://github.com/appium/WebDriverAgent/issues/699)) ([fc76aee](https://github.com/appium/WebDriverAgent/commit/fc76aeecb087429974b7b52b725173186e6f0246))
7
+
8
+
9
+ ### Code Refactoring
10
+
11
+ * Remove obsolete coordinate calculation workarounds needed for older xCode SDKs ([#698](https://github.com/appium/WebDriverAgent/issues/698)) ([025b42c](https://github.com/appium/WebDriverAgent/commit/025b42c8a34ff0beba4379f4cb0c1d79d2b222ed))
12
+
1
13
  ## [5.0.0](https://github.com/appium/WebDriverAgent/compare/v4.15.1...v5.0.0) (2023-05-14)
2
14
 
3
15
 
@@ -86,7 +86,6 @@
86
86
  641EE6042240C5CA00173FCB /* NSString+FBXMLSafeString.m in Sources */ = {isa = PBXBuildFile; fileRef = 716E0BCD1E917E810087A825 /* NSString+FBXMLSafeString.m */; };
87
87
  641EE6052240C5CA00173FCB /* FBUnknownCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7651CAEDF0C008C271F /* FBUnknownCommands.m */; };
88
88
  641EE6062240C5CA00173FCB /* FBOrientationCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB75D1CAEDF0C008C271F /* FBOrientationCommands.m */; };
89
- 641EE6072240C5CA00173FCB /* XCUICoordinate+FBFix.m in Sources */ = {isa = PBXBuildFile; fileRef = EEC9EED520064FAA00BC0D5B /* XCUICoordinate+FBFix.m */; };
90
89
  641EE6082240C5CA00173FCB /* FBRuntimeUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7921CAEDF0C008C271F /* FBRuntimeUtils.m */; };
91
90
  641EE6092240C5CA00173FCB /* XCUIElement+FBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = EEE376401D59F81400ED88DD /* XCUIElement+FBUtilities.m */; };
92
91
  641EE60A2240C5CA00173FCB /* FBLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9B76A41CF7A43900275851 /* FBLogger.m */; };
@@ -160,7 +159,6 @@
160
159
  641EE65B2240C5CA00173FCB /* XCUIElementHitPointCoordinate.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35AD011E3B77D600A02D78 /* XCUIElementHitPointCoordinate.h */; settings = {ATTRIBUTES = (Public, ); }; };
161
160
  641EE65C2240C5CA00173FCB /* XCTDarwinNotificationExpectation.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACCE1E3B77D600A02D78 /* XCTDarwinNotificationExpectation.h */; settings = {ATTRIBUTES = (Public, ); }; };
162
161
  641EE65D2240C5CA00173FCB /* XCTRunnerAutomationSession.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACEE1E3B77D600A02D78 /* XCTRunnerAutomationSession.h */; settings = {ATTRIBUTES = (Public, ); }; };
163
- 641EE65E2240C5CA00173FCB /* XCUICoordinate+FBFix.h in Headers */ = {isa = PBXBuildFile; fileRef = EEC9EED420064FAA00BC0D5B /* XCUICoordinate+FBFix.h */; };
164
162
  641EE65F2240C5CA00173FCB /* XCSourceCodeTreeNodeEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACC61E3B77D600A02D78 /* XCSourceCodeTreeNodeEnumerator.h */; settings = {ATTRIBUTES = (Public, ); }; };
165
163
  641EE6602240C5CA00173FCB /* XCUIElement+FBIsVisible.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB7471CAEDF0C008C271F /* XCUIElement+FBIsVisible.h */; settings = {ATTRIBUTES = (Public, ); }; };
166
164
  641EE6612240C5CA00173FCB /* XCUIElement+FBTap.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9AB74B1CAEDF0C008C271F /* XCUIElement+FBTap.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -456,7 +454,6 @@
456
454
  71A7EAF91E224648001DA4F2 /* FBClassChainQueryParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 71A7EAF71E224648001DA4F2 /* FBClassChainQueryParser.h */; };
457
455
  71A7EAFA1E224648001DA4F2 /* FBClassChainQueryParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 71A7EAF81E224648001DA4F2 /* FBClassChainQueryParser.m */; };
458
456
  71A7EAFC1E229302001DA4F2 /* FBClassChainTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71A7EAFB1E229302001DA4F2 /* FBClassChainTests.m */; };
459
- 71AB82B21FDAE8C000D1D7C3 /* FBElementScreenshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71AB82B11FDAE8C000D1D7C3 /* FBElementScreenshotTests.m */; };
460
457
  71ACF5B8242F2FDC00F0AAD4 /* FBSafariAlertTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71ACF5B7242F2FDC00F0AAD4 /* FBSafariAlertTests.m */; };
461
458
  71B155DA23070ECF00646AFB /* FBHTTPStatusCodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B155D923070ECF00646AFB /* FBHTTPStatusCodes.h */; settings = {ATTRIBUTES = (Public, ); }; };
462
459
  71B155DC230711E900646AFB /* FBCommandStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B155DB230711E900646AFB /* FBCommandStatus.m */; };
@@ -785,9 +782,6 @@
785
782
  EE9B76AA1CF7A43900275851 /* FBMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9B76A51CF7A43900275851 /* FBMacros.h */; settings = {ATTRIBUTES = (Public, ); }; };
786
783
  EEBBD48B1D47746D00656A81 /* XCUIElement+FBFind.h in Headers */ = {isa = PBXBuildFile; fileRef = EEBBD4891D47746D00656A81 /* XCUIElement+FBFind.h */; settings = {ATTRIBUTES = (Public, ); }; };
787
784
  EEBBD48C1D47746D00656A81 /* XCUIElement+FBFind.m in Sources */ = {isa = PBXBuildFile; fileRef = EEBBD48A1D47746D00656A81 /* XCUIElement+FBFind.m */; };
788
- EEC9EED620064FAA00BC0D5B /* XCUICoordinate+FBFix.h in Headers */ = {isa = PBXBuildFile; fileRef = EEC9EED420064FAA00BC0D5B /* XCUICoordinate+FBFix.h */; };
789
- EEC9EED720064FAA00BC0D5B /* XCUICoordinate+FBFix.m in Sources */ = {isa = PBXBuildFile; fileRef = EEC9EED520064FAA00BC0D5B /* XCUICoordinate+FBFix.m */; };
790
- EEC9EED920077D8E00BC0D5B /* XCUICoordinateFix.m in Sources */ = {isa = PBXBuildFile; fileRef = EEC9EED820077D8E00BC0D5B /* XCUICoordinateFix.m */; };
791
785
  EEDFE1211D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = EEDFE11F1D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.h */; settings = {ATTRIBUTES = (Public, ); }; };
792
786
  EEDFE1221D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = EEDFE1201D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.m */; };
793
787
  EEE16E971D33A25500172525 /* FBConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EEE16E961D33A25500172525 /* FBConfigurationTests.m */; };
@@ -1043,7 +1037,6 @@
1043
1037
  71A7EAF71E224648001DA4F2 /* FBClassChainQueryParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBClassChainQueryParser.h; sourceTree = "<group>"; };
1044
1038
  71A7EAF81E224648001DA4F2 /* FBClassChainQueryParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBClassChainQueryParser.m; sourceTree = "<group>"; };
1045
1039
  71A7EAFB1E229302001DA4F2 /* FBClassChainTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBClassChainTests.m; sourceTree = "<group>"; };
1046
- 71AB82B11FDAE8C000D1D7C3 /* FBElementScreenshotTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBElementScreenshotTests.m; sourceTree = "<group>"; };
1047
1040
  71ACF5B7242F2FDC00F0AAD4 /* FBSafariAlertTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBSafariAlertTests.m; sourceTree = "<group>"; };
1048
1041
  71B155D923070ECF00646AFB /* FBHTTPStatusCodes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBHTTPStatusCodes.h; sourceTree = "<group>"; };
1049
1042
  71B155DB230711E900646AFB /* FBCommandStatus.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBCommandStatus.m; sourceTree = "<group>"; };
@@ -1353,9 +1346,6 @@
1353
1346
  EEC088E41CB56AC000B65968 /* FBElementCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBElementCache.m; sourceTree = "<group>"; };
1354
1347
  EEC088E61CB56DA400B65968 /* FBExceptionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBExceptionHandler.h; sourceTree = "<group>"; };
1355
1348
  EEC088E71CB56DA400B65968 /* FBExceptionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBExceptionHandler.m; sourceTree = "<group>"; };
1356
- EEC9EED420064FAA00BC0D5B /* XCUICoordinate+FBFix.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUICoordinate+FBFix.h"; sourceTree = "<group>"; };
1357
- EEC9EED520064FAA00BC0D5B /* XCUICoordinate+FBFix.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUICoordinate+FBFix.m"; sourceTree = "<group>"; };
1358
- EEC9EED820077D8E00BC0D5B /* XCUICoordinateFix.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XCUICoordinateFix.m; sourceTree = "<group>"; };
1359
1349
  EEDBEBBA1CB2681900A790A2 /* WebDriverAgent.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = WebDriverAgent.bundle; sourceTree = "<group>"; };
1360
1350
  EEDFE11F1D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIDevice+FBHealthCheck.h"; sourceTree = "<group>"; };
1361
1351
  EEDFE1201D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCUIDevice+FBHealthCheck.m"; sourceTree = "<group>"; };
@@ -1737,8 +1727,6 @@
1737
1727
  716C9DFF27315EFF005AD475 /* XCUIApplication+FBUIInterruptions.m */,
1738
1728
  71D475C02538F5A8008D9401 /* XCUIApplicationProcess+FBQuiescence.h */,
1739
1729
  71D475C12538F5A8008D9401 /* XCUIApplicationProcess+FBQuiescence.m */,
1740
- EEC9EED420064FAA00BC0D5B /* XCUICoordinate+FBFix.h */,
1741
- EEC9EED520064FAA00BC0D5B /* XCUICoordinate+FBFix.m */,
1742
1730
  719CD8FA2126C88B00C7D0C2 /* XCUIApplication+FBAlert.h */,
1743
1731
  719CD8FB2126C88B00C7D0C2 /* XCUIApplication+FBAlert.m */,
1744
1732
  71BD20711F86116100B36EC2 /* XCUIApplication+FBTouchAction.h */,
@@ -1985,7 +1973,6 @@
1985
1973
  719A97AB1F88E7370063B4BD /* FBAppiumMultiTouchActionsIntegrationTests.m */,
1986
1974
  719CD8FE2126C90200C7D0C2 /* FBAutoAlertsHandlerTests.m */,
1987
1975
  EE26409C1D0EBA25009BE6B0 /* FBElementAttributeTests.m */,
1988
- 71AB82B11FDAE8C000D1D7C3 /* FBElementScreenshotTests.m */,
1989
1976
  71F5BE33252E5B2200EE9EBA /* FBElementSwipingTests.m */,
1990
1977
  EE006EAC1EB99B15006900A4 /* FBElementVisibilityTests.m */,
1991
1978
  EE6A89361D0B35920083E92B /* FBFailureProofTestCaseTests.m */,
@@ -2045,7 +2032,6 @@
2045
2032
  EE9B76581CF7987300275851 /* Info.plist */,
2046
2033
  7139145B1DF01A12005896C2 /* NSExpressionFBFormatTests.m */,
2047
2034
  71A224E71DE326C500844D55 /* NSPredicateFBFormatTests.m */,
2048
- EEC9EED820077D8E00BC0D5B /* XCUICoordinateFix.m */,
2049
2035
  713914591DF01989005896C2 /* XCUIElementHelpersTests.m */,
2050
2036
  );
2051
2037
  path = UnitTests;
@@ -2311,7 +2297,6 @@
2311
2297
  641EE65B2240C5CA00173FCB /* XCUIElementHitPointCoordinate.h in Headers */,
2312
2298
  641EE65C2240C5CA00173FCB /* XCTDarwinNotificationExpectation.h in Headers */,
2313
2299
  641EE65D2240C5CA00173FCB /* XCTRunnerAutomationSession.h in Headers */,
2314
- 641EE65E2240C5CA00173FCB /* XCUICoordinate+FBFix.h in Headers */,
2315
2300
  641EE65F2240C5CA00173FCB /* XCSourceCodeTreeNodeEnumerator.h in Headers */,
2316
2301
  641EE6602240C5CA00173FCB /* XCUIElement+FBIsVisible.h in Headers */,
2317
2302
  641EE6612240C5CA00173FCB /* XCUIElement+FBTap.h in Headers */,
@@ -2548,7 +2533,6 @@
2548
2533
  EE35AD3F1E3B77D600A02D78 /* XCTDarwinNotificationExpectation.h in Headers */,
2549
2534
  EE35AD5F1E3B77D600A02D78 /* XCTRunnerAutomationSession.h in Headers */,
2550
2535
  71C9EAAC25E8415A00470CD8 /* FBScreenshot.h in Headers */,
2551
- EEC9EED620064FAA00BC0D5B /* XCUICoordinate+FBFix.h in Headers */,
2552
2536
  EE35AD371E3B77D600A02D78 /* XCSourceCodeTreeNodeEnumerator.h in Headers */,
2553
2537
  EE158AB01CBD456F00A3E3F0 /* XCUIElement+FBIsVisible.h in Headers */,
2554
2538
  71414ED42670A1EE003A8C5D /* LRUCache.h in Headers */,
@@ -3141,7 +3125,6 @@
3141
3125
  641EE6052240C5CA00173FCB /* FBUnknownCommands.m in Sources */,
3142
3126
  641EE6062240C5CA00173FCB /* FBOrientationCommands.m in Sources */,
3143
3127
  641EE7092240CDEB00173FCB /* XCUIElement+FBTVFocuse.m in Sources */,
3144
- 641EE6072240C5CA00173FCB /* XCUICoordinate+FBFix.m in Sources */,
3145
3128
  641EE6082240C5CA00173FCB /* FBRuntimeUtils.m in Sources */,
3146
3129
  641EE6092240C5CA00173FCB /* XCUIElement+FBUtilities.m in Sources */,
3147
3130
  641EE60A2240C5CA00173FCB /* FBLogger.m in Sources */,
@@ -3259,7 +3242,6 @@
3259
3242
  EE158AC51CBD456F00A3E3F0 /* FBOrientationCommands.m in Sources */,
3260
3243
  71D475C42538F5A8008D9401 /* XCUIApplicationProcess+FBQuiescence.m in Sources */,
3261
3244
  641EE7082240CDEB00173FCB /* XCUIElement+FBTVFocuse.m in Sources */,
3262
- EEC9EED720064FAA00BC0D5B /* XCUICoordinate+FBFix.m in Sources */,
3263
3245
  71E75E6F254824230099FC87 /* XCUIElementQuery+FBHelpers.m in Sources */,
3264
3246
  71D04DCA25356C43008A052C /* XCUIElement+FBCaching.m in Sources */,
3265
3247
  EE158AEB1CBD456F00A3E3F0 /* FBRuntimeUtils.m in Sources */,
@@ -3330,7 +3312,6 @@
3330
3312
  715AFAC41FFA2AAF0053896D /* FBScreenTests.m in Sources */,
3331
3313
  EE22021E1ECC618900A29571 /* FBTapTest.m in Sources */,
3332
3314
  71930C472066434000D3AFEC /* FBPasteboardTests.m in Sources */,
3333
- 71AB82B21FDAE8C000D1D7C3 /* FBElementScreenshotTests.m in Sources */,
3334
3315
  7150FFF722476B3A00B2EE28 /* FBForceTouchTests.m in Sources */,
3335
3316
  );
3336
3317
  runOnlyForDeploymentPostprocessing = 0;
@@ -3382,7 +3363,6 @@
3382
3363
  ADBC39981D07842800327304 /* XCUIElementDouble.m in Sources */,
3383
3364
  7139145A1DF01989005896C2 /* XCUIElementHelpersTests.m in Sources */,
3384
3365
  EE6A89261D0B19E60083E92B /* FBSessionTests.m in Sources */,
3385
- EEC9EED920077D8E00BC0D5B /* XCUICoordinateFix.m in Sources */,
3386
3366
  71A7EAFC1E229302001DA4F2 /* FBClassChainTests.m in Sources */,
3387
3367
  EE18883D1DA663EB00307AA8 /* FBMathUtilsTests.m in Sources */,
3388
3368
  );
@@ -186,18 +186,6 @@
186
186
  }
187
187
  CGPoint midPoint = CGPointMake(visibleRect.origin.x + visibleRect.size.width / 2,
188
188
  visibleRect.origin.y + visibleRect.size.height / 2);
189
- #if !TARGET_OS_TV // TV has no orientation, so it does not need to coordinate
190
- id<FBXCElementSnapshot> appElement = ancestors.count > 0 ? [ancestors lastObject] : self;
191
- CGRect appFrame = appElement.frame;
192
- CGRect windowFrame = nil == parentWindow ? selfFrame : parentWindow.frame;
193
- if ((appFrame.size.height > appFrame.size.width && windowFrame.size.height < windowFrame.size.width) ||
194
- (appFrame.size.height < appFrame.size.width && windowFrame.size.height > windowFrame.size.width)) {
195
- // This is the indication of the fact that transformation is broken and coordinates should be
196
- // recalculated manually.
197
- // However, upside-down case cannot be covered this way, which is not important for Appium
198
- midPoint = FBInvertPointForApplication(midPoint, appFrame.size, FBApplication.fb_activeApplication.interfaceOrientation);
199
- }
200
- #endif
201
189
  id<FBXCAccessibilityElement> hitElement = [FBActiveAppDetectionPoint axElementWithPoint:midPoint];
202
190
  if (nil != hitElement) {
203
191
  if (FBIsAXElementEqualToOther(self.accessibilityElement, hitElement)) {
@@ -12,9 +12,7 @@
12
12
  #import "FBRunLoopSpinner.h"
13
13
  #import "FBXCElementSnapshot.h"
14
14
  #import "FBXCodeCompatibility.h"
15
- #import "XCUIApplication+FBTouchAction.h"
16
15
  #import "XCUICoordinate.h"
17
- #import "XCUICoordinate+FBFix.h"
18
16
  #import "XCUIElement+FBCaching.h"
19
17
  #import "XCUIElement+FBResolve.h"
20
18
 
@@ -31,16 +29,6 @@ static const NSTimeInterval VALUE_CHANGE_TIMEOUT = 2;
31
29
  NSString *previousValue = snapshot.value;
32
30
  XCUICoordinate *startCoord = [self coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)];
33
31
  XCUICoordinate *endCoord = [startCoord coordinateWithOffset:CGVectorMake(0.0, relativeHeightOffset * snapshot.frame.size.height)];
34
- CGPoint tapPoint = endCoord.fb_screenPoint;
35
- NSArray<NSDictionary<NSString *, id> *> *gesture =
36
- @[@{
37
- @"action": @"tap",
38
- @"options": @{
39
- @"x": @(tapPoint.x),
40
- @"y": @(tapPoint.y),
41
- }
42
- }
43
- ];
44
32
  // If picker value is reflected in its accessiblity id
45
33
  // then fetching of the next snapshot may fail with StaleElementReferenceError
46
34
  // because we bound elements by their accessbility ids by default.
@@ -48,9 +36,7 @@ static const NSTimeInterval VALUE_CHANGE_TIMEOUT = 2;
48
36
  // unique element identifier (UID), so it could be found next time even if its
49
37
  // id is different from the initial one. See https://github.com/appium/appium/issues/17569
50
38
  XCUIElement *stableInstance = self.fb_stableInstance;
51
- if (![self.application fb_performAppiumTouchActions:gesture elementCache:nil error:error]) {
52
- return NO;
53
- }
39
+ [endCoord tap];
54
40
  return [[[[FBRunLoopSpinner new]
55
41
  timeout:VALUE_CHANGE_TIMEOUT]
56
42
  timeoutErrorMessage:[NSString stringWithFormat:@"Picker wheel value has not been changed after %@ seconds timeout", @(VALUE_CHANGE_TIMEOUT)]]
@@ -16,11 +16,9 @@
16
16
  #import "FBXCodeCompatibility.h"
17
17
  #import "FBXCElementSnapshotWrapper.h"
18
18
  #import "FBXCElementSnapshotWrapper+Helpers.h"
19
- #import "XCUIApplication+FBTouchAction.h"
20
19
  #import "XCUIElement+FBCaching.h"
21
20
  #import "XCUIApplication.h"
22
21
  #import "XCUICoordinate.h"
23
- #import "XCUICoordinate+FBFix.h"
24
22
  #import "XCUIElement+FBIsVisible.h"
25
23
  #import "XCUIElement.h"
26
24
  #import "XCUIElement+FBUtilities.h"
@@ -28,7 +26,8 @@
28
26
 
29
27
  const CGFloat FBFuzzyPointThreshold = 20.f; //Smallest determined value that is not interpreted as touch
30
28
  const CGFloat FBScrollToVisibleNormalizedDistance = .5f;
31
- const CGFloat FBTouchEventDelay = 1.f;
29
+ const CGFloat FBTouchEventDelay = 0.5f;
30
+ const CGFloat FBTouchVelocity = 300; // pixels per sec
32
31
  const CGFloat FBScrollTouchProportion = 0.75f;
33
32
 
34
33
  #if !TARGET_OS_TV
@@ -321,45 +320,16 @@ const CGFloat FBScrollTouchProportion = 0.75f;
321
320
 
322
321
  XCUICoordinate *appCoordinate = [[XCUICoordinate alloc] initWithElement:application normalizedOffset:CGVectorMake(0.0, 0.0)];
323
322
  XCUICoordinate *startCoordinate = [[XCUICoordinate alloc] initWithCoordinate:appCoordinate pointsOffset:hitpointOffset];
324
- CGPoint startPoint = startCoordinate.fb_screenPoint;
325
323
  XCUICoordinate *endCoordinate = [[XCUICoordinate alloc] initWithCoordinate:startCoordinate pointsOffset:vector];
326
- CGPoint endPoint = endCoordinate.fb_screenPoint;
327
324
 
328
- if (FBPointFuzzyEqualToPoint(startPoint, endPoint, FBFuzzyPointThreshold)) {
325
+ if (FBPointFuzzyEqualToPoint(startCoordinate.screenPoint, endCoordinate.screenPoint, FBFuzzyPointThreshold)) {
329
326
  return YES;
330
327
  }
331
328
 
332
- NSArray<NSDictionary<NSString *, id> *> *gesture =
333
- @[@{
334
- @"action": @"press",
335
- @"options": @{
336
- @"x": @(startPoint.x),
337
- @"y": @(startPoint.y),
338
- }
339
- },
340
- @{
341
- @"action": @"wait",
342
- @"options": @{
343
- @"ms": @(FBTouchEventDelay * 1000),
344
- }
345
- },
346
- @{
347
- @"action": @"moveTo",
348
- @"options": @{
349
- @"x": @(endPoint.x),
350
- @"y": @(endPoint.y),
351
- }
352
- },
353
- @{
354
- @"action": @"release"
355
- }
356
- ];
357
- if (![application fb_performAppiumTouchActions:gesture
358
- elementCache:nil
359
- error:error]) {
360
- return NO;
361
- }
362
-
329
+ [startCoordinate pressForDuration:FBTouchEventDelay
330
+ thenDragToCoordinate:endCoordinate
331
+ withVelocity:FBTouchVelocity
332
+ thenHoldForDuration:FBTouchEventDelay];
363
333
  return YES;
364
334
  }
365
335
 
@@ -98,13 +98,6 @@ NS_ASSUME_NONNULL_BEGIN
98
98
  */
99
99
  - (void)fb_waitUntilStableWithTimeout:(NSTimeInterval)timeout;
100
100
 
101
- /**
102
- Returns screenshot of the particular element
103
- @param error If there is an error, upon return contains an NSError object that describes the problem.
104
- @return Element screenshot as PNG-encoded data or nil in case of failure
105
- */
106
- - (nullable NSData *)fb_screenshotWithError:(NSError*__autoreleasing*)error;
107
-
108
101
  @end
109
102
 
110
103
  NS_ASSUME_NONNULL_END
@@ -197,53 +197,4 @@
197
197
  FBConfiguration.waitForIdleTimeout = previousTimeout;
198
198
  }
199
199
 
200
- - (NSData *)fb_screenshotWithError:(NSError **)error
201
- {
202
- id<FBXCElementSnapshot> selfSnapshot = self.fb_isResolvedFromCache.boolValue
203
- ? self.lastSnapshot
204
- : self.fb_takeSnapshot;
205
- if (CGRectIsEmpty(selfSnapshot.frame)) {
206
- if (error) {
207
- *error = [[FBErrorBuilder.builder withDescription:@"Cannot get a screenshot of zero-sized element"] build];
208
- }
209
- return nil;
210
- }
211
-
212
- CGRect elementRect = selfSnapshot.frame;
213
- #if !TARGET_OS_TV
214
- UIInterfaceOrientation orientation = self.application.interfaceOrientation;
215
- if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight) {
216
- // Workaround XCTest bug when element frame is returned as in portrait mode even if the screenshot is rotated
217
- NSArray<id<FBXCElementSnapshot>> *ancestors = [FBXCElementSnapshotWrapper ensureWrapped:selfSnapshot].fb_ancestors;
218
- id<FBXCElementSnapshot> parentWindow = nil;
219
- if (1 == ancestors.count) {
220
- parentWindow = selfSnapshot;
221
- } else if (ancestors.count > 1) {
222
- parentWindow = [ancestors objectAtIndex:ancestors.count - 2];
223
- }
224
- if (nil != parentWindow) {
225
- CGRect appFrame = ancestors.lastObject.frame;
226
- CGRect parentWindowFrame = parentWindow.frame;
227
- if (CGRectEqualToRect(appFrame, parentWindowFrame)
228
- || (appFrame.size.width > appFrame.size.height && parentWindowFrame.size.width > parentWindowFrame.size.height)
229
- || (appFrame.size.width < appFrame.size.height && parentWindowFrame.size.width < parentWindowFrame.size.height)) {
230
- CGPoint fixedOrigin = orientation == UIInterfaceOrientationLandscapeLeft ?
231
- CGPointMake(appFrame.size.height - elementRect.origin.y - elementRect.size.height, elementRect.origin.x) :
232
- CGPointMake(elementRect.origin.y, appFrame.size.width - elementRect.origin.x - elementRect.size.width);
233
- elementRect = CGRectMake(fixedOrigin.x, fixedOrigin.y, elementRect.size.height, elementRect.size.width);
234
- }
235
- }
236
- }
237
- #endif
238
-
239
- // adjust element rect for the actual screen scale
240
- XCUIScreen *mainScreen = XCUIScreen.mainScreen;
241
- elementRect = CGRectMake(elementRect.origin.x * mainScreen.scale, elementRect.origin.y * mainScreen.scale,
242
- elementRect.size.width * mainScreen.scale, elementRect.size.height * mainScreen.scale);
243
-
244
- return [FBScreenshot takeInOriginalResolutionWithQuality:FBConfiguration.screenshotQuality
245
- rect:elementRect
246
- error:error];
247
- }
248
-
249
200
  @end
@@ -594,10 +594,10 @@
594
594
  {
595
595
  FBElementCache *elementCache = request.session.elementCache;
596
596
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
597
- NSError *error;
598
- NSData *screenshotData = [element fb_screenshotWithError:&error];
597
+ NSData *screenshotData = [element.screenshot PNGRepresentation];
599
598
  if (nil == screenshotData) {
600
- return FBResponseWithStatus([FBCommandStatus unableToCaptureScreenErrorWithMessage:error.description
599
+ NSString *errMsg = [NSString stringWithFormat:@"Cannot take a screenshot of %@", element.description];
600
+ return FBResponseWithStatus([FBCommandStatus unableToCaptureScreenErrorWithMessage:errMsg
601
601
  traceback:nil]);
602
602
  }
603
603
  NSString *screenshot = [screenshotData base64EncodedStringWithOptions:0];
@@ -606,36 +606,54 @@
606
606
 
607
607
 
608
608
  #if !TARGET_OS_TV
609
- static const CGFloat DEFAULT_OFFSET = (CGFloat)0.2;
609
+ static const CGFloat DEFAULT_PICKER_OFFSET = (CGFloat)0.2;
610
+ static const NSInteger DEFAULT_MAX_PICKER_ATTEMPTS = 25;
611
+
610
612
 
611
613
  + (id<FBResponsePayload>)handleWheelSelect:(FBRouteRequest *)request
612
614
  {
613
615
  FBElementCache *elementCache = request.session.elementCache;
614
616
  XCUIElement *element = [elementCache elementForUUID:(NSString *)request.parameters[@"uuid"]];
615
617
  if ([element.lastSnapshot elementType] != XCUIElementTypePickerWheel) {
616
- return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:[NSString stringWithFormat:@"The element is expected to be a valid Picker Wheel control. '%@' was given instead", element.wdType] traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
618
+ NSString *errMsg = [NSString stringWithFormat:@"The element is expected to be a valid Picker Wheel control. '%@' was given instead", element.wdType];
619
+ return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:errMsg
620
+ traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
617
621
  }
618
622
  NSString* order = [request.arguments[@"order"] lowercaseString];
619
- CGFloat offset = DEFAULT_OFFSET;
623
+ CGFloat offset = DEFAULT_PICKER_OFFSET;
620
624
  if (request.arguments[@"offset"]) {
621
625
  offset = (CGFloat)[request.arguments[@"offset"] doubleValue];
622
626
  if (offset <= 0.0 || offset > 0.5) {
623
- return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:[NSString stringWithFormat:@"'offset' value is expected to be in range (0.0, 0.5]. '%@' was given instead", request.arguments[@"offset"]] traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
627
+ NSString *errMsg = [NSString stringWithFormat:@"'offset' value is expected to be in range (0.0, 0.5]. '%@' was given instead", request.arguments[@"offset"]];
628
+ return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:errMsg
629
+ traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
624
630
  }
625
631
  }
626
- BOOL isSuccessful = false;
627
- NSError *error;
628
- if ([order isEqualToString:@"next"]) {
629
- isSuccessful = [element fb_selectNextOptionWithOffset:offset error:&error];
630
- } else if ([order isEqualToString:@"previous"]) {
631
- isSuccessful = [element fb_selectPreviousOptionWithOffset:offset error:&error];
632
- } else {
633
- return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:[NSString stringWithFormat:@"Only 'previous' and 'next' order values are supported. '%@' was given instead", request.arguments[@"order"]] traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
634
- }
635
- if (!isSuccessful) {
636
- return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description traceback:nil]);
632
+ NSNumber *maxAttempts = request.arguments[@"maxAttempts"] ?: @(DEFAULT_MAX_PICKER_ATTEMPTS);
633
+ NSString *expectedValue = request.arguments[@"value"];
634
+ NSInteger attempt = 0;
635
+ while (attempt < [maxAttempts integerValue]) {
636
+ BOOL isSuccessful = false;
637
+ NSError *error;
638
+ if ([order isEqualToString:@"next"]) {
639
+ isSuccessful = [element fb_selectNextOptionWithOffset:offset error:&error];
640
+ } else if ([order isEqualToString:@"previous"]) {
641
+ isSuccessful = [element fb_selectPreviousOptionWithOffset:offset error:&error];
642
+ } else {
643
+ NSString *errMsg = [NSString stringWithFormat:@"Only 'previous' and 'next' order values are supported. '%@' was given instead", request.arguments[@"order"]];
644
+ return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:errMsg
645
+ traceback:[NSString stringWithFormat:@"%@", NSThread.callStackSymbols]]);
646
+ }
647
+ if (!isSuccessful) {
648
+ return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:error.description traceback:nil]);
649
+ }
650
+ if (nil == expectedValue || [element.wdValue isEqualToString:expectedValue]) {
651
+ return FBResponseWithOK();
652
+ }
653
+ attempt++;
637
654
  }
638
- return FBResponseWithOK();
655
+ NSString *errMsg = [NSString stringWithFormat:@"Cannot select the expected picker wheel value '%@' after %ld attempts", expectedValue, attempt];
656
+ return FBResponseWithStatus([FBCommandStatus invalidElementStateErrorWithMessage:errMsg traceback:nil]);
639
657
  }
640
658
 
641
659
  #pragma mark - Helpers
@@ -80,7 +80,7 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
80
80
 
81
81
  - (nullable instancetype)initWithActionItem:(NSDictionary<NSString *, id> *)item
82
82
  application:(XCUIApplication *)application
83
- atPosition:(nullable NSValue *)atPosition
83
+ atPosition:(nullable XCUICoordinate *)atPosition
84
84
  offset:(double)offset
85
85
  error:(NSError **)error
86
86
  {
@@ -90,14 +90,14 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
90
90
  self.application = application;
91
91
  self.offset = offset;
92
92
  id options = [item objectForKey:FB_OPTIONS_KEY];
93
- if (atPosition) {
94
- self.atPosition = [atPosition CGPointValue];
93
+ if (nil != atPosition) {
94
+ self.atPosition = (id) atPosition;
95
95
  } else {
96
- NSValue *result = [self coordinatesWithOptions:options error:error];
96
+ XCUICoordinate *result = [self coordinatesWithOptions:options error:error];
97
97
  if (nil == result) {
98
98
  return nil;
99
99
  }
100
- self.atPosition = [result CGPointValue];
100
+ self.atPosition = result;
101
101
  }
102
102
  self.duration = [self durationWithOptions:options];
103
103
  if (self.duration < 0) {
@@ -124,7 +124,8 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
124
124
  0.0;
125
125
  }
126
126
 
127
- - (nullable NSValue *)coordinatesWithOptions:(nullable NSDictionary<NSString *, id> *)options error:(NSError **)error
127
+ - (nullable XCUICoordinate *)coordinatesWithOptions:(nullable NSDictionary<NSString *, id> *)options
128
+ error:(NSError **)error
128
129
  {
129
130
  if (![options isKindOfClass:NSDictionary.class]) {
130
131
  NSString *description = [NSString stringWithFormat:@"'%@' key is mandatory for '%@' action", FB_OPTIONS_KEY, self.class.actionName];
@@ -169,7 +170,7 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
169
170
  NSTimeInterval currentOffset = FBMillisToSeconds(self.offset);
170
171
  NSMutableArray<XCPointerEventPath *> *result = [NSMutableArray array];
171
172
  XCPointerEventPath *currentPath = [[XCPointerEventPath alloc]
172
- initForTouchAtPoint:self.atPosition
173
+ initForTouchAtPoint:self.atPosition.screenPoint
173
174
  offset:currentOffset];
174
175
  [result addObject:currentPath];
175
176
  currentOffset += FBMillisToSeconds(FB_TAP_DURATION_MS);
@@ -180,7 +181,8 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
180
181
  NSNumber *tapCount = [options objectForKey:FB_OPTION_COUNT] ?: @1;
181
182
  for (NSInteger times = 1; times < tapCount.integerValue; ++times) {
182
183
  currentOffset += FBMillisToSeconds(FB_INTERTAP_MIN_DURATION_MS);
183
- XCPointerEventPath *nextPath = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition offset:currentOffset];
184
+ XCPointerEventPath *nextPath = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint
185
+ offset:currentOffset];
184
186
  [result addObject:nextPath];
185
187
  currentOffset += FBMillisToSeconds(FB_TAP_DURATION_MS);
186
188
  [nextPath liftUpAtOffset:currentOffset];
@@ -204,7 +206,7 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
204
206
 
205
207
  - (nullable instancetype)initWithActionItem:(NSDictionary<NSString *, id> *)item
206
208
  application:(XCUIApplication *)application
207
- atPosition:(nullable NSValue *)atPosition
209
+ atPosition:(nullable XCUICoordinate *)atPosition
208
210
  offset:(double)offset
209
211
  error:(NSError **)error
210
212
  {
@@ -239,7 +241,7 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
239
241
  error:(NSError **)error
240
242
  {
241
243
  XCPointerEventPath *result = [[XCPointerEventPath alloc]
242
- initForTouchAtPoint:self.atPosition
244
+ initForTouchAtPoint:self.atPosition.screenPoint
243
245
  offset:FBMillisToSeconds(self.offset)];
244
246
  if (nil != self.pressure && nil != result.pointerEvents.lastObject) {
245
247
  XCPointerEvent *pointerEvent = (XCPointerEvent *)result.pointerEvents.lastObject;
@@ -272,7 +274,7 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
272
274
  currentItemIndex:(NSUInteger)currentItemIndex
273
275
  error:(NSError **)error
274
276
  {
275
- return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition
277
+ return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint
276
278
  offset:FBMillisToSeconds(self.offset)]];
277
279
  }
278
280
 
@@ -312,7 +314,8 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
312
314
  }
313
315
  }
314
316
  NSTimeInterval currentOffset = FBMillisToSeconds(self.offset + self.duration);
315
- XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition offset:currentOffset];
317
+ XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint
318
+ offset:currentOffset];
316
319
  if (currentItemIndex == allItems.count - 1) {
317
320
  [result liftUpAtOffset:currentOffset];
318
321
  }
@@ -353,7 +356,8 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
353
356
  return nil;
354
357
  }
355
358
 
356
- [eventPath moveToPoint:self.atPosition atOffset:FBMillisToSeconds(self.offset)];
359
+ [eventPath moveToPoint:self.atPosition.screenPoint
360
+ atOffset:FBMillisToSeconds(self.offset)];
357
361
  return @[];
358
362
  }
359
363
 
@@ -509,7 +513,11 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
509
513
  return nil;
510
514
  }
511
515
  FBAppiumGestureItem *lastItem = [chain.items lastObject];
512
- gestureItem = [[gestureItemClass alloc] initWithActionItem:actionItem application:self.application atPosition:[NSValue valueWithCGPoint:lastItem.atPosition] offset:chain.durationOffset error:error];
516
+ gestureItem = [[gestureItemClass alloc] initWithActionItem:actionItem
517
+ application:self.application
518
+ atPosition:lastItem.atPosition
519
+ offset:chain.durationOffset
520
+ error:error];
513
521
  }
514
522
  if (nil == gestureItem) {
515
523
  return nil;
@@ -527,7 +535,7 @@ static const double FB_LONG_TAP_DURATION_MS = 600.0;
527
535
  BOOL isMultiTouch = [self.actions.firstObject isKindOfClass:NSArray.class];
528
536
  eventRecord = [[XCSynthesizedEventRecord alloc]
529
537
  initWithName:(isMultiTouch ? @"Multi-Finger Touch Action" : @"Single-Finger Touch Action")
530
- interfaceOrientation:[FBXCTestDaemonsProxy orientationWithApplication:self.application]];
538
+ interfaceOrientation:self.application.interfaceOrientation];
531
539
  for (NSArray<NSDictionary<NSString *, id> *> *action in (isMultiTouch ? self.actions : @[self.actions])) {
532
540
  NSArray<NSDictionary<NSString *, id> *> *preprocessedAction = [self preprocessAction:action];
533
541
  NSArray<XCPointerEventPath *> *eventPaths = [self eventPathsWithAction:preprocessedAction error:error];
@@ -51,19 +51,10 @@ NS_ASSUME_NONNULL_BEGIN
51
51
  @interface FBBaseGestureItem : FBBaseActionItem
52
52
 
53
53
  /*! Absolute position on the screen where the gesure should be performed */
54
- @property (nonatomic) CGPoint atPosition;
54
+ @property (nonatomic) XCUICoordinate *atPosition;
55
55
  /*! Gesture duration in milliseconds */
56
56
  @property (nonatomic) double duration;
57
57
 
58
- /**
59
- Returns fixed hit point coordinates for the case when XCTest fails to transform element snaapshot properly on screen rotation.
60
-
61
- @param hitPoint The initial hitpoint coordinates
62
- @param snapshot Element's snapshot instance
63
- @return The fixed hit point coordinates, if there is a need to fix them, or the unchanged hit point value
64
- */
65
- - (CGPoint)fixedHitPointWith:(CGPoint)hitPoint forSnapshot:(id<FBXCElementSnapshot>)snapshot;
66
-
67
58
  /**
68
59
  Calculate absolute gesture position on the screen based on provided element and positionOffset values.
69
60
 
@@ -72,9 +63,9 @@ NS_ASSUME_NONNULL_BEGIN
72
63
  @param error If there is an error, upon return contains an NSError object that describes the problem
73
64
  @return Adbsolute gesture position on the screen or nil if the calculation fails (for example, the element is invisible)
74
65
  */
75
- - (nullable NSValue *)hitpointWithElement:(nullable XCUIElement *)element
76
- positionOffset:(nullable NSValue *)positionOffset
77
- error:(NSError **)error;
66
+ - (nullable XCUICoordinate *)hitpointWithElement:(nullable XCUIElement *)element
67
+ positionOffset:(nullable NSValue *)positionOffset
68
+ error:(NSError **)error;
78
69
 
79
70
  @end
80
71
 
@@ -31,7 +31,10 @@
31
31
  return nil;
32
32
  }
33
33
 
34
- - (NSArray<XCPointerEventPath *> *)addToEventPath:(XCPointerEventPath *)eventPath allItems:(NSArray *)allItems currentItemIndex:(NSUInteger)currentItemIndex error:(NSError **)error
34
+ - (NSArray<XCPointerEventPath *> *)addToEventPath:(XCPointerEventPath *)eventPath
35
+ allItems:(NSArray *)allItems
36
+ currentItemIndex:(NSUInteger)currentItemIndex
37
+ error:(NSError **)error
35
38
  {
36
39
  @throw [[FBErrorBuilder.builder withDescription:@"Override this method in subclasses"] build];
37
40
  return nil;
@@ -41,66 +44,40 @@
41
44
 
42
45
  @implementation FBBaseGestureItem
43
46
 
44
- - (CGPoint)fixedHitPointWith:(CGPoint)hitPoint forSnapshot:(id<FBXCElementSnapshot>)snapshot
47
+ - (nullable XCUICoordinate *)hitpointWithElement:(nullable XCUIElement *)element
48
+ positionOffset:(nullable NSValue *)positionOffset
49
+ error:(NSError **)error
45
50
  {
46
- UIInterfaceOrientation interfaceOrientation = self.application.interfaceOrientation;
47
- if (interfaceOrientation == UIInterfaceOrientationPortrait) {
48
- // There is no need to recalculate anything for portrait orientation
49
- return hitPoint;
50
- }
51
- // For Xcode11+ it is always necessary to adjust the tap point coordinates
52
- return FBInvertPointForApplication(hitPoint, self.application.frame.size, interfaceOrientation);
53
- }
54
-
55
- - (nullable NSValue *)hitpointWithElement:(nullable XCUIElement *)element positionOffset:(nullable NSValue *)positionOffset error:(NSError **)error
56
- {
57
- CGPoint hitPoint;
58
51
  if (nil == element) {
52
+ CGVector offset = CGVectorMake(positionOffset.CGPointValue.x, positionOffset.CGPointValue.y);
59
53
  // Only absolute offset is defined
60
- hitPoint = [positionOffset CGPointValue];
61
- /*
62
- Since iOS 10.0 XCTest has a bug when it always returns portrait coordinates for UI elements
63
- even if the device is not in portait mode. That is why we need to recalculate them manually
64
- based on the current orientation value
65
- */
66
- hitPoint = FBInvertPointForApplication(hitPoint, self.application.frame.size, self.application.interfaceOrientation);
67
- } else {
68
- // The offset relative to the element is defined
69
-
70
- id<FBXCElementSnapshot> snapshot = element.fb_isResolvedFromCache.boolValue
71
- ? element.lastSnapshot
72
- : element.fb_takeSnapshot;
73
- if (nil == positionOffset) {
74
- NSValue *hitPointValue = [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_hitPoint;
75
- if (nil != hitPointValue) {
76
- // short circuit element hitpoint
77
- return hitPointValue;
78
- }
79
- [FBLogger logFmt:@"Will use the frame of '%@' for hit point calculation instead", element.debugDescription];
80
- }
81
- CGRect visibleFrame = snapshot.visibleFrame;
82
- CGRect frame = CGRectIsEmpty(visibleFrame) ? element.frame : visibleFrame;
83
- if (CGRectIsEmpty(frame)) {
84
- [FBLogger log:self.application.fb_descriptionRepresentation];
85
- NSString *description = [NSString stringWithFormat:@"The element '%@' is not visible on the screen and thus is not interactable", element.description];
86
- if (error) {
87
- *error = [[FBErrorBuilder.builder withDescription:description] build];
88
- }
89
- return nil;
54
+ return [[self.application coordinateWithNormalizedOffset:CGVectorMake(0, 0)] coordinateWithOffset:offset];
55
+ }
56
+
57
+ // The offset relative to the element is defined
58
+ if (nil == positionOffset) {
59
+ if (element.hittable) {
60
+ // short circuit element hitpoint
61
+ return element.hitPointCoordinate;
90
62
  }
91
- if (nil == positionOffset) {
92
- hitPoint = CGPointMake(frame.origin.x + frame.size.width / 2,
93
- frame.origin.y + frame.size.height / 2);
94
- } else {
95
- CGPoint origin = frame.origin;
96
- hitPoint = CGPointMake(origin.x, origin.y);
97
- CGPoint offsetValue = [positionOffset CGPointValue];
98
- hitPoint = CGPointMake(hitPoint.x + offsetValue.x, hitPoint.y + offsetValue.y);
99
- // TODO: Shall we throw an exception if hitPoint is out of the element frame?
63
+ [FBLogger logFmt:@"Will use the frame of '%@' for hit point calculation instead", element.debugDescription];
64
+ }
65
+ if (CGRectIsEmpty(element.frame)) {
66
+ [FBLogger log:self.application.fb_descriptionRepresentation];
67
+ NSString *description = [NSString stringWithFormat:@"The element '%@' is not visible on the screen and thus is not interactable",
68
+ element.description];
69
+ if (error) {
70
+ *error = [[FBErrorBuilder.builder withDescription:description] build];
100
71
  }
101
- hitPoint = [self fixedHitPointWith:hitPoint forSnapshot:snapshot];
72
+ return nil;
73
+ }
74
+ if (nil == positionOffset) {
75
+ return [element coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)];
102
76
  }
103
- return [NSValue valueWithCGPoint:hitPoint];
77
+
78
+ CGVector offset = CGVectorMake(positionOffset.CGPointValue.x, positionOffset.CGPointValue.y);
79
+ // TODO: Shall we throw an exception if hitPoint is out of the element frame?
80
+ return [[element coordinateWithNormalizedOffset:CGVectorMake(0, 0)] coordinateWithOffset:offset];
104
81
  }
105
82
 
106
83
  @end
@@ -161,7 +138,10 @@
161
138
 
162
139
  @implementation FBBaseActionsSynthesizer
163
140
 
164
- - (instancetype)initWithActions:(NSArray *)actions forApplication:(XCUIApplication *)application elementCache:(nullable FBElementCache *)elementCache error:(NSError **)error
141
+ - (instancetype)initWithActions:(NSArray *)actions
142
+ forApplication:(XCUIApplication *)application
143
+ elementCache:(nullable FBElementCache *)elementCache
144
+ error:(NSError **)error
165
145
  {
166
146
  self = [super init];
167
147
  if (self) {
@@ -32,12 +32,6 @@ BOOL FBSizeFuzzyEqualToSize(CGSize size1, CGSize size2, CGFloat threshold);
32
32
  BOOL FBRectFuzzyEqualToRect(CGRect rect1, CGRect rect2, CGFloat threshold);
33
33
 
34
34
  #if !TARGET_OS_TV
35
- /*! Inverts point if necessary to match location on screen */
36
- CGPoint FBInvertPointForApplication(CGPoint point, CGSize screenSize, UIInterfaceOrientation orientation);
37
-
38
- /*! Inverts offset if necessary to match screen orientation */
39
- CGPoint FBInvertOffsetForOrientation(CGPoint offset, UIInterfaceOrientation orientation);
40
-
41
35
  /*! Inverts size if necessary to match current screen orientation */
42
36
  CGSize FBAdjustDimensionsForApplication(CGSize actualSize, UIInterfaceOrientation orientation);
43
37
  #endif
@@ -46,35 +46,6 @@ BOOL FBRectFuzzyEqualToRect(CGRect rect1, CGRect rect2, CGFloat threshold)
46
46
  }
47
47
 
48
48
  #if !TARGET_OS_TV
49
- CGPoint FBInvertPointForApplication(CGPoint point, CGSize screenSize, UIInterfaceOrientation orientation)
50
- {
51
- switch (orientation) {
52
- case UIInterfaceOrientationUnknown:
53
- case UIInterfaceOrientationPortrait:
54
- return point;
55
- case UIInterfaceOrientationPortraitUpsideDown:
56
- return CGPointMake(screenSize.width - point.x, screenSize.height - point.y);
57
- case UIInterfaceOrientationLandscapeLeft:
58
- return CGPointMake(point.y, MAX(screenSize.width, screenSize.height) - point.x);
59
- case UIInterfaceOrientationLandscapeRight:
60
- return CGPointMake(MIN(screenSize.width, screenSize.height) - point.y, point.x);
61
- }
62
- }
63
-
64
- CGPoint FBInvertOffsetForOrientation(CGPoint offset, UIInterfaceOrientation orientation)
65
- {
66
- switch (orientation) {
67
- case UIInterfaceOrientationUnknown:
68
- case UIInterfaceOrientationPortrait:
69
- return offset;
70
- case UIInterfaceOrientationPortraitUpsideDown:
71
- return CGPointMake(-offset.x, -offset.y);
72
- case UIInterfaceOrientationLandscapeLeft:
73
- return CGPointMake(offset.y, -offset.x);
74
- case UIInterfaceOrientationLandscapeRight:
75
- return CGPointMake(-offset.y, offset.x);
76
- }
77
- }
78
49
 
79
50
  CGSize FBAdjustDimensionsForApplication(CGSize actualSize, UIInterfaceOrientation orientation)
80
51
  {
@@ -133,16 +133,16 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
133
133
  return nil;
134
134
  }
135
135
  self.duration = durationObj.doubleValue;
136
- NSValue *position = [self positionWithError:error];
136
+ XCUICoordinate *position = [self positionWithError:error];
137
137
  if (nil == position) {
138
138
  return nil;
139
139
  }
140
- self.atPosition = [position CGPointValue];
140
+ self.atPosition = position;
141
141
  }
142
142
  return self;
143
143
  }
144
144
 
145
- - (nullable NSValue *)positionWithError:(NSError **)error
145
+ - (nullable XCUICoordinate *)positionWithError:(NSError **)error
146
146
  {
147
147
  if (nil == self.previousItem) {
148
148
  NSString *errorDescription = [NSString stringWithFormat:@"The '%@' action item must be preceded by %@ item", self.actionItem, FB_ACTION_ITEM_TYPE_POINTER_MOVE];
@@ -151,39 +151,32 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
151
151
  }
152
152
  return nil;
153
153
  }
154
- return [NSValue valueWithCGPoint:self.previousItem.atPosition];
154
+ return self.previousItem.atPosition;
155
155
  }
156
156
 
157
- - (nullable NSValue *)hitpointWithElement:(nullable XCUIElement *)element
158
- positionOffset:(nullable NSValue *)positionOffset
159
- error:(NSError **)error
157
+ - (nullable XCUICoordinate *)hitpointWithElement:(nullable XCUIElement *)element
158
+ positionOffset:(nullable NSValue *)positionOffset
159
+ error:(NSError **)error
160
160
  {
161
161
  if (nil == element || nil == positionOffset) {
162
162
  return [super hitpointWithElement:element positionOffset:positionOffset error:error];
163
163
  }
164
164
 
165
165
  // An offset relative to the element is defined
166
- id<FBXCElementSnapshot> snapshot = element.fb_isResolvedFromCache.boolValue
167
- ? element.lastSnapshot
168
- : element.fb_takeSnapshot;
169
- CGRect frame = snapshot.frame;
170
- if (CGRectIsEmpty(frame)) {
166
+ if (CGRectIsEmpty(element.frame)) {
171
167
  [FBLogger log:self.application.fb_descriptionRepresentation];
172
- NSString *description = [NSString stringWithFormat:@"The element '%@' is not visible on the screen and thus is not interactable", [FBXCElementSnapshotWrapper ensureWrapped:snapshot].fb_description];
168
+ NSString *description = [NSString stringWithFormat:@"The element '%@' is not visible on the screen and thus is not interactable",
169
+ element.description];
173
170
  if (error) {
174
171
  *error = [[FBErrorBuilder.builder withDescription:description] build];
175
172
  }
176
173
  return nil;
177
174
  }
178
- CGRect visibleFrame = snapshot.visibleFrame;
179
- frame = CGRectIsEmpty(visibleFrame) ? frame : visibleFrame;
175
+
180
176
  // W3C standard requires that relative element coordinates start at the center of the element's rectangle
181
- CGPoint hitPoint = CGPointMake(frame.origin.x + frame.size.width / 2, frame.origin.y + frame.size.height / 2);
182
- CGPoint offsetValue = [positionOffset CGPointValue];
183
- hitPoint = CGPointMake(hitPoint.x + offsetValue.x, hitPoint.y + offsetValue.y);
177
+ CGVector offset = CGVectorMake(positionOffset.CGPointValue.x, positionOffset.CGPointValue.y);
184
178
  // TODO: Shall we throw an exception if hitPoint is out of the element frame?
185
- hitPoint = [self fixedHitPointWith:hitPoint forSnapshot:snapshot];
186
- return [NSValue valueWithCGPoint:hitPoint];
179
+ return [[element coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)] coordinateWithOffset:offset];
187
180
  }
188
181
 
189
182
  @end
@@ -220,7 +213,7 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
220
213
  }
221
214
  }
222
215
  if (nil == self.pressure) {
223
- XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition
216
+ XCPointerEventPath *result = [[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint
224
217
  offset:FBMillisToSeconds(self.offset)];
225
218
  return @[result];
226
219
  }
@@ -247,7 +240,7 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
247
240
 
248
241
  @implementation FBPointerMoveItem
249
242
 
250
- - (nullable NSValue *)positionWithError:(NSError **)error
243
+ - (nullable XCUICoordinate *)positionWithError:(NSError **)error
251
244
  {
252
245
  static NSArray<NSString *> *supportedOriginTypes;
253
246
  static dispatch_once_t onceToken;
@@ -295,10 +288,9 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
295
288
  }
296
289
  return nil;
297
290
  }
298
- CGPoint recentPosition = self.previousItem.atPosition;
299
- CGPoint offsetRelativeToRecentPosition = (nil == x && nil == y) ? CGPointMake(0.0, 0.0) : CGPointMake(x.floatValue, y.floatValue);
300
- offsetRelativeToRecentPosition = FBInvertOffsetForOrientation(offsetRelativeToRecentPosition, self.application.interfaceOrientation);
301
- return [NSValue valueWithCGPoint:CGPointMake(recentPosition.x + offsetRelativeToRecentPosition.x, recentPosition.y + offsetRelativeToRecentPosition.y)];
291
+ XCUICoordinate *recentPosition = self.previousItem.atPosition;
292
+ CGVector offsetRelativeToRecentPosition = (nil == x && nil == y) ? CGVectorMake(0, 0) : CGVectorMake(x.floatValue, y.floatValue);
293
+ return [recentPosition coordinateWithOffset:offsetRelativeToRecentPosition];
302
294
  }
303
295
 
304
296
  + (NSString *)actionName
@@ -312,9 +304,11 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
312
304
  error:(NSError **)error
313
305
  {
314
306
  if (nil == eventPath) {
315
- return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition offset:FBMillisToSeconds(self.offset + self.duration)]];
307
+ return @[[[XCPointerEventPath alloc] initForTouchAtPoint:self.atPosition.screenPoint
308
+ offset:FBMillisToSeconds(self.offset + self.duration)]];
316
309
  }
317
- [eventPath moveToPoint:self.atPosition atOffset:FBMillisToSeconds(self.offset + self.duration)];
310
+ [eventPath moveToPoint:self.atPosition.screenPoint
311
+ atOffset:FBMillisToSeconds(self.offset + self.duration)];
318
312
  return @[];
319
313
  }
320
314
 
@@ -888,7 +882,7 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
888
882
  {
889
883
  XCSynthesizedEventRecord *eventRecord = [[XCSynthesizedEventRecord alloc]
890
884
  initWithName:@"W3C Touch Action"
891
- interfaceOrientation:[FBXCTestDaemonsProxy orientationWithApplication:self.application]];
885
+ interfaceOrientation:self.application.interfaceOrientation];
892
886
  NSMutableDictionary<NSString *, NSDictionary<NSString *, id> *> *actionsMapping = [NSMutableDictionary new];
893
887
  NSMutableArray<NSString *> *actionIds = [NSMutableArray new];
894
888
  for (NSDictionary<NSString *, id> *action in self.actions) {
@@ -23,10 +23,6 @@ NS_ASSUME_NONNULL_BEGIN
23
23
 
24
24
  + (id<XCTestManager_ManagerInterface>)testRunnerProxy;
25
25
 
26
- #if !TARGET_OS_TV
27
- + (UIInterfaceOrientation)orientationWithApplication:(XCUIApplication *)application;
28
- #endif
29
-
30
26
  + (BOOL)synthesizeEventWithRecord:(XCSynthesizedEventRecord *)record
31
27
  error:(NSError *__autoreleasing*)error;
32
28
 
@@ -30,7 +30,6 @@ static dispatch_once_t onceTestRunnerDaemonClass;
30
30
 
31
31
  + (void)load
32
32
  {
33
- // XCTRunnerDaemonSession class is only available since Xcode 8.3
34
33
  dispatch_once(&onceTestRunnerDaemonClass, ^{
35
34
  FBXCTRunnerDaemonSessionClass = objc_lookUpClass("XCTRunnerDaemonSession");
36
35
  });
@@ -60,17 +59,6 @@ static dispatch_once_t onceTestRunnerDaemonClass;
60
59
  return ((XCTRunnerDaemonSession *)[FBXCTRunnerDaemonSessionClass sharedSession]).daemonProxy;
61
60
  }
62
61
 
63
- #if !TARGET_OS_TV
64
- + (UIInterfaceOrientation)orientationWithApplication:(XCUIApplication *)application
65
- {
66
- if (nil == FBXCTRunnerDaemonSessionClass ||
67
- [[FBXCTRunnerDaemonSessionClass sharedSession] useLegacyEventCoordinateTransformationPath]) {
68
- return application.interfaceOrientation;
69
- }
70
- return UIInterfaceOrientationPortrait;
71
- }
72
- #endif
73
-
74
62
  + (BOOL)synthesizeEventWithRecord:(XCSynthesizedEventRecord *)record error:(NSError *__autoreleasing*)error
75
63
  {
76
64
  __block BOOL didSucceed = NO;
@@ -194,14 +194,6 @@
194
194
 
195
195
  - (void)testDoubleTap
196
196
  {
197
- if ([UIDevice.currentDevice userInterfaceIdiom] == UIUserInterfaceIdiomPad &&
198
- SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
199
- // "tap the element" does not work on iPadOS simulator after change the rotation in iOS 15
200
- // while selecting the element worked. (I confirmed with getting an element screenshot that
201
- // the FBShowAlertButtonName was actually selected after changing the orientation.)
202
- return;
203
- }
204
-
205
197
  NSArray<NSDictionary<NSString *, id> *> *gesture =
206
198
  @[@{
207
199
  @"action": @"tap",
@@ -214,16 +206,8 @@
214
206
  [self verifyGesture:gesture orientation:UIDeviceOrientationLandscapeLeft];
215
207
  }
216
208
 
217
- // TODO: UIDeviceOrientationLandscapeRight is not so good in iOS 16? (Especially simulators)
218
209
  - (void)testPress
219
210
  {
220
- if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
221
- // Does not work on iOS 15.0.
222
- // The same action tap the FBShowAlertButtonName after rotating the screen
223
- // worked with W3C actions. `.click` action did not work.
224
- return;
225
- }
226
-
227
211
  NSArray<NSDictionary<NSString *, id> *> *gesture =
228
212
  @[@{
229
213
  @"action": @"press",
@@ -294,18 +294,8 @@
294
294
  [self verifyGesture:gesture orientation:UIDeviceOrientationPortrait];
295
295
  }
296
296
 
297
- // TODO: UIDeviceOrientationLandscapeLeft did not work in iOS 16 simumlator.
298
- // UIDeviceOrientationPortrait was ok.
299
297
  - (void)testDoubleTap
300
298
  {
301
- if ([UIDevice.currentDevice userInterfaceIdiom] == UIUserInterfaceIdiomPad &&
302
- SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
303
- // "tap the element" does not work on iPadOS simulator after change the rotation in iOS 15
304
- // while selecting the element worked. (I confirmed with getting an element screenshot that
305
- // the FBShowAlertButtonName was actually selected after changing the orientation.)
306
- return;
307
- }
308
-
309
299
  NSArray<NSDictionary<NSString *, id> *> *gesture =
310
300
  @[@{
311
301
  @"type": @"pointer",
@@ -326,17 +316,8 @@
326
316
  [self verifyGesture:gesture orientation:UIDeviceOrientationLandscapeLeft];
327
317
  }
328
318
 
329
- // TODO: UIDeviceOrientationLandscapeRight did not work in iOS 16 simumlator.
330
- // UIDeviceOrientationPortrait was ok.
331
319
  - (void)testLongPressWithCombinedPause
332
320
  {
333
- if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"15.0")) {
334
- // Xcode 13 x iOS 14 also does not work while Xcode 12.5 x iOS 14 worked.
335
- // Skip this test for iOS 15 since iOS 15 works with Xcode 13 at least.
336
- return;
337
- }
338
-
339
-
340
321
  NSArray<NSDictionary<NSString *, id> *> *gesture =
341
322
  @[@{
342
323
  @"type": @"pointer",
@@ -98,18 +98,6 @@
98
98
  XCTAssertFalse(FBRectFuzzyEqualToRect(referenceRect, CGRectMake(-1, -1, 1, 1), 1));
99
99
  }
100
100
 
101
-
102
- - (void)testPointInvertion
103
- {
104
- const CGPoint testPoint = CGPointMake(1, 2);
105
- const CGSize screenSize = CGSizeMake(10, 15);
106
- const CGFloat t = FBDefaultFrameFuzzyThreshold;
107
- XCTAssertTrue(FBPointFuzzyEqualToPoint(CGPointMake(1, 2), FBInvertPointForApplication(testPoint, screenSize, UIInterfaceOrientationPortrait), t));
108
- XCTAssertTrue(FBPointFuzzyEqualToPoint(CGPointMake(9, 13), FBInvertPointForApplication(testPoint, screenSize, UIInterfaceOrientationPortraitUpsideDown), t));
109
- XCTAssertTrue(FBPointFuzzyEqualToPoint(CGPointMake(2, 14), FBInvertPointForApplication(testPoint, screenSize, UIInterfaceOrientationLandscapeLeft), t));
110
- XCTAssertTrue(FBPointFuzzyEqualToPoint(CGPointMake(8, 1), FBInvertPointForApplication(testPoint, screenSize, UIInterfaceOrientationLandscapeRight), t));
111
- }
112
-
113
101
  - (void)testSizeInversion
114
102
  {
115
103
  const CGSize screenSizePortrait = CGSizeMake(10, 15);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-webdriveragent",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "Package bundling WebDriverAgent",
5
5
  "main": "./build/index.js",
6
6
  "scripts": {
@@ -1,18 +0,0 @@
1
- /**
2
- * Copyright (c) 2015-present, Facebook, Inc.
3
- * All rights reserved.
4
- *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
8
- */
9
-
10
- #import <XCTest/XCTest.h>
11
-
12
- #if !TARGET_OS_TV
13
- @interface XCUICoordinate (FBFix)
14
-
15
- - (CGPoint)fb_screenPoint;
16
-
17
- @end
18
- #endif
@@ -1,46 +0,0 @@
1
- /**
2
- * Copyright (c) 2015-present, Facebook, Inc.
3
- * All rights reserved.
4
- *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
8
- */
9
-
10
- #import "XCUICoordinate+FBFix.h"
11
-
12
- #import "XCUICoordinate.h"
13
- #import "XCUIElement+FBUtilities.h"
14
-
15
- # if !TARGET_OS_TV
16
- @implementation XCUICoordinate (FBFix)
17
-
18
- - (CGPoint)fb_screenPoint
19
- {
20
- CGPoint referencePoint = CGPointMake(0, 0);
21
- NSValue *referencedElementFrame = nil;
22
- if (self.element) {
23
- CGRect elementFrame = self.element.frame;
24
- if (self.referencedElement == self.element) {
25
- referencedElementFrame = [NSValue valueWithCGRect:elementFrame];
26
- }
27
- referencePoint = CGPointMake(
28
- CGRectGetMinX(elementFrame) + CGRectGetWidth(elementFrame) * self.normalizedOffset.dx,
29
- CGRectGetMinY(elementFrame) + CGRectGetHeight(elementFrame) * self.normalizedOffset.dy);
30
- } else if (self.coordinate) {
31
- referencePoint = self.coordinate.fb_screenPoint;
32
- }
33
-
34
- CGPoint screenPoint = CGPointMake(
35
- referencePoint.x + self.pointsOffset.dx,
36
- referencePoint.y + self.pointsOffset.dy);
37
- if (nil == referencedElementFrame) {
38
- referencedElementFrame = [NSValue valueWithCGRect:self.referencedElement.frame];
39
- }
40
- return CGPointMake(
41
- MIN(CGRectGetMaxX(referencedElementFrame.CGRectValue), screenPoint.x),
42
- MIN(CGRectGetMaxY(referencedElementFrame.CGRectValue), screenPoint.y));
43
- }
44
-
45
- @end
46
- #endif
@@ -1,52 +0,0 @@
1
- /**
2
- * Copyright (c) 2015-present, Facebook, Inc.
3
- * All rights reserved.
4
- *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
8
- */
9
-
10
- #import <XCTest/XCTest.h>
11
-
12
- #import "FBMacros.h"
13
- #import "FBIntegrationTestCase.h"
14
- #import "XCUIDevice+FBRotation.h"
15
- #import "XCUIElement+FBUtilities.h"
16
- #import "XCUIScreen.h"
17
-
18
- @interface FBElementScreenshotTests : FBIntegrationTestCase
19
- @end
20
-
21
- @implementation FBElementScreenshotTests
22
-
23
- - (void)setUp
24
- {
25
- [super setUp];
26
- static dispatch_once_t onceToken;
27
- dispatch_once(&onceToken, ^{
28
- [self launchApplication];
29
- [self goToAlertsPage];
30
- });
31
- }
32
-
33
- - (void)tearDown
34
- {
35
- [self resetOrientation];
36
- [super tearDown];
37
- }
38
-
39
- - (void)testElementScreenshot
40
- {
41
- [[XCUIDevice sharedDevice] fb_setDeviceInterfaceOrientation:UIDeviceOrientationLandscapeLeft];
42
- XCUIElement *button = self.testedApplication.buttons[FBShowAlertButtonName];
43
- NSError *error = nil;
44
- NSData *screenshotData = [button fb_screenshotWithError:&error];
45
- XCTAssertNotNil(screenshotData);
46
- XCTAssertNil(error);
47
- UIImage *image = [UIImage imageWithData:screenshotData];
48
- XCTAssertNotNil(image);
49
- XCTAssertTrue(image.size.width > image.size.height);
50
- }
51
-
52
- @end
@@ -1,63 +0,0 @@
1
- /**
2
- * Copyright (c) 2015-present, Facebook, Inc.
3
- * All rights reserved.
4
- *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
8
- */
9
-
10
- #import <XCTest/XCTest.h>
11
-
12
- #import "FBMathUtils.h"
13
- #import "XCUICoordinate.h"
14
- #import "XCUICoordinate+FBFix.h"
15
- #import "XCUIElementDouble.h"
16
-
17
- @interface XCUICoordinateFix : XCTestCase
18
- @property (nonatomic, strong, nullable) XCUIElement *mockElement;
19
- @property (nonatomic, strong, nullable) XCUICoordinate *defaultCoordinate;
20
- @end
21
-
22
- @implementation XCUICoordinateFix
23
-
24
- - (void)setUp
25
- {
26
- [super setUp];
27
- XCUIElementDouble *element = [XCUIElementDouble new];
28
- element.frame = CGRectMake(1, 2, 9, 10);
29
- self.mockElement = (XCUIElement *)element;
30
- self.defaultCoordinate = [[XCUICoordinate alloc] initWithElement:self.mockElement normalizedOffset:CGVectorMake(0.0, 0.0)];
31
- }
32
-
33
- - (void)testCoordinateWithElement
34
- {
35
- XCUICoordinate *coordinate = [[XCUICoordinate alloc] initWithElement:self.mockElement normalizedOffset:CGVectorMake(0.0, 0.0)];
36
- XCTAssertTrue(FBPointFuzzyEqualToPoint(coordinate.fb_screenPoint, CGPointMake(1, 2), 0.1));
37
- }
38
-
39
- - (void)testCoordinateWithElementWithOffset
40
- {
41
- XCUICoordinate *coordinate = [[XCUICoordinate alloc] initWithElement:self.mockElement normalizedOffset:CGVectorMake(0.5, 0.5)];
42
- XCTAssertTrue(FBPointFuzzyEqualToPoint(coordinate.fb_screenPoint, CGPointMake(5.5, 7), 0.1));
43
- }
44
-
45
- - (void)testCoordinateWithCoordinate
46
- {
47
- XCUICoordinate *coordinate = [[XCUICoordinate alloc] initWithCoordinate:self.defaultCoordinate pointsOffset:CGVectorMake(0, 0)];
48
- XCTAssertTrue(FBPointFuzzyEqualToPoint(coordinate.fb_screenPoint, CGPointMake(1, 2), 0.1));
49
- }
50
-
51
- - (void)testCoordinateWithCoordinateWithOffset
52
- {
53
- XCUICoordinate *coordinate = [[XCUICoordinate alloc] initWithCoordinate:self.defaultCoordinate pointsOffset:CGVectorMake(1, 2)];
54
- XCTAssertTrue(FBPointFuzzyEqualToPoint(coordinate.fb_screenPoint, CGPointMake(2, 4), 0.1));
55
- }
56
-
57
- - (void)testCoordinateWithCoordinateWithOffsetOffBounds
58
- {
59
- XCUICoordinate *coordinate = [[XCUICoordinate alloc] initWithCoordinate:self.defaultCoordinate pointsOffset:CGVectorMake(200, 200)];
60
- XCTAssertTrue(FBPointFuzzyEqualToPoint(coordinate.fb_screenPoint, CGPointMake(10, 12), 0.1));
61
- }
62
-
63
- @end