appium-webdriveragent 16.12.1 → 16.12.3

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,15 @@
1
+ ## [16.12.3](https://github.com/appium/WebDriverAgent/compare/v16.12.2...v16.12.3) (2026-09-04)
2
+
3
+ ### Bug Fixes
4
+
5
+ * resolve key name lookup for dictionary-form keyboardInput keys ([#1247](https://github.com/appium/WebDriverAgent/issues/1247)) ([f40bac6](https://github.com/appium/WebDriverAgent/commit/f40bac6ea77f6220883fe4437ee63e51fe44d74f))
6
+
7
+ ## [16.12.2](https://github.com/appium/WebDriverAgent/compare/v16.12.1...v16.12.2) (2026-09-03)
8
+
9
+ ### Bug Fixes
10
+
11
+ * allow pause action items to appear before any pointer movement ([#1246](https://github.com/appium/WebDriverAgent/issues/1246)) ([282478a](https://github.com/appium/WebDriverAgent/commit/282478a2e631501fd904b0675717123c779d9b84))
12
+
1
13
  ## [16.12.1](https://github.com/appium/WebDriverAgent/compare/v16.12.0...v16.12.1) (2026-09-01)
2
14
 
3
15
  ### Miscellaneous Chores
@@ -118,6 +118,7 @@
118
118
  205E75731851D363B53A61DE /* UITestingUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7FD1CAEE048008C271F /* UITestingUITests.m */; };
119
119
  208F3FB46E41B0A1C87B8800 /* FBScreenshot.m in Sources */ = {isa = PBXBuildFile; fileRef = 71C9EAAB25E8415A00470CD8 /* FBScreenshot.m */; };
120
120
  2112EC67BDFFA4A0B2CF24EB /* RouteRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = D585660F7A04651223F29B07 /* RouteRequest.h */; };
121
+ 21C0068C990412E75A135DD4 /* FBCustomCommandsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B817F776DE7106D3B7B1C049 /* FBCustomCommandsTests.m */; };
121
122
  2238B4FC5C7DCD4B4215444D /* XCTMessagingRole_ProtectedResourceAuthorization-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = CCCBEAE654102DBB1C8C22CD /* XCTMessagingRole_ProtectedResourceAuthorization-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
122
123
  227E3F36FAA2C3881F89FD81 /* WDAClickIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C878996F07A9B26E66FC4EAC /* WDAClickIntegrationTests.swift */; };
123
124
  229F9F5B85C1255447495847 /* XCUIApplicationAutomationSessionProviding-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 603D97F0F9A5B9D4E6442BF2 /* XCUIApplicationAutomationSessionProviding-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -604,7 +605,6 @@
604
605
  716F0DA12A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 716F0D9F2A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h */; };
605
606
  716F0DA32A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 716F0DA02A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.m */; };
606
607
  716F0DA62A17323300CDD977 /* NSDictionaryFBUtf8SafeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 716F0DA52A17323300CDD977 /* NSDictionaryFBUtf8SafeTests.m */; };
607
- E82332D32C4E06280CBE3F4C /* FBResponseJSONPayloadTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F5C37472190A686297D3534 /* FBResponseJSONPayloadTests.m */; };
608
608
  7182A87F3CAA27F71B624AD2 /* XCTRunnerAutomationSession-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 01AF8E73DD47455B4854E470 /* XCTRunnerAutomationSession-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
609
609
  718F49C8230844330045FE8B /* FBProtocolHelpersTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 718F49C7230844330045FE8B /* FBProtocolHelpersTests.m */; };
610
610
  718F49C923087ACF0045FE8B /* FBProtocolHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 71B155DD23080CA600646AFB /* FBProtocolHelpers.h */; };
@@ -840,6 +840,7 @@
840
840
  9E914062BD3388A4F3B8100B /* FBXPathExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 71B2E0022733FB970074B002 /* FBXPathExtensions.m */; };
841
841
  9E97481489FB2345F690578E /* XCTMessagingRole_HIDEventRecording-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 94D7F0C1E30FBDB5D2583908 /* XCTMessagingRole_HIDEventRecording-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
842
842
  9F9218F11A1D06F8DCC8308B /* FBXCElementSnapshotWrapper+Helpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A5A287CA444003243C6 /* FBXCElementSnapshotWrapper+Helpers.m */; };
843
+ A09D847635CA4C155583B967 /* FBXCAXClientProxyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6231A764C3FAAB29B87CD987 /* FBXCAXClientProxyTests.m */; };
843
844
  A0A7AB48F1A3AEEC70AF92D7 /* XCTMessagingRole_ForcePressureSupportQuerying-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = AA2351C66A4616534FB81AE4 /* XCTMessagingRole_ForcePressureSupportQuerying-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
844
845
  A14687C1A2FC70A2356B7839 /* XCUIApplicationImplReporter-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 221BC403F42F61DDB1F11DD0 /* XCUIApplicationImplReporter-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
845
846
  A14CB090646BCB0B50F213CF /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D7DD32943CAC7838F942ED5 /* ViewController.m */; };
@@ -940,6 +941,7 @@
940
941
  C22CA4AEE1C7395AE82B3BD3 /* XCTMessagingRole_PerformanceMeasurementReporting-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 2B650ADFEEA2369A10F6C1F1 /* XCTMessagingRole_PerformanceMeasurementReporting-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
941
942
  C2F6BB3D8A49F762E5172768 /* libxml2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 7155B419224D5B460042A993 /* libxml2.tbd */; };
