@@ -60,6 +60,12 @@ private async Task<ActionResult> FindElementFrom(Func<AutomationElement> startNo
6060 {
6161 element = await Wait . Until ( ( ) => startNode ( ) . FindFirstByXPath ( findElementRequest . Value ) , element => element != null , session . ImplicitWaitTimeout ) ;
6262 }
63+ else if ( findElementRequest . Using == "css selector" )
64+ {
65+ var ( strategy , value ) = ParseCssSelector ( findElementRequest . Value ) ;
66+ var condition = _conditionParser . ParseCondition ( session . Automation . ConditionFactory , strategy , value ) ;
67+ element = await Wait . Until ( ( ) => startNode ( ) . FindFirstDescendant ( condition ) , element => element != null , session . ImplicitWaitTimeout ) ;
68+ }
6369 else
6470 {
6571 var condition = _conditionParser . ParseCondition ( session . Automation . ConditionFactory , findElementRequest . Using , findElementRequest . Value ) ;
@@ -71,7 +77,7 @@ private async Task<ActionResult> FindElementFrom(Func<AutomationElement> startNo
7177 return NoSuchElement ( findElementRequest ) ;
7278 }
7379
74- var knownElement = session . GetOrAddKnownElement ( element ) ;
80+ var knownElement = session . GetOrAddKnownElement ( element ) ;
7581 return await Task . FromResult ( WebDriverResult . Success ( new FindElementResponse
7682 {
7783 ElementReference = knownElement . ElementReference ,
@@ -85,6 +91,12 @@ private async Task<ActionResult> FindElementsFrom(Func<AutomationElement> startN
8591 {
8692 elements = await Wait . Until ( ( ) => startNode ( ) . FindAllByXPath ( findElementRequest . Value ) , elements => elements . Length > 0 , session . ImplicitWaitTimeout ) ;
8793 }
94+ else if ( findElementRequest . Using == "css selector" )
95+ {
96+ var ( strategy , value ) = ParseCssSelector ( findElementRequest . Value ) ;
97+ var condition = _conditionParser . ParseCondition ( session . Automation . ConditionFactory , strategy , value ) ;
98+ elements = await Wait . Until ( ( ) => startNode ( ) . FindAllDescendants ( condition ) , elements => elements . Length > 0 , session . ImplicitWaitTimeout ) ;
99+ }
88100 else
89101 {
90102 var condition = _conditionParser . ParseCondition ( session . Automation . ConditionFactory , findElementRequest . Using , findElementRequest . Value ) ;
@@ -140,5 +152,47 @@ private Session GetSession(string sessionId)
140152 session . SetLastCommandTimeToNow ( ) ;
141153 return session ;
142154 }
155+
156+ private ( string strategy , string value ) ParseCssSelector ( string cssSelector )
157+ {
158+ if ( cssSelector . StartsWith ( "#" ) )
159+ {
160+ return ( "id" , cssSelector . Substring ( 1 ) ) ;
161+ }
162+ if ( cssSelector . StartsWith ( "." ) )
163+ {
164+ return ( "class name" , cssSelector . Substring ( 1 ) ) ;
165+ }
166+
167+ var nameMatch = Regex . Match ( cssSelector , @"\*?\[name\s*=\s*""(.+?)""\]" , RegexOptions . IgnoreCase ) ;
168+ if ( nameMatch . Success )
169+ {
170+ return ( "name" , UnescapeCssValue ( nameMatch . Groups [ 1 ] . Value ) ) ;
171+ }
172+
173+ var idMatch = Regex . Match ( cssSelector , @"\*?\[id\s*=\s*""(.+?)""\]" , RegexOptions . IgnoreCase ) ;
174+ if ( idMatch . Success )
175+ {
176+ return ( "id" , UnescapeCssValue ( idMatch . Groups [ 1 ] . Value ) ) ;
177+ }
178+
179+ var classMatch = Regex . Match ( cssSelector , @"\*?\[class\s*=\s*""(.+?)""\]" , RegexOptions . IgnoreCase ) ;
180+ if ( classMatch . Success )
181+ {
182+ return ( "class name" , UnescapeCssValue ( classMatch . Groups [ 1 ] . Value ) ) ;
183+ }
184+
185+ return ( "name" , cssSelector ) ;
186+ }
187+
188+ private string UnescapeCssValue ( string cssValue )
189+ {
190+ var result = Regex . Replace ( cssValue , @"\\([0-9a-fA-F]{1,6})\s?" , m =>
191+ ( ( char ) Convert . ToInt32 ( m . Groups [ 1 ] . Value , 16 ) ) . ToString ( ) ) ;
192+
193+ result = Regex . Replace ( result , @"\\(.)" , "$1" ) ;
194+
195+ return result ;
196+ }
143197 }
144198}
0 commit comments