Skip to content

Commit

Permalink
Merge pull request #115 from 2gis/114-automation-properties
Browse files Browse the repository at this point in the history
Add support of AutomationProperties to GetElementAttribute
  • Loading branch information
skyline-gleb committed Dec 7, 2015
2 parents 8467c25 + eaa1f8f commit c24e977
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 35 deletions.
3 changes: 2 additions & 1 deletion Winium/TestApp.Test/py-functional/tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ def test_get_element_text(self):
@pytest.mark.parametrize(("attr_name", "expected_value"), [
('Width', '300'),
('DesiredSize.Width', '300'),
], ids=['simple property', 'nested property'])
('AutomationIdProperty', 'MyTextBox')
], ids=['simple property', 'nested property', 'automation property'])
def test_get_element_attribute(self, attr_name, expected_value):
"""
GET /session/:sessionId/element/:id/attribute/:name Get the value of an element's attribute.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ private string ExecuteAttributeScript(string command)
var attributeName = args[1].ToString();
var value = args[2];

element.SetAttribute(attributeName, value);
element.SetProperty(attributeName, value);

return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using Newtonsoft.Json.Linq;

using Winium.StoreApps.Common;
using Winium.StoreApps.Common.Exceptions;

#endregion

Expand All @@ -21,7 +20,7 @@ internal class GetElementAttributeCommand : CommandBase

#endregion

#region Public Methods and Operators
#region Methods

protected override string DoImpl()
{
Expand All @@ -43,21 +42,15 @@ protected override string DoImpl()
* property value as plain string if property is scalar or string,
* JSON encoded property if property is Lists, Dictionary or other nonscalar types
*/
try
{
var propertyObject = element.GetAttribute(attributeName);
object propertyObject;

return this.JsonResponse(ResponseStatus.Success, SerializeObjectAsString(propertyObject));
}
catch (AutomationException)
if (!element.TryGetAutomationProperty(attributeName, out propertyObject))
{
return this.JsonResponse();
element.TryGetProperty(attributeName, out propertyObject);
}
}

#endregion

#region Methods
return this.JsonResponse(ResponseStatus.Success, SerializeObjectAsString(propertyObject));
}

private static bool IsTypeSerializedUsingToString(Type type)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace Winium.StoreApps.InnerServer.Element.Helpers
{
#region

using Windows.UI.Xaml;

#endregion

internal static class AutomationPropertiesAccessor
{
#region Public Methods and Operators

public static bool TryGetAutomationProperty(FrameworkElement element, string propertyName, out object value)
{
value = null;
DependencyProperty property;
if (!AutomationPropertiesHelper.Instance.TryGetAutomationProperty(propertyName, out property))
{
return false;
}

value = element.GetValue(property);
return true;
}

#endregion
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
namespace Winium.StoreApps.InnerServer.Element.Helpers
{
#region

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

using Windows.UI.Xaml;
using Windows.UI.Xaml.Automation;

#endregion

internal class AutomationPropertiesHelper
{
#region Static Fields

private static readonly Lazy<AutomationPropertiesHelper> LazyInstance =
new Lazy<AutomationPropertiesHelper>(() => new AutomationPropertiesHelper());

#endregion

#region Fields

private readonly Dictionary<string, DependencyProperty> properties;

#endregion

#region Constructors and Destructors

private AutomationPropertiesHelper()
{
this.properties = typeof(AutomationProperties).GetRuntimeProperties()
.ToDictionary(f => f.Name, f => (DependencyProperty)f.GetValue(null));
}

#endregion

#region Public Properties

public static AutomationPropertiesHelper Instance
{
get
{
return LazyInstance.Value;
}
}

#endregion

#region Public Methods and Operators

public bool TryGetAutomationProperty(string name, out DependencyProperty property)
{
return this.properties.TryGetValue(name, out property);
}

#endregion
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Winium.StoreApps.InnerServer.Element
namespace Winium.StoreApps.InnerServer.Element.Helpers
{
#region

Expand All @@ -8,55 +8,64 @@

using Newtonsoft.Json.Linq;

using Windows.UI.Xaml;

using Winium.StoreApps.Common.Exceptions;

#endregion

internal partial class WiniumElement
internal static class PropertiesAccessor
{
#region Methods
#region Public Methods and Operators

internal object GetAttribute(string attributeName)
public static void SetProperty(FrameworkElement element, string propertyName, JToken value)
{
object targetObject;
PropertyInfo targetPropertyInfo;

if (this.GetAttributeTarget(attributeName, out targetObject, out targetPropertyInfo))
if (GetPropertyTarget(element, propertyName, out targetObject, out targetPropertyInfo))
{
return targetPropertyInfo.GetValue(targetObject, null);
targetPropertyInfo.SetValue(targetObject, value.ToObject(targetPropertyInfo.PropertyType));
}
else
{
throw new AutomationException("Could not access attribute {0}.", propertyName);
}

throw new AutomationException("Could not access attribute {0}.", attributeName);
}

internal void SetAttribute(string attributeName, JToken value)
public static bool TryGetProperty(FrameworkElement element, string propertyName, out object value)
{
value = null;
object targetObject;
PropertyInfo targetPropertyInfo;

if (this.GetAttributeTarget(attributeName, out targetObject, out targetPropertyInfo))
{
targetPropertyInfo.SetValue(targetObject, value.ToObject(targetPropertyInfo.PropertyType));
}
else
if (!GetPropertyTarget(element, propertyName, out targetObject, out targetPropertyInfo))
{
throw new AutomationException("Could not access attribute {0}.", attributeName);
return false;
}

value = targetPropertyInfo.GetValue(targetObject, null);
return true;
}

private bool GetAttributeTarget(
string attributeName,
#endregion

#region Methods

private static bool GetPropertyTarget(
object sourceObject,
string propertyName,
out object targetObject,
out PropertyInfo targetPropertyInfo)
{
targetObject = null;
targetPropertyInfo = null;

object parent = null;
var curObject = (object)this.Element;
var curObject = sourceObject;
PropertyInfo propertyInfo = null;

var properties = attributeName.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
var properties = propertyName.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

if (!properties.Any())
{
Expand Down
21 changes: 21 additions & 0 deletions Winium/Winium.StoreApps.InnerServer/Element/WiniumElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@

using System;

using Newtonsoft.Json.Linq;

using Windows.UI.Xaml;

using Winium.StoreApps.Common;
using Winium.StoreApps.Common.Exceptions;
using Winium.StoreApps.InnerServer.Commands.Helpers;
using Winium.StoreApps.InnerServer.Element.Helpers;

#endregion

Expand Down Expand Up @@ -135,6 +138,24 @@ public override int GetHashCode()
return this.weakElement != null ? this.weakElement.GetHashCode() : 0;
}

public void SetProperty(string attributeName, JToken value)
{
PropertiesAccessor.SetProperty(this.Element, attributeName, value);
}

public bool TryGetAutomationProperty(string automationPropertyName, out object value)
{
return AutomationPropertiesAccessor.TryGetAutomationProperty(
this.Element,
automationPropertyName,
out value);
}

public bool TryGetProperty(string attributeName, out object value)
{
return PropertiesAccessor.TryGetProperty(this.Element, attributeName, out value);
}

#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,13 @@
<Compile Include="Commands\GetElementTagNameCommand.cs" />
<Compile Include="Commands\TextCommand.cs" />
<Compile Include="Commands\ValueCommand.cs" />
<Compile Include="Element\Helpers\AutomationPropertiesAccessor.cs" />
<Compile Include="Element\Helpers\AutomationPropertiesHelper.cs" />
<Compile Include="Element\Helpers\PropertiesAccessor.cs" />
<Compile Include="Element\ISearchable.cs" />
<Compile Include="Element\WiniumElement.GetText.cs" />
<Compile Include="Element\WiniumElement.Find.cs" />
<Compile Include="Element\WiniumElement.Location.cs" />
<Compile Include="Element\WiniumElement.GetSetAttribute.cs" />
<Compile Include="Element\WiniumElement.cs" />
<Compile Include="Element\WiniumElement.IsUserVisible.cs" />
<Compile Include="Element\WiniumVirtualRoot.cs" />
Expand Down

0 comments on commit c24e977

Please sign in to comment.