diff --git a/.gitignore b/.gitignore
index 098d4d74..1c390528 100644
--- a/.gitignore
+++ b/.gitignore
@@ -106,4 +106,7 @@ packages
# our output folder for build artifacts
build
-Thumbs.db
\ No newline at end of file
+Thumbs.db
+
+# sample project
+src/WhiteProject/*
\ No newline at end of file
diff --git a/src/.nuget/packages.config b/src/.nuget/packages.config
new file mode 100644
index 00000000..a8e522d2
--- /dev/null
+++ b/src/.nuget/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/TestStack.White.sln b/src/TestStack.White.sln
index d79fdf24..dbc26aa3 100644
--- a/src/TestStack.White.sln
+++ b/src/TestStack.White.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.40629.0
+# Visual Studio Express 2013 for Windows Desktop
+VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1BCBA4C4-8C47-496C-B0D4-FDE9D066ED27}"
ProjectSection(SolutionItems) = preProject
@@ -57,6 +57,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinformsTodo", "Samples\Win
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Todo.Core", "Samples\Todo.Core\Todo.Core.csproj", "{F5604A48-3BD0-4418-83F1-3ECC03DD2FF0}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{81F4B351-6572-4CEA-9E39-B1978CB6DFA2}"
+ ProjectSection(SolutionItems) = preProject
+ .nuget\packages.config = .nuget\packages.config
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WhiteProject", "WhiteProject\WhiteProject.csproj", "{39964358-1A5B-4F78-9520-1B106F70CE72}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -131,6 +138,10 @@ Global
{F5604A48-3BD0-4418-83F1-3ECC03DD2FF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5604A48-3BD0-4418-83F1-3ECC03DD2FF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5604A48-3BD0-4418-83F1-3ECC03DD2FF0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {39964358-1A5B-4F78-9520-1B106F70CE72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {39964358-1A5B-4F78-9520-1B106F70CE72}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {39964358-1A5B-4F78-9520-1B106F70CE72}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {39964358-1A5B-4F78-9520-1B106F70CE72}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -138,13 +149,13 @@ Global
GlobalSection(NestedProjects) = preSolution
{24929CE3-4000-4600-8830-503BE6A2BA42} = {1AF6AEE7-C9D5-4B05-BEFE-AB61D83667D4}
{492E6340-32CC-4D03-A9C4-36FB4C40CF5C} = {1AF6AEE7-C9D5-4B05-BEFE-AB61D83667D4}
- {DFCF10D7-82C1-4916-A829-B520E8C65321} = {37EE7583-778A-481E-ADD4-52A357BE95F0}
- {5620401C-0857-4F7C-869A-F3F56DF1697F} = {37EE7583-778A-481E-ADD4-52A357BE95F0}
{EC32732F-6CB9-4078-B3A8-E3F038D5C2E1} = {1AF6AEE7-C9D5-4B05-BEFE-AB61D83667D4}
{C186FEFC-D0B7-4FED-822D-688302B3B8A0} = {1AF6AEE7-C9D5-4B05-BEFE-AB61D83667D4}
+ {DFCF10D7-82C1-4916-A829-B520E8C65321} = {37EE7583-778A-481E-ADD4-52A357BE95F0}
+ {5620401C-0857-4F7C-869A-F3F56DF1697F} = {37EE7583-778A-481E-ADD4-52A357BE95F0}
+ {F5604A48-3BD0-4418-83F1-3ECC03DD2FF0} = {37EE7583-778A-481E-ADD4-52A357BE95F0}
+ {D0ED95E7-584A-45B9-B8E2-1A7ADD78C366} = {DFCF10D7-82C1-4916-A829-B520E8C65321}
{3CC2654B-2108-4A38-AFFF-82718703EBE3} = {5620401C-0857-4F7C-869A-F3F56DF1697F}
{51509F9D-12C4-4043-A68F-16A300F38FDB} = {5620401C-0857-4F7C-869A-F3F56DF1697F}
- {D0ED95E7-584A-45B9-B8E2-1A7ADD78C366} = {DFCF10D7-82C1-4916-A829-B520E8C65321}
- {F5604A48-3BD0-4418-83F1-3ECC03DD2FF0} = {37EE7583-778A-481E-ADD4-52A357BE95F0}
EndGlobalSection
EndGlobal
diff --git a/src/TestStack.White/AutomationElementSearch/DescendantFinder.cs b/src/TestStack.White/AutomationElementSearch/DescendantFinder.cs
index 23b9dbc6..160bda25 100644
--- a/src/TestStack.White/AutomationElementSearch/DescendantFinder.cs
+++ b/src/TestStack.White/AutomationElementSearch/DescendantFinder.cs
@@ -1,13 +1,17 @@
+using Castle.Core.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Automation;
+using TestStack.White.Configuration;
+using TestStack.White.UIItems.Finders;
namespace TestStack.White.AutomationElementSearch
{
public class DescendantFinder : IDescendantFinder
{
private readonly AutomationElement automationElement;
+ private readonly ILogger logger = CoreAppXmlConfiguration.Instance.LoggerFactory.Create(typeof(DescendantFinder));
public DescendantFinder(AutomationElement automationElement)
{
@@ -28,6 +32,17 @@ public virtual AutomationElement Descendant(Condition condition)
public virtual List Descendants(AutomationSearchCondition automationSearchCondition)
{
var collection = automationElement.FindAll(TreeScope.Descendants, automationSearchCondition.Condition);
+
+ //Automation elements identified in current window...
+ //AutomationElement[] elementsArray = new AutomationElement[collection.Count];
+
+ //collection.CopyTo(elementsArray, 0);
+
+ //foreach (AutomationElement e in elementsArray)
+ //{
+ // logger.InfoFormat("Element Automation Id: ({0})..", e.Current.AutomationId);
+ //}
+
var enumerable = collection.Cast();
return new List(enumerable);
}
diff --git a/src/TestStack.White/Interceptors/CoreInterceptor.cs b/src/TestStack.White/Interceptors/CoreInterceptor.cs
index 91163edb..f56a8d24 100644
--- a/src/TestStack.White/Interceptors/CoreInterceptor.cs
+++ b/src/TestStack.White/Interceptors/CoreInterceptor.cs
@@ -25,8 +25,9 @@ public virtual void Intercept(IInvocation invocation)
{
CoreAppXmlConfiguration.Instance.Interceptors.Process(invocation, coreInterceptContext);
}
- catch (Exception)
+ catch (Exception e)
{
+ logger.Error(e.Message);
logger.Error(DynamicProxyInterceptors.ToString(invocation));
throw;
}
diff --git a/src/TestStack.White/Mappings/ControlDictionary.cs b/src/TestStack.White/Mappings/ControlDictionary.cs
index 88e1d7a4..befd6dc7 100644
--- a/src/TestStack.White/Mappings/ControlDictionary.cs
+++ b/src/TestStack.White/Mappings/ControlDictionary.cs
@@ -154,6 +154,10 @@ public virtual Type GetTestControlType(string className, string name, ControlTyp
if (isPrimary.Length == 1)
return isPrimary.Single().TestControlType;
+ //Get the first TestControldType when 'dictionaryItems' contains multiple elements...
+ var isFirstItem = dictionaryItems.First();
+ return isFirstItem.TestControlType;
+
throw new ControlDictionaryException(string.Format(
"Multiple TestControls found for ControlType={0} and FrameworkId:{1} - {2}",
controlType.LocalizedControlType, frameWorkId,
diff --git a/src/TestStack.White/TestStack.White.csproj b/src/TestStack.White/TestStack.White.csproj
index 65b07908..73dd3b70 100644
--- a/src/TestStack.White/TestStack.White.csproj
+++ b/src/TestStack.White/TestStack.White.csproj
@@ -62,8 +62,13 @@
1591, 1570
-
+
..\packages\Castle.Core.3.3.0\lib\net40-client\Castle.Core.dll
+ True
+
+
+ ..\packages\Castle.Windsor.3.3.0\lib\net40\Castle.Windsor.dll
+ True
diff --git a/src/TestStack.White/UIItems/Finders/SearchConditionFactory.cs b/src/TestStack.White/UIItems/Finders/SearchConditionFactory.cs
index 5d55b6f8..98ba3624 100644
--- a/src/TestStack.White/UIItems/Finders/SearchConditionFactory.cs
+++ b/src/TestStack.White/UIItems/Finders/SearchConditionFactory.cs
@@ -1,8 +1,11 @@
using System;
using System.Linq;
using System.Windows.Automation;
+using System.Xml;
+using System.Xml.XPath;
using TestStack.White.Mappings;
using TestStack.White.UIItems.Custom;
+using TestStack.White.UIItems.WindowItems;
namespace TestStack.White.UIItems.Finders
{
@@ -41,6 +44,72 @@ public static SearchCondition CreateForAutomationId(string id)
new AutomationElementProperty(id, "AutomationId", AutomationElement.AutomationIdProperty));
}
+ ///
+ /// Getting the objects (AutomationElement) hierarchy of the given window
+ /// Create SimpleSearchCondition with AutomationId for given xpath
+ ///
+ ///
+ ///
+ ///
+ public static SearchCondition CreateForXPath(string xpath, Window window)
+ {
+ XmlDocument xmlDoc = new XmlDocument();
+ string hierarchy = window.GetHierarchy(window.AutomationElement);
+
+ xmlDoc.LoadXml(hierarchy);
+ XmlNodeList nodeList = xmlDoc.SelectNodes(xpath);
+ if (nodeList.Count == 0)
+ {
+ throw new Exception("No element found for given XPath: " + xpath);
+ }
+ else if (nodeList.Count > 1)
+ {
+ throw new Exception("Multiple elements found for given XPath: " + xpath);
+ }
+ else
+ {
+ foreach (XmlNode node in nodeList)
+ {
+ var automationId = node.Attributes["AutomationId"].Value;
+ var className = node.Attributes["ClassName"].Value;
+ //var controlType = node.Attributes["ControlType"].Value;
+ var frameworkId = node.Attributes["FrameworkId"].Value;
+ var name = node.Attributes["Name"].Value;
+ var helpText = node.Attributes["HelpText"].Value;
+
+ if (!String.IsNullOrEmpty(name))
+ {
+ return new SimpleSearchCondition(automationElement => automationElement.Current.Name,
+ new AutomationElementProperty(name, "Name", AutomationElement.NameProperty));
+ }
+ else if (!String.IsNullOrEmpty(automationId))
+ {
+ return new SimpleSearchCondition(automationElement => automationElement.Current.AutomationId,
+ new AutomationElementProperty(automationId, "AutomationId", AutomationElement.AutomationIdProperty));
+ }
+ else if (!String.IsNullOrEmpty(helpText))
+ {
+ return new SimpleSearchCondition(automationElement => automationElement.Current.HelpText,
+ new AutomationElementProperty(helpText, "HelpText", AutomationElement.HelpTextProperty));
+ }
+ else if (!String.IsNullOrEmpty(className))
+ {
+ return new SimpleSearchCondition(automationElement => automationElement.Current.ClassName,
+ new AutomationElementProperty(className, "ClassName", AutomationElement.ClassNameProperty));
+ }
+ else if (!String.IsNullOrEmpty(frameworkId))
+ {
+ return new SimpleSearchCondition(automationElement => automationElement.Current.FrameworkId,
+ new AutomationElementProperty(frameworkId, "FrameworkId", AutomationElement.FrameworkIdProperty));
+ }
+
+
+ }
+ }
+
+ throw new Exception("Invalid Xpath");
+ }
+
public static SearchCondition CreateForName(string name)
{
return new SimpleSearchCondition(automationElement => automationElement.Current.Name, new AutomationElementProperty(name, "Name", AutomationElement.NameProperty));
diff --git a/src/TestStack.White/UIItems/Finders/SearchCriteria.cs b/src/TestStack.White/UIItems/Finders/SearchCriteria.cs
index 6b01c92d..d722c071 100644
--- a/src/TestStack.White/UIItems/Finders/SearchCriteria.cs
+++ b/src/TestStack.White/UIItems/Finders/SearchCriteria.cs
@@ -6,6 +6,7 @@
using System.Windows.Automation;
using TestStack.White.AutomationElementSearch;
using TestStack.White.UIItems.Custom;
+using TestStack.White.UIItems.WindowItems;
using TestStack.White.UIItems.WindowStripControls;
namespace TestStack.White.UIItems.Finders
@@ -72,6 +73,17 @@ public static SearchCriteria ByAutomationId(string identification)
return new SearchCriteria(SearchConditionFactory.CreateForAutomationId(identification));
}
+ ///
+ /// Create criteria for specified window with specified xpath
+ ///
+ ///
+ ///
+ ///
+ public static SearchCriteria ByXPath(string xpath, Window window)
+ {
+ return new SearchCriteria(SearchConditionFactory.CreateForXPath(xpath, window));
+ }
+
public static SearchCriteria ByFramework(string framework)
{
return new SearchCriteria(SearchConditionFactory.CreateForFrameworkId(framework));
diff --git a/src/TestStack.White/UIItems/ListBoxItems/ComboBox.cs b/src/TestStack.White/UIItems/ListBoxItems/ComboBox.cs
index a7d07f60..c26e36c2 100644
--- a/src/TestStack.White/UIItems/ListBoxItems/ComboBox.cs
+++ b/src/TestStack.White/UIItems/ListBoxItems/ComboBox.cs
@@ -1,3 +1,4 @@
+using System;
using System.Windows.Automation;
using TestStack.White.AutomationElementSearch;
using TestStack.White.Recording;
@@ -67,26 +68,72 @@ private AutomationElement EditableElement()
public override void Select(string itemText)
{
- if (!Enabled)
+ //if (!Enabled)
+ //{
+ // Logger.WarnFormat("Could not select {0}in {1} since it is disabled", itemText, Name);
+ // return;
+ //}
+ //if (Equals(itemText, SelectedItemText)) return;
+ //base.Select(itemText);
+
+ AutomationElement comboboxList = this.AutomationElement.FindFirst(TreeScope.Children,
+ new PropertyCondition(AutomationElement.ControlTypeProperty,
+ ControlType.List));
+
+ AutomationElementCollection comboboxItem = comboboxList.FindAll(TreeScope.Children,
+ new PropertyCondition(AutomationElement.ControlTypeProperty,
+ ControlType.ListItem));
+
+ AutomationElement[] itemArray = new AutomationElement[comboboxItem.Count];
+ comboboxItem.CopyTo(itemArray, 0);
+
+ AutomationElement itemToSelect = null;
+
+ for (int i = 0; i < itemArray.Length; i++)
+ {
+ if (itemArray[i].Current.Name.Equals(itemText))
+ {
+ itemToSelect = itemArray[i];
+ }
+ }
+
+ if (itemToSelect != null)
{
- Logger.WarnFormat("Could not select {0}in {1} since it is disabled", itemText, Name);
- return;
+ Object selectPattern = null;
+ if (itemToSelect.TryGetCurrentPattern(SelectionItemPattern.Pattern, out selectPattern))
+ {
+ ((SelectionItemPattern)selectPattern).Select();
+ }
}
- if (Equals(itemText, SelectedItemText)) return;
- base.Select(itemText);
}
public override void Select(int index)
{
- if (!Enabled)
+ //if (!Enabled)
+ //{
+ // Logger.Warn("Could not select " + index + "in " + Name + " since it is disabled");
+ // return;
+ //}
+ //base.Select(index);
+ //var p = (ExpandCollapsePattern) this.AutomationElement.GetCurrentPattern(ExpandCollapsePattern.Pattern);
+ //if (p.Current.ExpandCollapseState.Equals(ExpandCollapseState.Expanded))
+ // p.Collapse();
+
+ AutomationElement comboboxList = this.AutomationElement.FindFirst(TreeScope.Children,
+ new PropertyCondition(AutomationElement.ControlTypeProperty,
+ ControlType.List));
+
+ AutomationElementCollection comboboxItem = comboboxList.FindAll(TreeScope.Children,
+ new PropertyCondition(AutomationElement.ControlTypeProperty,
+ ControlType.ListItem));
+
+ AutomationElement itemToSelect = comboboxItem[index];
+
+ Object selectPattern = null;
+ if (itemToSelect.TryGetCurrentPattern(SelectionItemPattern.Pattern, out selectPattern))
{
- Logger.Warn("Could not select " + index + "in " + Name + " since it is disabled");
- return;
+ ((SelectionItemPattern)selectPattern).Select();
}
- base.Select(index);
- var p = (ExpandCollapsePattern) this.AutomationElement.GetCurrentPattern(ExpandCollapsePattern.Pattern);
- if (p.Current.ExpandCollapseState.Equals(ExpandCollapseState.Expanded))
- p.Collapse();
}
public override void HookEvents(IUIItemEventListener eventListener)
diff --git a/src/TestStack.White/UIItems/UIItem.cs b/src/TestStack.White/UIItems/UIItem.cs
index e4a286d2..4ed554f1 100644
--- a/src/TestStack.White/UIItems/UIItem.cs
+++ b/src/TestStack.White/UIItems/UIItem.cs
@@ -370,8 +370,10 @@ public virtual void SetValue(object value)
///
public virtual void Enter(string value)
{
- var pattern = Pattern(ValuePattern.Pattern) as ValuePattern;
- if (pattern != null) pattern.SetValue(string.Empty);
+ //
+ //var pattern = Pattern(ValuePattern.Pattern) as ValuePattern;
+ //if (pattern != null) pattern.SetValue(string.Empty);
+
if (string.IsNullOrEmpty(value)) return;
actionListener.ActionPerformed(Action.WindowMessage);
diff --git a/src/TestStack.White/UIItems/UIItemCollection.cs b/src/TestStack.White/UIItems/UIItemCollection.cs
index 13ad463a..0133afe1 100644
--- a/src/TestStack.White/UIItems/UIItemCollection.cs
+++ b/src/TestStack.White/UIItems/UIItemCollection.cs
@@ -49,8 +49,10 @@ public UIItemCollection(IEnumerable automationElements, IActionListener actionLi
var uiItem = DictionaryMappedItemFactory.Create(automationElement, actionListener, customItemType);
if (uiItem != null) Add(uiItem);
}
- catch (ControlDictionaryException)
+ catch (ControlDictionaryException e)
{
+ //Printing the Bease exception message...
+ logger.Warn(e.GetBaseException().Message);
logger.WarnFormat("Couldn't create UIItem for AutomationElement, {0}", automationElement.Display());
}
}
diff --git a/src/TestStack.White/UIItems/WindowItems/Window.cs b/src/TestStack.White/UIItems/WindowItems/Window.cs
index 229104f3..a78c05e4 100644
--- a/src/TestStack.White/UIItems/WindowItems/Window.cs
+++ b/src/TestStack.White/UIItems/WindowItems/Window.cs
@@ -1,12 +1,15 @@
+using Castle.Core.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Automation;
+using System.Xml;
using TestStack.White.AutomationElementSearch;
using TestStack.White.Configuration;
using TestStack.White.Factory;
@@ -43,6 +46,10 @@ public abstract class Window : UIItemContainer, IDisposable
public delegate bool WaitTillDelegate();
+ public string Hierarchy { get; set; }
+
+ private readonly ILogger logger = CoreAppXmlConfiguration.Instance.LoggerFactory.Create(typeof(Window));
+
static Window()
{
WindowStates.Add(DisplayState.Maximized, WindowVisualState.Maximized);
@@ -78,6 +85,112 @@ private void InitializeWindow()
WindowSession.Register(this);
}
+ ///
+ /// Getting AutomationElement proerties and child AutomationElements..
+ /// Create XMLDocument of the AutomationElement hierarchy..
+ ///
+ ///
+ ///
+ internal string GetHierarchy(AutomationElement element)
+ {
+ XmlDocument xmlDoc = new XmlDocument();
+ XmlNode rootNode = xmlDoc.CreateElement(element.Current.LocalizedControlType.Replace(" ", "-"));
+ xmlDoc.AppendChild(rootNode);
+ addAttributes(element, xmlDoc, rootNode);
+ findChildElement(element, xmlDoc, rootNode);
+
+ return xmlDoc.OuterXml;
+ }
+
+ ///
+ /// Find the child element of given element recursively
+ ///
+ ///
+ ///
+ ///
+ private void findChildElement(AutomationElement element, XmlDocument xmlDoc, XmlNode node)
+ {
+ try
+ {
+ AutomationElementCollection childElementCollection = element.FindAll(TreeScope.Children, Condition.TrueCondition);
+ foreach (AutomationElement childElement in childElementCollection)
+ {
+ XmlNode childNode;
+ if (String.IsNullOrWhiteSpace(childElement.Current.LocalizedControlType))
+ {
+ childNode = xmlDoc.CreateElement("Unknown");
+ }
+ else
+ {
+ childNode = xmlDoc.CreateElement(childElement.Current.LocalizedControlType.Replace(" ", "-"));
+ }
+ node.AppendChild(childNode);
+ addAttributes(childElement, xmlDoc, childNode);
+ findChildElement(childElement, xmlDoc, childNode);
+ }
+ }
+ catch (InvalidOperationException e)
+ {
+ logger.Warn(e.Message);
+ }
+ catch (ArgumentException e)
+ {
+ logger.Warn(e.Message);
+ }
+ }
+
+ ///
+ /// Getting the important attributes of AutomationElement..
+ ///
+ ///
+ ///
+ ///
+ private void addAttributes(AutomationElement element, XmlDocument xmlDoc, XmlNode node)
+ {
+ try
+ {
+ XmlAttribute automationIdAttr = xmlDoc.CreateAttribute("AutomationId");
+ automationIdAttr.Value = element.Current.AutomationId;
+ node.Attributes.Append(automationIdAttr);
+
+ XmlAttribute classAttr = xmlDoc.CreateAttribute("ClassName");
+ classAttr.Value = element.Current.ClassName;
+ node.Attributes.Append(classAttr);
+
+ //XmlAttribute controlTypeAttr = xmlDoc.CreateAttribute("ControlType");
+ //controlTypeAttr.Value = element.Current.ControlType;
+ //node.Attributes.Append(controlTypeAttr);
+
+ XmlAttribute frameworkAttr = xmlDoc.CreateAttribute("FrameworkId");
+ frameworkAttr.Value = element.Current.FrameworkId;
+ node.Attributes.Append(frameworkAttr);
+
+ XmlAttribute nameAttr = xmlDoc.CreateAttribute("Name");
+ nameAttr.Value = element.Current.Name;
+ node.Attributes.Append(nameAttr);
+
+ XmlAttribute helpTextAttr = xmlDoc.CreateAttribute("HelpText");
+ helpTextAttr.Value = element.Current.HelpText;
+ node.Attributes.Append(helpTextAttr);
+
+ object patternObj;
+ if (element.TryGetCurrentPattern(TextPattern.Pattern, out patternObj))
+ {
+ XmlAttribute textAttr = xmlDoc.CreateAttribute("Text");
+ var textPattern = (TextPattern) patternObj;
+ textAttr.Value = textPattern.DocumentRange.GetText(-1).TrimEnd('\r');
+ Console.WriteLine("Text attribute added..");
+ node.Attributes.Append(textAttr);
+ }
+
+
+ }
+ catch (Exception e)
+ {
+ logger.Warn(e.Message);
+ }
+ }
+
protected override IActionListener ChildrenActionListener
{
get { return this; }
diff --git a/src/TestStack.White/packages.config b/src/TestStack.White/packages.config
index 72098ad9..fceddc39 100644
--- a/src/TestStack.White/packages.config
+++ b/src/TestStack.White/packages.config
@@ -1,4 +1,5 @@
+
\ No newline at end of file
diff --git a/src/UpgradeLog.htm b/src/UpgradeLog.htm
new file mode 100644
index 00000000..78b1e5f1
Binary files /dev/null and b/src/UpgradeLog.htm differ
diff --git a/src/UpgradeLog2.htm b/src/UpgradeLog2.htm
new file mode 100644
index 00000000..78b1e5f1
Binary files /dev/null and b/src/UpgradeLog2.htm differ
diff --git a/src/UpgradeLog3.htm b/src/UpgradeLog3.htm
new file mode 100644
index 00000000..5b10e095
Binary files /dev/null and b/src/UpgradeLog3.htm differ
diff --git a/src/UpgradeLog4.htm b/src/UpgradeLog4.htm
new file mode 100644
index 00000000..5b10e095
Binary files /dev/null and b/src/UpgradeLog4.htm differ
diff --git a/src/UpgradeLog5.htm b/src/UpgradeLog5.htm
new file mode 100644
index 00000000..5b10e095
Binary files /dev/null and b/src/UpgradeLog5.htm differ
diff --git a/src/WhiteProject/App.config b/src/WhiteProject/App.config
new file mode 100644
index 00000000..8e156463
--- /dev/null
+++ b/src/WhiteProject/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/WhiteProject/Program.cs b/src/WhiteProject/Program.cs
new file mode 100644
index 00000000..594bcc33
--- /dev/null
+++ b/src/WhiteProject/Program.cs
@@ -0,0 +1,185 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Automation;
+using TestStack.White;
+using TestStack.White.AutomationElementSearch;
+using TestStack.White.Factory;
+using TestStack.White.InputDevices;
+using TestStack.White.UIItems;
+using TestStack.White.UIItems.Finders;
+using TestStack.White.UIItems.ListBoxItems;
+using TestStack.White.UIItems.WindowItems;
+
+namespace WhiteProject
+{
+ class Program
+ {
+ [DllImport("kernel32.dll", ExactSpelling = true)]
+
+ private static extern IntPtr GetConsoleWindow();
+ private static IntPtr ThisConsole = GetConsoleWindow();
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+
+ private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
+ private const int HIDE = 0;
+ private const int MAXIMIZE = 3;
+ private const int MINIMIZE = 6;
+ private const int RESTORE = 9;
+
+ const string WINDOW_PROPERTY = "Name";
+ const string WINDOW_VALUE = "Untitled - Notepad";
+
+ static void Main(string[] args)
+ {
+ //------------------------------ Maximizing Console Window ------------------------------
+ Console.SetWindowSize(Console.LargestWindowWidth, Console.LargestWindowHeight);
+ ShowWindow(ThisConsole, MAXIMIZE);
+
+ //------------------------------ Type in Notepad the save.. ------------------------------
+ //TypeAndSaveNotepad();
+
+ Console.ReadLine();
+ }
+
+ public static Window SelectWindow(String property, String value)
+ {
+ List windows = WindowFactory.Desktop.DesktopWindows();
+ Window selectedWindow = null;
+ foreach (Window window in windows)
+ {
+ System.Reflection.PropertyInfo propertyInfo = window.GetType().GetProperty(property);
+ String propertyValue = (String)(propertyInfo.GetValue(window, null));
+
+ if (propertyValue.Equals(value))
+ {
+ selectedWindow = window;
+ }
+ }
+ return selectedWindow;
+ }
+
+ private static void TypeAndSaveNotepad()
+ {
+ //------------------------------ Selecting Window ------------------------------
+ Console.WriteLine("------------------------------ Select Window for given Property and Value /------------------------------");
+ Window selectedWindow = SelectWindow(WINDOW_PROPERTY, WINDOW_VALUE);
+ selectedWindow.Focus();
+
+ //------------------------------ Type in Notepad ------------------------------
+ String edit_Notepad = "//document[@ClassName='Edit']";
+ String btn_File = "//menu-item[@Name='File']";
+ String btn_New = "//menu-item[@Name='Save']";
+ String combo_FileName = "//combo-box[@Name='File name:']";
+
+ IUIItem edit_NotepadObj = selectedWindow.Get(SearchCriteria.ByXPath(edit_Notepad, selectedWindow));
+ edit_NotepadObj.Enter("Testing Purpose............");
+
+ IUIItem btn_FileObj = selectedWindow.Get(SearchCriteria.ByXPath(btn_File, selectedWindow));
+ btn_FileObj.Click();
+
+ IUIItem btn_NewObj = selectedWindow.Get(SearchCriteria.ByXPath(btn_New, selectedWindow));
+ btn_NewObj.Click();
+ }
+
+ public static void ComboBoxClick(Window w, AutomationElement ele)
+ {
+ if (w.AutomationElement != null)
+ {
+ AutomationElement comboboxInstance = ele;
+ if (comboboxInstance == null)
+ {
+ Console.WriteLine("ComboBox instance not found.");
+ }
+ else
+ {
+ AutomationElement comboboxList = comboboxInstance.FindFirst(TreeScope.Children,
+ new PropertyCondition
+ (AutomationElement.ControlTypeProperty, ControlType.List));
+
+ AutomationElementCollection comboboxItem =
+ comboboxList.FindAll(TreeScope.Children,
+ new PropertyCondition(AutomationElement.ControlTypeProperty,
+ ControlType.ListItem));
+
+ AutomationElement[] itemArray = new AutomationElement[comboboxItem.Count];
+
+ comboboxItem.CopyTo(itemArray, 0);
+
+ for (int i = 0; i < itemArray.Length; i++)
+ {
+ Console.WriteLine(itemArray[1]);
+ }
+
+ AutomationElement itemToSelect = comboboxItem[1];
+
+ Object selectPattern = null;
+ if (itemToSelect.TryGetCurrentPattern(SelectionItemPattern.Pattern, out selectPattern))
+ {
+ ((SelectionItemPattern)selectPattern).Select();
+ }
+ }
+ }
+ }
+
+ public static void SetCombobValueByUIA(AutomationElement ctrl, string newValue)
+ {
+ ExpandCollapsePattern exPat = ctrl.GetCurrentPattern(ExpandCollapsePattern.Pattern)
+ as ExpandCollapsePattern;
+
+ if (exPat == null)
+ {
+ throw new ApplicationException("Bad Control type...");
+ }
+
+ exPat.Expand();
+
+ AutomationElement itemToSelect = ctrl.FindFirst(TreeScope.Children, new
+ PropertyCondition(AutomationElement.NameProperty, newValue));
+
+ SelectionItemPattern sPat = itemToSelect.GetCurrentPattern(
+ SelectionItemPattern.Pattern) as SelectionItemPattern;
+ sPat.Select();
+ }
+
+ public static void SelectListItem(AutomationElement selectionContainer, String itemText)
+ {
+ if ((selectionContainer == null) || (itemText == ""))
+ {
+ throw new ArgumentException(
+ "Argument cannot be null or empty.");
+ }
+
+ Condition propertyCondition = new PropertyCondition(
+ AutomationElement.AutomationIdProperty,
+ itemText,
+ PropertyConditionFlags.IgnoreCase);
+
+ AutomationElement firstMatch =
+ selectionContainer.FindFirst(TreeScope.Children, propertyCondition);
+
+ if (firstMatch != null)
+ {
+ try
+ {
+ SelectionItemPattern selectionItemPattern;
+ selectionItemPattern =
+ firstMatch.GetCurrentPattern(
+ SelectionItemPattern.Pattern) as SelectionItemPattern;
+ selectionItemPattern.Select();
+ }
+ catch (InvalidOperationException)
+ {
+ // Unable to select
+ return;
+ }
+ }
+ }
+ }
+}
diff --git a/src/WhiteProject/Properties/AssemblyInfo.cs b/src/WhiteProject/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..b0a8475f
--- /dev/null
+++ b/src/WhiteProject/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("WhiteProject")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("WhiteProject")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("d913d1d2-26cd-4679-93c4-d131abbd8eaf")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/WhiteProject/WhiteProject.csproj b/src/WhiteProject/WhiteProject.csproj
new file mode 100644
index 00000000..22ec1848
--- /dev/null
+++ b/src/WhiteProject/WhiteProject.csproj
@@ -0,0 +1,66 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {39964358-1A5B-4F78-9520-1B106F70CE72}
+ Exe
+ Properties
+ WhiteProject
+ WhiteProject
+ v4.5
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {12c59ce2-9cf7-44f4-b27c-90754609f979}
+ TestStack.White
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/UISpy.zip b/tools/UISpy.zip
new file mode 100644
index 00000000..1a388d4d
Binary files /dev/null and b/tools/UISpy.zip differ