942
943
  C309FAE89D050C90496FB87B /* XCTRemoteSignpostListenerProxy-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E47AA1A44A4A3C6EDCB6804 /* XCTRemoteSignpostListenerProxy-Protocol.h */; };
944
+ C312172CE7EE9B10B7A3034B /* FBHTTPServerSessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FB741D78562232A78902B374 /* FBHTTPServerSessionTests.m */; };
943
945
  C3A3578B56BF260A77EB1ECF /* XCUIAlertMonitoring-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = DB5797DE5A0B4E7EE3D166F7 /* XCUIAlertMonitoring-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
944
946
  C3E6942879518EC529341A25 /* XCTRemoteSignpostListenerProxy-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E47AA1A44A4A3C6EDCB6804 /* XCTRemoteSignpostListenerProxy-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
945
947
  C3F7218DAB6B07E34AFDDF44 /* WatchSpikeApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE921136A147FD01D630869 /* WatchSpikeApp.swift */; };
@@ -1017,6 +1019,7 @@
1017
1019
  DE2D708340ED70EBF9244D0F /* NSDictionary+FBUtf8SafeDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 716F0D9F2A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h */; };
1018
1020
  DE75F01A64FBC6A58012E6B4 /* FBXCElementSnapshotDouble.m in Sources */ = {isa = PBXBuildFile; fileRef = F46F78706C5157469122F730 /* FBXCElementSnapshotDouble.m */; };
1019
1021
  DF0FF8388E4C4CFDD1746BF7 /* XCTRunnerIDESessionDelegate-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 8A5EC96F8F1C3888B9E24FAA /* XCTRunnerIDESessionDelegate-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
1022
+ DF82F4A8758B79DD91FA20CC /* FBHTTPServerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 76B7399DDF52C85A21433C1D /* FBHTTPServerTests.m */; };
1020
1023
  DFB9638AF3480053CA39AB3C /* XCUIElement+FBVisibleFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 71AE3CF52D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.h */; };
1021
1024
  DFC01347FC6A5308D5C6765D /* XCTMessagingRole_MemoryTesting-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 13D863EAE7F6F8B7E42D99B9 /* XCTMessagingRole_MemoryTesting-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
1022
1025
  E046D4602540FA7272DCBCB4 /* XCUIElement+FBWebDriverAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = EEE376481D59FAE900ED88DD /* XCUIElement+FBWebDriverAttributes.m */; };
@@ -1039,6 +1042,7 @@
1039
1042
  E66195839119DC5A8BB7A5D9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD1ABD1093739852B52C472B /* Foundation.framework */; };
1040
1043
  E6B214145FE46BBFD824FAE7 /* FBMathUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = EE1888381DA661C400307AA8 /* FBMathUtils.h */; };
1041
1044
  E78F581F8E7530B24AC31A8B /* XCTMessagingRole_UIAutomation-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 92182E4007B37665AB8CD88E /* XCTMessagingRole_UIAutomation-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
1045
+ E82332D32C4E06280CBE3F4C /* FBResponseJSONPayloadTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F5C37472190A686297D3534 /* FBResponseJSONPayloadTests.m */; };
1042
1046
  E8E894CD81C41AC4467A4F4C /* XCTCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = DB5400B170F08C71779CCD0E /* XCTCapabilities.h */; settings = {ATTRIBUTES = (Public, ); }; };
1043
1047
  E8E917CF8B3ADB4F24CD0B96 /* _TtC10XCTestCore19XCTReportingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DFEF3D0F3F006AC53F9E525 /* _TtC10XCTestCore19XCTReportingContext.h */; settings = {ATTRIBUTES = (Public, ); }; };
1044
1048
  E8FE8448E0118775E7C789CC /* FBXMLGenerationOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 714D88CA2733FB970074A925 /* FBXMLGenerationOptions.h */; };
@@ -1158,7 +1162,6 @@
1158
1162
  EE3A18661CDE734B00DE4205 /* FBKeyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = EE3A18641CDE734B00DE4205 /* FBKeyboard.h */; settings = {ATTRIBUTES = (Public, ); }; };
1159
1163
  EE3A18671CDE734B00DE4205 /* FBKeyboard.m in Sources */ = {isa = PBXBuildFile; fileRef = EE3A18651CDE734B00DE4205 /* FBKeyboard.m */; };
1160
1164
  EE3F8CFE1D08AA17006F02CE /* FBRunLoopSpinnerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EE3F8CFD1D08AA17006F02CE /* FBRunLoopSpinnerTests.m */; };
1161
- A09D847635CA4C155583B967 /* FBXCAXClientProxyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6231A764C3FAAB29B87CD987 /* FBXCAXClientProxyTests.m */; };
1162
1165
  EE3F8D001D08B05F006F02CE /* FBElementTypeTransformerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EE3F8CFF1D08B05F006F02CE /* FBElementTypeTransformerTests.m */; };
1163
1166
  EE5095E51EBCC9090028E2FE /* FBTypingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = AD76723F1D6B826F00610457 /* FBTypingTest.m */; };
1164
1167
  EE5095EB1EBCC9090028E2FE /* XCElementSnapshotHitPointTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EE006EB21EBA1C7B006900A4 /* XCElementSnapshotHitPointTests.m */; };
@@ -1191,8 +1194,6 @@
1191
1194
  EE8DDD7F20C5733C004D4925 /* XCUIElement+FBForceTouch.h in Headers */ = {isa = PBXBuildFile; fileRef = EE8DDD7D20C5733C004D4925 /* XCUIElement+FBForceTouch.h */; settings = {ATTRIBUTES = (Public, ); }; };
