appium-webdriveragent 13.3.0 → 14.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.
- package/CHANGELOG.md +16 -0
- package/WebDriverAgent.xcodeproj/project.pbxproj +33 -17
- package/WebDriverAgentLib/Categories/XCUIDevice+FBVoiceOver.h +66 -0
- package/WebDriverAgentLib/Categories/XCUIDevice+FBVoiceOver.m +216 -0
- package/WebDriverAgentLib/Commands/FBCustomCommands.m +80 -0
- package/WebDriverAgentLib/Info.plist +2 -2
- package/WebDriverAgentLib/WebDriverAgentLib.h +1 -0
- package/WebDriverAgentTests/IntegrationTests/FBVoiceOverTests.m +103 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## [14.1.0](https://github.com/appium/WebDriverAgent/compare/v14.0.0...v14.1.0) (2026-06-10)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* Add VoiceOver automation support ([#1153](https://github.com/appium/WebDriverAgent/issues/1153)) ([6b3631a](https://github.com/appium/WebDriverAgent/commit/6b3631aed7a95439b01a9a3bb87189df384dcf06))
|
|
6
|
+
|
|
7
|
+
## [14.0.0](https://github.com/appium/WebDriverAgent/compare/v13.3.0...v14.0.0) (2026-06-09)
|
|
8
|
+
|
|
9
|
+
### ⚠ BREAKING CHANGES
|
|
10
|
+
|
|
11
|
+
* bump the deployment target to 15
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* bump the deployment target to 15 ([#1152](https://github.com/appium/WebDriverAgent/issues/1152)) ([74498f7](https://github.com/appium/WebDriverAgent/commit/74498f79c9f00678f2bc37b9afb50f70e30d0f88))
|
|
16
|
+
|
|
1
17
|
## [13.3.0](https://github.com/appium/WebDriverAgent/compare/v13.2.4...v13.3.0) (2026-06-09)
|
|
2
18
|
|
|
3
19
|
### Features
|
|
@@ -52,7 +52,6 @@
|
|
|
52
52
|
641EE5D92240C5CA00173FCB /* XCUIElement+FBPickerWheel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7136A4781E8918E60024FC3D /* XCUIElement+FBPickerWheel.m */; };
|
|
53
53
|
641EE5DA2240C5CA00173FCB /* XCUIApplicationProcessDelay.m in Sources */ = {isa = PBXBuildFile; fileRef = 6385F4A5220A40760095BBDB /* XCUIApplicationProcessDelay.m */; };
|
|
54
54
|
641EE5DB2240C5CA00173FCB /* FBXPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 711084431DA3AA7500F913D6 /* FBXPath.m */; };
|
|
55
|
-
71B2E0042733FB970074B004 /* FBXPathExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B2E0022733FB970074B002 /* FBXPathExtensions.m */; };
|
|
56
55
|
641EE5DC2240C5CA00173FCB /* XCUIApplication+FBAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 719CD8FB2126C88B00C7D0C2 /* XCUIApplication+FBAlert.m */; };
|
|
57
56
|
641EE5DE2240C5CA00173FCB /* XCUIApplication+FBTouchAction.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BD20721F86116100B36EC2 /* XCUIApplication+FBTouchAction.m */; };
|
|
58
57
|
641EE5DF2240C5CA00173FCB /* FBWebServer.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB78D1CAEDF0C008C271F /* FBWebServer.m */; };
|
|
@@ -317,7 +316,6 @@
|
|
|
317
316
|
64E3502F2AC0B6FE005F3ACB /* NSDictionary+FBUtf8SafeDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 716F0D9F2A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h */; };
|
|
318
317
|
711084441DA3AA7500F913D6 /* FBXPath.h in Headers */ = {isa = PBXBuildFile; fileRef = 711084421DA3AA7500F913D6 /* FBXPath.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
319
318
|
711084451DA3AA7500F913D6 /* FBXPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 711084431DA3AA7500F913D6 /* FBXPath.m */; };
|
|
320
|
-
71B2E0062733FB970074B006 /* FBXPathExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B2E0022733FB970074B002 /* FBXPathExtensions.m */; };
|
|
321
319
|
7119097C2152580600BA3C7E /* XCUIScreen.h in Headers */ = {isa = PBXBuildFile; fileRef = 7119097B2152580600BA3C7E /* XCUIScreen.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
322
320
|
7119E1EC1E891F8600D0B125 /* FBPickerWheelSelectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7119E1EB1E891F8600D0B125 /* FBPickerWheelSelectTests.m */; };
|
|
323
321
|
711CD03425ED1106001C01D2 /* XCUIScreenDataSource-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 711CD03325ED1106001C01D2 /* XCUIScreenDataSource-Protocol.h */; };
|
|
@@ -469,6 +467,8 @@
|
|
|
469
467
|
71B155DC230711E900646AFB /* FBCommandStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B155DB230711E900646AFB /* FBCommandStatus.m */; };
|
|
470
468
|
71B155DF23080CA600646AFB /* FBProtocolHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B155DD23080CA600646AFB /* FBProtocolHelpers.h */; };
|
|
471
469
|
71B155E123080CA600646AFB /* FBProtocolHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B155DE23080CA600646AFB /* FBProtocolHelpers.m */; };
|
|
470
|
+
71B2E0042733FB970074B004 /* FBXPathExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B2E0022733FB970074B002 /* FBXPathExtensions.m */; };
|
|
471
|
+
71B2E0062733FB970074B006 /* FBXPathExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B2E0022733FB970074B002 /* FBXPathExtensions.m */; };
|
|
472
472
|
71B49EC71ED1A58100D51AD6 /* XCUIElement+FBUID.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B49EC51ED1A58100D51AD6 /* XCUIElement+FBUID.h */; };
|
|
473
473
|
71B49EC81ED1A58100D51AD6 /* XCUIElement+FBUID.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B49EC61ED1A58100D51AD6 /* XCUIElement+FBUID.m */; };
|
|
474
474
|
71BB58DE2B9631B700CB9BFE /* FBVideoRecordingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BB58DD2B9631B700CB9BFE /* FBVideoRecordingTests.m */; };
|
|
@@ -535,6 +535,12 @@
|
|
|
535
535
|
71F5BE50252F14EB00EE9EBA /* FBExceptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 71F5BE4D252F14EB00EE9EBA /* FBExceptions.h */; };
|
|
536
536
|
71F5BE51252F14EB00EE9EBA /* FBExceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 71F5BE4E252F14EB00EE9EBA /* FBExceptions.m */; };
|
|
537
537
|
71F5BE52252F14EB00EE9EBA /* FBExceptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 71F5BE4E252F14EB00EE9EBA /* FBExceptions.m */; };
|
|
538
|
+
A1B2C3D41F001A00A1B0004 /* XCUIDevice+FBVoiceOver.h in Headers */ = {isa = PBXBuildFile; fileRef = A1B2C3D41F001A00A1B0001 /* XCUIDevice+FBVoiceOver.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
539
|
+
A1B2C3D41F001A00A1B0005 /* XCUIDevice+FBVoiceOver.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D41F001A00A1B0002 /* XCUIDevice+FBVoiceOver.m */; };
|
|
540
|
+
A1B2C3D41F001A00A1B0006 /* XCUIDevice+FBVoiceOver.h in Headers */ = {isa = PBXBuildFile; fileRef = A1B2C3D41F001A00A1B0001 /* XCUIDevice+FBVoiceOver.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
541
|
+
A1B2C3D41F001A00A1B0007 /* XCUIDevice+FBVoiceOver.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D41F001A00A1B0002 /* XCUIDevice+FBVoiceOver.m */; };
|
|
542
|
+
A1B2C3D41F001A00A1B0008 /* FBVoiceOverTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D41F001A00A1B0003 /* FBVoiceOverTests.m */; };
|
|
543
|
+
A1B2C3D4E5F600000000001B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F600000000001A /* Assets.xcassets */; };
|
|
538
544
|
AABBCCDDEEFF001122334457 /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = AABBCCDDEEFF001122334456 /* SceneDelegate.m */; };
|
|
539
545
|
AD35D06C1CF1C35500870A75 /* WebDriverAgentLib.framework in Copy frameworks */ = {isa = PBXBuildFile; fileRef = EE158A991CBD452B00A3E3F0 /* WebDriverAgentLib.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
|
540
546
|
AD6C26941CF2379700F8B5FF /* FBAlert.h in Headers */ = {isa = PBXBuildFile; fileRef = AD6C26921CF2379700F8B5FF /* FBAlert.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
@@ -832,7 +838,6 @@
|
|
|
832
838
|
F59CD6D52EF16E5E00F91287 /* XCUIElement+FBCustomActions.m in Sources */ = {isa = PBXBuildFile; fileRef = F59CD6D32EF16E5E00F91287 /* XCUIElement+FBCustomActions.m */; };
|
|
833
839
|
F59CD6D62EF16E5E00F91287 /* XCUIElement+FBCustomActions.h in Headers */ = {isa = PBXBuildFile; fileRef = F59CD6D22EF16E5E00F91287 /* XCUIElement+FBCustomActions.h */; };
|
|
834
840
|
F59CD6D72EF16E5E00F91287 /* XCUIElement+FBCustomActions.m in Sources */ = {isa = PBXBuildFile; fileRef = F59CD6D32EF16E5E00F91287 /* XCUIElement+FBCustomActions.m */; };
|
|
835
|
-
A1B2C3D4E5F600000000001B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F600000000001A /* Assets.xcassets */; };
|
|
836
841
|
/* End PBXBuildFile section */
|
|
837
842
|
|
|
838
843
|
/* Begin PBXContainerItemProxy section */
|
|
@@ -982,8 +987,6 @@
|
|
|
982
987
|
64B26509228CE4FF002A5025 /* FBTVNavigationTracker-Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FBTVNavigationTracker-Private.h"; sourceTree = "<group>"; };
|
|
983
988
|
711084421DA3AA7500F913D6 /* FBXPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXPath.h; sourceTree = "<group>"; };
|
|
984
989
|
711084431DA3AA7500F913D6 /* FBXPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBXPath.m; sourceTree = "<group>"; };
|
|
985
|
-
71B2E0012733FB970074B001 /* FBXPathExtensions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBXPathExtensions.h; sourceTree = "<group>"; };
|
|
986
|
-
71B2E0022733FB970074B002 /* FBXPathExtensions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXPathExtensions.m; sourceTree = "<group>"; };
|
|
987
990
|
7119097B2152580600BA3C7E /* XCUIScreen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XCUIScreen.h; sourceTree = "<group>"; };
|
|
988
991
|
7119E1EB1E891F8600D0B125 /* FBPickerWheelSelectTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBPickerWheelSelectTests.m; sourceTree = "<group>"; };
|
|
989
992
|
711CD03325ED1106001C01D2 /* XCUIScreenDataSource-Protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIScreenDataSource-Protocol.h"; sourceTree = "<group>"; };
|
|
@@ -1090,6 +1093,8 @@
|
|
|
1090
1093
|
71B155DB230711E900646AFB /* FBCommandStatus.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBCommandStatus.m; sourceTree = "<group>"; };
|
|
1091
1094
|
71B155DD23080CA600646AFB /* FBProtocolHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBProtocolHelpers.h; sourceTree = "<group>"; };
|
|
1092
1095
|
71B155DE23080CA600646AFB /* FBProtocolHelpers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBProtocolHelpers.m; sourceTree = "<group>"; };
|
|
1096
|
+
71B2E0012733FB970074B001 /* FBXPathExtensions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBXPathExtensions.h; sourceTree = "<group>"; };
|
|
1097
|
+
71B2E0022733FB970074B002 /* FBXPathExtensions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXPathExtensions.m; sourceTree = "<group>"; };
|
|
1093
1098
|
71B49EC51ED1A58100D51AD6 /* XCUIElement+FBUID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBUID.h"; sourceTree = "<group>"; };
|
|
1094
1099
|
71B49EC61ED1A58100D51AD6 /* XCUIElement+FBUID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBUID.m"; sourceTree = "<group>"; };
|
|
1095
1100
|
71BB58DD2B9631B700CB9BFE /* FBVideoRecordingTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBVideoRecordingTests.m; sourceTree = "<group>"; };
|
|
@@ -1125,6 +1130,10 @@
|
|
|
1125
1130
|
71F5BE33252E5B2200EE9EBA /* FBElementSwipingTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBElementSwipingTests.m; sourceTree = "<group>"; };
|
|
1126
1131
|
71F5BE4D252F14EB00EE9EBA /* FBExceptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBExceptions.h; sourceTree = "<group>"; };
|
|
1127
1132
|
71F5BE4E252F14EB00EE9EBA /* FBExceptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBExceptions.m; sourceTree = "<group>"; };
|
|
1133
|
+
A1B2C3D41F001A00A1B0001 /* XCUIDevice+FBVoiceOver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIDevice+FBVoiceOver.h"; sourceTree = "<group>"; };
|
|
1134
|
+
A1B2C3D41F001A00A1B0002 /* XCUIDevice+FBVoiceOver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCUIDevice+FBVoiceOver.m"; sourceTree = "<group>"; };
|
|
1135
|
+
A1B2C3D41F001A00A1B0003 /* FBVoiceOverTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBVoiceOverTests.m; sourceTree = "<group>"; };
|
|
1136
|
+
A1B2C3D4E5F600000000001A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = WebDriverAgentRunner/Assets.xcassets; sourceTree = SOURCE_ROOT; };
|
|
1128
1137
|
AABBCCDDEEFF001122334455 /* SceneDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = "<group>"; };
|
|
1129
1138
|
AABBCCDDEEFF001122334456 /* SceneDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = "<group>"; };
|
|
1130
1139
|
AD42DD2A1CF121E600806E5D /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
|
|
@@ -1379,7 +1388,6 @@
|
|
|
1379
1388
|
EE9AB7921CAEDF0C008C271F /* FBRuntimeUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBRuntimeUtils.m; sourceTree = "<group>"; };
|
|
1380
1389
|
EE9AB7FC1CAEE048008C271F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = WebDriverAgentRunner/Info.plist; sourceTree = SOURCE_ROOT; };
|
|
1381
1390
|
EE9AB7FD1CAEE048008C271F /* UITestingUITests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UITestingUITests.m; path = WebDriverAgentRunner/UITestingUITests.m; sourceTree = SOURCE_ROOT; };
|
|
1382
|
-
A1B2C3D4E5F600000000001A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = WebDriverAgentRunner/Assets.xcassets; sourceTree = SOURCE_ROOT; };
|
|
1383
1391
|
EE9AB8031CAEE182008C271F /* build.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build.sh; sourceTree = "<group>"; };
|
|
1384
1392
|
EE9B75D41CF7956C00275851 /* IntegrationApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IntegrationApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
1385
1393
|
EE9B75EC1CF7956C00275851 /* IntegrationTests_1.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IntegrationTests_1.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
@@ -1798,6 +1806,8 @@
|
|
|
1798
1806
|
EEDFE1201D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.m */,
|
|
1799
1807
|
AD6C26961CF2481700F8B5FF /* XCUIDevice+FBHelpers.h */,
|
|
1800
1808
|
AD6C26971CF2481700F8B5FF /* XCUIDevice+FBHelpers.m */,
|
|
1809
|
+
A1B2C3D41F001A00A1B0001 /* XCUIDevice+FBVoiceOver.h */,
|
|
1810
|
+
A1B2C3D41F001A00A1B0002 /* XCUIDevice+FBVoiceOver.m */,
|
|
1801
1811
|
EEE3763D1D59F81400ED88DD /* XCUIDevice+FBRotation.h */,
|
|
1802
1812
|
EEE3763E1D59F81400ED88DD /* XCUIDevice+FBRotation.m */,
|
|
1803
1813
|
EE9AB7451CAEDF0C008C271F /* XCUIElement+FBAccessibility.h */,
|
|
@@ -2012,11 +2022,11 @@
|
|
|
2012
2022
|
714D88CA2733FB970074A925 /* FBXMLGenerationOptions.h */,
|
|
2013
2023
|
714D88CB2733FB970074A925 /* FBXMLGenerationOptions.m */,
|
|
2014
2024
|
712A0C861DA3E55D007D02E5 /* FBXPath-Private.h */,
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2025
|
+
711084421DA3AA7500F913D6 /* FBXPath.h */,
|
|
2026
|
+
711084431DA3AA7500F913D6 /* FBXPath.m */,
|
|
2027
|
+
71B2E0012733FB970074B001 /* FBXPathExtensions.h */,
|
|
2028
|
+
71B2E0022733FB970074B002 /* FBXPathExtensions.m */,
|
|
2029
|
+
EE6B64FB1D0F86EF00E85F5D /* XCTestPrivateSymbols.h */,
|
|
2020
2030
|
EE6B64FC1D0F86EF00E85F5D /* XCTestPrivateSymbols.m */,
|
|
2021
2031
|
633E904A220DEE7F007CADF9 /* XCUIApplicationProcessDelay.h */,
|
|
2022
2032
|
6385F4A5220A40760095BBDB /* XCUIApplicationProcessDelay.m */,
|
|
@@ -2070,6 +2080,7 @@
|
|
|
2070
2080
|
AD76723F1D6B826F00610457 /* FBTypingTest.m */,
|
|
2071
2081
|
714CA3C61DC23186000F12C9 /* FBXPathIntegrationTests.m */,
|
|
2072
2082
|
71BB58DD2B9631B700CB9BFE /* FBVideoRecordingTests.m */,
|
|
2083
|
+
A1B2C3D41F001A00A1B0003 /* FBVoiceOverTests.m */,
|
|
2073
2084
|
71241D7D1FAF084E00B9559F /* FBW3CTouchActionsIntegrationTests.m */,
|
|
2074
2085
|
71241D7F1FAF087500B9559F /* FBW3CMultiTouchActionsIntegrationTests.m */,
|
|
2075
2086
|
7136C0F8243A182400921C76 /* FBW3CTypeActionsTests.m */,
|
|
@@ -2513,6 +2524,7 @@
|
|
|
2513
2524
|
71822777258744CE00661B83 /* DDNumber.h in Headers */,
|
|
2514
2525
|
641EE6C82240C5CA00173FCB /* XCTKVOExpectation.h in Headers */,
|
|
2515
2526
|
641EE6C92240C5CA00173FCB /* XCUIDevice+FBRotation.h in Headers */,
|
|
2527
|
+
A1B2C3D41F001A00A1B0004 /* XCUIDevice+FBVoiceOver.h in Headers */,
|
|
2516
2528
|
641EE6CA2240C5CA00173FCB /* XCEventGenerator.h in Headers */,
|
|
2517
2529
|
719DCF162601EAFB000E765F /* FBNotificationsHelper.h in Headers */,
|
|
2518
2530
|
71414ED52670A1EE003A8C5D /* LRUCache.h in Headers */,
|
|
@@ -2760,6 +2772,7 @@
|
|
|
2760
2772
|
EE35AD591E3B77D600A02D78 /* XCTKVOExpectation.h in Headers */,
|
|
2761
2773
|
13DE7A43287C2A8D003243C6 /* FBXCAccessibilityElement.h in Headers */,
|
|
2762
2774
|
EEE376431D59F81400ED88DD /* XCUIDevice+FBRotation.h in Headers */,
|
|
2775
|
+
A1B2C3D41F001A00A1B0006 /* XCUIDevice+FBVoiceOver.h in Headers */,
|
|
2763
2776
|
EE35AD2E1E3B77D600A02D78 /* XCEventGenerator.h in Headers */,
|
|
2764
2777
|
EE9B76A61CF7A43900275851 /* FBConfiguration.h in Headers */,
|
|
2765
2778
|
EE35AD571E3B77D600A02D78 /* XCTestSuiteRun.h in Headers */,
|
|
@@ -3206,6 +3219,7 @@
|
|
|
3206
3219
|
641EE5F22240C5CA00173FCB /* NSPredicate+FBFormat.m in Sources */,
|
|
3207
3220
|
718F49CA23087AD30045FE8B /* FBProtocolHelpers.m in Sources */,
|
|
3208
3221
|
641EE5F42240C5CA00173FCB /* XCUIDevice+FBRotation.m in Sources */,
|
|
3222
|
+
A1B2C3D41F001A00A1B0005 /* XCUIDevice+FBVoiceOver.m in Sources */,
|
|
3209
3223
|
13815F722328D20400CDAB61 /* FBActiveAppDetectionPoint.m in Sources */,
|
|
3210
3224
|
71D475C52538F5A8008D9401 /* XCUIApplicationProcess+FBQuiescence.m in Sources */,
|
|
3211
3225
|
641EE5F52240C5CA00173FCB /* XCUIElement+FBUID.m in Sources */,
|
|
@@ -3333,6 +3347,7 @@
|
|
|
3333
3347
|
71A224E61DE2F56600844D55 /* NSPredicate+FBFormat.m in Sources */,
|
|
3334
3348
|
E444DC85249131B10060D7EB /* DDNumber.m in Sources */,
|
|
3335
3349
|
EEE376441D59F81400ED88DD /* XCUIDevice+FBRotation.m in Sources */,
|
|
3350
|
+
A1B2C3D41F001A00A1B0007 /* XCUIDevice+FBVoiceOver.m in Sources */,
|
|
3336
3351
|
13815F712328D20400CDAB61 /* FBActiveAppDetectionPoint.m in Sources */,
|
|
3337
3352
|
71B49EC81ED1A58100D51AD6 /* XCUIElement+FBUID.m in Sources */,
|
|
3338
3353
|
EE158AE21CBD456F00A3E3F0 /* FBRouteRequest.m in Sources */,
|
|
@@ -3422,6 +3437,7 @@
|
|
|
3422
3437
|
files = (
|
|
3423
3438
|
71241D801FAF087500B9559F /* FBW3CMultiTouchActionsIntegrationTests.m in Sources */,
|
|
3424
3439
|
71BB58DE2B9631B700CB9BFE /* FBVideoRecordingTests.m in Sources */,
|
|
3440
|
+
A1B2C3D41F001A00A1B0008 /* FBVoiceOverTests.m in Sources */,
|
|
3425
3441
|
71241D7E1FAF084E00B9559F /* FBW3CTouchActionsIntegrationTests.m in Sources */,
|
|
3426
3442
|
63FD950221F9D06100A3E356 /* FBImageProcessorTests.m in Sources */,
|
|
3427
3443
|
719CD8FF2126C90200C7D0C2 /* FBAutoAlertsHandlerTests.m in Sources */,
|
|
@@ -3976,13 +3992,13 @@
|
|
|
3976
3992
|
"$(SDKROOT)/usr/include/libxml2",
|
|
3977
3993
|
"$(SRCROOT)/Modules",
|
|
3978
3994
|
);
|
|
3979
|
-
IPHONEOS_DEPLOYMENT_TARGET =
|
|
3995
|
+
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
|
3980
3996
|
MTL_ENABLE_DEBUG_INFO = YES;
|
|
3981
3997
|
ONLY_ACTIVE_ARCH = YES;
|
|
3982
3998
|
SDKROOT = iphoneos;
|
|
3983
3999
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
|
3984
4000
|
TARGETED_DEVICE_FAMILY = "1,2";
|
|
3985
|
-
TVOS_DEPLOYMENT_TARGET =
|
|
4001
|
+
TVOS_DEPLOYMENT_TARGET = 15.0;
|
|
3986
4002
|
VALIDATE_WORKSPACE = NO;
|
|
3987
4003
|
};
|
|
3988
4004
|
name = Debug;
|
|
@@ -4039,12 +4055,12 @@
|
|
|
4039
4055
|
"$(SDKROOT)/usr/include/libxml2",
|
|
4040
4056
|
"$(SRCROOT)/Modules",
|
|
4041
4057
|
);
|
|
4042
|
-
IPHONEOS_DEPLOYMENT_TARGET =
|
|
4058
|
+
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
|
4043
4059
|
MTL_ENABLE_DEBUG_INFO = NO;
|
|
4044
4060
|
SDKROOT = iphoneos;
|
|
4045
4061
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
|
4046
4062
|
TARGETED_DEVICE_FAMILY = "1,2";
|
|
4047
|
-
TVOS_DEPLOYMENT_TARGET =
|
|
4063
|
+
TVOS_DEPLOYMENT_TARGET = 15.0;
|
|
4048
4064
|
VALIDATE_PRODUCT = YES;
|
|
4049
4065
|
VALIDATE_WORKSPACE = NO;
|
|
4050
4066
|
};
|
|
@@ -4300,7 +4316,7 @@
|
|
|
4300
4316
|
CLANG_ANALYZER_NONNULL = YES;
|
|
4301
4317
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
|
4302
4318
|
INFOPLIST_FILE = WebDriverAgentTests/IntegrationApp/Info.plist;
|
|
4303
|
-
IPHONEOS_DEPLOYMENT_TARGET =
|
|
4319
|
+
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
|
4304
4320
|
LD_RUNPATH_SEARCH_PATHS = (
|
|
4305
4321
|
"$(inherited)",
|
|
4306
4322
|
"@executable_path/Frameworks",
|
|
@@ -4317,7 +4333,7 @@
|
|
|
4317
4333
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
|
4318
4334
|
CLANG_ANALYZER_NONNULL = YES;
|
|
4319
4335
|
INFOPLIST_FILE = WebDriverAgentTests/IntegrationApp/Info.plist;
|
|
4320
|
-
IPHONEOS_DEPLOYMENT_TARGET =
|
|
4336
|
+
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
|
4321
4337
|
LD_RUNPATH_SEARCH_PATHS = (
|
|
4322
4338
|
"$(inherited)",
|
|
4323
4339
|
"@executable_path/Frameworks",
|
|
@@ -0,0 +1,66 @@
|
|
|
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.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#import <XCTest/XCTest.h>
|
|
10
|
+
|
|
11
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
12
|
+
|
|
13
|
+
@interface XCUIDevice (FBVoiceOver)
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
Whether VoiceOver control APIs are available in the current Xcode SDK.
|
|
17
|
+
|
|
18
|
+
@return YES if the VoiceOver service is exposed by XCUIDevice
|
|
19
|
+
*/
|
|
20
|
+
- (BOOL)fb_isVoiceOverServiceAvailable;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
Enable VoiceOver. Only works since Xcode 27/iOS 27.
|
|
24
|
+
|
|
25
|
+
@param error If there is an error, upon return contains an NSError object that describes the problem.
|
|
26
|
+
@return YES if VoiceOver has been successfully enabled
|
|
27
|
+
*/
|
|
28
|
+
- (BOOL)fb_enableVoiceOver:(NSError **)error;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
Disable VoiceOver. Only works since Xcode 27/iOS 27.
|
|
32
|
+
|
|
33
|
+
@param error If there is an error, upon return contains an NSError object that describes the problem.
|
|
34
|
+
@return YES if VoiceOver has been successfully disabled
|
|
35
|
+
*/
|
|
36
|
+
- (BOOL)fb_disableVoiceOver:(NSError **)error;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
Whether VoiceOver is currently enabled. Only works since Xcode 27/iOS 27.
|
|
40
|
+
|
|
41
|
+
@param error If there is an error, upon return contains an NSError object that describes the problem.
|
|
42
|
+
@return YES if VoiceOver is enabled
|
|
43
|
+
*/
|
|
44
|
+
- (BOOL)fb_isVoiceOverEnabled:(NSError **)error;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
Move VoiceOver focus and return speech for the newly focused element.
|
|
48
|
+
Only works since Xcode 27/iOS 27.
|
|
49
|
+
|
|
50
|
+
@param direction One of: forward, backward, in (iOS only), out (iOS only)
|
|
51
|
+
@param error If there is an error, upon return contains an NSError object that describes the problem.
|
|
52
|
+
@return The spoken utterance or nil in case of failure
|
|
53
|
+
*/
|
|
54
|
+
- (nullable NSString *)fb_voiceOverMove:(NSString *)direction error:(NSError **)error;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
Return the speech for the currently focused element. Only works since Xcode 27/iOS 27.
|
|
58
|
+
|
|
59
|
+
@param error If there is an error, upon return contains an NSError object that describes the problem.
|
|
60
|
+
@return The spoken utterance or nil in case of failure
|
|
61
|
+
*/
|
|
62
|
+
- (nullable NSString *)fb_voiceOverCurrentSpeech:(NSError **)error;
|
|
63
|
+
|
|
64
|
+
@end
|
|
65
|
+
|
|
66
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,216 @@
|
|
|
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.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#import "XCUIDevice+FBVoiceOver.h"
|
|
10
|
+
|
|
11
|
+
#import "FBErrorBuilder.h"
|
|
12
|
+
|
|
13
|
+
static NSString *const FBVoiceOverSDKUnsupportedError =
|
|
14
|
+
@"The current Xcode SDK does not support VoiceOver control. Consider upgrading to Xcode 27+/iOS 27+";
|
|
15
|
+
|
|
16
|
+
static BOOL FBVoiceOverBuildSDKUnsupportedError(NSError **error)
|
|
17
|
+
{
|
|
18
|
+
return [[[FBErrorBuilder builder]
|
|
19
|
+
withDescription:FBVoiceOverSDKUnsupportedError]
|
|
20
|
+
buildError:error];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static BOOL FBIsVoiceOverServiceAvailable(void)
|
|
24
|
+
{
|
|
25
|
+
static BOOL isAvailable = NO;
|
|
26
|
+
static dispatch_once_t onceToken;
|
|
27
|
+
dispatch_once(&onceToken, ^{
|
|
28
|
+
isAvailable = [XCUIDevice.sharedDevice respondsToSelector:NSSelectorFromString(@"voiceOverService")];
|
|
29
|
+
});
|
|
30
|
+
return isAvailable;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static id FBVoiceOverService(NSError **error)
|
|
34
|
+
{
|
|
35
|
+
if (!FBIsVoiceOverServiceAvailable()) {
|
|
36
|
+
FBVoiceOverBuildSDKUnsupportedError(error);
|
|
37
|
+
return nil;
|
|
38
|
+
}
|
|
39
|
+
return [XCUIDevice.sharedDevice valueForKey:@"voiceOverService"];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static BOOL FBInvokeVoiceOverBoolMethod(id voiceOverService,
|
|
43
|
+
SEL selector,
|
|
44
|
+
NSError **error)
|
|
45
|
+
{
|
|
46
|
+
if (![voiceOverService respondsToSelector:selector]) {
|
|
47
|
+
return FBVoiceOverBuildSDKUnsupportedError(error);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
NSMethodSignature *signature = [voiceOverService methodSignatureForSelector:selector];
|
|
51
|
+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
|
|
52
|
+
[invocation setSelector:selector];
|
|
53
|
+
[invocation setTarget:voiceOverService];
|
|
54
|
+
NSError *invokeError = nil;
|
|
55
|
+
[invocation setArgument:&invokeError atIndex:2];
|
|
56
|
+
[invocation invoke];
|
|
57
|
+
if (nil != invokeError) {
|
|
58
|
+
if (error) {
|
|
59
|
+
*error = invokeError;
|
|
60
|
+
}
|
|
61
|
+
return NO;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
BOOL result = NO;
|
|
65
|
+
[invocation getReturnValue:&result];
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static id FBInvokeVoiceOverOutputMethod(id voiceOverService,
|
|
70
|
+
SEL selector,
|
|
71
|
+
NSError **error)
|
|
72
|
+
{
|
|
73
|
+
if (![voiceOverService respondsToSelector:selector]) {
|
|
74
|
+
FBVoiceOverBuildSDKUnsupportedError(error);
|
|
75
|
+
return nil;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
NSMethodSignature *signature = [voiceOverService methodSignatureForSelector:selector];
|
|
79
|
+
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
|
|
80
|
+
[invocation setSelector:selector];
|
|
81
|
+
[invocation setTarget:voiceOverService];
|
|
82
|
+
NSError *invokeError = nil;
|
|
83
|
+
[invocation setArgument:&invokeError atIndex:2];
|
|
84
|
+
[invocation invoke];
|
|
85
|
+
if (nil != invokeError) {
|
|
86
|
+
if (error) {
|
|
87
|
+
*error = invokeError;
|
|
88
|
+
}
|
|
89
|
+
return nil;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
id __unsafe_unretained output = nil;
|
|
93
|
+
[invocation getReturnValue:&output];
|
|
94
|
+
return output;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
static NSString *FBUtteranceFromVoiceOverOutput(id output, NSError **error)
|
|
98
|
+
{
|
|
99
|
+
if (nil == output) {
|
|
100
|
+
return nil;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (![output respondsToSelector:NSSelectorFromString(@"utterance")]) {
|
|
104
|
+
[[[FBErrorBuilder builder]
|
|
105
|
+
withDescription:@"VoiceOver output does not provide an utterance"]
|
|
106
|
+
buildError:error];
|
|
107
|
+
return nil;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
id utterance = [output valueForKey:@"utterance"];
|
|
111
|
+
return [utterance isKindOfClass:NSString.class] ? utterance : nil;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static NSString *FBVoiceOverSpeechFromSelector(SEL selector, NSError **error)
|
|
115
|
+
{
|
|
116
|
+
id service = FBVoiceOverService(error);
|
|
117
|
+
if (nil == service) {
|
|
118
|
+
return nil;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
id output = FBInvokeVoiceOverOutputMethod(service, selector, error);
|
|
122
|
+
if (nil != error && nil != *error) {
|
|
123
|
+
return nil;
|
|
124
|
+
}
|
|
125
|
+
return FBUtteranceFromVoiceOverOutput(output, error);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
static NSDictionary<NSString *, NSString *> *FBVoiceOverMoveSelectors(void)
|
|
129
|
+
{
|
|
130
|
+
static NSDictionary<NSString *, NSString *> *selectors = nil;
|
|
131
|
+
static dispatch_once_t onceToken;
|
|
132
|
+
dispatch_once(&onceToken, ^{
|
|
133
|
+
NSMutableDictionary<NSString *, NSString *> *mapping = [@{
|
|
134
|
+
@"forward": @"moveForwardAndReturnError:",
|
|
135
|
+
@"backward": @"moveBackwardAndReturnError:",
|
|
136
|
+
} mutableCopy];
|
|
137
|
+
#if TARGET_OS_IOS
|
|
138
|
+
mapping[@"in"] = @"moveInAndReturnError:";
|
|
139
|
+
mapping[@"out"] = @"moveOutAndReturnError:";
|
|
140
|
+
#endif
|
|
141
|
+
selectors = mapping.copy;
|
|
142
|
+
});
|
|
143
|
+
return selectors;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@implementation XCUIDevice (FBVoiceOver)
|
|
147
|
+
|
|
148
|
+
- (BOOL)fb_isVoiceOverServiceAvailable
|
|
149
|
+
{
|
|
150
|
+
return FBIsVoiceOverServiceAvailable();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
- (BOOL)fb_enableVoiceOver:(NSError **)error
|
|
154
|
+
{
|
|
155
|
+
id service = FBVoiceOverService(error);
|
|
156
|
+
if (nil == service) {
|
|
157
|
+
return NO;
|
|
158
|
+
}
|
|
159
|
+
return FBInvokeVoiceOverBoolMethod(service,
|
|
160
|
+
NSSelectorFromString(@"enableAndReturnError:"),
|
|
161
|
+
error);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
- (BOOL)fb_disableVoiceOver:(NSError **)error
|
|
165
|
+
{
|
|
166
|
+
id service = FBVoiceOverService(error);
|
|
167
|
+
if (nil == service) {
|
|
168
|
+
return NO;
|
|
169
|
+
}
|
|
170
|
+
return FBInvokeVoiceOverBoolMethod(service,
|
|
171
|
+
NSSelectorFromString(@"disableAndReturnError:"),
|
|
172
|
+
error);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
- (BOOL)fb_isVoiceOverEnabled:(NSError **)error
|
|
176
|
+
{
|
|
177
|
+
id service = FBVoiceOverService(error);
|
|
178
|
+
if (nil == service) {
|
|
179
|
+
return NO;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (![service respondsToSelector:NSSelectorFromString(@"isEnabled")] &&
|
|
183
|
+
![service respondsToSelector:NSSelectorFromString(@"enabled")]) {
|
|
184
|
+
return FBVoiceOverBuildSDKUnsupportedError(error);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return [[service valueForKey:@"enabled"] boolValue];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
- (nullable NSString *)fb_voiceOverMove:(NSString *)direction error:(NSError **)error
|
|
191
|
+
{
|
|
192
|
+
if (![direction isKindOfClass:NSString.class] || 0 == direction.length) {
|
|
193
|
+
return [[[FBErrorBuilder builder]
|
|
194
|
+
withDescription:@"VoiceOver move direction must be a non-empty string"]
|
|
195
|
+
buildError:error], nil;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
NSString *normalizedDirection = direction.lowercaseString;
|
|
199
|
+
NSString *selectorName = FBVoiceOverMoveSelectors()[normalizedDirection];
|
|
200
|
+
if (nil == selectorName) {
|
|
201
|
+
NSArray *supportedDirections = [FBVoiceOverMoveSelectors().allKeys sortedArrayUsingSelector:@selector(compare:)];
|
|
202
|
+
return [[[FBErrorBuilder builder]
|
|
203
|
+
withDescriptionFormat:@"Unsupported VoiceOver move direction '%@'. Supported directions: %@",
|
|
204
|
+
direction, supportedDirections]
|
|
205
|
+
buildError:error], nil;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return FBVoiceOverSpeechFromSelector(NSSelectorFromString(selectorName), error);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
- (nullable NSString *)fb_voiceOverCurrentSpeech:(NSError **)error
|
|
212
|
+
{
|
|
213
|
+
return FBVoiceOverSpeechFromSelector(NSSelectorFromString(@"currentSpeechAndReturnError:"), error);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
@end
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
#import "XCUIApplication.h"
|
|
27
27
|
#import "XCUIApplication+FBHelpers.h"
|
|
28
28
|
#import "XCUIDevice+FBHelpers.h"
|
|
29
|
+
#import "XCUIDevice+FBVoiceOver.h"
|
|
29
30
|
#import "XCUIElement.h"
|
|
30
31
|
#import "XCUIElement+FBIsVisible.h"
|
|
31
32
|
#import "XCUIElementQuery.h"
|
|
@@ -81,6 +82,16 @@
|
|
|
81
82
|
[[FBRoute DELETE:@"/wda/simulatedLocation"] respondWithTarget:self action:@selector(handleClearSimulatedLocation:)],
|
|
82
83
|
[[FBRoute DELETE:@"/wda/simulatedLocation"].withoutSession respondWithTarget:self action:@selector(handleClearSimulatedLocation:)],
|
|
83
84
|
#endif
|
|
85
|
+
[[FBRoute POST:@"/wda/voiceOver/enable"] respondWithTarget:self action:@selector(handleVoiceOverEnable:)],
|
|
86
|
+
[[FBRoute POST:@"/wda/voiceOver/enable"].withoutSession respondWithTarget:self action:@selector(handleVoiceOverEnable:)],
|
|
87
|
+
[[FBRoute POST:@"/wda/voiceOver/disable"] respondWithTarget:self action:@selector(handleVoiceOverDisable:)],
|
|
88
|
+
[[FBRoute POST:@"/wda/voiceOver/disable"].withoutSession respondWithTarget:self action:@selector(handleVoiceOverDisable:)],
|
|
89
|
+
[[FBRoute GET:@"/wda/voiceOver/enabled"] respondWithTarget:self action:@selector(handleVoiceOverEnabled:)],
|
|
90
|
+
[[FBRoute GET:@"/wda/voiceOver/enabled"].withoutSession respondWithTarget:self action:@selector(handleVoiceOverEnabled:)],
|
|
91
|
+
[[FBRoute POST:@"/wda/voiceOver/move"] respondWithTarget:self action:@selector(handleVoiceOverMove:)],
|
|
92
|
+
[[FBRoute POST:@"/wda/voiceOver/move"].withoutSession respondWithTarget:self action:@selector(handleVoiceOverMove:)],
|
|
93
|
+
[[FBRoute GET:@"/wda/voiceOver/currentSpeech"] respondWithTarget:self action:@selector(handleVoiceOverCurrentSpeech:)],
|
|
94
|
+
[[FBRoute GET:@"/wda/voiceOver/currentSpeech"].withoutSession respondWithTarget:self action:@selector(handleVoiceOverCurrentSpeech:)],
|
|
84
95
|
[[FBRoute OPTIONS:@"/*"].withoutSession respondWithTarget:self action:@selector(handlePingCommand:)],
|
|
85
96
|
];
|
|
86
97
|
}
|
|
@@ -611,6 +622,75 @@
|
|
|
611
622
|
#endif
|
|
612
623
|
#endif
|
|
613
624
|
|
|
625
|
+
+ (id<FBResponsePayload>)fb_handleVoiceOverSpeechResponse:(nullable NSString *)utterance
|
|
626
|
+
error:(NSError *)error
|
|
627
|
+
{
|
|
628
|
+
if (nil != error) {
|
|
629
|
+
return FBResponseWithStatus([FBCommandStatus unknownErrorWithMessage:error.description
|
|
630
|
+
traceback:nil]);
|
|
631
|
+
}
|
|
632
|
+
return FBResponseWithObject(@{
|
|
633
|
+
@"utterance": utterance ?: NSNull.null,
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
+ (id<FBResponsePayload>)handleVoiceOverEnable:(FBRouteRequest *)request
|
|
638
|
+
{
|
|
639
|
+
NSError *error;
|
|
640
|
+
if (![XCUIDevice.sharedDevice fb_enableVoiceOver:&error]) {
|
|
641
|
+
return FBResponseWithStatus([FBCommandStatus unknownErrorWithMessage:error.description
|
|
642
|
+
traceback:nil]);
|
|
643
|
+
}
|
|
644
|
+
return FBResponseWithOK();
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
+ (id<FBResponsePayload>)handleVoiceOverDisable:(FBRouteRequest *)request
|
|
648
|
+
{
|
|
649
|
+
NSError *error;
|
|
650
|
+
if (![XCUIDevice.sharedDevice fb_disableVoiceOver:&error]) {
|
|
651
|
+
return FBResponseWithStatus([FBCommandStatus unknownErrorWithMessage:error.description
|
|
652
|
+
traceback:nil]);
|
|
653
|
+
}
|
|
654
|
+
return FBResponseWithOK();
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
+ (id<FBResponsePayload>)handleVoiceOverEnabled:(FBRouteRequest *)request
|
|
658
|
+
{
|
|
659
|
+
NSError *error;
|
|
660
|
+
BOOL isEnabled = [XCUIDevice.sharedDevice fb_isVoiceOverEnabled:&error];
|
|
661
|
+
if (nil != error) {
|
|
662
|
+
return FBResponseWithStatus([FBCommandStatus unknownErrorWithMessage:error.description
|
|
663
|
+
traceback:nil]);
|
|
664
|
+
}
|
|
665
|
+
return FBResponseWithObject(@{@"enabled": @(isEnabled)});
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
+ (id<FBResponsePayload>)handleVoiceOverMove:(FBRouteRequest *)request
|
|
669
|
+
{
|
|
670
|
+
NSString *direction = request.arguments[@"direction"];
|
|
671
|
+
if (nil == direction) {
|
|
672
|
+
return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:@"The 'direction' argument must be provided"
|
|
673
|
+
traceback:nil]);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
NSError *error;
|
|
677
|
+
NSString *utterance = [XCUIDevice.sharedDevice fb_voiceOverMove:direction error:&error];
|
|
678
|
+
if (nil != error) {
|
|
679
|
+
FBCommandStatus *status = [error.localizedDescription containsString:@"Unsupported VoiceOver move direction"]
|
|
680
|
+
? [FBCommandStatus invalidArgumentErrorWithMessage:error.description traceback:nil]
|
|
681
|
+
: [FBCommandStatus unknownErrorWithMessage:error.description traceback:nil];
|
|
682
|
+
return FBResponseWithStatus(status);
|
|
683
|
+
}
|
|
684
|
+
return [self fb_handleVoiceOverSpeechResponse:utterance error:nil];
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
+ (id<FBResponsePayload>)handleVoiceOverCurrentSpeech:(FBRouteRequest *)request
|
|
688
|
+
{
|
|
689
|
+
NSError *error;
|
|
690
|
+
NSString *utterance = [XCUIDevice.sharedDevice fb_voiceOverCurrentSpeech:&error];
|
|
691
|
+
return [self fb_handleVoiceOverSpeechResponse:utterance error:error];
|
|
692
|
+
}
|
|
693
|
+
|
|
614
694
|
+ (id<FBResponsePayload>)handlePerformAccessibilityAudit:(FBRouteRequest *)request
|
|
615
695
|
{
|
|
616
696
|
NSError *error;
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
<key>CFBundlePackageType</key>
|
|
16
16
|
<string>FMWK</string>
|
|
17
17
|
<key>CFBundleShortVersionString</key>
|
|
18
|
-
<string>
|
|
18
|
+
<string>14.1.0</string>
|
|
19
19
|
<key>CFBundleSignature</key>
|
|
20
20
|
<string>????</string>
|
|
21
21
|
<key>CFBundleVersion</key>
|
|
22
|
-
<string>
|
|
22
|
+
<string>14.1.0</string>
|
|
23
23
|
<key>NSPrincipalClass</key>
|
|
24
24
|
<string/>
|
|
25
25
|
</dict>
|
|
@@ -48,6 +48,7 @@ FOUNDATION_EXPORT const unsigned char WebDriverAgentLib_VersionString[];
|
|
|
48
48
|
#import <WebDriverAgentLib/XCUIApplication+FBHelpers.h>
|
|
49
49
|
#import <WebDriverAgentLib/XCUIDevice+FBHelpers.h>
|
|
50
50
|
#import <WebDriverAgentLib/XCUIDevice+FBRotation.h>
|
|
51
|
+
#import <WebDriverAgentLib/XCUIDevice+FBVoiceOver.h>
|
|
51
52
|
#import <WebDriverAgentLib/XCUIElement.h>
|
|
52
53
|
#import <WebDriverAgentLib/XCUIElement+FBAccessibility.h>
|
|
53
54
|
#import <WebDriverAgentLib/XCUIElement+FBFind.h>
|
|
@@ -0,0 +1,103 @@
|
|
|
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.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#import <XCTest/XCTest.h>
|
|
10
|
+
|
|
11
|
+
#import "FBIntegrationTestCase.h"
|
|
12
|
+
#import "FBMacros.h"
|
|
13
|
+
#import "FBTestMacros.h"
|
|
14
|
+
#import "XCUIDevice+FBVoiceOver.h"
|
|
15
|
+
|
|
16
|
+
@interface FBVoiceOverTests : FBIntegrationTestCase
|
|
17
|
+
@end
|
|
18
|
+
|
|
19
|
+
@implementation FBVoiceOverTests
|
|
20
|
+
|
|
21
|
+
- (void)tearDown
|
|
22
|
+
{
|
|
23
|
+
if ([XCUIDevice.sharedDevice fb_isVoiceOverServiceAvailable]) {
|
|
24
|
+
NSError *error = nil;
|
|
25
|
+
if ([XCUIDevice.sharedDevice fb_isVoiceOverEnabled:&error] && nil == error) {
|
|
26
|
+
[XCUIDevice.sharedDevice fb_disableVoiceOver:&error];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
[super tearDown];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
- (void)testVoiceOverUnavailableOnOlderSDK
|
|
33
|
+
{
|
|
34
|
+
if ([XCUIDevice.sharedDevice fb_isVoiceOverServiceAvailable]) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
NSError *error = nil;
|
|
39
|
+
XCTAssertFalse([XCUIDevice.sharedDevice fb_enableVoiceOver:&error]);
|
|
40
|
+
XCTAssertNotNil(error);
|
|
41
|
+
XCTAssertTrue([error.localizedDescription containsString:@"Xcode 27"]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
- (void)testVoiceOverEnableDisableAndNavigation
|
|
45
|
+
{
|
|
46
|
+
if (SYSTEM_VERSION_LESS_THAN(@"27.0")) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (![XCUIDevice.sharedDevice fb_isVoiceOverServiceAvailable]) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
[self launchApplication];
|
|
54
|
+
|
|
55
|
+
NSError *error = nil;
|
|
56
|
+
XCTAssertTrue([XCUIDevice.sharedDevice fb_enableVoiceOver:&error]);
|
|
57
|
+
XCTAssertNil(error);
|
|
58
|
+
XCTAssertTrue([XCUIDevice.sharedDevice fb_isVoiceOverEnabled:&error]);
|
|
59
|
+
XCTAssertNil(error);
|
|
60
|
+
|
|
61
|
+
NSString *utterance = [XCUIDevice.sharedDevice fb_voiceOverMove:@"forward" error:&error];
|
|
62
|
+
XCTAssertNil(error);
|
|
63
|
+
XCTAssertNotNil(utterance);
|
|
64
|
+
XCTAssertTrue(utterance.length > 0);
|
|
65
|
+
|
|
66
|
+
NSString *currentSpeech = [XCUIDevice.sharedDevice fb_voiceOverCurrentSpeech:&error];
|
|
67
|
+
XCTAssertNil(error);
|
|
68
|
+
XCTAssertNotNil(currentSpeech);
|
|
69
|
+
XCTAssertEqualObjects(currentSpeech, utterance);
|
|
70
|
+
|
|
71
|
+
XCTAssertTrue([XCUIDevice.sharedDevice fb_disableVoiceOver:&error]);
|
|
72
|
+
XCTAssertNil(error);
|
|
73
|
+
XCTAssertFalse([XCUIDevice.sharedDevice fb_isVoiceOverEnabled:&error]);
|
|
74
|
+
XCTAssertNil(error);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#if TARGET_OS_IOS
|
|
78
|
+
- (void)testVoiceOverMoveBackward
|
|
79
|
+
{
|
|
80
|
+
if (SYSTEM_VERSION_LESS_THAN(@"27.0")) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (![XCUIDevice.sharedDevice fb_isVoiceOverServiceAvailable]) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
[self launchApplication];
|
|
88
|
+
|
|
89
|
+
NSError *error = nil;
|
|
90
|
+
XCTAssertTrue([XCUIDevice.sharedDevice fb_enableVoiceOver:&error]);
|
|
91
|
+
XCTAssertNil(error);
|
|
92
|
+
|
|
93
|
+
XCTAssertNotNil([XCUIDevice.sharedDevice fb_voiceOverMove:@"forward" error:&error]);
|
|
94
|
+
XCTAssertNil(error);
|
|
95
|
+
|
|
96
|
+
NSString *utterance = [XCUIDevice.sharedDevice fb_voiceOverMove:@"backward" error:&error];
|
|
97
|
+
XCTAssertNil(error);
|
|
98
|
+
XCTAssertNotNil(utterance);
|
|
99
|
+
XCTAssertTrue(utterance.length > 0);
|
|
100
|
+
}
|
|
101
|
+
#endif
|
|
102
|
+
|
|
103
|
+
@end
|