appium-webdriveragent 9.9.0 → 9.10.1
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 +19 -7
- package/WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m +5 -0
- package/WebDriverAgentLib/Categories/XCUIElement+FBAccessibility.h +1 -1
- package/WebDriverAgentLib/Categories/XCUIElement+FBIsVisible.h +1 -1
- package/WebDriverAgentLib/Categories/XCUIElement+FBUtilities.h +1 -1
- package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.h +1 -1
- package/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m +17 -0
- package/WebDriverAgentLib/Info.plist +2 -2
- package/WebDriverAgentLib/Routing/FBElement.h +3 -0
- package/WebDriverAgentLib/Utilities/FBAccessibilityTraits.h +21 -0
- package/WebDriverAgentLib/Utilities/FBAccessibilityTraits.m +62 -0
- package/WebDriverAgentLib/Utilities/FBXPath.h +1 -1
- package/WebDriverAgentLib/Utilities/FBXPath.m +24 -7
- package/WebDriverAgentLib/WebDriverAgentLib.h +9 -0
- package/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m +46 -0
- package/WebDriverAgentTests/IntegrationTests/XCUIElementFBFindTests.m +9 -0
- package/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h +2 -0
- package/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m +8 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
## [9.10.1](https://github.com/appium/WebDriverAgent/compare/v9.10.0...v9.10.1) (2025-05-30)
|
|
2
|
+
|
|
3
|
+
### Miscellaneous Chores
|
|
4
|
+
|
|
5
|
+
* Make sure the same import style is used everywhere ([#1024](https://github.com/appium/WebDriverAgent/issues/1024)) ([1c50072](https://github.com/appium/WebDriverAgent/commit/1c50072457a8b82eec3684029386ccfa9432eccc))
|
|
6
|
+
|
|
7
|
+
## [9.10.0](https://github.com/appium/WebDriverAgent/compare/v9.9.0...v9.10.0) (2025-05-27)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Add accessibility traits of the element ([#1020](https://github.com/appium/WebDriverAgent/issues/1020)) ([9465aaf](https://github.com/appium/WebDriverAgent/commit/9465aafd5e81ef57be7f78e9f2e188d3c1ba1bee))
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* Use native snapshots if hittable attribute is requested in xPath ([#1023](https://github.com/appium/WebDriverAgent/issues/1023)) ([49d26cb](https://github.com/appium/WebDriverAgent/commit/49d26cb02a8515d1a1b52b65b7cb65512dfd749b))
|
|
16
|
+
|
|
1
17
|
## [9.9.0](https://github.com/appium/WebDriverAgent/compare/v9.8.0...v9.9.0) (2025-05-26)
|
|
2
18
|
|
|
3
19
|
### Features
|
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
13DE7A4A287C4005003243C6 /* FBXCDeviceEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A47287C4005003243C6 /* FBXCDeviceEvent.h */; };
|
|
22
22
|
13DE7A4B287C4005003243C6 /* FBXCDeviceEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A48287C4005003243C6 /* FBXCDeviceEvent.m */; };
|
|
23
23
|
13DE7A4C287C4005003243C6 /* FBXCDeviceEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A48287C4005003243C6 /* FBXCDeviceEvent.m */; };
|
|
24
|
-
13DE7A4F287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A4D287C46BB003243C6 /* FBXCElementSnapshot.h */; };
|
|
25
|
-
13DE7A50287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A4D287C46BB003243C6 /* FBXCElementSnapshot.h */; };
|
|
24
|
+
13DE7A4F287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A4D287C46BB003243C6 /* FBXCElementSnapshot.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
25
|
+
13DE7A50287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A4D287C46BB003243C6 /* FBXCElementSnapshot.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
26
26
|
13DE7A51287C46BB003243C6 /* FBXCElementSnapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A4E287C46BB003243C6 /* FBXCElementSnapshot.m */; };
|
|
27
27
|
13DE7A52287C46BB003243C6 /* FBXCElementSnapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A4E287C46BB003243C6 /* FBXCElementSnapshot.m */; };
|
|
28
|
-
13DE7A55287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A53287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h */; };
|
|
29
|
-
13DE7A56287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A53287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h */; };
|
|
28
|
+
13DE7A55287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A53287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
29
|
+
13DE7A56287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A53287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
30
30
|
13DE7A57287CA1EC003243C6 /* FBXCElementSnapshotWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A54287CA1EC003243C6 /* FBXCElementSnapshotWrapper.m */; };
|
|
31
31
|
13DE7A58287CA1EC003243C6 /* FBXCElementSnapshotWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 13DE7A54287CA1EC003243C6 /* FBXCElementSnapshotWrapper.m */; };
|
|
32
32
|
13DE7A5B287CA444003243C6 /* FBXCElementSnapshotWrapper+Helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 13DE7A59287CA444003243C6 /* FBXCElementSnapshotWrapper+Helpers.h */; };
|
|
@@ -539,6 +539,10 @@
|
|
|
539
539
|
ADBC39981D07842800327304 /* XCUIElementDouble.m in Sources */ = {isa = PBXBuildFile; fileRef = ADBC39971D07842800327304 /* XCUIElementDouble.m */; };
|
|
540
540
|
ADDA07241D6BB2BF001700AC /* FBScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ADDA07231D6BB2BF001700AC /* FBScrollViewController.m */; };
|
|
541
541
|
ADEF63AF1D09DEBE0070A7E3 /* FBRuntimeUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = ADEF63AE1D09DEBE0070A7E3 /* FBRuntimeUtilsTests.m */; };
|
|
542
|
+
B316351C2DDF0CF5007D9317 /* FBAccessibilityTraits.m in Sources */ = {isa = PBXBuildFile; fileRef = B316351B2DDF0CF5007D9317 /* FBAccessibilityTraits.m */; };
|
|
543
|
+
B316351D2DDF0CF5007D9317 /* FBAccessibilityTraits.m in Sources */ = {isa = PBXBuildFile; fileRef = B316351B2DDF0CF5007D9317 /* FBAccessibilityTraits.m */; };
|
|
544
|
+
B316351F2DDF0D0B007D9317 /* FBAccessibilityTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = B316351E2DDF0D0B007D9317 /* FBAccessibilityTraits.h */; };
|
|
545
|
+
B31635202DDF0D0B007D9317 /* FBAccessibilityTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = B316351E2DDF0D0B007D9317 /* FBAccessibilityTraits.h */; };
|
|
542
546
|
C845206222D5E79400EA68CB /* FBUnattachedAppLauncher.h in Headers */ = {isa = PBXBuildFile; fileRef = C8FB547722D4C1FC00B69954 /* FBUnattachedAppLauncher.h */; };
|
|
543
547
|
C845206322D5E79700EA68CB /* FBUnattachedAppLauncher.m in Sources */ = {isa = PBXBuildFile; fileRef = C8FB547822D4C1FC00B69954 /* FBUnattachedAppLauncher.m */; };
|
|
544
548
|
C8FB547422D3949C00B69954 /* LSApplicationWorkspace.h in Headers */ = {isa = PBXBuildFile; fileRef = C8FB547322D3949C00B69954 /* LSApplicationWorkspace.h */; };
|
|
@@ -1115,6 +1119,8 @@
|
|
|
1115
1119
|
ADDA07221D6BB2BF001700AC /* FBScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBScrollViewController.h; sourceTree = "<group>"; };
|
|
1116
1120
|
ADDA07231D6BB2BF001700AC /* FBScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBScrollViewController.m; sourceTree = "<group>"; };
|
|
1117
1121
|
ADEF63AE1D09DEBE0070A7E3 /* FBRuntimeUtilsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBRuntimeUtilsTests.m; sourceTree = "<group>"; };
|
|
1122
|
+
B316351B2DDF0CF5007D9317 /* FBAccessibilityTraits.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBAccessibilityTraits.m; sourceTree = "<group>"; };
|
|
1123
|
+
B316351E2DDF0D0B007D9317 /* FBAccessibilityTraits.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBAccessibilityTraits.h; sourceTree = "<group>"; };
|
|
1118
1124
|
C8FB547322D3949C00B69954 /* LSApplicationWorkspace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LSApplicationWorkspace.h; sourceTree = "<group>"; };
|
|
1119
1125
|
C8FB547722D4C1FC00B69954 /* FBUnattachedAppLauncher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBUnattachedAppLauncher.h; sourceTree = "<group>"; };
|
|
1120
1126
|
C8FB547822D4C1FC00B69954 /* FBUnattachedAppLauncher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBUnattachedAppLauncher.m; sourceTree = "<group>"; };
|
|
@@ -1979,6 +1985,8 @@
|
|
|
1979
1985
|
EE6B64FC1D0F86EF00E85F5D /* XCTestPrivateSymbols.m */,
|
|
1980
1986
|
633E904A220DEE7F007CADF9 /* XCUIApplicationProcessDelay.h */,
|
|
1981
1987
|
6385F4A5220A40760095BBDB /* XCUIApplicationProcessDelay.m */,
|
|
1988
|
+
B316351B2DDF0CF5007D9317 /* FBAccessibilityTraits.m */,
|
|
1989
|
+
B316351E2DDF0D0B007D9317 /* FBAccessibilityTraits.h */,
|
|
1982
1990
|
);
|
|
1983
1991
|
name = Utilities;
|
|
1984
1992
|
path = WebDriverAgentLib/Utilities;
|
|
@@ -2292,6 +2300,8 @@
|
|
|
2292
2300
|
641EE6392240C5CA00173FCB /* FBRouteRequest.h in Headers */,
|
|
2293
2301
|
648C10AC22AAAD9C00B81B9A /* UIKeyboardImpl.h in Headers */,
|
|
2294
2302
|
718226CD2587443700661B83 /* GCDAsyncSocket.h in Headers */,
|
|
2303
|
+
13DE7A50287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */,
|
|
2304
|
+
13DE7A56287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h in Headers */,
|
|
2295
2305
|
71F3E7D525417FF400E0C22B /* FBSettings.h in Headers */,
|
|
2296
2306
|
641EE63A2240C5CA00173FCB /* XCTest.h in Headers */,
|
|
2297
2307
|
641EE63B2240C5CA00173FCB /* FBAlertsMonitor.h in Headers */,
|
|
@@ -2340,7 +2350,6 @@
|
|
|
2340
2350
|
641EE6632240C5CA00173FCB /* FBUnknownCommands.h in Headers */,
|
|
2341
2351
|
641EE7062240CDCF00173FCB /* XCUIElement+FBTVFocuse.h in Headers */,
|
|
2342
2352
|
71822738258744B800661B83 /* HTTPConnection.h in Headers */,
|
|
2343
|
-
13DE7A56287CA1EC003243C6 /* FBXCElementSnapshotWrapper.h in Headers */,
|
|
2344
2353
|
641EE6642240C5CA00173FCB /* NSPredicate+FBFormat.h in Headers */,
|
|
2345
2354
|
641EE6652240C5CA00173FCB /* UILongPressGestureRecognizer-RecordingAdditions.h in Headers */,
|
|
2346
2355
|
641EE6662240C5CA00173FCB /* XCTestCase.h in Headers */,
|
|
@@ -2420,6 +2429,7 @@
|
|
|
2420
2429
|
641EE6A62240C5CA00173FCB /* FBImageProcessor.h in Headers */,
|
|
2421
2430
|
641EE6A72240C5CA00173FCB /* FBSession-Private.h in Headers */,
|
|
2422
2431
|
641EE6A82240C5CA00173FCB /* NSString+FBXMLSafeString.h in Headers */,
|
|
2432
|
+
B316351F2DDF0D0B007D9317 /* FBAccessibilityTraits.h in Headers */,
|
|
2423
2433
|
64E3502F2AC0B6FE005F3ACB /* NSDictionary+FBUtf8SafeDictionary.h in Headers */,
|
|
2424
2434
|
641EE6A92240C5CA00173FCB /* FBCommandStatus.h in Headers */,
|
|
2425
2435
|
71822702258744A400661B83 /* HTTPResponseProxy.h in Headers */,
|
|
@@ -2501,7 +2511,6 @@
|
|
|
2501
2511
|
641EE6E72240C5CA00173FCB /* XCUIElement+FBFind.h in Headers */,
|
|
2502
2512
|
641EE6E82240C5CA00173FCB /* XCTestManager_ManagerInterface-Protocol.h in Headers */,
|
|
2503
2513
|
641EE6E92240C5CA00173FCB /* FBFailureProofTestCase.h in Headers */,
|
|
2504
|
-
13DE7A50287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */,
|
|
2505
2514
|
641EE6EA2240C5CA00173FCB /* XCTTestRunSessionDelegate-Protocol.h in Headers */,
|
|
2506
2515
|
641EE6EB2240C5CA00173FCB /* XCTestCaseSuite.h in Headers */,
|
|
2507
2516
|
641EE6EC2240C5CA00173FCB /* _XCInternalTestRun.h in Headers */,
|
|
@@ -2572,6 +2581,7 @@
|
|
|
2572
2581
|
EE35AD721E3B77D600A02D78 /* XCUIElementHitPointCoordinate.h in Headers */,
|
|
2573
2582
|
EE35AD3F1E3B77D600A02D78 /* XCTDarwinNotificationExpectation.h in Headers */,
|
|
2574
2583
|
EE35AD5F1E3B77D600A02D78 /* XCTRunnerAutomationSession.h in Headers */,
|
|
2584
|
+
13DE7A4F287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */,
|
|
2575
2585
|
71C9EAAC25E8415A00470CD8 /* FBScreenshot.h in Headers */,
|
|
2576
2586
|
EE35AD371E3B77D600A02D78 /* XCSourceCodeTreeNodeEnumerator.h in Headers */,
|
|
2577
2587
|
EE158AB01CBD456F00A3E3F0 /* XCUIElement+FBIsVisible.h in Headers */,
|
|
@@ -2669,7 +2679,6 @@
|
|
|
2669
2679
|
EE158AB81CBD456F00A3E3F0 /* FBAlertViewCommands.h in Headers */,
|
|
2670
2680
|
EE35AD651E3B77D600A02D78 /* XCTWaiter.h in Headers */,
|
|
2671
2681
|
EE35AD681E3B77D600A02D78 /* XCTWaiterManagement-Protocol.h in Headers */,
|
|
2672
|
-
13DE7A4F287C46BB003243C6 /* FBXCElementSnapshot.h in Headers */,
|
|
2673
2682
|
EE35AD451E3B77D600A02D78 /* XCTestContext.h in Headers */,
|
|
2674
2683
|
EE35AD661E3B77D600A02D78 /* XCTWaiterDelegate-Protocol.h in Headers */,
|
|
2675
2684
|
EE35AD0E1E3B77D600A02D78 /* _XCTestExpectationImplementation.h in Headers */,
|
|
@@ -2712,6 +2721,7 @@
|
|
|
2712
2721
|
EE35AD571E3B77D600A02D78 /* XCTestSuiteRun.h in Headers */,
|
|
2713
2722
|
EE35AD701E3B77D600A02D78 /* XCUIElementAsynchronousHandlerWrapper.h in Headers */,
|
|
2714
2723
|
EE35AD4C1E3B77D600A02D78 /* XCTestLog.h in Headers */,
|
|
2724
|
+
B31635202DDF0D0B007D9317 /* FBAccessibilityTraits.h in Headers */,
|
|
2715
2725
|
71BB58E82B96328700CB9BFE /* FBScreenRecordingRequest.h in Headers */,
|
|
2716
2726
|
EE35AD231E3B77D600A02D78 /* UITapGestureRecognizer-RecordingAdditions.h in Headers */,
|
|
2717
2727
|
EE35AD2A1E3B77D600A02D78 /* XCDebugLogDelegate-Protocol.h in Headers */,
|
|
@@ -3173,6 +3183,7 @@
|
|
|
3173
3183
|
641EE6082240C5CA00173FCB /* FBRuntimeUtils.m in Sources */,
|
|
3174
3184
|
641EE6092240C5CA00173FCB /* XCUIElement+FBUtilities.m in Sources */,
|
|
3175
3185
|
641EE60A2240C5CA00173FCB /* FBLogger.m in Sources */,
|
|
3186
|
+
B316351D2DDF0CF5007D9317 /* FBAccessibilityTraits.m in Sources */,
|
|
3176
3187
|
641EE60B2240C5CA00173FCB /* FBCustomCommands.m in Sources */,
|
|
3177
3188
|
71BB58E42B9631F100CB9BFE /* FBScreenRecordingPromise.m in Sources */,
|
|
3178
3189
|
641EE60C2240C5CA00173FCB /* XCUIDevice+FBHelpers.m in Sources */,
|
|
@@ -3257,6 +3268,7 @@
|
|
|
3257
3268
|
71AE3CFA2D38EE8E0039FC36 /* XCUIElement+FBVisibleFrame.m in Sources */,
|
|
3258
3269
|
EEBBD48C1D47746D00656A81 /* XCUIElement+FBFind.m in Sources */,
|
|
3259
3270
|
EE158ADD1CBD456F00A3E3F0 /* FBResponsePayload.m in Sources */,
|
|
3271
|
+
B316351C2DDF0CF5007D9317 /* FBAccessibilityTraits.m in Sources */,
|
|
3260
3272
|
E444DCB524913C220060D7EB /* RouteRequest.m in Sources */,
|
|
3261
3273
|
C8FB547A22D4C1FC00B69954 /* FBUnattachedAppLauncher.m in Sources */,
|
|
3262
3274
|
EE158ADF1CBD456F00A3E3F0 /* FBRoute.m in Sources */,
|
|
@@ -48,6 +48,7 @@ static NSString* const FBExclusionAttributeAccessible = @"accessible";
|
|
|
48
48
|
static NSString* const FBExclusionAttributeFocused = @"focused";
|
|
49
49
|
static NSString* const FBExclusionAttributePlaceholderValue = @"placeholderValue";
|
|
50
50
|
static NSString* const FBExclusionAttributeNativeFrame = @"nativeFrame";
|
|
51
|
+
static NSString* const FBExclusionAttributeTraits = @"traits";
|
|
51
52
|
|
|
52
53
|
_Nullable id extractIssueProperty(id issue, NSString *propertyName) {
|
|
53
54
|
SEL selector = NSSelectorFromString(propertyName);
|
|
@@ -209,6 +210,7 @@ NSDictionary<NSString *, NSString *> *customExclusionAttributesMap(void) {
|
|
|
209
210
|
FBExclusionAttributeFrame,
|
|
210
211
|
FBExclusionAttributePlaceholderValue,
|
|
211
212
|
FBExclusionAttributeNativeFrame,
|
|
213
|
+
FBExclusionAttributeTraits,
|
|
212
214
|
nil];
|
|
213
215
|
|
|
214
216
|
for (NSString *key in attributeBlocks) {
|
|
@@ -265,6 +267,9 @@ NSDictionary<NSString *, NSString *> *customExclusionAttributesMap(void) {
|
|
|
265
267
|
},
|
|
266
268
|
FBExclusionAttributeFocused: ^{
|
|
267
269
|
return [@([wrappedSnapshot isWDFocused]) stringValue];
|
|
270
|
+
},
|
|
271
|
+
FBExclusionAttributeTraits: ^{
|
|
272
|
+
return wrappedSnapshot.wdTraits;
|
|
268
273
|
}
|
|
269
274
|
} mutableCopy];
|
|
270
275
|
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
#import "FBElementUtils.h"
|
|
23
23
|
#import "XCTestPrivateSymbols.h"
|
|
24
24
|
#import "XCUIHitPointResult.h"
|
|
25
|
+
#import "FBAccessibilityTraits.h"
|
|
25
26
|
|
|
26
27
|
#define BROKEN_RECT CGRectMake(-1, -1, 0, 0)
|
|
27
28
|
|
|
@@ -159,6 +160,22 @@
|
|
|
159
160
|
return self.frame;
|
|
160
161
|
}
|
|
161
162
|
|
|
163
|
+
/**
|
|
164
|
+
Returns a comma-separated string of accessibility traits for the element.
|
|
165
|
+
This method converts the element's accessibility traits bitmask into human-readable strings
|
|
166
|
+
using FBAccessibilityTraitsToStringsArray. The traits represent various accessibility
|
|
167
|
+
characteristics of the element such as Button, Link, Image, etc.
|
|
168
|
+
You can find the list of possible traits in the Apple documentation:
|
|
169
|
+
https://developer.apple.com/documentation/uikit/uiaccessibilitytraits?language=objc
|
|
170
|
+
|
|
171
|
+
@return A comma-separated string of accessibility traits, or an empty string if no traits are set
|
|
172
|
+
*/
|
|
173
|
+
- (NSString *)wdTraits
|
|
174
|
+
{
|
|
175
|
+
NSArray<NSString *> *traits = FBAccessibilityTraitsToStringsArray(self.snapshot.traits);
|
|
176
|
+
return [traits componentsJoinedByString:@", "];
|
|
177
|
+
}
|
|
178
|
+
|
|
162
179
|
- (BOOL)isWDVisible
|
|
163
180
|
{
|
|
164
181
|
return self.fb_isVisible;
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
<key>CFBundlePackageType</key>
|
|
16
16
|
<string>FMWK</string>
|
|
17
17
|
<key>CFBundleShortVersionString</key>
|
|
18
|
-
<string>9.
|
|
18
|
+
<string>9.10.1</string>
|
|
19
19
|
<key>CFBundleSignature</key>
|
|
20
20
|
<string>????</string>
|
|
21
21
|
<key>CFBundleVersion</key>
|
|
22
|
-
<string>9.
|
|
22
|
+
<string>9.10.1</string>
|
|
23
23
|
<key>NSPrincipalClass</key>
|
|
24
24
|
<string/>
|
|
25
25
|
</dict>
|
|
@@ -38,6 +38,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
38
38
|
/*! Element's type */
|
|
39
39
|
@property (nonatomic, readonly, copy) NSString *wdType;
|
|
40
40
|
|
|
41
|
+
/*! Element's accessibility traits as a comma-separated string */
|
|
42
|
+
@property (nonatomic, readonly, copy) NSString *wdTraits;
|
|
43
|
+
|
|
41
44
|
/*! Element's value */
|
|
42
45
|
@property (nonatomic, readonly, strong, nullable) NSString *wdValue;
|
|
43
46
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
|
7
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#import <XCTest/XCTest.h>
|
|
11
|
+
|
|
12
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
Converts accessibility traits bitmask to an array of string representations
|
|
16
|
+
@param traits The accessibility traits bitmask
|
|
17
|
+
@return Array of strings representing the accessibility traits
|
|
18
|
+
*/
|
|
19
|
+
NSArray<NSString *> *FBAccessibilityTraitsToStringsArray(unsigned long long traits);
|
|
20
|
+
|
|
21
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree. An additional grant
|
|
7
|
+
* of patent rights can be found in the PATENTS file in the same directory.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#import "FBAccessibilityTraits.h"
|
|
11
|
+
|
|
12
|
+
NSArray<NSString *> *FBAccessibilityTraitsToStringsArray(unsigned long long traits) {
|
|
13
|
+
NSMutableArray<NSString *> *traitStringsArray;
|
|
14
|
+
NSNumber *key;
|
|
15
|
+
|
|
16
|
+
static NSDictionary<NSNumber *, NSString *> *traitsMapping;
|
|
17
|
+
static dispatch_once_t onceToken;
|
|
18
|
+
|
|
19
|
+
dispatch_once(&onceToken, ^{
|
|
20
|
+
NSMutableDictionary<NSNumber *, NSString *> *mapping = [@{
|
|
21
|
+
@(UIAccessibilityTraitNone): @"None",
|
|
22
|
+
@(UIAccessibilityTraitButton): @"Button",
|
|
23
|
+
@(UIAccessibilityTraitLink): @"Link",
|
|
24
|
+
@(UIAccessibilityTraitHeader): @"Header",
|
|
25
|
+
@(UIAccessibilityTraitSearchField): @"SearchField",
|
|
26
|
+
@(UIAccessibilityTraitImage): @"Image",
|
|
27
|
+
@(UIAccessibilityTraitSelected): @"Selected",
|
|
28
|
+
@(UIAccessibilityTraitPlaysSound): @"PlaysSound",
|
|
29
|
+
@(UIAccessibilityTraitKeyboardKey): @"KeyboardKey",
|
|
30
|
+
@(UIAccessibilityTraitStaticText): @"StaticText",
|
|
31
|
+
@(UIAccessibilityTraitSummaryElement): @"SummaryElement",
|
|
32
|
+
@(UIAccessibilityTraitNotEnabled): @"NotEnabled",
|
|
33
|
+
@(UIAccessibilityTraitUpdatesFrequently): @"UpdatesFrequently",
|
|
34
|
+
@(UIAccessibilityTraitStartsMediaSession): @"StartsMediaSession",
|
|
35
|
+
@(UIAccessibilityTraitAdjustable): @"Adjustable",
|
|
36
|
+
@(UIAccessibilityTraitAllowsDirectInteraction): @"AllowsDirectInteraction",
|
|
37
|
+
@(UIAccessibilityTraitCausesPageTurn): @"CausesPageTurn",
|
|
38
|
+
@(UIAccessibilityTraitTabBar): @"TabBar"
|
|
39
|
+
} mutableCopy];
|
|
40
|
+
|
|
41
|
+
#if __clang_major__ >= 16
|
|
42
|
+
// Add iOS 17.0 specific traits if available
|
|
43
|
+
if (@available(iOS 17.0, *)) {
|
|
44
|
+
[mapping addEntriesFromDictionary:@{
|
|
45
|
+
@(UIAccessibilityTraitToggleButton): @"ToggleButton",
|
|
46
|
+
@(UIAccessibilityTraitSupportsZoom): @"SupportsZoom"
|
|
47
|
+
}];
|
|
48
|
+
}
|
|
49
|
+
#endif
|
|
50
|
+
|
|
51
|
+
traitsMapping = [mapping copy];
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
traitStringsArray = [NSMutableArray array];
|
|
55
|
+
for (key in traitsMapping) {
|
|
56
|
+
if (traits & [key unsignedLongLongValue] && nil != traitsMapping[key]) {
|
|
57
|
+
[traitStringsArray addObject:(id)traitsMapping[key]];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return [traitStringsArray copy];
|
|
62
|
+
}
|
|
@@ -146,7 +146,8 @@ static NSString *const topNodeIndexPath = @"top";
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
if (rc >= 0) {
|
|
149
|
-
|
|
149
|
+
[self waitUntilStableWithElement:root];
|
|
150
|
+
rc = [self xmlRepresentationWithRootElement:[self snapshotWithRoot:root useNative:NO]
|
|
150
151
|
writer:writer
|
|
151
152
|
elementStore:nil
|
|
152
153
|
query:nil
|
|
@@ -196,17 +197,23 @@ static NSString *const topNodeIndexPath = @"top";
|
|
|
196
197
|
int rc = xmlTextWriterStartDocument(writer, NULL, _UTF8Encoding, NULL);
|
|
197
198
|
id<FBXCElementSnapshot> lookupScopeSnapshot = nil;
|
|
198
199
|
id<FBXCElementSnapshot> contextRootSnapshot = nil;
|
|
200
|
+
BOOL useNativeSnapshot = nil == xpathQuery
|
|
201
|
+
? NO
|
|
202
|
+
: [[self.class elementAttributesWithXPathQuery:xpathQuery] containsObject:FBHittableAttribute.class];
|
|
199
203
|
if (rc < 0) {
|
|
200
204
|
[FBLogger logFmt:@"Failed to invoke libxml2>xmlTextWriterStartDocument. Error code: %d", rc];
|
|
201
205
|
} else {
|
|
206
|
+
[self waitUntilStableWithElement:root];
|
|
202
207
|
if (FBConfiguration.limitXpathContextScope) {
|
|
203
|
-
lookupScopeSnapshot = [self snapshotWithRoot:root];
|
|
208
|
+
lookupScopeSnapshot = [self snapshotWithRoot:root useNative:useNativeSnapshot];
|
|
204
209
|
} else {
|
|
205
210
|
if ([root isKindOfClass:XCUIElement.class]) {
|
|
206
|
-
lookupScopeSnapshot = [self snapshotWithRoot:[(XCUIElement *)root application]
|
|
211
|
+
lookupScopeSnapshot = [self snapshotWithRoot:[(XCUIElement *)root application]
|
|
212
|
+
useNative:useNativeSnapshot];
|
|
207
213
|
contextRootSnapshot = [root isKindOfClass:XCUIApplication.class]
|
|
208
214
|
? nil
|
|
209
|
-
: ([(XCUIElement *)root lastSnapshot] ?: [(XCUIElement *)root
|
|
215
|
+
: ([(XCUIElement *)root lastSnapshot] ?: [self snapshotWithRoot:(XCUIElement *)root
|
|
216
|
+
useNative:useNativeSnapshot]);
|
|
210
217
|
} else {
|
|
211
218
|
lookupScopeSnapshot = (id<FBXCElementSnapshot>)root;
|
|
212
219
|
contextRootSnapshot = nil == lookupScopeSnapshot.parent ? nil : (id<FBXCElementSnapshot>)root;
|
|
@@ -483,19 +490,29 @@ static NSString *const topNodeIndexPath = @"top";
|
|
|
483
490
|
}
|
|
484
491
|
|
|
485
492
|
+ (id<FBXCElementSnapshot>)snapshotWithRoot:(id<FBElement>)root
|
|
493
|
+
useNative:(BOOL)useNative
|
|
486
494
|
{
|
|
487
495
|
if (![root isKindOfClass:XCUIElement.class]) {
|
|
488
496
|
return (id<FBXCElementSnapshot>)root;
|
|
489
497
|
}
|
|
490
498
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
499
|
+
if (useNative) {
|
|
500
|
+
return [(XCUIElement *)root fb_nativeSnapshot];
|
|
501
|
+
}
|
|
494
502
|
return [root isKindOfClass:XCUIApplication.class]
|
|
495
503
|
? [(XCUIElement *)root fb_standardSnapshot]
|
|
496
504
|
: [(XCUIElement *)root fb_customSnapshot];
|
|
497
505
|
}
|
|
498
506
|
|
|
507
|
+
+ (void)waitUntilStableWithElement:(id<FBElement>)root
|
|
508
|
+
{
|
|
509
|
+
if ([root isKindOfClass:XCUIElement.class]) {
|
|
510
|
+
// If the app is not idle state while we retrieve the visiblity state
|
|
511
|
+
// then the snapshot retrieval operation might freeze and time out
|
|
512
|
+
[[(XCUIElement *)root application] fb_waitUntilStableWithTimeout:FBConfiguration.animationCoolOffTimeout];
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
499
516
|
@end
|
|
500
517
|
|
|
501
518
|
|
|
@@ -15,6 +15,7 @@ FOUNDATION_EXPORT double WebDriverAgentLib_VersionNumber;
|
|
|
15
15
|
//! Project version string for WebDriverAgentLib_.
|
|
16
16
|
FOUNDATION_EXPORT const unsigned char WebDriverAgentLib_VersionString[];
|
|
17
17
|
|
|
18
|
+
#import <WebDriverAgentLib/CDStructures.h>
|
|
18
19
|
#import <WebDriverAgentLib/FBAlert.h>
|
|
19
20
|
#import <WebDriverAgentLib/FBCommandHandler.h>
|
|
20
21
|
#import <WebDriverAgentLib/FBCommandStatus.h>
|
|
@@ -38,9 +39,17 @@ FOUNDATION_EXPORT const unsigned char WebDriverAgentLib_VersionString[];
|
|
|
38
39
|
#import <WebDriverAgentLib/FBRuntimeUtils.h>
|
|
39
40
|
#import <WebDriverAgentLib/FBSession.h>
|
|
40
41
|
#import <WebDriverAgentLib/FBWebServer.h>
|
|
42
|
+
#import <WebDriverAgentLib/FBXCElementSnapshot.h>
|
|
43
|
+
#import <WebDriverAgentLib/FBXCElementSnapshotWrapper.h>
|
|
44
|
+
#import <WebDriverAgentLib/FBXPath.h>
|
|
45
|
+
#import <WebDriverAgentLib/WebDriverAgentLib.h>
|
|
46
|
+
#import <WebDriverAgentLib/XCDebugLogDelegate-Protocol.h>
|
|
47
|
+
#import <WebDriverAgentLib/XCTestCase.h>
|
|
48
|
+
#import <WebDriverAgentLib/XCTIssue+FBPatcher.h>
|
|
41
49
|
#import <WebDriverAgentLib/XCUIApplication+FBHelpers.h>
|
|
42
50
|
#import <WebDriverAgentLib/XCUIDevice+FBHelpers.h>
|
|
43
51
|
#import <WebDriverAgentLib/XCUIDevice+FBRotation.h>
|
|
52
|
+
#import <WebDriverAgentLib/XCUIElement.h>
|
|
44
53
|
#import <WebDriverAgentLib/XCUIElement+FBAccessibility.h>
|
|
45
54
|
#import <WebDriverAgentLib/XCUIElement+FBFind.h>
|
|
46
55
|
#import <WebDriverAgentLib/XCUIElement+FBIsVisible.h>
|
|
@@ -96,6 +96,52 @@
|
|
|
96
96
|
XCTAssertEqual(element2.wdIndex, 0);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
- (void)testAccessibilityTraits
|
|
100
|
+
{
|
|
101
|
+
XCUIElement *button = self.testedApplication.buttons.firstMatch;
|
|
102
|
+
XCTAssertTrue(button.exists);
|
|
103
|
+
NSArray *buttonTraits = [button.wdTraits componentsSeparatedByString:@", "];
|
|
104
|
+
NSArray *expectedButtonTraits = @[@"Button"];
|
|
105
|
+
XCTAssertEqual(buttonTraits.count, expectedButtonTraits.count, @"Button should have exactly 1 trait");
|
|
106
|
+
XCTAssertEqualObjects(buttonTraits, expectedButtonTraits);
|
|
107
|
+
XCTAssertEqualObjects(button.wdType, @"XCUIElementTypeButton");
|
|
108
|
+
|
|
109
|
+
XCUIElement *toggle = self.testedApplication.switches.firstMatch;
|
|
110
|
+
XCTAssertTrue(toggle.exists);
|
|
111
|
+
|
|
112
|
+
// iOS 17.0 specific traits if available
|
|
113
|
+
NSArray *toggleTraits = [toggle.wdTraits componentsSeparatedByString:@", "];
|
|
114
|
+
NSArray *expectedToggleTraits;
|
|
115
|
+
|
|
116
|
+
#if __clang_major__ >= 16
|
|
117
|
+
if (@available(iOS 17.0, *)) {
|
|
118
|
+
expectedToggleTraits = @[@"ToggleButton", @"Button"];
|
|
119
|
+
XCTAssertEqual(toggleTraits.count, 2, @"Toggle should have exactly 2 traits on iOS 17+");
|
|
120
|
+
}
|
|
121
|
+
#else
|
|
122
|
+
expectedToggleTraits = @[@"Button"];
|
|
123
|
+
XCTAssertEqual(toggleTraits.count, 1, @"Toggle should have exactly 1 trait on iOS < 17");
|
|
124
|
+
#endif
|
|
125
|
+
XCTAssertEqualObjects(toggleTraits, expectedToggleTraits);
|
|
126
|
+
XCTAssertEqualObjects(toggle.wdType, @"XCUIElementTypeSwitch");
|
|
127
|
+
|
|
128
|
+
XCUIElement *slider = self.testedApplication.sliders.firstMatch;
|
|
129
|
+
XCTAssertTrue(slider.exists);
|
|
130
|
+
NSArray *sliderTraits = [slider.wdTraits componentsSeparatedByString:@", "];
|
|
131
|
+
NSArray *expectedSliderTraits = @[@"Adjustable"];
|
|
132
|
+
XCTAssertEqual(sliderTraits.count, expectedSliderTraits.count, @"Slider should have exactly 1 trait");
|
|
133
|
+
XCTAssertEqualObjects(sliderTraits, expectedSliderTraits);
|
|
134
|
+
XCTAssertEqualObjects(slider.wdType, @"XCUIElementTypeSlider");
|
|
135
|
+
|
|
136
|
+
XCUIElement *picker = self.testedApplication.pickerWheels.firstMatch;
|
|
137
|
+
XCTAssertTrue(picker.exists);
|
|
138
|
+
NSArray *pickerTraits = [picker.wdTraits componentsSeparatedByString:@", "];
|
|
139
|
+
NSArray *expectedPickerTraits = @[@"Adjustable"];
|
|
140
|
+
XCTAssertEqual(pickerTraits.count, expectedPickerTraits.count, @"Picker should have exactly 1 trait");
|
|
141
|
+
XCTAssertEqualObjects(pickerTraits, expectedPickerTraits);
|
|
142
|
+
XCTAssertEqualObjects(picker.wdType, @"XCUIElementTypePickerWheel");
|
|
143
|
+
}
|
|
144
|
+
|
|
99
145
|
- (void)testTextFieldAttributes
|
|
100
146
|
{
|
|
101
147
|
XCUIElement *element = self.testedApplication.textFields[@"Value"];
|
|
@@ -461,4 +461,13 @@
|
|
|
461
461
|
XCTAssertFalse(matchingSnapshots.lastObject.fb_isVisible);
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
+
- (void)testNonHittableDescendantWithXPathQuery
|
|
465
|
+
{
|
|
466
|
+
NSArray<XCUIElement *> *matchingSnapshots = [self.testedApplication fb_descendantsMatchingXPathQuery:@"//XCUIElementTypeStaticText[@hittable='false']"
|
|
467
|
+
shouldReturnAfterFirstMatch:NO];
|
|
468
|
+
XCTAssertGreaterThan(matchingSnapshots.count, 1);
|
|
469
|
+
XCTAssertEqual(matchingSnapshots.lastObject.elementType, XCUIElementTypeStaticText);
|
|
470
|
+
XCTAssertFalse(matchingSnapshots.lastObject.fb_isVisible);
|
|
471
|
+
}
|
|
472
|
+
|
|
464
473
|
@end
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
@property (nonatomic, strong, readwrite, nullable) NSString *wdValue;
|
|
29
29
|
@property (nonatomic, readwrite, getter=isWDEnabled) BOOL wdEnabled;
|
|
30
30
|
@property (nonatomic, readwrite, getter=isWDSelected) BOOL wdSelected;
|
|
31
|
+
@property (nonatomic, readwrite, assign) CGRect wdNativeFrame;
|
|
31
32
|
@property (nonatomic, readwrite) NSUInteger wdIndex;
|
|
32
33
|
@property (nonatomic, readwrite, getter=isWDVisible) BOOL wdVisible;
|
|
33
34
|
@property (nonatomic, readwrite, getter=isWDAccessible) BOOL wdAccessible;
|
|
@@ -37,6 +38,7 @@
|
|
|
37
38
|
@property (copy, nonnull) NSArray *children;
|
|
38
39
|
@property (nonatomic, readwrite, assign) XCUIElementType elementType;
|
|
39
40
|
@property (nonatomic, readwrite, getter=isWDAccessibilityContainer) BOOL wdAccessibilityContainer;
|
|
41
|
+
@property (nonatomic, copy, readwrite, nullable) NSString *wdTraits;
|
|
40
42
|
|
|
41
43
|
- (void)resolve;
|
|
42
44
|
- (id _Nonnull)fb_standardSnapshot;
|
|
@@ -19,11 +19,13 @@
|
|
|
19
19
|
{
|
|
20
20
|
self = [super init];
|
|
21
21
|
if (self) {
|
|
22
|
-
self.wdFrame =
|
|
22
|
+
self.wdFrame = CGRectZero;
|
|
23
|
+
self.wdNativeFrame = CGRectZero;
|
|
23
24
|
self.wdName = @"testName";
|
|
24
25
|
self.wdLabel = @"testLabel";
|
|
25
26
|
self.wdValue = @"magicValue";
|
|
26
27
|
self.wdPlaceholderValue = @"testPlaceholderValue";
|
|
28
|
+
self.wdTraits = @"testTraits";
|
|
27
29
|
self.wdVisible = YES;
|
|
28
30
|
self.wdAccessible = YES;
|
|
29
31
|
self.wdEnabled = YES;
|
|
@@ -94,4 +96,9 @@
|
|
|
94
96
|
return self.wdUID;
|
|
95
97
|
}
|
|
96
98
|
|
|
99
|
+
- (NSString *)wdTraits
|
|
100
|
+
{
|
|
101
|
+
return self.wdTraits;
|
|
102
|
+
}
|
|
103
|
+
|
|
97
104
|
@end
|