1192
1195
  EE9AB8011CAEE048008C271F /* UITestingUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7FD1CAEE048008C271F /* UITestingUITests.m */; };
1193
1196
  EE9B76591CF7987800275851 /* FBRouteTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9B76571CF7987300275851 /* FBRouteTests.m */; };
1194
- C312172CE7EE9B10B7A3034B /* FBHTTPServerSessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FB741D78562232A78902B374 /* FBHTTPServerSessionTests.m */; };
1195
- DF82F4A8758B79DD91FA20CC /* FBHTTPServerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 76B7399DDF52C85A21433C1D /* FBHTTPServerTests.m */; };
1196
1197
  EE9B768E1CF7997600275851 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9B76831CF7997600275851 /* AppDelegate.m */; };
1197
1198
  EE9B768F1CF7997600275851 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9B76851CF7997600275851 /* ViewController.m */; };
1198
1199
  EE9B76911CF7997600275851 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9B76871CF7997600275851 /* main.m */; };
@@ -1478,6 +1479,7 @@
1478
1479
  3BA71BCF1FDA482419CA8596 /* XCUIPlatformApplicationServicesProviding-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCUIPlatformApplicationServicesProviding-Protocol.h"; sourceTree = "<group>"; };
1479
1480
  3C710FE3AB9E9C22BD2A9E84 /* XCUIApplicationProcessManaging-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCUIApplicationProcessManaging-Protocol.h"; sourceTree = "<group>"; };
1480
1481
  3DD2F42015E89D253EA57F63 /* XCUIRemoteAccessibilityInterface-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCUIRemoteAccessibilityInterface-Protocol.h"; sourceTree = "<group>"; };
1482
+ 3F5C37472190A686297D3534 /* FBResponseJSONPayloadTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBResponseJSONPayloadTests.m; sourceTree = "<group>"; };
1481
1483
  42D2B5A0C490D9698C2A87A9 /* XCTMacCatalystStatusProviding-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCTMacCatalystStatusProviding-Protocol.h"; sourceTree = "<group>"; };
1482
1484
  42F7AB68482BA168011C52EA /* XCTTestSelection.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = XCTTestSelection.h; sourceTree = "<group>"; };
1483
1485
  43FCB89739438814F43BCA24 /* XCUIApplicationProcessDelegate-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCUIApplicationProcessDelegate-Protocol.h"; sourceTree = "<group>"; };
@@ -1498,6 +1500,7 @@
1498
1500
  5CF2F53B94CC13C628FC7760 /* XCUIDeviceAutomationModeInterface-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCUIDeviceAutomationModeInterface-Protocol.h"; sourceTree = "<group>"; };
1499
1501
  5D7DD32943CAC7838F942ED5 /* ViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
1500
1502
  603D97F0F9A5B9D4E6442BF2 /* XCUIApplicationAutomationSessionProviding-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCUIApplicationAutomationSessionProviding-Protocol.h"; sourceTree = "<group>"; };
1503
+ 6231A764C3FAAB29B87CD987 /* FBXCAXClientProxyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXCAXClientProxyTests.m; sourceTree = "<group>"; };
1501
1504
  62A682C55077710D1D90ABC3 /* XCTMessagingRole_CapabilityExchange-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_CapabilityExchange-Protocol.h"; sourceTree = "<group>"; };
1502
1505
  631B523421F6174300625362 /* FBImageProcessorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBImageProcessorTests.m; sourceTree = "<group>"; };
1503
1506
  633E904A220DEE7F007CADF9 /* XCUIApplicationProcessDelay.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCUIApplicationProcessDelay.h; sourceTree = "<group>"; };
@@ -1599,7 +1602,6 @@
1599
1602
  716F0D9F2A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+FBUtf8SafeDictionary.h"; sourceTree = "<group>"; };
1600
1603
  716F0DA02A16CA1000CDD977 /* NSDictionary+FBUtf8SafeDictionary.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+FBUtf8SafeDictionary.m"; sourceTree = "<group>"; };
1601
1604
  716F0DA52A17323300CDD977 /* NSDictionaryFBUtf8SafeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSDictionaryFBUtf8SafeTests.m; sourceTree = "<group>"; };
1602
- 3F5C37472190A686297D3534 /* FBResponseJSONPayloadTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBResponseJSONPayloadTests.m; sourceTree = "<group>"; };
1603
1605
  717C0D702518ED2800CAA6EC /* TVOSSettings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = TVOSSettings.xcconfig; sourceTree = "<group>"; };
1604
1606
  717C0D862518ED7000CAA6EC /* TVOSTestSettings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = TVOSTestSettings.xcconfig; sourceTree = "<group>"; };
1605
1607
  7183E8C2B556594311CB8898 /* XCUIRemoteSiriInterface-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCUIRemoteSiriInterface-Protocol.h"; sourceTree = "<group>"; };
@@ -1676,6 +1678,7 @@
1676
1678
  75438FC693C39052C82C27DB /* XCUIApplicationRegistry.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = XCUIApplicationRegistry.h; sourceTree = "<group>"; };
1677
1679
  758FC0D745C185A2C28BEDA1 /* IntegrationApp_watchOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IntegrationApp_watchOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
1678
1680
  75F677B5B7737E7E1F321C20 /* WDAScreenshotAndSourceIntegrationTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WDAScreenshotAndSourceIntegrationTests.swift; sourceTree = "<group>"; };
1681
+ 76B7399DDF52C85A21433C1D /* FBHTTPServerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBHTTPServerTests.m; sourceTree = "<group>"; };
1679
1682
  7AA21CEBA6E92AAC73FB6A48 /* XCTAggregateSuiteRunStatistics.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = XCTAggregateSuiteRunStatistics.h; sourceTree = "<group>"; };
1680
1683
  7CBAA574F7786985E01D0B6F /* XCTHarnessEventReporting-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCTHarnessEventReporting-Protocol.h"; sourceTree = "<group>"; };
1681
1684
  7E079E00FE148476F94BC42F /* XCTTestIdentifierSet.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = XCTTestIdentifierSet.h; sourceTree = "<group>"; };
@@ -1741,6 +1744,7 @@
1741
1744
  B38AC76FAF9275974F272DE9 /* XCUIEventRecording-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCUIEventRecording-Protocol.h"; sourceTree = "<group>"; };
1742
1745
  B3FDA51EB36F03592BF48762 /* XCTMeasureOptions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = XCTMeasureOptions.h; sourceTree = "<group>"; };
1743
1746
  B43D656732067585371ADD31 /* XCTMessagingRole_ProcessMonitoring-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_ProcessMonitoring-Protocol.h"; sourceTree = "<group>"; };
1747
+ B817F776DE7106D3B7B1C049 /* FBCustomCommandsTests.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FBCustomCommandsTests.m; sourceTree = "<group>"; };
1744
1748
  B8A163261EFA440E42CA6AC1 /* XCTRunnerDaemonSessionUIAutomationDelegate-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCTRunnerDaemonSessionUIAutomationDelegate-Protocol.h"; sourceTree = "<group>"; };
1745
1749
  B98A9F937EF98D6359FCCC7A /* XCTRuntimeIssueDetectionPolicy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = XCTRuntimeIssueDetectionPolicy.h; sourceTree = "<group>"; };
1746
1750
  BCED63DFD03326F6351165FE /* WDAFindIntegrationTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = WDAFindIntegrationTests.swift; sourceTree = "<group>"; };
@@ -1829,7 +1833,6 @@
1829
1833
  EE3A18641CDE734B00DE4205 /* FBKeyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FBKeyboard.h; path = WebDriverAgentLib/Utilities/FBKeyboard.h; sourceTree = SOURCE_ROOT; };
1830
1834
  EE3A18651CDE734B00DE4205 /* FBKeyboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FBKeyboard.m; path = WebDriverAgentLib/Utilities/FBKeyboard.m; sourceTree = SOURCE_ROOT; };
1831
1835
  EE3F8CFD1D08AA17006F02CE /* FBRunLoopSpinnerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBRunLoopSpinnerTests.m; sourceTree = "<group>"; };
1832
- 6231A764C3FAAB29B87CD987 /* FBXCAXClientProxyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXCAXClientProxyTests.m; sourceTree = "<group>"; };
1833
1836
  EE3F8CFF1D08B05F006F02CE /* FBElementTypeTransformerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBElementTypeTransformerTests.m; sourceTree = "<group>"; };
1834
1837
  EE5095FE1EBCC9090028E2FE /* IntegrationTests_2.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IntegrationTests_2.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
1835
1838
  EE55B3221D1D5388003AAAEC /* FBTableDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBTableDataSource.h; sourceTree = "<group>"; };
@@ -1909,8 +1912,6 @@
1909
1912
  EE9B75D41CF7956C00275851 /* IntegrationApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IntegrationApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
1910
1913
  EE9B75EC1CF7956C00275851 /* IntegrationTests_1.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IntegrationTests_1.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
1911
1914
  EE9B76571CF7987300275851 /* FBRouteTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBRouteTests.m; sourceTree = "<group>"; };
1912
- FB741D78562232A78902B374 /* FBHTTPServerSessionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBHTTPServerSessionTests.m; sourceTree = "<group>"; };
1913
- 76B7399DDF52C85A21433C1D /* FBHTTPServerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBHTTPServerTests.m; sourceTree = "<group>"; };
1914
1915
  EE9B76581CF7987300275851 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
1915
1916
  EE9B76821CF7997600275851 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
1916
1917
  EE9B76831CF7997600275851 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -1954,6 +1955,7 @@
1954
1955
  F46F78706C5157469122F730 /* FBXCElementSnapshotDouble.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXCElementSnapshotDouble.m; sourceTree = "<group>"; };
1955
1956
  F59CD6D22EF16E5E00F91287 /* XCUIElement+FBCustomActions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBCustomActions.h"; sourceTree = "<group>"; };
1956
1957
  F59CD6D32EF16E5E00F91287 /* XCUIElement+FBCustomActions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBCustomActions.m"; sourceTree = "<group>"; };
1958
+ FB741D78562232A78902B374 /* FBHTTPServerSessionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBHTTPServerSessionTests.m; sourceTree = "<group>"; };
1957
1959
  FCD1815F2BF21CA0936B04E1 /* XCTMessagingRole_SiriAutomation-Protocol.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_SiriAutomation-Protocol.h"; sourceTree = "<group>"; };
1958
1960
  FDB15E393EA0850C004D26B2 /* XCTScreenCapturePolicy.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = XCTScreenCapturePolicy.h; sourceTree = "<group>"; };
1959
1961
  FF8E3B470FC9639D5F18E2EA /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -2697,6 +2699,7 @@
2697
2699
  7139145B1DF01A12005896C2 /* NSExpressionFBFormatTests.m */,
