Skip to content

Commit 0e4e7e7

Browse files
feat: add minimum and maximum value attributes to page source (#1031)
* feat: add minimum and maximum value attributes to page source * Add tests * refcator: XCUIElement+FBMinMax * add placeholderValue and min/max value to settings * Replace NSLogger with FBLogger * remove includePlaceholderValueInPageSource setting and minor refactoring
1 parent a97883e commit 0e4e7e7

18 files changed

Lines changed: 292 additions & 10 deletions

WebDriverAgent.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
0E0413382DF1E15100AF007C /* XCUIElement+FBMinMax.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E0413372DF1E15100AF007C /* XCUIElement+FBMinMax.m */; };
11+
0E0413392DF1E15100AF007C /* XCUIElement+FBMinMax.m in Sources */ = {isa = PBXBuildFile; fileRef = 0E0413372DF1E15100AF007C /* XCUIElement+FBMinMax.m */; };
12+
0E04133B2DF1E15900AF007C /* XCUIElement+FBMinMax.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E04133A2DF1E15900AF007C /* XCUIElement+FBMinMax.h */; };
13+
0E04133C2DF1E15900AF007C /* XCUIElement+FBMinMax.h in Headers */ = {isa = PBXBuildFile; fileRef = 0E04133A2DF1E15900AF007C /* XCUIElement+FBMinMax.h */; };
1014
1357E296233D05240054BDB8 /* XCUIHitPointResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1357E295233D05240054BDB8 /* XCUIHitPointResult.h */; };
1115
1357E297233D05240054BDB8 /* XCUIHitPointResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 1357E295233D05240054BDB8 /* XCUIHitPointResult.h */; };
1216
13815F6F2328D20400CDAB61 /* FBActiveAppDetectionPoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 13815F6D2328D20400CDAB61 /* FBActiveAppDetectionPoint.h */; };
@@ -918,6 +922,8 @@
918922
/* End PBXCopyFilesBuildPhase section */
919923

920924
/* Begin PBXFileReference section */
925+
0E0413372DF1E15100AF007C /* XCUIElement+FBMinMax.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "XCUIElement+FBMinMax.m"; sourceTree = "<group>"; };
926+
0E04133A2DF1E15900AF007C /* XCUIElement+FBMinMax.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBMinMax.h"; sourceTree = "<group>"; };
921927
1357E295233D05240054BDB8 /* XCUIHitPointResult.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCUIHitPointResult.h; sourceTree = "<group>"; };
922928
13815F6D2328D20400CDAB61 /* FBActiveAppDetectionPoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBActiveAppDetectionPoint.h; sourceTree = "<group>"; };
923929
13815F6E2328D20400CDAB61 /* FBActiveAppDetectionPoint.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBActiveAppDetectionPoint.m; sourceTree = "<group>"; };
@@ -1785,6 +1791,8 @@
17851791
EE8DDD7C20C5733B004D4925 /* XCUIElement+FBForceTouch.m */,
17861792
EE9AB7471CAEDF0C008C271F /* XCUIElement+FBIsVisible.h */,
17871793
EE9AB7481CAEDF0C008C271F /* XCUIElement+FBIsVisible.m */,
1794+
0E04133A2DF1E15900AF007C /* XCUIElement+FBMinMax.h */,
1795+
0E0413372DF1E15100AF007C /* XCUIElement+FBMinMax.m */,
17881796
7136A4771E8918E60024FC3D /* XCUIElement+FBPickerWheel.h */,
17891797
7136A4781E8918E60024FC3D /* XCUIElement+FBPickerWheel.m */,
17901798
71D3B3D3267FC7260076473D /* XCUIElement+FBResolve.h */,
@@ -2377,6 +2385,7 @@
23772385
641EE6782240C5CA00173FCB /* XCTNSNotificationExpectation.h in Headers */,
23782386
641EE6792240C5CA00173FCB /* XCUIRecorderNodeFinder.h in Headers */,
23792387
641EE67A2240C5CA00173FCB /* XCUIElement+FBAccessibility.h in Headers */,
2388+
0E04133C2DF1E15900AF007C /* XCUIElement+FBMinMax.h in Headers */,
23802389
641EE67B2240C5CA00173FCB /* XCUIRecorderUtilities.h in Headers */,
23812390
6496A5DA230D6EB30087F8CB /* AXSettings.h in Headers */,
23822391
641EE67C2240C5CA00173FCB /* XCTestCaseRun.h in Headers */,
@@ -2701,6 +2710,7 @@
27012710
EEE9B4721CD02B88009D2030 /* FBRunLoopSpinner.h in Headers */,
27022711
EE3A18621CDE618F00DE4205 /* FBErrorBuilder.h in Headers */,
27032712
EE35AD261E3B77D600A02D78 /* XCApplicationMonitor_iOS.h in Headers */,
2713+
0E04133B2DF1E15900AF007C /* XCUIElement+FBMinMax.h in Headers */,
27042714
EE3A18661CDE734B00DE4205 /* FBKeyboard.h in Headers */,
27052715
AD6C269C1CF2494200F8B5FF /* XCUIApplication+FBHelpers.h in Headers */,
27062716
714D88CC2733FB970074A925 /* FBXMLGenerationOptions.h in Headers */,
@@ -3202,6 +3212,7 @@
32023212
71BB58F92B96531900CB9BFE /* FBScreenRecordingContainer.m in Sources */,
32033213
641EE6152240C5CA00173FCB /* XCUIElement+FBScrolling.m in Sources */,
32043214
641EE6162240C5CA00173FCB /* FBSessionCommands.m in Sources */,
3215+
0E0413392DF1E15100AF007C /* XCUIElement+FBMinMax.m in Sources */,
32053216
641EE6192240C5CA00173FCB /* FBConfiguration.m in Sources */,
32063217
641EE61A2240C5CA00173FCB /* FBElementCache.m in Sources */,
32073218
71F5BE26252E576C00EE9EBA /* XCUIElement+FBSwiping.m in Sources */,
@@ -3249,6 +3260,7 @@
32493260
13DE7A45287C2A8D003243C6 /* FBXCAccessibilityElement.m in Sources */,
32503261
641EE70E2240CE4800173FCB /* FBTVNavigationTracker.m in Sources */,
32513262
71BD20741F86116100B36EC2 /* XCUIApplication+FBTouchAction.m in Sources */,
3263+
0E0413382DF1E15100AF007C /* XCUIElement+FBMinMax.m in Sources */,
32523264
EE158AE71CBD456F00A3E3F0 /* FBWebServer.m in Sources */,
32533265
715557D4211DBCE700613B26 /* FBTCPSocket.m in Sources */,
32543266
EE3A18631CDE618F00DE4205 /* FBErrorBuilder.m in Sources */,

