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 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
- 711084421DA3AA7500F913D6 /* FBXPath.h */,
2016
- 711084431DA3AA7500F913D6 /* FBXPath.m */,
2017
- 71B2E0012733FB970074B001 /* FBXPathExtensions.h */,
2018
- 71B2E0022733FB970074B002 /* FBXPathExtensions.m */,
2019
- EE6B64FB1D0F86EF00E85F5D /* XCTestPrivateSymbols.h */,
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 = 13.0;
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 = 13.0;
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 = 13.0;
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 = 13.0;
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 = 13.0;
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 = 13.0;
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>13.3.0</string>
18
+ <string>14.1.0</string>
19
19
  <key>CFBundleSignature</key>
20
20
  <string>????</string>
21
21
  <key>CFBundleVersion</key>
22
- <string>13.3.0</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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-webdriveragent",
3
- "version": "13.3.0",
3
+ "version": "14.1.0",
4
4
  "description": "Package bundling WebDriverAgent",
5
5
  "main": "./build/lib/index.js",
6
6
  "types": "./build/lib/index.d.ts",