diff --git a/CHANGELOG.md b/CHANGELOG.md
index 169152856..727a8d507 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## [9.1.0](https://github.com/appium/WebDriverAgent/compare/v9.0.6...v9.1.0) (2025-03-09)
+
+### Features
+
+* add placeholderValue ([#987](https://github.com/appium/WebDriverAgent/issues/987)) ([8c3a1cb](https://github.com/appium/WebDriverAgent/commit/8c3a1cb30655ed8d1a77d25bbeca71ee48c2ec3e))
+
## [9.0.6](https://github.com/appium/WebDriverAgent/compare/v9.0.5...v9.0.6) (2025-02-28)
### Bug Fixes
diff --git a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m
index f99158c7f..4efe2dde6 100644
--- a/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m
+++ b/WebDriverAgentLib/Categories/XCUIElement+FBWebDriverAttributes.m
@@ -115,6 +115,15 @@ - (NSString *)wdLabel
return FBTransferEmptyStringToNil(label);
}
+- (NSString *)wdPlaceholderValue
+{
+ NSString *placehlderValue = self.placeholderValue;
+ if (nil != placehlderValue) {
+ return placehlderValue;
+ }
+ return FBTransferEmptyStringToNil(placehlderValue);
+}
+
- (NSString *)wdType
{
return [FBElementTypeTransformer stringWithElementType:self.elementType];
diff --git a/WebDriverAgentLib/Info.plist b/WebDriverAgentLib/Info.plist
index 39be9a6fe..3bc3b1dc7 100644
--- a/WebDriverAgentLib/Info.plist
+++ b/WebDriverAgentLib/Info.plist
@@ -15,11 +15,11 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 9.0.6
+ 9.1.0
CFBundleSignature
????
CFBundleVersion
- 9.0.6
+ 9.1.0
NSPrincipalClass
diff --git a/WebDriverAgentLib/Routing/FBElement.h b/WebDriverAgentLib/Routing/FBElement.h
index 7cc8f269c..0b3b8b098 100644
--- a/WebDriverAgentLib/Routing/FBElement.h
+++ b/WebDriverAgentLib/Routing/FBElement.h
@@ -62,6 +62,9 @@ NS_ASSUME_NONNULL_BEGIN
/*! Element's index relatively to its parent. Starts from zero */
@property (nonatomic, readonly) NSUInteger wdIndex;
+/*! Element's placeholder value */
+@property (nonatomic, readonly, copy, nullable) NSString *wdPlaceholderValue;
+
/**
Returns value of given property specified in WebDriver Spec
Check the FBElement protocol to get list of supported attributes.
diff --git a/WebDriverAgentLib/Utilities/FBXPath.m b/WebDriverAgentLib/Utilities/FBXPath.m
index 6276cfae6..d36291fdd 100644
--- a/WebDriverAgentLib/Utilities/FBXPath.m
+++ b/WebDriverAgentLib/Utilities/FBXPath.m
@@ -100,6 +100,10 @@ + (int)recordWithWriter:(xmlTextWriterPtr)writer forValue:(NSString *)value;
@end
+@interface FBPlaceholderValueAttribute : FBElementAttribute
+
+@end
+
#if TARGET_OS_TV
@interface FBFocusedAttribute : FBElementAttribute
@@ -491,6 +495,7 @@ + (int)recordWithWriter:(xmlTextWriterPtr)writer forElement:(id)eleme
FBHeightAttribute.class,
FBIndexAttribute.class,
FBHittableAttribute.class,
+ FBPlaceholderValueAttribute.class,
];
}
@@ -713,3 +718,18 @@ + (int)recordWithWriter:(xmlTextWriterPtr)writer forValue:(NSString *)value
return rc;
}
@end
+
+
+@implementation FBPlaceholderValueAttribute
+
++ (NSString *)name
+{
+ return @"placeholderValue";
+}
+
++ (NSString *)valueForElement:(id)element
+{
+ return element.wdPlaceholderValue;
+}
+
+@end
diff --git a/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m b/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m
index 7c094b600..15cf628ab 100644
--- a/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m
+++ b/WebDriverAgentTests/IntegrationTests/FBElementAttributeTests.m
@@ -154,6 +154,7 @@ - (void)testSwitchAttributes
XCTAssertEqualObjects(element.wdType, @"XCUIElementTypeSwitch");
XCTAssertNil(element.wdName);
XCTAssertNil(element.wdLabel);
+ XCTAssertNil(element.wdPlaceholderValue);
XCTAssertEqualObjects(element.wdValue, @"1");
XCTAssertFalse(element.wdSelected);
XCTAssertTrue(element.wdHittable);
diff --git a/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m b/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m
index 461a2ae94..adbadeb32 100644
--- a/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m
+++ b/WebDriverAgentTests/IntegrationTests/FBXPathIntegrationTests.m
@@ -57,7 +57,7 @@ - (void)testSingleDescendantXMLRepresentation
NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot
options:nil];
XCTAssertNotNil(xmlStr);
- NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\"/>\n", wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdEnabled), FBBoolToString(wrappedSnapshot.wdVisible), FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdIndex];
+ NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" placeholderValue=\"%@\"/>\n", wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdEnabled), FBBoolToString(wrappedSnapshot.wdVisible), FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdIndex, wrappedSnapshot.wdPlaceholderValue];
XCTAssertEqualObjects(xmlStr, expectedXml);
}
@@ -70,7 +70,7 @@ - (void)testSingleDescendantXMLRepresentationWithScope
NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot
options:options];
XCTAssertNotNil(xmlStr);
- NSString *expectedXml = [NSString stringWithFormat:@"\n<%@>\n <%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\"/>\n%@>\n", scope, wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdEnabled), FBBoolToString(wrappedSnapshot.wdVisible), FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdIndex, scope];
+ NSString *expectedXml = [NSString stringWithFormat:@"\n<%@>\n <%@ type=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" placeholderValue=\"%@\"/>\n%@>\n", scope, wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdEnabled), FBBoolToString(wrappedSnapshot.wdVisible), FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdIndex, wrappedSnapshot.wdPlaceholderValue, scope];
XCTAssertEqualObjects(xmlStr, expectedXml);
}
@@ -83,7 +83,7 @@ - (void)testSingleDescendantXMLRepresentationWithoutAttributes
NSString *xmlStr = [FBXPath xmlStringWithRootElement:wrappedSnapshot
options:options];
XCTAssertNotNil(xmlStr);
- NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\"/>\n", wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue]];
+ NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" name=\"%@\" label=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" placeholderValue=\"%@\"/>\n", wrappedSnapshot.wdType, wrappedSnapshot.wdType, wrappedSnapshot.wdName, wrappedSnapshot.wdLabel, FBBoolToString(wrappedSnapshot.wdAccessible), [wrappedSnapshot.wdRect[@"x"] stringValue], [wrappedSnapshot.wdRect[@"y"] stringValue], [wrappedSnapshot.wdRect[@"width"] stringValue], [wrappedSnapshot.wdRect[@"height"] stringValue], wrappedSnapshot.wdPlaceholderValue];
XCTAssertEqualObjects(xmlStr, expectedXml);
}
diff --git a/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m b/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m
index fc0814c1e..e9e1a2a76 100644
--- a/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m
+++ b/WebDriverAgentTests/UnitTests/Doubles/XCElementSnapshotDouble.m
@@ -60,7 +60,7 @@ - (XCUIUserInterfaceSizeClass)verticalSizeClass
- (NSString *)placeholderValue
{
- return @"";
+ return @"testPlaceholderValue";
}
- (BOOL)isSelected
diff --git a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h
index 5720ef8ab..b2269874f 100644
--- a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h
+++ b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.h
@@ -33,6 +33,7 @@
@property (nonatomic, readwrite, getter=isWDAccessible) BOOL wdAccessible;
@property (nonatomic, readwrite, getter = isWDFocused) BOOL wdFocused;
@property (nonatomic, readwrite, getter = isWDHittable) BOOL wdHittable;
+@property (nonatomic, copy, readwrite, nullable) NSString *wdPlaceholderValue;
@property (copy, nonnull) NSArray *children;
@property (nonatomic, readwrite, assign) XCUIElementType elementType;
@property (nonatomic, readwrite, getter=isWDAccessibilityContainer) BOOL wdAccessibilityContainer;
diff --git a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m
index 9e65324b3..5f731d7ba 100644
--- a/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m
+++ b/WebDriverAgentTests/UnitTests/Doubles/XCUIElementDouble.m
@@ -23,6 +23,7 @@ - (id)init
self.wdName = @"testName";
self.wdLabel = @"testLabel";
self.wdValue = @"magicValue";
+ self.wdPlaceholderValue = @"testPlaceholderValue";
self.wdVisible = YES;
self.wdAccessible = YES;
self.wdEnabled = YES;
diff --git a/WebDriverAgentTests/UnitTests/FBXPathTests.m b/WebDriverAgentTests/UnitTests/FBXPathTests.m
index ce9171107..ad0d1988f 100644
--- a/WebDriverAgentTests/UnitTests/FBXPathTests.m
+++ b/WebDriverAgentTests/UnitTests/FBXPathTests.m
@@ -63,8 +63,8 @@ - (void)testDefaultXPathPresentation
NSString *resultXml = [self xmlStringWithElement:element
xpathQuery:nil
excludingAttributes:nil];
- NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" private_indexPath=\"top\"/>\n",
- element.wdType, element.wdType, element.wdValue, element.wdName, element.wdLabel, FBBoolToString(element.wdEnabled), FBBoolToString(element.wdVisible), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdIndex];
+ NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" placeholderValue=\"%@\" private_indexPath=\"top\"/>\n",
+ element.wdType, element.wdType, element.wdValue, element.wdName, element.wdLabel, FBBoolToString(element.wdEnabled), FBBoolToString(element.wdVisible), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdIndex, element.wdPlaceholderValue];
XCTAssertTrue([resultXml isEqualToString: expectedXml]);
}
@@ -75,8 +75,8 @@ - (void)testtXPathPresentationWithSomeAttributesExcluded
NSString *resultXml = [self xmlStringWithElement:element
xpathQuery:nil
excludingAttributes:@[@"type", @"visible", @"value", @"index"]];
- NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ name=\"%@\" label=\"%@\" enabled=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" private_indexPath=\"top\"/>\n",
- element.wdType, element.wdName, element.wdLabel, FBBoolToString(element.wdEnabled), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"]];
+ NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ name=\"%@\" label=\"%@\" enabled=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" placeholderValue=\"%@\" private_indexPath=\"top\"/>\n",
+ element.wdType, element.wdName, element.wdLabel, FBBoolToString(element.wdEnabled), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdPlaceholderValue];
XCTAssertEqualObjects(resultXml, expectedXml);
}
@@ -89,8 +89,8 @@ - (void)testXPathPresentationBasedOnQueryMatchingAllAttributes
NSString *resultXml = [self xmlStringWithElement:element
xpathQuery:[NSString stringWithFormat:@"//%@[@*]", element.wdType]
excludingAttributes:@[@"visible"]];
- NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" hittable=\"%@\" private_indexPath=\"top\"/>\n",
- element.wdType, element.wdType, @"йоло<>&"", element.wdName, @"a
b", FBBoolToString(element.wdEnabled), FBBoolToString(element.wdVisible), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdIndex, FBBoolToString(element.wdHittable)];
+ NSString *expectedXml = [NSString stringWithFormat:@"\n<%@ type=\"%@\" value=\"%@\" name=\"%@\" label=\"%@\" enabled=\"%@\" visible=\"%@\" accessible=\"%@\" x=\"%@\" y=\"%@\" width=\"%@\" height=\"%@\" index=\"%lu\" hittable=\"%@\" placeholderValue=\"%@\" private_indexPath=\"top\"/>\n",
+ element.wdType, element.wdType, @"йоло<>&"", element.wdName, @"a
b", FBBoolToString(element.wdEnabled), FBBoolToString(element.wdVisible), FBBoolToString(element.wdAccessible), element.wdRect[@"x"], element.wdRect[@"y"], element.wdRect[@"width"], element.wdRect[@"height"], element.wdIndex, FBBoolToString(element.wdHittable), element.wdPlaceholderValue];
XCTAssertEqualObjects(expectedXml, resultXml);
}
diff --git a/package.json b/package.json
index 95f0b1b33..ab880bb02 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "appium-webdriveragent",
- "version": "9.0.6",
+ "version": "9.1.0",
"description": "Package bundling WebDriverAgent",
"main": "./build/index.js",
"types": "./build/index.d.ts",