WebDriverAgentLib/Categories/XCUIApplication+FBHelpers.m

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
static NSString* const FBExclusionAttributePlaceholderValue = @"placeholderValue";
5050
static NSString* const FBExclusionAttributeNativeFrame = @"nativeFrame";
5151
static NSString* const FBExclusionAttributeTraits = @"traits";
52+
static NSString* const FBExclusionAttributeMinValue = @"minValue";
53+
static NSString* const FBExclusionAttributeMaxValue = @"maxValue";
5254

5355
_Nullable id extractIssueProperty(id issue, NSString *propertyName) {
5456
SEL selector = NSSelectorFromString(propertyName);
@@ -211,6 +213,8 @@ + (NSDictionary *)dictionaryForElement:(id<FBXCElementSnapshot>)snapshot
211213
FBExclusionAttributePlaceholderValue,
212214
FBExclusionAttributeNativeFrame,
213215
FBExclusionAttributeTraits,
216+
FBExclusionAttributeMinValue,
217+
FBExclusionAttributeMaxValue,
214218
nil];
215219

216220
for (NSString *key in attributeBlocks) {
@@ -248,7 +252,7 @@ + (NSDictionary *)dictionaryForElement:(id<FBXCElementSnapshot>)snapshot
248252

249253
{
250254
// Base attributes common to every element
251-
NSMutableDictionary<NSString *, NSString *(^)(void)> *blocks =
255+
NSMutableDictionary<NSString *, id(^)(void)> *blocks =
252256
[@{
253257
FBExclusionAttributeFrame: ^{
254258
return NSStringFromCGRect(wrappedSnapshot.wdFrame);
@@ -282,6 +286,16 @@ + (NSDictionary *)dictionaryForElement:(id<FBXCElementSnapshot>)snapshot
282286
};
283287
}
284288

289+
// Only for elements that support min/max value
290+
if (FBDoesElementSupportMinMaxValue(elementType)) {
291+
blocks[FBExclusionAttributeMinValue] = ^{
292+
return wrappedSnapshot.wdMinValue;
293+
};
294+
blocks[FBExclusionAttributeMaxValue] = ^{
295+
return wrappedSnapshot.wdMaxValue;
296+
};
297+
}
298+
285299
return [blocks copy];
286300
}
287301

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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 <WebDriverAgentLib/FBXCElementSnapshotWrapper.h>
11+
12+
NS_ASSUME_NONNULL_BEGIN
13+
14+
@interface XCUIElement (FBMinMax)
15+
16+
/*! Minimum value (minValue) – may be nil if the element does not have this attribute */
17+
@property (nonatomic, readonly, nullable) NSNumber *fb_minValue;
18+
19+
/*! Maximum value (maxValue) - may be nil if the element does not have this attribute */
20+
@property (nonatomic, readonly, nullable) NSNumber *fb_maxValue;
21+
22+
@end
23+
24+
@interface FBXCElementSnapshotWrapper (FBMinMax)
25+
26+
/*! Minimum value (minValue) – may be nil if the element does not have this attribute */
27+
@property (nonatomic, readonly, nullable) NSNumber *fb_minValue;
28+
29+
/*! Maximum value (maxValue) - may be nil if the element does not have this attribute */
30+
@property (nonatomic, readonly, nullable) NSNumber *fb_maxValue;
31+
32+
@end
33+
34+
NS_ASSUME_NONNULL_END
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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 "FBLogger.h"
11+
#import "XCUIElement+FBMinMax.h"
12+
#import "FBXCElementSnapshotWrapper+Helpers.h"
13+
#import "XCUIElement+FBUtilities.h"
14+
#import "XCTestPrivateSymbols.h"
15+
16+
@interface FBXCElementSnapshotWrapper (FBMinMaxInternal)
17+
18+
- (NSNumber *)fb_numericAttribute:(NSString *)attributeName symbol:(NSNumber *)symbol;
19+
20+
@end
21+
22+
@implementation XCUIElement (FBMinMax)
23+
24+
- (NSNumber *)fb_minValue
25+
{
26+
@autoreleasepool {
27+
id<FBXCElementSnapshot> snapshot = [self fb_standardSnapshot];
28+
return [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_minValue];
29+
}
30+
}
31+
32+
- (NSNumber *)fb_maxValue
33+
{
34+
@autoreleasepool {
35+
id<FBXCElementSnapshot> snapshot = [self fb_standardSnapshot];
36+
return [[FBXCElementSnapshotWrapper ensureWrapped:snapshot] fb_maxValue];
37+
}
38+
}
39+
40+
@end
41+
42+
@implementation FBXCElementSnapshotWrapper (FBMinMax)
43+
44+
- (NSNumber *)fb_minValue
45+
{
46+
return [self fb_numericAttribute:FB_XCAXACustomMinValueAttributeName
47+
symbol:FB_XCAXACustomMinValueAttribute];
48+
}
49+
50+
- (NSNumber *)fb_maxValue
51+
{
52+
return [self fb_numericAttribute:FB_XCAXACustomMaxValueAttributeName
53+
symbol:FB_XCAXACustomMaxValueAttribute];
54+
}
55+
56+
- (NSNumber *)fb_numericAttribute:(NSString *)attributeName symbol:(NSNumber *)symbol
57+
{
58+
NSNumber *cached = (self.snapshot.additionalAttributes ?: @{})[symbol];
59+
if (cached) {
60+
return cached;
61+
}
62+
63+
NSError *error = nil;
64+
NSNumber *raw = [self fb_attributeValue:attributeName error:&error];
65+
if (nil != raw) {
66+
NSMutableDictionary *updated = [NSMutableDictionary dictionaryWithDictionary:self.additionalAttributes ?: @{}];
67+
updated[symbol] = raw;
68+
self.snapshot.additionalAttributes = updated.copy;
69+
return raw;
70+
}
71+
72+
[FBLogger logFmt:@"[FBMinMax] Cannot determine %@ for %@: %@", attributeName, self.fb_description, error.localizedDescription];
73+
return nil;
74+
}
75+
76+
@end

WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#import "XCTestPrivateSymbols.h"
2424
#import "XCUIHitPointResult.h"
2525
#import "FBAccessibilityTraits.h"
26+
#import "XCUIElement+FBMinMax.h"
2627

2728
#define BROKEN_RECT CGRectMake(-1, -1, 0, 0)
2829

@@ -76,6 +77,16 @@ - (id)fb_valueForWDAttributeName:(NSString *)name
7677
return [self valueForKey:[FBElementUtils wdAttributeNameForAttributeName:name]];
7778
}
7879

80+
- (NSNumber *)wdMinValue
81+
{
82+
return self.fb_minValue;
83+
}
84+
85+
- (NSNumber *)wdMaxValue
86+
{
87+
return self.fb_maxValue;
88+
}
89+
7990
- (NSString *)wdValue
8091
{
8192
id value = self.value;

WebDriverAgentLib/Commands/FBSessionCommands.m

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ + (NSArray *)routes
355355
FB_SETTING_USE_CLEAR_TEXT_SHORTCUT: @([FBConfiguration useClearTextShortcut]),
356356
FB_SETTING_INCLUDE_HITTABLE_IN_PAGE_SOURCE: @([FBConfiguration includeHittableInPageSource]),
357357
FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE: @([FBConfiguration includeNativeFrameInPageSource]),
358+
FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE: @([FBConfiguration includeMinMaxValueInPageSource]),
358359
FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE: @([FBConfiguration limitXpathContextScope]),
359360
#if !TARGET_OS_TV
360361
FB_SETTING_SCREENSHOT_ORIENTATION: [FBConfiguration humanReadableScreenshotOrientation],
@@ -463,6 +464,9 @@ + (NSArray *)routes
463464
if (nil != [settings objectForKey:FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE]) {
464465
[FBConfiguration setIncludeNativeFrameInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_NATIVE_FRAME_IN_PAGE_SOURCE] boolValue]];
465466
}
467+
if (nil != [settings objectForKey:FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE]) {
468+
[FBConfiguration setIncludeMinMaxValueInPageSource:[[settings objectForKey:FB_SETTING_INCLUDE_MIN_MAX_VALUE_IN_PAGE_SOURCE] boolValue]];
469+
}
466470
if (nil != [settings objectForKey:FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE]) {
467471
[FBConfiguration setLimitXpathContextScope:[[settings objectForKey:FB_SETTING_LIMIT_XPATH_CONTEXT_SCOPE] boolValue]];
468472
}