2698
2700
  71A224E71DE326C500844D55 /* NSPredicateFBFormatTests.m */,
2699
2701
  713914591DF01989005896C2 /* XCUIElementHelpersTests.m */,
2702
+ B817F776DE7106D3B7B1C049 /* FBCustomCommandsTests.m */,
2700
2703
  );
2701
2704
  path = UnitTests;
2702
2705
  sourceTree = "<group>";
@@ -4834,6 +4837,7 @@
4834
4837
  EE6A89261D0B19E60083E92B /* FBSessionTests.m in Sources */,
4835
4838
  71A7EAFC1E229302001DA4F2 /* FBClassChainTests.m in Sources */,
4836
4839
  EE18883D1DA663EB00307AA8 /* FBMathUtilsTests.m in Sources */,
4840
+ 21C0068C990412E75A135DD4 /* FBCustomCommandsTests.m in Sources */,
4837
4841
  );
4838
4842
  runOnlyForDeploymentPostprocessing = 0;
4839
4843
  };
@@ -676,7 +676,7 @@
676
676
  if ([modifiers isKindOfClass:NSNumber.class]) {
677
677
  modifierFlags = [(NSNumber *)modifiers unsignedIntValue];
678
678
  }
679
- NSString *keyValue = [FBKeyboard keyValueForName:item] ?: key;
679
+ NSString *keyValue = [FBKeyboard keyValueForName:key] ?: key;
680
680
  [destination typeKey:keyValue modifierFlags:(XCUIKeyModifierFlags)modifierFlags];
