1
+ using G4 . WebDriver . Remote ;
2
+
3
+ using System . Collections . Generic ;
4
+ using System . Net . Http ;
5
+ using System . Reflection ;
6
+ using System . Text . Json ;
7
+
8
+ #pragma warning disable S3011 // Necessary to interact with internal fields for sending native actions.
9
+ namespace G4 . WebDriver . Extensions
10
+ {
11
+ /// <summary>
12
+ /// Provides extension methods for UI automation using WebDriver.
13
+ /// </summary>
14
+ public static class UiaExtensions
15
+ {
16
+ // Initialize the static HttpClient instance for sending requests to the WebDriver server
17
+ private static HttpClient HttpClient => new ( ) ;
18
+
19
+ // Initialize the static JsonSerializerOptions instance for deserializing JSON responses
20
+ private static JsonSerializerOptions JsonSerializerOptions => new ( )
21
+ {
22
+ PropertyNamingPolicy = JsonNamingPolicy . CamelCase ,
23
+ PropertyNameCaseInsensitive = true
24
+ } ;
25
+
26
+ /// <summary>
27
+ /// Gets the UI Automation attribute value of a web element.
28
+ /// </summary>
29
+ /// <param name="element">The web element to get the attribute from.</param>
30
+ /// <param name="name">The name of the attribute.</param>
31
+ /// <returns>The attribute value as a string.</returns>
32
+ public static string GetUiaAttribute ( this IWebElement element , string name )
33
+ {
34
+ // Get the session ID and element ID from the web element
35
+ var ( sessionId , elementId ) = GetRouteData ( element ) ;
36
+
37
+ // Get the WebDriver instance from the web element
38
+ var driver = element . Driver ;
39
+
40
+ // Get the remote server URI from the command executor
41
+ var url = GetRemoteServerUri ( driver ) ;
42
+
43
+ // Construct the route for the attribute command
44
+ var requestUri = $ "{ url } /session/{ sessionId } /element/{ elementId } /attribute/{ name } ";
45
+
46
+ // Create the HTTP request for the attribute
47
+ var request = new HttpRequestMessage ( HttpMethod . Get , requestUri ) ;
48
+
49
+ // Send the HTTP request
50
+ var response = HttpClient . Send ( request ) ;
51
+
52
+ // Read the response content and deserialize the JSON response
53
+ var responseContent = response . Content . ReadAsStringAsync ( ) . Result ;
54
+ var responseObject = JsonSerializer . Deserialize < Dictionary < string , object > > ( responseContent , JsonSerializerOptions ) ;
55
+
56
+ // Try to get the value from the response object
57
+ var isValue = responseObject . TryGetValue ( "value" , out var value ) ;
58
+
59
+ // Ensure the response is successful
60
+ response . EnsureSuccessStatusCode ( ) ;
61
+
62
+ // Return the value as a string if it exists, otherwise return an empty string
63
+ return isValue ? $ "{ value } " : string . Empty ;
64
+ }
65
+
66
+ /// <summary>
67
+ /// Sends a native click command to a web element.
68
+ /// </summary>
69
+ /// <param name="element">The web element to click.</param>
70
+ public static void SendNativeClick ( this IWebElement element )
71
+ {
72
+ // Get the session ID and element ID from the web element
73
+ var ( sessionId , elementId ) = GetRouteData ( element ) ;
74
+
75
+ // Get the WebDriver instance from the web element
76
+ var driver = element . Driver ;
77
+
78
+ // Get the remote server URI from the command executor
79
+ var url = GetRemoteServerUri ( driver ) ;
80
+
81
+ // Construct the route for the native click command
82
+ var requestUri = $ "{ url } /session/{ sessionId } /user32/element/{ elementId } /click";
83
+
84
+ // Create the HTTP request for the native click
85
+ var request = new HttpRequestMessage ( HttpMethod . Post , requestUri ) ;
86
+
87
+ // Send the HTTP request
88
+ var response = HttpClient . Send ( request ) ;
89
+
90
+ // Ensure the response is successful
91
+ response . EnsureSuccessStatusCode ( ) ;
92
+ }
93
+
94
+ /// <summary>
95
+ /// Sends a native double-click command to a web element.
96
+ /// </summary>
97
+ /// <param name="element">The web element to double-click.</param>
98
+ public static void SendNativeDoubleClick ( this IWebElement element )
99
+ {
100
+ // Get the session ID and element ID from the web element
101
+ var ( sessionId , elementId ) = GetRouteData ( element ) ;
102
+
103
+ // Get the WebDriver instance from the web element
104
+ var driver = element . Driver ;
105
+
106
+ // Get the remote server URI from the command executor
107
+ var url = GetRemoteServerUri ( driver ) ;
108
+
109
+ // Construct the route for the native double-click command
110
+ var requestUri = $ "{ url } /session/{ sessionId } /user32/element/{ elementId } /dclick";
111
+
112
+ // Create the HTTP request for the native double-click
113
+ var request = new HttpRequestMessage ( HttpMethod . Post , requestUri ) ;
114
+
115
+ // Send the HTTP request
116
+ var response = HttpClient . Send ( request ) ;
117
+
118
+ // Ensure the response is successful
119
+ response . EnsureSuccessStatusCode ( ) ;
120
+ }
121
+
122
+ /// <summary>
123
+ /// Sets focus on a web element.
124
+ /// </summary>
125
+ /// <param name="element">The web element to set focus on.</param>
126
+ public static void SetFocus ( this IWebElement element )
127
+ {
128
+ // Get the session ID and element ID from the web element
129
+ var ( sessionId , elementId ) = GetRouteData ( element ) ;
130
+
131
+ // Get the WebDriver instance from the web element
132
+ var driver = element . Driver ;
133
+
134
+ // Get the remote server URI from the command executor
135
+ var url = GetRemoteServerUri ( driver ) ;
136
+
137
+ // Construct the route for the native focus command
138
+ var requestUri = $ "{ url } /session/{ sessionId } /user32/element/{ elementId } /focus";
139
+
140
+ // Create the HTTP request for the native focus
141
+ var request = new HttpRequestMessage ( HttpMethod . Get , requestUri ) ;
142
+
143
+ // Send the HTTP request
144
+ var response = HttpClient . Send ( request ) ;
145
+
146
+ // Ensure the response is successful
147
+ response . EnsureSuccessStatusCode ( ) ;
148
+ }
149
+
150
+ // Gets the remote server URI from the WebDriver command executor.
151
+ private static string GetRemoteServerUri ( IWebDriver driver )
152
+ {
153
+ // Get the remote server URI from the command executor using reflection
154
+ return driver . GetServerAddress ( ) . AbsoluteUri . Trim ( '/' ) ;
155
+ }
156
+
157
+ // Gets the session ID and element ID from a web element.
158
+ private static ( string SessionId , string ElementId ) GetRouteData ( IWebElement element )
159
+ {
160
+ const BindingFlags bindingFlags = BindingFlags . Instance | BindingFlags . NonPublic ;
161
+
162
+ // Get the WebDriver instance from the web element
163
+ var driver = element . Driver ;
164
+
165
+ // Get the session ID from the WebDriver
166
+ var sessionId = $ "{ ( ( IWebDriverSession ) driver ) . Session } ";
167
+
168
+ // Return the session ID and element ID as a tuple
169
+ return ( sessionId , element . Id ) ;
170
+ }
171
+ }
172
+ }
0 commit comments