WebDriverAgentLib/Routing/FBElement.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ NS_ASSUME_NONNULL_BEGIN
7171
/*! Element's placeholder value */
7272
@property (nonatomic, readonly, copy, nullable) NSString *wdPlaceholderValue;
7373

74+
/*! Element's minimum value */
75+
@property (nonatomic, readonly, strong, nullable) NSNumber *wdMinValue;
76+
77+
/*! Element's maximum value */
78+
@property (nonatomic, readonly, strong, nullable) NSNumber *wdMaxValue;
79+
7480
/**
7581
Returns value of given property specified in WebDriver Spec
7682
Check the FBElement protocol to get list of supported attributes.

WebDriverAgentLib/Utilities/FBConfiguration.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,18 @@ typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) {
359359
+ (void)setIncludeNativeFrameInPageSource:(BOOL)enabled;
360360
+ (BOOL)includeNativeFrameInPageSource;
361361

362+
/**
363+
* Whether to include `minValue`/`maxValue` attributes in the page source.
364+
* These attributes are retrieved from native element snapshots and represent
365+
* value boundaries for elements like sliders or progress indicators.
366+
* This may affect performance if used on many elements.
367+
* Disabled by default.
368+
*
369+
* @param enabled Either YES or NO
370+
*/
371+
+ (void)setIncludeMinMaxValueInPageSource:(BOOL)enabled;
372+
+ (BOOL)includeMinMaxValueInPageSource;
373+
362374
@end
363375

