GPAL - Generally Positive Automation Library v1.0
GPAL The Fluent Automation LIbrary
Loading...
Searching...
No Matches
Selector.cs
1// =============================================================================
2// GPAL - Generally Positive Automation Library
3// Copyright © 2026 Software Decisions, Inc. All rights reserved.
4//
5// This file is part of GPAL.
6// Licensed under the Business Source License 1.1
7//
8// Primary development, architecture, and vision by Michael B. Vederman,
9// CEO of Software Decisions, Inc., Texas.
10//
11// Internal development maintained privately.
12// Public releases appear on GitHub: https://github.com/SoftwareDecisionsInc/GPAL.
13//
14// See LICENSE for full terms, including Additional Use Grant.
15// =============================================================================
16
17using System;
18using System.Collections.Generic;
19using System.Drawing;
20using System.Linq;
21using System.Text;
22using System.Threading.Tasks;
23using OpenQA.Selenium;
24using static GenerallyPositive.Enums;
27using System.Windows.Automation;
29using System.Reflection;
31
32/*
33 var searchSelector = GPAL.Selector
34 .WithCSS(string) // class
35 .WithXpath(string) // id / name
36 .WithText(string) // value
37 .WithImage(string) // image path or image ptr?
38 .WithOffset(coor) // for clicking x,y coord
39 .EvaluationOrder(enum) // order to try finding object
40*/
41namespace GenerallyPositive
42{
43 internal class SmallSelectorNode
44 {
45 public InteractionType InteractionType { get; internal set; }
46 public int OffsetX { get; internal set; }
47 public int OffsetY { get; internal set; }
48 public int DeltaX { get; internal set; }
49 public int DeltaY { get; internal set; }
50 }
55 public class Selector : IAllowSelectorSettings
56 {
57 // deep copy cannot have property passed as ref
58 internal SelectorSettings selectorSettings = null;
59 public SelectorSettings SelectorSettings
60 {
61 get
62 {
63 return selectorSettings;
64 }
65 internal set
66 {
67 selectorSettings = value;
68 }
69 }
70
71 public SelectorType SelectorType
72 {
73 get
74 {
75 return SelectorSettings.SelectorType;
76 }
77
78 set
79 {
80 selectorSettings.SelectorType = value;
81 }
82 }
83 private Application.Application MyApplication { get; set; } = null;
84
85 public Selector ToGPALObject()
86 {
87 return this;
88 }
89
99 public delegate CallIfStatus webMatchingFunction(List<IGPALElement> foundElements, out List<IGPALElement> matchedElements, out bool matchedAll, Selector selector, bool ExactMatch = true);
100
110 public delegate CallIfStatus appMatchingFunction(List<GPALAutomationElement> foundElements, out List<GPALAutomationElement> matchedElements, out bool matchedAll, Selector selector, bool ExactMatch = true);
111
112
113 internal Selector(Browser.Browser browser, Selector selector)
114 {
115 SelectorSettings = new SelectorSettings();
116
117 Browser = browser;
118 selectorSettings = ObjectCopier.DeepCopyObject(selector.SelectorSettings, selectorSettings, DeepCopy.FieldsAndProperties);
119 if (true == string.IsNullOrEmpty(selector.Name))
120 Name = $"Selector{browser.CurrentUOW.WithSelectorList.Count}";
121 else
122 Name = selector.Name; // shoulda been copied?
123
125 }
126 internal Selector(Browser.Browser browser)
127 {
128 Browser = browser;
130 Name = $"Selector{browser.CurrentUOW.WithSelectorList.Count}";
131 }
132
133 internal Selector(Application.Application application, Selector selector)
134 {
135 SelectorSettings = new SelectorSettings();
136
137 MyApplication = application;
138 selectorSettings = ObjectCopier.DeepCopyObject(selector.SelectorSettings, selectorSettings, DeepCopy.FieldsAndProperties);
139 if (true == string.IsNullOrEmpty(selector.Name))
140 Name = $"Selector{application.CurrentUOW.WithSelectorList.Count}";
141 else
142 Name = selector.Name; // shoulda been copied?
143
145 }
146 internal Selector(Application.Application application)
147 {
148 MyApplication = application;
149 SelectorSettings = new SelectorSettings();
150 Name = $"Selector{application.CurrentUOW.WithSelectorList.Count}";
151 }
152 internal Selector()
153 {
154 SelectorSettings = new SelectorSettings();
155 }
156 internal bool AnyMatchCriteria()
157 {
158 return 0 < MatchCriteria.Count;
159 }
160
161 #region <Fluent Settings>
169 {
170 SelectorSettings.SelectorPathEntry selectorPathEntry = new SelectorSettings.SelectorPathEntry { SelectorPath = css, SelectorPathType = SelectorPathType.Css };
171 SelectorSettings.SelectorPaths.Add(selectorPathEntry);
172 return this;
173 }
174
181 {
182 SelectorSettings.SelectorPathEntry selectorPathEntry = new SelectorSettings.SelectorPathEntry { SelectorPath = xPath, SelectorPathType = SelectorPathType.Xpath };
183 SelectorSettings.SelectorPaths.Add(selectorPathEntry);
184 return this;
185 }
186
193 {
194 SelectorSettings.SelectorPathEntry selectorPathEntry = new SelectorSettings.SelectorPathEntry { SelectorPath = text, SelectorPathType = SelectorPathType.Text };
195 SelectorSettings.SelectorPaths.Add(selectorPathEntry);
196 return this;
197 }
198
205 {
206 SelectorSettings.SelectorPathEntry selectorPathEntry = new SelectorSettings.SelectorPathEntry { SelectorPath = value, SelectorPathType = SelectorPathType.Value };
207 SelectorSettings.SelectorPaths.Add(selectorPathEntry);
208 return this;
209 }
210
217 {
218 SelectorSettings.SelectorPathEntry selectorPathEntry = new SelectorSettings.SelectorPathEntry { SelectorPath = name, SelectorPathType = SelectorPathType.Name };
219 SelectorSettings.SelectorPaths.Add(selectorPathEntry);
220 return this;
221 }
222
228 public IAllowSelectorSettings WithClassName(string className)
229 {
230 SelectorSettings.SelectorPathEntry selectorPathEntry = new SelectorSettings.SelectorPathEntry { SelectorPath = className, SelectorPathType = SelectorPathType.ClassName };
231 SelectorSettings.SelectorPaths.Add(selectorPathEntry);
232 return this;
233 }
234
240 public IAllowSelectorSettings WithAutomationID(string automationID)
241 {
242 SelectorSettings.SelectorPathEntry selectorPathEntry = new SelectorSettings.SelectorPathEntry { SelectorPath = automationID, SelectorPathType = SelectorPathType.AutomationID };
243 SelectorSettings.SelectorPaths.Add(selectorPathEntry);
244 return this;
245 }
246
253 public IAllowSelectorSettings WithImage(string base64String)
254 {
255 try
256 {
257 Image image = ImageHelper.Base64ToImage(base64String);
258 SelectorSettings.SelectorPathEntry selectorPathEntry = new SelectorSettings.SelectorPathEntry { SelectorPathType = SelectorPathType.Image, Image = image };
259 SelectorSettings.SelectorPaths.Add(selectorPathEntry);
260 } catch
261 {
262 // try passing the string as a filename, it's not base64
263 return WithImage((GPALFile)base64String);
264 }
265 return this;
266 }
267
275 {
276 SelectorSettings.SelectorPathEntry selectorPathEntry = new SelectorSettings.SelectorPathEntry { SelectorPathType = SelectorPathType.Image, Image = image };
277 SelectorSettings.SelectorPaths.Add(selectorPathEntry);
278 return this;
279 }
280
286 [SingleUse(Description = "")]
287 public IAllowSelectorSettings WithSearchForSelector(bool searchForElement)
288 {
289 SelectorSettings.SearchForSelector = searchForElement;
290 return this;
291 }
292
298 [SingleUse(Description = "")]
300 {
301 SelectorSettings.Name = name;
302 return this;
303 }
304
309 [SingleUse(Description = "")]
311 {
312 SelectorSettings.DeltaX = deltaX;
313 return this;
314 }
315
320 [SingleUse(Description = "")]
322 {
323 SelectorSettings.DeltaY = deltaY;
324 return this;
325 }
326
331 [SingleUse(Description = "")]
333 {
334 SelectorSettings.OffsetX = offsetX;
335 return this;
336 }
337
342 [SingleUse(Description = "")]
344 {
345 SelectorSettings.OffsetY = offsetY;
346 return this;
347 }
348
353 [SingleUse(Description = "")]
355 {
356 SelectorSettings.SimulateMouse = moveWithArc;
357 SelectorSettings.InteractionType = InteractionType.Hardware;
358 SelectorSettings.RequestedInteractionType = InteractionType.Hardware;
359 return this;
360 }
361 [SingleUse(Description = "")]
362 public IAllowSelectorSettings UseAttribute(string attributeName)
363 {
364 SelectorSettings.AttributeName = attributeName;
365 return this;
366 }
372 public IAllowSelectorSettings MatchFunction(Selector.appMatchingFunction matchingFunction)
373 {
374 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Custom, AppMatchingFunction = matchingFunction };
375 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
376 return this;
377 }
378
383 public IAllowSelectorSettings MatchFunction(Selector.webMatchingFunction matchingFunction)
384 {
385 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Custom, WebMatchingFunction = matchingFunction };
386 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
387 return this;
388 }
389
394 public IAllowSelectorSettings MatchAttribute(string attributeToMatch)
395 {
396 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Attribute, StringToMatch = attributeToMatch };
397 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
398 return this;
399 }
400
405 public IAllowSelectorSettings MatchAttributeRegex(string attributeToMatch)
406 {
407 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Regex | MatchType.Attribute, StringToMatch = attributeToMatch };
408 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
409 return this;
410 }
411
416 public IAllowSelectorSettings MatchHRef(string hrefToMatch) // image path or actual image?
417 {
418 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Href, StringToMatch = hrefToMatch };
419 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
420 return this;
421 }
422
427 public IAllowSelectorSettings MatchHRefRegex(string hrefToMatch) // image path or actual image?
428 {
429 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Regex | MatchType.Href, StringToMatch = hrefToMatch };
430 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
431 return this;
432 }
433
438 public IAllowSelectorSettings MatchPlaceholder(string placeholderToMatch) // image path or actual image?
439 {
440 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Placeholder, StringToMatch = placeholderToMatch };
441 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
442 return this;
443 }
444
449 public IAllowSelectorSettings MatchPlaceholderRegex(string placeholderToMatch) // image path or actual image?
450 {
451 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Regex | MatchType.Placeholder, StringToMatch = placeholderToMatch };
452 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
453 return this;
454 }
455
460 public IAllowSelectorSettings MatchSrc(string srcToMatch)
461 {
462 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Src, StringToMatch = srcToMatch };
463 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
464 return this;
465 }
466
471 public IAllowSelectorSettings MatchSrcRegex(string srcToMatch)
472 {
473 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Regex | MatchType.Src, StringToMatch = srcToMatch };
474 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
475 return this;
476 }
477
482 public IAllowSelectorSettings MatchText(string textToMatch)
483 {
484 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Text, StringToMatch = textToMatch };
485 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
486 return this;
487 }
488
493 public IAllowSelectorSettings MatchTextRegex(string textToMatch)
494 {
495 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Regex | MatchType.Text, StringToMatch = textToMatch };
496 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
497 return this;
498 }
499
504 public IAllowSelectorSettings MatchValue(string valueToMatch)
505 {
506 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Value, StringToMatch = valueToMatch };
507 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
508 return this;
509 }
510
515 public IAllowSelectorSettings MatchValueRegex(string valueToMatch)
516 {
517 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Regex | MatchType.Value, StringToMatch = valueToMatch };
518 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
519 return this;
520 }
521
524 public void Remove()
525 {
526 DeleteMe = true;
527 }
528
533 public IAllowSelectorSettings WithOCR(string textToFind)
534 {
535 throw new NotImplementedException();
536 }
537
542 public IAllowSelectorSettings WithStopOnNotFound(bool stopOnNotFound)
543 {
544 SelectorSettings.StopOnNotFound = stopOnNotFound;
545 return this;
546 }
547 public IAllowSelectorSettings CallIfFound(CallIfDelegate callIfFound)
548 {
549 SelectorSettings.CallIfFound.Add(callIfFound);
550 return this;
551 }
552 public IAllowSelectorSettings CallIfNotFound(CallIfDelegate callIfNotFound)
553 {
554 SelectorSettings.CallIfNotFound.Add(callIfNotFound);
555 return this;
556 }
557
566 {
567 foreach (string filename in imageToFindPath.Filenames)
568 {
569 SelectorSettings.SelectorPathEntry selectorPathEntry = new SelectorSettings.SelectorPathEntry { SelectorPath = filename, SelectorPathType = SelectorPathType.Image };
570 SelectorSettings.SelectorPaths.Add(selectorPathEntry);
571 }
572 return this;
573 }
574
575 public IAllowSelectorSettings WithHRef(string HRefFullOrPartial)
576 {
577 selectorSettings.HRef = HRefFullOrPartial;
578 return this;
579 }
580 #endregion <Fluent Settings>
581
582 #region <Getter/Setters>
583
584 // TECHNIQUES of dealing with Selector
590 {
591 get
592 {
593 SelectorSettings.InteractionType = InteractionType.Hardware;
594 SelectorSettings.RequestedInteractionType = InteractionType.Hardware;
595 return this;
596 }
597 }
598
603 {
604 get
605 {
606 SelectorSettings.InteractionType = InteractionType.JavaScript;
607 SelectorSettings.RequestedInteractionType = InteractionType.JavaScript;
608 return this;
609 }
610 }
611 [Obsolete("This method is not preferred. Consider using WithJavaScript instead.", false)]
612 public IAllowSelectorSettings WithJavascript
613 {
614 get
615 {
616 SelectorSettings.InteractionType = InteractionType.JavaScript;
617 SelectorSettings.RequestedInteractionType = InteractionType.JavaScript;
618 return this;
619 }
620 }
626 {
627 get
628 {
629 SelectorSettings.InteractionType = InteractionType.Selenium;
630 SelectorSettings.RequestedInteractionType = InteractionType.Selenium;
631 return this;
632 }
633 }
634
639 {
640 get
641 {
642 return SelectorSettings.ElementsFoundAndMatchedCount;
643 }
644 internal set
645 {
646 SelectorSettings.ElementsFoundAndMatchedCount = value;
647 }
648 }
649 internal CallIfStatus AppCallIfFoundHandled
650 {
651 get
652 {
653 return SelectorSettings.AppCallIfFoundHandled;
654 }
655 set
656 {
657 SelectorSettings.AppCallIfFoundHandled = value;
658 }
659 }
660 internal CallIfStatus AppCallIfNotFoundHandled
661 {
662 get
663 {
664 return SelectorSettings.AppCallIfNotFoundHandled;
665 }
666 set
667 {
668 SelectorSettings.AppCallIfNotFoundHandled = value;
669 }
670 }
671 internal CallIfStatus CallIfFoundHandled
672 {
673 get
674 {
675 return SelectorSettings.CallIfFoundHandled;
676 }
677 set
678 {
679 SelectorSettings.CallIfFoundHandled = value;
680 }
681 }
682 internal CallIfStatus CallIfNotFoundHandled
683 {
684 get
685 {
686 return SelectorSettings.CallIfNotFoundHandled;
687 }
688 set
689 {
690 SelectorSettings.CallIfNotFoundHandled = value;
691 }
692 }
693 internal Application.Application Application
694 {
695 get
696 {
697 return MyApplication;
698 }
699 set
700 {
701 MyApplication = value;
702 }
703 }
704 internal List<Application.Application.CallIfDelegate> AppCallIfFound
705 {
706 get
707 {
708 return SelectorSettings.AppCallIfFound;
709 }
710 }
711 internal List<Application.Application.CallIfDelegate> AppCallIfNotFound
712 {
713 get
714 {
715 return SelectorSettings.AppCallIfNotFound;
716 }
717 }
718 internal string AttributeName
719 {
720 get
721 {
722 return SelectorSettings.AttributeName;
723 }
724 }
731 {
732 get
733 {
734 return SelectorSettings.InteractionType;
735 }
736 internal set
737 {
738 SelectorSettings.InteractionType = value;
739 }
740 }
741
746 {
747 get;
748 internal set;
749 }
750
753 public string SelectorPath
754 {
755 get
756 {
757 return SelectorSettings.SelectorPaths[0].SelectorPath;
758 }
759 }
760
764 public List<SelectorSettings.SelectorPathEntry> SelectorPaths
765 {
766 get
767 {
768 return SelectorSettings.SelectorPaths;
769 }
770 }
771 internal List<SelectorSettings.MatchCriteriaEntry> MatchCriteria
772 {
773 get
774 {
775 return SelectorSettings.MatchCriteria;
776 }
777 }
783 {
784 get
785 {
786 return SelectorSettings.SearchForSelector;
787 }
788 }
789
794 public int OffsetX
795 {
796 get
797 {
798 return SelectorSettings.OffsetX;
799 }
800 internal set
801 {
802 SelectorSettings.OffsetX = value;
803 }
804 }
805
810 public int OffsetY
811 {
812 get
813 {
814 return SelectorSettings.OffsetY;
815 }
816 internal set
817 {
818 SelectorSettings.OffsetY = value;
819 }
820 }
821
825 public int DeltaX
826 {
827 get
828 {
829 return SelectorSettings.DeltaX;
830 }
831 internal set
832 {
833 SelectorSettings.DeltaX = value;
834 }
835 }
836
840 public int DeltaY
841 {
842 get
843 {
844 return SelectorSettings.DeltaY;
845 }
846 internal set
847 {
848 SelectorSettings.DeltaY = value;
849 }
850 }
851
857 public string Name
858 {
859 get
860 {
861 return SelectorSettings.Name;
862 }
863
864 internal set
865 {
866 SelectorSettings.Name = value;
867 }
868 }
869
872 internal bool DeleteMe
873 {
874 get
875 {
876 return SelectorSettings.DeleteMe;
877 }
878 set
879 {
880 SelectorSettings.DeleteMe = value;
881 }
882 }
888 internal List<Browser.Browser.CallIfDelegate> RemovedMethods
889 {
890 get
891 {
892 return SelectorSettings.RemovedMethods;
893 }
894 set
895 {
896 SelectorSettings.RemovedMethods = value;
897 }
898 }
905 internal InteractionType? RequestedInteractionType
906 {
907 get
908 {
909 return SelectorSettings.RequestedInteractionType;
910 }
911 set
912 {
913 SelectorSettings.RequestedInteractionType = value;
914 }
915 }
920 public bool SimulateMouse
921 {
922 get
923 {
924 return SelectorSettings.SimulateMouse;
925 }
926 }
927
931 public bool StopOnNotFound
932 {
933 get
934 {
935 return SelectorSettings.StopOnNotFound;
936 }
937 }
938
939 public List<GPALElement> WebSelectorFoundResults
940 {
941 get
942 {
943 foreach (var selectorPathEntry in SelectorPaths)
944 if (null != selectorPathEntry.WebSelectorFoundResults)
945 return selectorPathEntry.WebSelectorFoundResults;
946
947 return null;
948 }
949 set
950 {
951 foreach (var selectorPathEntry in SelectorPaths)
952 selectorPathEntry.WebSelectorFoundResults = value;
953 }
954 }
955 public List<GPALElement> WebSelectorMatchedResults
956 {
957 get
958 {
959 foreach (var selectorPathEntry in SelectorPaths)
960 if (null != selectorPathEntry.WebSelectorMatchedResults)
961 return selectorPathEntry.WebSelectorMatchedResults;
962
963 return null;
964 }
965 set
966 {
967 foreach (var selectorPathEntry in SelectorPaths)
968 selectorPathEntry.WebSelectorMatchedResults = value;
969 }
970 }
971
972 #endregion <Getter/Setters>
973
974 #region Implicit String Conversion, so wherever Selector parameter is expected, a string can be used directly
975 // implicit ToString
976 public static implicit operator string(Selector sel) => sel.Name;
977
978 private static int implicitCount = 0;
979 // ────────────────────────────────────────────────
980 // 1. Implicit conversion from string to Selector
981 // ────────────────────────────────────────────────
982 public static implicit operator Selector(string selectorString)
983 {
984 var sel = new Selector();
985
986 if (string.IsNullOrWhiteSpace(selectorString))
987 {
988 // Fail forward: warn + continue with empty/invalid-but-safe selector
989 GPAL.PublishSimpleEvent(
990 GPALEventType.WARNING,
991 "Invalid selector path treating as empty selector (no paths added).",
992 selectorString,
993 GPALObjectType.Selector
994 );
995
996 // Optional: give it a name so it's obvious in logs/reports
997 sel.WithSelectorName($"EmptySelector{implicitCount++}");
998 }
999 else
1000 {
1001 bool looksLikeXPath = IsLikelyXPath(selectorString);
1002
1003 if (looksLikeXPath)
1004 {
1005 // XPath first - more specific / less false positives in ambiguous cases
1006 sel.WithXPath(selectorString);
1007 sel.WithCSS(selectorString); // still try as CSS as fallback
1008 }
1009 else
1010 {
1011 // CSS first - most people intuitively write CSS selectors
1012 sel.WithCSS(selectorString);
1013 sel.WithXPath(selectorString); // still try as XPath fallback
1014 }
1015
1016 // give it a recognizable debug name
1017 sel.WithSelectorName($"Implicit{implicitCount++}.{(looksLikeXPath ? "XPath" : "CSS")}.{Shorten(selectorString, 10)}");
1018 }
1019
1020 GPAL.PublishSimpleEvent(GPALEventType.DEBUG, $"Implicit selector [{sel.Name}] created for [{selectorString}]");
1021
1022 // emit warning once.
1023 if (1 == implicitCount)
1024 GPAL.PublishSimpleEvent(GPALEventType.DEBUG, $"Implicit selector conversions lack equality, even if paths match. Create instance using GPAL.Selector for reuse.", sel, GPALObjectType.Selector);
1025
1026 return sel;
1027 }
1028
1029 // Very short helper for debug/readable names
1030 private static string Shorten(string s, int maxLen)
1031 {
1032 if (s.Length <= maxLen) return s;
1033 return s.Substring(0, maxLen - 3) + "...";
1034 }
1035
1036 // ────────────────────────────────────────────────
1037 // 2. The helper that guesses CSS vs XPath
1038 // ────────────────────────────────────────────────
1042 public static bool IsLikelyXPath(string s)
1043 {
1044 if (string.IsNullOrWhiteSpace(s)) return false;
1045 s = s.Trim();
1046
1047 // Strong XPath starters (absolute, descendant-or-self, id function)
1048 if (s.StartsWith("/") || s.StartsWith(".//") || s.StartsWith("//") || s.StartsWith("id("))
1049 return true;
1050
1051 // Classic browser-copied XPath: html/body/div[NN]/... pattern
1052 if (char.IsLetter(s[0]) && s.Contains("/") && s.Contains("["))
1053 return true;
1054
1055 // XPath-specific constructs that almost never appear in CSS
1056 if (s.Contains("::") ||
1057 s.Contains("/following") ||
1058 s.Contains("/preceding") ||
1059 s.Contains("/ancestor") ||
1060 s.Contains("/parent") ||
1061 s.Contains("/child") ||
1062 s.Contains("position()") ||
1063 s.Contains("last()") ||
1064 s.Contains("normalize-space") ||
1065 s.Contains("contains(text()") ||
1066 (s.Contains("@") && s.Contains("=") && !s.Contains("["))) // @attr="value" without [
1067 {
1068 return true;
1069 }
1070
1071 // Lone @attr (very strong XPath signal)
1072 if (s.Contains("@") && !s.Contains("["))
1073 return true;
1074
1075 // Very strong CSS indicators -> definitely treat as CSS, not XPath
1076 if (s.StartsWith("#") ||
1077 s.StartsWith(".") ||
1078 s.Contains(">") ||
1079 s.Contains("+") ||
1080 s.Contains("~") ||
1081 s.Contains(":not(") ||
1082 s.Contains(":nth-child") ||
1083 s.Contains(":nth-of-type"))
1084 {
1085 return false;
1086 }
1087
1088 // Contains [ but no other strong CSS markers -> lean toward XPath
1089 if (s.Contains("[") && !s.Contains(":") && !s.Contains("#") && !s.Contains("."))
1090 return true;
1091
1092 // Final fallback - assume CSS unless strong XPath evidence
1093 return false;
1094 }
1095 #endregion
1096
1097 public IAllowSelectorSettings ContainsAttribute(string attributeToMatch)
1098 {
1099 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Attribute, StringToMatch = attributeToMatch };
1100 matchCriteriaEntry.ExactMatch = false;
1101 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
1102 return this;
1103 }
1104
1105 public IAllowSelectorSettings ContainsHRef(string hrefToMatch)
1106 {
1107 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Href, StringToMatch = hrefToMatch };
1108 matchCriteriaEntry.ExactMatch = false;
1109 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
1110 return this;
1111 }
1112
1113 public IAllowSelectorSettings ContainsPlaceholder(string placeholderToMatch)
1114 {
1115 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Placeholder, StringToMatch = placeholderToMatch };
1116 matchCriteriaEntry.ExactMatch = false;
1117 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
1118 return this;
1119 }
1120
1121 public IAllowSelectorSettings ContainsSrc(string srcToMatch)
1122 {
1123 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Src, StringToMatch = srcToMatch };
1124 matchCriteriaEntry.ExactMatch = false;
1125 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
1126 return this;
1127 }
1128
1129 public IAllowSelectorSettings ContainsText(string textToMatch)
1130 {
1131 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Text, StringToMatch = textToMatch };
1132 matchCriteriaEntry.ExactMatch = false;
1133 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
1134 return this;
1135 }
1136
1137 public IAllowSelectorSettings ContainsValue(string valueToMatch)
1138 {
1139 SelectorSettings.MatchCriteriaEntry matchCriteriaEntry = new SelectorSettings.MatchCriteriaEntry { MatchType = MatchType.Value, StringToMatch = valueToMatch };
1140 matchCriteriaEntry.ExactMatch = false;
1141 SelectorSettings.MatchCriteria.Add(matchCriteriaEntry);
1142 return this;
1143 }
1144 }
1145}
1146
Application object that contains the fluent methods to create your Application workflow....
Browser object that contains the fluent methods to create your Browser workflow. Instatiated using G...
Definition Browser.cs:68
GPAL File object instantied with GPAL.File Used to load tokens into a GPALGrid [rows/columns].
Definition GPALFile.cs:36
Provides comprehensive image capture, conversion, and matching capabilities for automation scenarios....
static Image Base64ToImage(string base64String)
Converts a Base64 string (with or without data URI prefix) to a System.Drawing.Image.
GPAL Selector used to locate Application and Browser elements. Instantiated with GPAL....
Definition Selector.cs:56
IAllowSelectorSettings WithSelectorName(string name)
A common name for this selector. Used in Information and Exception channel messages.
Definition Selector.cs:299
string SelectorPath
Returns the first defined selector path string.
Definition Selector.cs:754
int DeltaX
Drag-and-drop deltaX to move from the elemenet.X + OffsetX.
Definition Selector.cs:826
IAllowSelectorSettings MatchText(string textToMatch)
Found elements must match the text supplied in order to interact with them.
Definition Selector.cs:482
IAllowSelectorSettings WithJavaScript
Interact with this element using javascript injected into the page.
Definition Selector.cs:603
IAllowSelectorSettings MatchValueRegex(string valueToMatch)
Found elements must match the value regular expression supplied in order to interact with them.
Definition Selector.cs:515
IAllowSelectorSettings MatchTextRegex(string textToMatch)
Found elements must match the text regular expression supplied in order to interact with them.
Definition Selector.cs:493
IAllowSelectorSettings MatchAttribute(string attributeToMatch)
Found elements must have attribute supplied in order to interact with them.
Definition Selector.cs:394
Browser.Browser Browser
Browser associated with this selector.
Definition Selector.cs:746
IAllowSelectorSettings WithDeltaY(int deltaY)
Define the y offset from the Top Left corner to perform clicks.
Definition Selector.cs:321
IAllowSelectorSettings WithImage(Image image)
Define an image to match on-screen. The top left corner is used as the start of the element....
Definition Selector.cs:274
bool StopOnNotFound
Stop the workflow if no elements are found for this selector.
Definition Selector.cs:932
void Remove()
Remove this selector from the current Unit of Work.
Definition Selector.cs:524
IAllowSelectorSettings WithText(string text)
Define Text used to find elements by text attribute. Browser only.
Definition Selector.cs:192
IAllowSelectorSettings WithDeltaX(int deltaX)
Define the x offset from the Top Left corner to perform clicks.
Definition Selector.cs:310
IAllowSelectorSettings MatchPlaceholder(string placeholderToMatch)
Found elements must match the placeholder supplied in order to interact with them.
Definition Selector.cs:438
bool SearchForSelector
Search for elements on the page.
Definition Selector.cs:783
IAllowSelectorSettings MatchFunction(Selector.appMatchingFunction matchingFunction)
Your custom application element matching function to examine found elements and return only those you...
Definition Selector.cs:372
IAllowSelectorSettings MatchSrc(string srcToMatch)
Found elements must match the src supplied in order to interact with them.
Definition Selector.cs:460
int DeltaY
Drag-and-drop deltaY to move from the elemenet.Y + OffsetY.
Definition Selector.cs:841
int OffsetY
Y offset fromm the top left corner to interact with the element, image match included....
Definition Selector.cs:811
IAllowSelectorSettings MatchFunction(Selector.webMatchingFunction matchingFunction)
Your custom web element matching function to examine found elements and return only those you 'match'...
Definition Selector.cs:383
IAllowSelectorSettings WithClassName(string className)
Define Name used to find elements by name attribute. Application only.
Definition Selector.cs:228
IAllowSelectorSettings MatchAttributeRegex(string attributeToMatch)
Found elements must have the attribute specified by regular expression in order to interact with them...
Definition Selector.cs:405
int ElementsFoundAndMatchedCount
Count of elements found for this selector (after match).
Definition Selector.cs:639
InteractionType InteractionType
Defined method to interact with this element. NOTE: This can be overridden in the workflow.
Definition Selector.cs:731
IAllowSelectorSettings WithSelenium
Interact with this element using Selenium [default].
Definition Selector.cs:626
IAllowSelectorSettings WithValue(string value)
Define Value used to find elements by value attribute. Browser only.
Definition Selector.cs:204
IAllowSelectorSettings WithName(string name)
Define Name used to find elements by name attribute. Application only.
Definition Selector.cs:216
IAllowSelectorSettings WithOCR(string textToFind)
Use OCR to find the text on-screen.
Definition Selector.cs:533
IAllowSelectorSettings WithXPath(string xPath)
Define XPath used to find elements Both.
Definition Selector.cs:180
IAllowSelectorSettings WithImage(GPALFile imageToFindPath)
Define an image to match on-screen. The top left corner is used as the start of the element....
Definition Selector.cs:565
IAllowSelectorSettings MatchHRefRegex(string hrefToMatch)
Found elements must match the HRef regular expression supplied in order to interact with them.
Definition Selector.cs:427
IAllowSelectorSettings MatchValue(string valueToMatch)
Found elements must match the value supplied in order to interact with them.
Definition Selector.cs:504
delegate CallIfStatus webMatchingFunction(List< IGPALElement > foundElements, out List< IGPALElement > matchedElements, out bool matchedAll, Selector selector, bool ExactMatch=true)
Custom matching function, must return all matched elements and an indicator as to whether all element...
static bool IsLikelyXPath(string s)
Rudimentary but reasonably effective guess: is this string more likely an XPath than a CSS selector?
Definition Selector.cs:1042
IAllowSelectorSettings WithSimulateMouse(bool moveWithArc)
Simulate a human moving the mouse when interacting with this element. Implies hardware input.
Definition Selector.cs:354
IAllowSelectorSettings WithAutomationID(string automationID)
Define Name used to find elements by name attribute. Application only.
Definition Selector.cs:240
IAllowSelectorSettings WithOffsetX(int offsetX)
Define the x offset from the Top Left corner to perform clicks.
Definition Selector.cs:332
delegate CallIfStatus appMatchingFunction(List< GPALAutomationElement > foundElements, out List< GPALAutomationElement > matchedElements, out bool matchedAll, Selector selector, bool ExactMatch=true)
Custom matching function, must return all matched elements and an indicator as to whether all element...
IAllowSelectorSettings MatchPlaceholderRegex(string placeholderToMatch)
Found elements must match the placeholder regular expression supplied in order to interact with them.
Definition Selector.cs:449
IAllowSelectorSettings WithImage(string base64String)
Define an image to match on-screen. The top left corner is used as the start of the element....
Definition Selector.cs:253
List< SelectorSettings.SelectorPathEntry > SelectorPaths
The selector paths defined to locate elements.
Definition Selector.cs:765
IAllowSelectorSettings MatchHRef(string hrefToMatch)
Found elements must match the HRef supplied in order to interact with them.
Definition Selector.cs:416
IAllowSelectorSettings WithCSS(string css)
Define CSS used to find elements. Browser only.
Definition Selector.cs:168
bool SimulateMouse
Simulate moving the mouse to interact with this element?
Definition Selector.cs:921
IAllowSelectorSettings WithOffsetY(int offsetY)
Define the y offset from the Top Left corner to perform clicks.
Definition Selector.cs:343
IAllowSelectorSettings WithSearchForSelector(bool searchForElement)
Search for a matching image when using hardware emulation or image matching. Finding an element on p...
Definition Selector.cs:287
IAllowSelectorSettings MatchSrcRegex(string srcToMatch)
Found elements must match the src regular expression supplied in order to interact with them.
Definition Selector.cs:471
string Name
The name you gave this selector, or one assigned by GPAL [selector1, selector2...] Used in Informati...
Definition Selector.cs:858
IAllowSelectorSettings WithStopOnNotFound(bool stopOnNotFound)
Stop the workflow if this selector is not found.
Definition Selector.cs:542
int OffsetX
X offset from the top left corner to interact with the element, image match included....
Definition Selector.cs:795
IAllowSelectorSettings WithHardware
Interact with this element using hardware emulation.
Definition Selector.cs:590
An entry defining a selector locator, a selector path.
Settings for the current selector. Use this only for debugging.