Add support for custom HTML control classes derived from a specific HTML control class in `Microsoft.VisualStudio.TestTools.UITesting.HtmlControls`
icnocop opened this issue · comments
Hi.
I'd like to request support for custom HTML control classes derived from a specific HTML control class in Microsoft.VisualStudio.TestTools.UITesting.HtmlControls
For example, if I try to automate selecting an item in a drop down list control by using the HtmlComboBox
class, but the element is rendered on the HTML page using the Kendo UI DropDownList widget, the test will fail to select the item.
Instead, I can run JavaScript on the page using the ExecuteScript
method on the IBrowser
instance to get the selected value and set a new value.
For example, here is a helper class I created:
internal class KendoDropDownList
{
private readonly IBrowser browser;
private readonly string elementSelector;
internal KendoDropDownList(IBrowser browser, string elementSelector)
{
this.browser = browser;
this.elementSelector = elementSelector;
}
internal string GetValue()
{
return (string)this.browser.ExecuteScript($"return $('{this.elementSelector}').data('kendoDropDownList').value();");
}
internal void SetValue(object value)
{
this.browser.ExecuteScript($"$('{this.elementSelector}').data('kendoDropDownList').value('{value}');");
// trigger the change event to update the bindings
this.browser.ExecuteScript($"$('{this.elementSelector}').data('kendoDropDownList').trigger('change');");
}
}
I can then use it my page/dialog like this:
public class PersonPage : HtmlDocument
{
private readonly IBrowser browser;
private readonly KendoDropDownList genderDropDownList;
public PersonPage(IBrowser browser, UITestControl parent)
: base(parent)
{
this.browser = browser;
this.genderDropDownList = new KendoDropDownList(browser, "#gender");
}
public string Gender
{
get
{
return this.genderDropDownList.GetValue();
}
set
{
this.roleDropDownList.SetValue(value);
}
}
}
This works fine, but when I tried to simplify the page/dialog model as follows:
public class PersonPage : HtmlDocument
{
public PersonPage(UITestControl parent)
: base(parent)
{
}
[ElementLocator(Id = "gender")]
public KendoDropDownList Gender { get; set; }
}
And refactored the class as follows:
public class KendoDropDownList : HtmlComboBox
{
private readonly IBrowser browser;
public KendoDropDownList()
{
}
public KendoDropDownList(UITestControl parent)
{
this.browser = ScenarioContext.Current.Get<IBrowser>("CurrentBrowser");
}
public override string SelectedItem
{
get
{
return (string)this.browser.ExecuteScript($"return $('#{this.Id}').data('kendoDropDownList').value();");
}
set
{
this.browser.ExecuteScript($"$('#{this.Id}').data('kendoDropDownList').value({value});");
// trigger the change event to update the bindings
this.browser.ExecuteScript($"$('#{this.Id}').data('kendoDropDownList').trigger('change');");
}
}
}
And run a scenario like this:
Given I entered data
| Field | Value |
| Gender | Male |
I get the following exception:
SpecBind.Pages.ElementExecuteException: Errors occurred while entering data. Details: Cannot find input handler for property 'Gender' on page PersonPage. Element propertyValue was: KendoDropDownList;
I expect SpecBind to be able to support HTML control classes that inherit from HtmlComboBox
.
In this example, I think the issue is in the GetPageFillMethod
method of the CodedUIPage
class here: https://github.com/dpiessens/specbind/blob/master/src/SpecBind.CodedUI/CodedUIPage.cs#L275:
if (propertyType == typeof(HtmlComboBox))
Since my class inherits from HtmlComboBox
, this condition returns false
.
Instead, I think those types of condition statements should be refactored as follows:
if (typeof(HtmlComboBox).IsAssignableFrom(propertyType))
Thank you.
For reference, http://docs.telerik.com/kendo-ui/api/javascript/ui/dropdownlist