681
681
  } else {
682
682
  NSString *message = @"All items of the 'keys' array must be either dictionaries or strings";
@@ -15,11 +15,11 @@
15
15
  <key>CFBundlePackageType</key>
16
16
  <string>FMWK</string>
17
17
  <key>CFBundleShortVersionString</key>
18
- <string>16.12.1</string>
18
+ <string>16.12.3</string>
19
19
  <key>CFBundleSignature</key>
20
20
  <string>????</string>
21
21
  <key>CFBundleVersion</key>
22
- <string>16.12.1</string>
22
+ <string>16.12.3</string>
23
23
  <key>NSPrincipalClass</key>
24
24
  <string/>
25
25
  </dict>
@@ -133,7 +133,8 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
133
133
  }
134
134
  self.duration = durationObj.doubleValue;
135
135
  XCUICoordinate *position = [self positionWithError:error];
136
- if (nil == position) {
136
+ // A pause may legally have no position yet (nil position, no error set)
137
+ if (nil == position && error && nil != *error) {
137
138
  return nil;
138
139
  }
139
140
  self.atPosition = position;
@@ -143,7 +144,7 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
143
144
 
144
145
  - (nullable XCUICoordinate *)positionWithError:(NSError **)error
145
146
  {
146
- if (nil == self.previousItem) {
147
+ if (nil == self.previousItem || nil == self.previousItem.atPosition) {
147
148
  NSString *errorDescription = [NSString stringWithFormat:@"The '%@' action item must be preceded by %@ item", self.actionItem, FB_ACTION_ITEM_TYPE_POINTER_MOVE];
148
149
  if (error) {
149
150
  *error = [[FBErrorBuilder.builder withDescription:errorDescription] build];
@@ -205,9 +206,19 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
205
206
  currentItemIndex:(NSUInteger)currentItemIndex
206
207
  error:(NSError **)error
207
208
  {
208
- if (nil != eventPath && currentItemIndex == 1) {
209
+ if (nil != eventPath && currentItemIndex >= 1) {
209
210
  FBW3CGestureItem *preceedingItem = [allItems objectAtIndex:currentItemIndex - 1];
210
- if ([preceedingItem isKindOfClass:FBPointerMoveItem.class]) {
211
+ // Only skip creating a new touch if the preceding pointerMove is the one that
212
+ // implicitly opened this touch, i.e. nothing but (possibly zero-duration) pauses
213
+ // came before it. Pauses never create an event path themselves.
214
+ BOOL isPreceedingMoveTheFirstRealItem = YES;
215
+ for (NSInteger index = (NSInteger)currentItemIndex - 2; index >= 0; index--) {
216
+ if (![[allItems objectAtIndex:index] isKindOfClass:FBPointerPauseItem.class]) {
217
+ isPreceedingMoveTheFirstRealItem = NO;
218
+ break;
219
+ }
220
+ }
221
+ if ([preceedingItem isKindOfClass:FBPointerMoveItem.class] && isPreceedingMoveTheFirstRealItem) {
211
222
  return @[];
212
223
  }
213
224
  }
@@ -280,7 +291,7 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
280
291
  }
281
292
 
282
293
  // origin == FB_ORIGIN_TYPE_POINTER
283
- if (nil == self.previousItem) {
294
+ if (nil == self.previousItem || nil == self.previousItem.atPosition) {
284
295
  NSString *errorDescription = [NSString stringWithFormat:@"There is no previous item for '%@' action item, however %@ is set to '%@'", self.actionItem, FB_ACTION_ITEM_KEY_ORIGIN, FB_ORIGIN_TYPE_POINTER];
285
296
  if (error) {
286
297
  *error = [[FBErrorBuilder.builder withDescription:errorDescription] build];
@@ -320,6 +331,13 @@ static NSString *const FB_KEY_ACTIONS = @"actions";
320
331
  return FB_ACTION_ITEM_TYPE_PAUSE;
321
332
  }
322
333
 
334
+ - (nullable XCUICoordinate *)positionWithError:(NSError **)error
335
+ {
336
+ // A pause has no position of its own; proxy whatever real move preceded
337
+ // it, or nil (not a fabricated point) if none has run yet
338
+ return self.previousItem.atPosition;
339
+ }
340
+
323
341
  - (NSArray<XCPointerEventPath *> *)addToEventPath:(XCPointerEventPath *)eventPath
324
342
  allItems:(NSArray *)allItems
325
343
  currentItemIndex:(NSUInteger)currentItemIndex
@@ -120,5 +120,40 @@
120
120
  [self verifyGesture:gesture orientation:UIDeviceOrientationPortrait];
121
121
  }
122
122
 
123
+ - (void)testTwoFingersTapWithLeadingZeroDurationPause
124
+ {
125
+ // Selenium clients pad shorter action sequences with a zero-duration pause
126
+ // so that all pointers/devices end up with the same number of ticks
127
+ XCUIElement *element = self.testedApplication.buttons[FBShowAlertButtonName];
128
+ NSArray<NSDictionary<NSString *, id> *> *gesture =
129
+ @[
130
+ @{
131
+ @"type": @"pointer",
132
+ @"id": @"finger1",
133
+ @"parameters": @{@"pointerType": @"touch"},
134
+ @"actions": @[
135
+ @{@"type": @"pointerMove", @"duration": @0, @"origin": element, @"x": @0, @"y": @0},
136
+ @{@"type": @"pointerDown"},
137
+ @{@"type": @"pause", @"duration": @100},
138
+ @{@"type": @"pointerUp"},
139
+ ],
140
+ },
141
+ @{
142
+ @"type": @"pointer",
143
+ @"id": @"finger2",
144
+ @"parameters": @{@"pointerType": @"touch"},
145
+ @"actions": @[
146
+ @{@"type": @"pause", @"duration": @0},
147
+ @{@"type": @"pointerMove", @"duration": @0, @"origin": element, @"x": @0, @"y": @0},
148
+ @{@"type": @"pointerDown"},
149
+ @{@"type": @"pause", @"duration": @100},
150
+ @{@"type": @"pointerUp"},
151
+ ],
152
+ },
153
+ ];
154
+
155
+ [self verifyGesture:gesture orientation:UIDeviceOrientationPortrait];
156
+ }
157
+
123
158
  @end
124
159
 
@@ -17,6 +17,10 @@
17
17
  #import "XCUIDevice+FBRotation.h"
18
18
  #import "FBRunLoopSpinner.h"
19
19
  #import "FBXCodeCompatibility.h"
20
+ #import "FBW3CActionsSynthesizer.h"
21
+ #import "XCSynthesizedEventRecord.h"
22
+ #import "XCPointerEventPath.h"
23
+ #import "XCPointerEvent.h"
20
24
 
21
25
  @interface FBW3CTouchActionsIntegrationTestsPart1 : FBIntegrationTestCase
22
26
  @end
@@ -185,14 +189,13 @@
185
189
  },
186
190
  ],
187
191
 
188
- // Chain element where action items start with an incorrect item
192
+ // Chain element where pointerMove action item does not contain coordinates
189
193
  @[@{
190
194
  @"type": @"pointer",
191
195
  @"id": @"finger1",
192
196
  @"parameters": @{@"pointerType": @"touch"},
193
197
  @"actions": @[
194
- @{@"type": @"pause", @"duration": @100},
195
- @{@"type": @"pointerMove", @"duration": @0, @"x": @1, @"y": @1},
198
+ @{@"type": @"pointerMove", @"duration": @0},
196
199
  @{@"type": @"pointerDown"},
197
200
  @{@"type": @"pause", @"duration": @100},
198
201
  @{@"type": @"pointerUp"},
@@ -200,13 +203,13 @@
200
203
  },
201
204
  ],
202
205
 
203
- // Chain element where pointerMove action item does not contain coordinates
206
+ // Chain element where pointerMove action item cannot use coordinates of the previous item
204
207
  @[@{
205
208
  @"type": @"pointer",
206
209
  @"id": @"finger1",
207
210
  @"parameters": @{@"pointerType": @"touch"},
208
211
  @"actions": @[
209
- @{@"type": @"pointerMove", @"duration": @0},
212
+ @{@"type": @"pointerMove", @"duration": @0, @"origin": @"pointer"},
210
213
  @{@"type": @"pointerDown"},
211
214
  @{@"type": @"pause", @"duration": @100},
212
215
  @{@"type": @"pointerUp"},
@@ -214,34 +217,51 @@
214
217
  },
215
218
  ],
216
219
 
217
- // Chain element where pointerMove action item cannot use coordinates of the previous item
220
+ // Chain element where action items contains negative duration
218
221
  @[@{
219
222
  @"type": @"pointer",
220
223
  @"id": @"finger1",
221
224
  @"parameters": @{@"pointerType": @"touch"},
222
225
  @"actions": @[
223
- @{@"type": @"pointerMove", @"duration": @0, @"origin": @"pointer"},
226
+ @{@"type": @"pointerMove", @"duration": @0, @"x": @1, @"y": @1},
224
227
  @{@"type": @"pointerDown"},
225
- @{@"type": @"pause", @"duration": @100},
228
+ @{@"type": @"pause", @"duration": @-100},
226
229
  @{@"type": @"pointerUp"},
227
230
  ],
228
231
  },
229
232
  ],
230
233
 
231
- // Chain element where action items contains negative duration
234
+ // Chain element where a leading pause is followed directly by pointerDown,
235
+ // with no real pointerMove ever establishing a position
232
236
  @[@{
233
237
  @"type": @"pointer",
234
238
  @"id": @"finger1",
235
239
  @"parameters": @{@"pointerType": @"touch"},
236
240
  @"actions": @[
237
- @{@"type": @"pointerMove", @"duration": @0, @"x": @1, @"y": @1},
241
+ @{@"type": @"pause", @"duration": @0},
238
242
  @{@"type": @"pointerDown"},
239
- @{@"type": @"pause", @"duration": @-100},
243
+ @{@"type": @"pause", @"duration": @100},
240
244
  @{@"type": @"pointerUp"},
241
245
  ],
242
246
  },
243
247
  ],
244
-
248
+
249
+ // Chain element where a leading pause is followed directly by a relative
250
+ // pointerMove, with no real preceding position to be relative to
251
+ @[@{
252
+ @"type": @"pointer",
253
+ @"id": @"finger1",
254
+ @"parameters": @{@"pointerType": @"touch"},
255
+ @"actions": @[
256
+ @{@"type": @"pause", @"duration": @0},
257
+ @{@"type": @"pointerMove", @"duration": @0, @"origin": @"pointer"},
258
+ @{@"type": @"pointerDown"},
259
+ @{@"type": @"pause", @"duration": @100},
260
+ @{@"type": @"pointerUp"},
261
+ ],
262
+ },
263
+ ],
264
+
245
265
  // Chain element where action items start with an incorrect one, because the correct one is canceled
246
266
  @[@{
247
267
  @"type": @"pointer",
@@ -299,6 +319,69 @@
299
319
  [self verifyGesture:gesture orientation:UIDeviceOrientationPortrait];
300
320
  }
301
321
 
322
+ - (void)testLeadingZeroDurationPauseDoesNotAddExtraTouch
323
+ {
324
+ // A leading pause must not defeat the down-after-move dedup logic in
325
+ // FBPointerDownItem and make WDA synthesize a second, separate touch-down
326
+ // for the same finger. Inspect the actual synthesized XCTest event stream
327
+ // (without dispatching it) rather than only checking the gesture's visible
328
+ // side effect, since a duplicate touch at the same point may still produce
329
+ // the same visible outcome.
330
+ XCUIElement *element = self.testedApplication.buttons[FBShowAlertButtonName];
331
+ NSDictionary<NSString *, id> *(^sequenceWithLeadingPause)(BOOL) = ^NSDictionary<NSString *, id> *(BOOL withLeadingPause) {
332
+ NSMutableArray<NSDictionary<NSString *, id> *> *actions = [NSMutableArray array];
333
+ if (withLeadingPause) {
334
+ [actions addObject:@{@"type": @"pause", @"duration": @0}];
335
+ }
336
+ [actions addObjectsFromArray:@[
337
+ @{@"type": @"pointerMove", @"duration": @0, @"origin": element, @"x": @0, @"y": @0},
338
+ @{@"type": @"pointerDown"},
339
+ @{@"type": @"pause", @"duration": @100},
340
+ @{@"type": @"pointerUp"},
341
+ ]];
342
+ return @{
343
+ @"type": @"pointer",
344
+ @"id": @"finger1",
345
+ @"parameters": @{@"pointerType": @"touch"},
346
+ @"actions": actions.copy,
347
+ };
348
+ };
349
+
350
+ NSError *error;
351
+ FBW3CActionsSynthesizer *baselineSynthesizer =
352
+ [[FBW3CActionsSynthesizer alloc] initWithActions:@[sequenceWithLeadingPause(NO)]
353
+ forApplication:self.testedApplication
354
+ elementCache:nil
355
+ error:&error];
356
+ XCTAssertNotNil(baselineSynthesizer);
357
+ XCSynthesizedEventRecord *baselineRecord = [baselineSynthesizer synthesizeWithError:&error];
358
+ XCTAssertNotNil(baselineRecord, @"%@", error);
359
+
360
+ FBW3CActionsSynthesizer *pausedSynthesizer =
361
+ [[FBW3CActionsSynthesizer alloc] initWithActions:@[sequenceWithLeadingPause(YES)]
362
+ forApplication:self.testedApplication
363
+ elementCache:nil
364
+ error:&error];
365
+ XCTAssertNotNil(pausedSynthesizer);
366
+ XCSynthesizedEventRecord *pausedRecord = [pausedSynthesizer synthesizeWithError:&error];
367
+ XCTAssertNotNil(pausedRecord, @"%@", error);
368
+
369
+ XCTAssertEqual(baselineRecord.eventPaths.count, (NSUInteger)1);
370
+ XCTAssertEqual(pausedRecord.eventPaths.count, baselineRecord.eventPaths.count);
371
+
372
+ XCPointerEventPath *baselinePath = baselineRecord.eventPaths.firstObject;
373
+ XCPointerEventPath *pausedPath = pausedRecord.eventPaths.firstObject;
374
+ XCTAssertEqual(pausedPath.pointerEvents.count, baselinePath.pointerEvents.count);
375
+ for (NSUInteger i = 0; i < baselinePath.pointerEvents.count; i++) {
376
+ XCPointerEvent *baselineEvent = baselinePath.pointerEvents[i];
377
+ XCPointerEvent *pausedEvent = pausedPath.pointerEvents[i];
378
+ XCTAssertEqual(pausedEvent.eventType, baselineEvent.eventType);
379
+ XCTAssertEqualWithAccuracy(pausedEvent.offset, baselineEvent.offset, 0.001);
380
+ XCTAssertEqualWithAccuracy(pausedEvent.coordinate.x, baselineEvent.coordinate.x, 0.001);
381
+ XCTAssertEqualWithAccuracy(pausedEvent.coordinate.y, baselineEvent.coordinate.y, 0.001);
382
+ }
383
+ }
384
+
302
385
  - (void)testDoubleTap
303
386
  {
304
387
  NSArray<NSDictionary<NSString *, id> *> *gesture =
@@ -45,8 +45,11 @@
45
45
  - (id _Nonnull)fb_standardSnapshot;
46
46
  - (id _Nonnull)fb_customSnapshot;
47
47
  - (nullable id)query;
48
+ - (void)typeKey:(nonnull NSString *)key modifierFlags:(NSUInteger)modifierFlags;
48
49
 
49
50
  // Checks
50
51
  @property (nonatomic, assign, readonly) BOOL didResolve;
52
+ @property (nonatomic, copy, readonly, nonnull) NSArray<NSString *> *typedKeys;
53
+ @property (nonatomic, assign, readonly) NSUInteger lastTypedModifierFlags;
51
54
 
52
55
  @end
@@ -10,6 +10,8 @@
10
10
 
11
11
  @interface XCUIElementDouble ()
12
12
  @property (nonatomic, assign, readwrite) BOOL didResolve;
13
+ @property (nonatomic, copy, readwrite, nonnull) NSArray<NSString *> *typedKeys;
14
+ @property (nonatomic, assign, readwrite) NSUInteger lastTypedModifierFlags;
13
15
  @end
14
16
 
15
17
  @implementation XCUIElementDouble
@@ -48,10 +50,17 @@
48
50
  self.wdType = @"XCUIElementTypeOther";
49
51
  self.wdUID = @"0";
50
52
  self.lastSnapshot = nil;
53
+ self.typedKeys = @[];
51
54
  }
52
55
  return self;
53
56
  }
54
57
 
58
+ - (void)typeKey:(NSString *)key modifierFlags:(NSUInteger)modifierFlags
59
+ {
60
+ self.typedKeys = [self.typedKeys arrayByAddingObject:key];
61
+ self.lastTypedModifierFlags = modifierFlags;
62
+ }
63
+
55
64
  - (id)fb_valueForWDAttributeName:(NSString *)name
56
65
  {
57
66
  return @"test";
@@ -0,0 +1,83 @@
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 "FBCustomCommands.h"
12
+ #import "FBElementCache.h"
13
+ #import "FBRouteRequest-Private.h"
14
+ #import "FBSession.h"
15
+ #import "Doubles/XCUIElementDouble.h"
16
+
17
+ #if !TARGET_OS_TV && __clang_major__ >= 15
18
+
19
+ @interface FBCustomCommands (FBWDATestable)
20
+ + (id<FBResponsePayload>)handleKeyboardInput:(FBRouteRequest *)request;
21
+ @end
22
+
23
+ @interface FBCustomCommandsTests : XCTestCase
24
+ @property (nonatomic, strong) FBSession *session;
25
+ @end
26
+
27
+ @implementation FBCustomCommandsTests
28
+
29
+ - (void)setUp
30
+ {
31
+ [super setUp];
32
+ self.session = [FBSession initWithApplication:nil];
33
+ }
34
+
35
+ - (void)tearDown
36
+ {
37
+ [self.session kill];
38
+ [super tearDown];
39
+ }
40
+
41
+ - (FBRouteRequest *)requestWithElement:(XCUIElementDouble *)element keys:(NSArray *)keys
42
+ {
43
+ // uuid "0" is reserved by handleKeyboardInput: to mean "no element" (use the active application).
44
+ element.wdUID = @"1";
45
+ NSString *uuid = [self.session.elementCache storeElement:(XCUIElement *)element];
46
+ FBRouteRequest *request = [FBRouteRequest routeRequestWithURL:[NSURL URLWithString:@"http://localhost:8100/"]
47
+ parameters:@{@"uuid": uuid}
48
+ arguments:@{@"keys": keys}];
49
+ request.session = self.session;
50
+ return request;
51
+ }
52
+
53
+ - (void)testDictionaryKeyWithConstantNameIsResolved
54
+ {
55
+ XCUIElementDouble *element = XCUIElementDouble.new;
56
+ FBRouteRequest *request = [self requestWithElement:element
57
+ keys:@[@{@"key": @"XCUIKeyboardKeyTab"}]];
58
+ [FBCustomCommands handleKeyboardInput:request];
59
+ XCTAssertEqualObjects(element.typedKeys, @[XCUIKeyboardKeyTab]);
60
+ }
61
+
62
+ - (void)testDictionaryKeyWithLiteralCharacterIsPassedThrough
63
+ {
64
+ XCUIElementDouble *element = XCUIElementDouble.new;
65
+ FBRouteRequest *request = [self requestWithElement:element
66
+ keys:@[@{@"key": @"a"}]];
67
+ [FBCustomCommands handleKeyboardInput:request];
68
+ XCTAssertEqualObjects(element.typedKeys, @[@"a"]);
69
+ }
70
+
71
+ - (void)testDictionaryKeyWithConstantNameAndModifierFlagsIsResolved
72
+ {
73
+ XCUIElementDouble *element = XCUIElementDouble.new;
74
+ FBRouteRequest *request = [self requestWithElement:element
75
+ keys:@[@{@"key": @"XCUIKeyboardKeyTab", @"modifierFlags": @2}]];
76
+ [FBCustomCommands handleKeyboardInput:request];
77
+ XCTAssertEqualObjects(element.typedKeys, @[XCUIKeyboardKeyTab]);
78
+ XCTAssertEqual(element.lastTypedModifierFlags, 2);
79
+ }
80
+
81
+ @end
82
+
83
+ #endif
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appium-webdriveragent",
3
- "version": "16.12.1",
3
+ "version": "16.12.3",
4
4
  "description": "Package bundling WebDriverAgent",
5
5
  "keywords": [
6
6
  "Appium",