364376
NS_ASSUME_NONNULL_END

WebDriverAgentLib/Utilities/FBConfiguration.m

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#endif
6464
static BOOL FBShouldIncludeHittableInPageSource = NO;
6565
static BOOL FBShouldIncludeNativeFrameInPageSource = NO;
66+
static BOOL FBShouldIncludeMinMaxValueInPageSource = NO;
6667

6768
@implementation FBConfiguration
6869

@@ -664,4 +665,14 @@ + (BOOL)includeNativeFrameInPageSource
664665
return FBShouldIncludeNativeFrameInPageSource;
665666
}
666667

668+
+ (void)setIncludeMinMaxValueInPageSource:(BOOL)enabled
669+
{
670+
FBShouldIncludeMinMaxValueInPageSource = enabled;
671+
}
672+
673+
+ (BOOL)includeMinMaxValueInPageSource
674+
{
675+
return FBShouldIncludeMinMaxValueInPageSource;
676+
}
677+
667678
@end

WebDriverAgentLib/Utilities/FBElementHelpers.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,16 @@ NS_ASSUME_NONNULL_BEGIN
1515
Checks if the element is a text field
1616
1717
@param elementType XCTest element type
18-
@return YES if the elemnt is a text field
18+
@return YES if the element is a text field
1919
*/
2020
BOOL FBDoesElementSupportInnerText(XCUIElementType elementType);
2121

22+
/**
23+
Checks if the element supports min/max value attributes
24+
25+
@param elementType XCTest element type
26+
@return YES if the element type supports min/max value attributes
27+
*/
28+
BOOL FBDoesElementSupportMinMaxValue(XCUIElementType elementType);
29+
2230
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)