18using System.Collections.Generic;
19using System.Collections.ObjectModel;
23using System.Threading.Tasks;
27using System.Reflection;
28using DocumentFormat.OpenXml.Spreadsheet;
41 public string Xpath {
get;
set; }
63 public class ClientRectangle
66 public float Top {
get;
set; }
68 public float Left {
get;
set; }
72 public float Right {
get;
set; }
74 public float X {
get;
set; }
76 public float Y {
get;
set; }
78 public float Width {
get;
set; }
101 return new Dictionary<string, object>
157 public Dictionary<string, object>
Attributes {
get;
set; } =
new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
159 private Dictionary<string, object> _cssAttributes;
167 if (
null == _cssAttributes)
169 GPAL.
PublishSimpleEvent(GPALEventType.DEBUG, $
"Getting Css Attributes for element [{TagName}]",
this, GPALObjectType.Other);
172 _cssAttributes =
Browser.PuppeteerClient.GetCssAttributes(ElementBackendNodeId.ToString()).Execute<Dictionary<string, object>>();
174 _cssAttributes =
Browser.MagicHelper.GetCssAttributes(
Css);
178 if (
null == _cssAttributes)
179 _cssAttributes =
new Dictionary<string, object>();
181 GPAL.
PublishSimpleEvent(GPALEventType.DEBUG, $
"Got [{_cssAttributes.Count}] Css Attributes for element [{TagName}]",
this, GPALObjectType.Other);
183 return _cssAttributes;
185 set => _cssAttributes = value;
188 private Dictionary<string, object> _domAttributes;
196 if (
null == _domAttributes)
198 GPAL.
PublishSimpleEvent(GPALEventType.DEBUG, $
"Getting Dom Attributes for element [{TagName}]",
this, GPALObjectType.Other);
201 _domAttributes =
Browser.PuppeteerClient.GetDomAttributes(ElementBackendNodeId.ToString()).Execute<Dictionary<string, object>>();
203 _domAttributes =
Browser.MagicHelper.GetDomAttributes(
Css);
207 if (
null == _domAttributes)
208 _domAttributes =
new Dictionary<string, object>();
210 GPAL.
PublishSimpleEvent(GPALEventType.DEBUG, $
"Got [{_domAttributes.Count}] Dom Attributes for element [{TagName}]",
this, GPALObjectType.Other);
212 return _domAttributes;
214 set => _domAttributes = value;
217 private Dictionary<string, object> _domProperties;
225 if (
null == _domProperties)
227 GPAL.
PublishSimpleEvent(GPALEventType.DEBUG, $
"Getting Dom Properties for element [{TagName}]",
this, GPALObjectType.Other);
230 _domProperties =
Browser.PuppeteerClient.GetDomProperties(ElementBackendNodeId.ToString()).Execute<Dictionary<string, object>>();
232 _domProperties =
Browser.MagicHelper.GetDomProperties(
Css);
236 if (
null == _domProperties)
237 _domProperties =
new Dictionary<string, object>();
239 GPAL.
PublishSimpleEvent(GPALEventType.DEBUG, $
"Got [{_domProperties.Count}] Dom Properties for element [{TagName}]",
this, GPALObjectType.Other);
241 return _domProperties;
243 set => _domProperties = value;
251 internal dynamic iWebElement;
258 internal set => iWebElement = value;
261 public string ElementHandle {
get;
set; }
262 public int ElementNodeId {
get;
set; }
263 public int ElementBackendNodeId {
get;
set; }
264 internal long? ContextId {
get;
set; }
265 internal bool IsShadowRoot {
get;
set; } =
false;
271 internal bool IsClosedShadowRoot {
get;
set; } =
false;
290 get {
return Attributes.ContainsKey(
"attributeName") ?
Attributes[
"attributeName"] as string :
null; }
333 bool indeterminate =
Attributes.ContainsKey(
"indeterminate")
337 return true == indeterminate ? (
bool?)
null :
Selected;
353 internal CoordinateSpace CoordinateSpace
355 get {
return Attributes.ContainsKey(
"coordinateSpace") &&
Attributes[
"coordinateSpace"] is CoordinateSpace ? (CoordinateSpace)
Attributes[
"coordinateSpace"] : CoordinateSpace.Screen; }
356 set {
Attributes[
"coordinateSpace"] = value; }
365 internal GPALElement ImageMatch {
get;
set; }
379 bool visibilty =
true;
384 visibilty =
CssAttributes[
"visibility"]?.ToString() !=
"hidden";
392 bool notHidden = visibilty && display && opacity;
394 bool hasSize = BoundingRect.Width > 0 && BoundingRect.Height > 0;
396 return notHidden && hasSize;
425 get {
return Attributes.ContainsKey(
"placeholder") ?
Attributes[
"placeholder"] as string :
null; }
493 internal GPALElement(Point location,
Size size,
string text, IWebDriver webDriver,
string tagname =
"img")
497 Text = CleanText(text);
503 internal GPALElement(IWebElement webElement,
string attributeName =
"")
505 iWebElement = webElement;
507 if (webElement !=
null)
510 Text = CleanText(webElement.Text);
514 Size = webElement.Size;
516 Href = webElement.GetAttribute(
"href");
517 Src = webElement.GetAttribute(
"src");
518 Value = CleanText(webElement.GetAttribute(
"value"));
519 Placeholder = CleanText(webElement.GetAttribute(
"placeholder"));
520 Type = webElement.GetAttribute(
"type");
541 internal GPALElement(IWebElement webElement,
string attributeName, Dictionary<string, object> properties,
string pageUrl)
543 iWebElement = webElement;
546 TagName = StringOf(properties,
"tag");
547 Text = CleanText(StringOf(properties,
"text"));
548 Enabled = BoolOf(properties,
"enabled");
549 Selected = BoolOf(properties,
"selected");
550 Attributes[
"indeterminate"] = BoolOf(properties,
"indeterminate");
551 Displayed = BoolOf(properties,
"displayed");
552 Location =
new Point(IntOf(properties,
"x"), IntOf(properties,
"y"));
553 Size =
new Size(IntOf(properties,
"w"), IntOf(properties,
"h"));
554 Href = StringOf(properties,
"href");
555 Src = StringOf(properties,
"src");
556 Value = CleanText(StringOf(properties,
"value"));
557 Placeholder = CleanText(StringOf(properties,
"placeholder"));
558 Type = StringOf(properties,
"type");
567 static string StringOf(Dictionary<string, object> properties,
string name)
569 return true == properties.TryGetValue(name, out
object value) ? value?.ToString() :
null;
575 static bool BoolOf(Dictionary<string, object> properties,
string name)
577 return true == properties.TryGetValue(name, out
object value) &&
true == Convert.ToBoolean(value);
583 static int IntOf(Dictionary<string, object> properties,
string name)
585 return true == properties.TryGetValue(name, out
object value) &&
null != value ? Convert.ToInt32(value) : 0;
588 internal GPALElement(Dictionary<string, object> attributes,
Browser.Browser browser)
591 Attributes = attributes ??
new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
598 if (iWebElement !=
null)
607 public void Click(ModifierKeys modifierKeys)
609 string currentUrl =
Browser.BrowserSettings.CurrentURL;
610 Browser.CurrentUOW.ActionCalled =
true;
613 ElementHelper.Click(
Browser,
Selector,
this, ClickType.LeftClick, modifierKeys);
615 string currentUrl2 =
Browser.GetSetCurrentUrl();
617 if (
false == UrlHelper.AreEquivalent(currentUrl, currentUrl2))
624 Click(ModifierKeys.NONE);
628 public void MiddleClick(ModifierKeys modifierKeys = ModifierKeys.NONE)
630 Browser.CurrentUOW.ActionCalled =
true;
632 ElementHelper.Click(
Browser,
Selector,
this, ClickType.MiddleClick, modifierKeys);
639 Browser.CurrentUOW.ActionCalled =
true;
640 ElementHelper.Hide(
Browser,
this);
646 if (iWebElement !=
null)
647 return iWebElement.FindElement(by);
648 throw new NoSuchElementException(
"Element not found using " + by);
654 if (iWebElement !=
null)
655 return iWebElement.FindElements(by);
656 return new ReadOnlyCollection<IWebElement>(
new List<IWebElement>());
662 string seleniumValue =
null;
664 if (iWebElement !=
null)
665 seleniumValue = iWebElement.GetAttribute(
char.ToUpper(attributeName[0]) + attributeName.Substring(1));
667 if (
null == seleniumValue)
671 if (value is Point p)
672 return string.Format(
"({0},{1})", p.X, p.Y);
674 return string.Format(
"({0},{1})", s.Width, s.Height);
676 return string.Join(
"; ", arr.Select(x =>
string.Format(
"{0} ({1})", x.Xpath, x.MatchedElements)));
678 return string.Format(
"(top={0}, left={1}, bottom={2}, right={3}, x={4}, y={5}, width={6}, height={7})",
679 r.Top, r.Left, r.Bottom, r.Right, r.X, r.Y, r.Width, r.Height);
682 return value.ToString();
685 PropertyInfo
property = GetType().GetProperty(attributeName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
686 if (property !=
null && property.CanRead)
687 return property.GetValue(
this,
null)?.ToString();
703 ElementHelper.SetAttribute(
Browser,
this, attributeName, value);
709 return iWebElement !=
null ? iWebElement.GetCssValue(propertyName) :
CssAttributes[propertyName];
715 return iWebElement !=
null ? iWebElement.GetDomAttribute(attributeName) :
DomAttributes[attributeName];
721 return iWebElement !=
null ? iWebElement.GetDomProperty(propertyName) :
DomProperties[propertyName];
728 var shadowRoot = iWebElement !=
null ? iWebElement.GetShadowRoot() :
ShadowRoot;
736 if (iWebElement !=
null)
737 iWebElement.SendKeys(text);
743 if (iWebElement !=
null)
744 iWebElement.Submit();
750 bool attrDisabled =
Attributes.ContainsKey(
"disabled") &&
Attributes[
"disabled"].ToString() ==
"true";
751 bool propDisabled =
false;
754 propDisabled =
DomProperties[
"disabled"].ToString() ==
"true";
756 return attrDisabled || propDisabled;
771 bool isClickable =
true;
773 if (
true ==
Browser.UseOttoMagic)
774 isClickable =
Browser.MagicHelper.IsClickAble(
Css);
782 Attributes.TryGetValue(
"aria-disabled", out var aria) &&
783 aria.ToString().Equals(
"true", StringComparison.OrdinalIgnoreCase);
785 bool pointerOk =
true;
786 if (
true ==
CssAttributes.TryGetValue(
"pointer-events", out var pe))
787 pointerOk = pe.ToString() !=
"none";
795 if (
false == isClickable &&
true == publishEvent)
797 GPALEventType.WARNING,
798 $
"Element [{TagName}] does not appear clickable.",
800 GPALObjectType.Other);
807 private bool disposed =
false;
814 if (disposed ||
string.IsNullOrEmpty(ElementHandle))
return;
816 if (
true ==
Browser.UsePuppeteer)
820 await
Browser.PuppeteerCommunicator.SendCommand<
object>(
821 DevToolsMethods.RuntimeReleaseObject,
822 new { objectId = ElementHandle },
830 ElementHandle =
null;
842 static string CleanText(
string str) => str is
null ? null : System.Text.RegularExpressions.Regex.Replace(str,
@"\s+",
" ").Trim();
Browser object that contains the fluent methods to create your Browser workflow. Instatiated using G...
Represents a client-side bounding rectangle (similar to DOMRect) with additional convenience properti...
float Top
Gets or sets the top coordinate.
float Right
Gets or sets the right coordinate.
float Bottom
Gets or sets the bottom coordinate.
Dictionary< string, object > ToDictionary()
Converts the rectangle properties to a dictionary for easy serialization or logging.
float Y
Gets or sets the Y coordinate.
ClientRectangle()
Creates an empty ClientRectangle.
float Height
Gets or sets the height.
Size Size
Gets or sets the Size as a System.Drawing.Size.
bool IsEmpty
Determines whether the rectangle has zero dimensions and position.
float Left
Gets or sets the left coordinate.
float Width
Gets or sets the width.
float X
Gets or sets the X coordinate.
Pseudo element used in Applications and Browser workflows for image matching and unified automation....
void MiddleClick(ModifierKeys modifierKeys=ModifierKeys.NONE)
Performs a middle mouse button click.
string Xpath
XPath used to locate this element.
bool Displayed
Whether the element is visible on the page.
async Task DisposeAsync()
Asynchronously releases resources (especially Puppeteer object handles).
bool IsClickable(bool publishEvent=true)
Determines whether the element appears clickable based on visibility, disabled state,...
bool IsDisabled()
Checks if the element is disabled via attributes or properties.
string PageURL
Current page URL when the element was captured.
bool? Checked
A checkbox's state, which has three of them: true ticked, false clear, and null for the third one,...
string Text
Visible text content of the element.
string Placeholder
placeholder attribute.
Dictionary< string, object > Attributes
All raw attributes returned from the automation backend.
string Type
The type of the element, for input, this can be many.
string Name
Name attribute of the element.
Size Size
Dimensions of the element.
void Click(ModifierKeys modifierKeys)
Performs a click with optional keyboard modifiers.
bool IsEnabled()
Checks if the element is enabled.
IWebElement FindElement(By by)
Finds a child element using Selenium By locator.
void SendKeys(string text)
Sends keystrokes to the element.
string GetDomAttribute(string attributeName)
Gets a DOM attribute.
Dictionary< string, object > CssAttributes
CSS computed style properties for the element.
bool Selected
Whether the element is selected (e.g. checkboxes, radio buttons).
string GetCssValue(string propertyName)
Gets a computed CSS value.
string TagName
HTML tag name of the element.
void Click()
Performs a standard left click.
Browser.Browser Browser
Associated Browser instance.
string GetAttribute(string attributeName)
Gets an attribute value with fallback to internal dictionary.
void Submit()
Submits the form if the element is part of one.
Point Location
Screen coordinates of the element.
GPALElement ShadowRoot
Shadow root if the element contains one.
string Value
value attribute (inputs, textareas, etc.).
ISearchContext GetShadowRoot()
Returns the ShadowRoot if available.
void SetAttribute(string attributeName, string value)
Directly sets a DOM attribute on this element via element.setAttribute(attributeName,...
string AttributeName
Custom attribute name (used internally).
void Hide()
Hides the element via JavaScript (sets display:none).
string FullXPath
Full absolute XPath.
string Css
CSS selector used to locate this element.
ClientRectangle BoundingRect
Client bounding rectangle with detailed coordinates.
string GetDomProperty(string propertyName)
Gets a DOM property.
Dictionary< string, object > DomAttributes
DOM attributes of the element.
void Clear()
Clears the element's value (if supported by underlying element).
string Href
href attribute (for links).
Dictionary< string, object > DomProperties
DOM properties of the element.
IWebDriver WrappedDriver
The underlying Selenium WebDriver instance.
void Dispose()
Disposes the element (fire-and-forget async cleanup).
bool Enabled
Whether the element is enabled.
Selector Selector
Selector used to locate this element.
XPathInfo[] Xpaths
Array of alternative XPaths with match counts.
string Src
src attribute (for images, scripts, etc.).
dynamic WebElement
The wrapped Selenium IWebElement or internal dynamic element.
ReadOnlyCollection< IWebElement > FindElements(By by)
Finds all child elements using Selenium By locator.
Everything starts here, all the GPAL controls and global settings using fluent syntax are here....
static void PublishSimpleEvent(GPALEventType gPALEventType, string msg, dynamic gPALObject=null, Enums.GPALObjectType gPALObjectType=GPALObjectType.None, Exception ex=null)
Publish a message to either the information channel or exception channel (if exception passed in) Pub...
Represents XPath matching information returned by advanced selector strategies.
XPathInfo(string xpath, int matchedElements)
Creates a new XPathInfo instance.
int MatchedElements
Number of elements matched by this XPath on the page.
string Xpath
The generated XPath expression.