Skip to content

Commit

Permalink
GitHub issues #404 and #380 Completing boolean Gets & Sets for all 3 …
Browse files Browse the repository at this point in the history
…field formats. Sorry this is a lot at once but I thought it made sense to keep it together (#483)
  • Loading branch information
jlattimer authored and TYLEROL committed May 21, 2019
1 parent d4b1e72 commit 8808642
Show file tree
Hide file tree
Showing 7 changed files with 383 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ public static class Entity
public static string DuplicateDetectionGridRows = "Entity_DuplicateDetectionGridRows";
public static string DuplicateDetectionIgnoreAndSaveButton = "Entity_DuplicateDetectionIgnoreAndSaveButton";
public static string FooterStatusValue = "Entity_FooterStatusField";
public static string EntityBooleanFieldRadioContainer = "Entity_BooleanFieldRadioContainer";
public static string EntityBooleanFieldRadioTrue = "Entity_BooleanFieldRadioTrue";
public static string EntityBooleanFieldRadioFalse = "Entity_BooleanFieldRadioFalse";
public static string EntityBooleanFieldCheckboxContainer = "Entity_BooleanFieldCheckboxContainer";
public static string EntityBooleanFieldCheckbox = "Entity_BooleanFieldCheckbox";
public static string EntityBooleanFieldList = "Entity_BooleanFieldList";

}

Expand Down Expand Up @@ -314,6 +320,12 @@ public static class AppElements
{ "Entity_DuplicateDetectionGridRows", "//div[contains(@class,'data-selectable')]" },
{ "Entity_DuplicateDetectionIgnoreAndSaveButton", "//button[contains(@data-id,'ignore_save')]"},
{ "Entity_FooterStatusField",".//span[contains(@role,'status')]"},
{ "Entity_BooleanFieldRadioContainer", "//div[contains(@data-id, '[NAME].fieldControl-checkbox-container') and contains(@role,'radiogroup')]"},
{ "Entity_BooleanFieldRadioTrue", "//div[contains(@data-id, '[NAME].fieldControl-checkbox-containercheckbox-inner-second')]"},
{ "Entity_BooleanFieldRadioFalse", "//div[contains(@data-id, '[NAME].fieldControl-checkbox-containercheckbox-inner-first')]"},
{ "Entity_BooleanFieldCheckboxContainer", "//div[contains(@data-id, '[NAME].fieldControl-checkbox-container')]"},
{ "Entity_BooleanFieldCheckbox", "//input[contains(@data-id, '[NAME].fieldControl-checkbox-toggle')]"},
{ "Entity_BooleanFieldList", "//select[contains(@data-id, '[NAME].fieldControl-checkbox-select')]"},


//CommandBar
Expand Down
34 changes: 31 additions & 3 deletions Microsoft.Dynamics365.UIAutomation.Api.UCI/Elements/Entity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,16 @@ public string GetHeaderValue(OptionSet control)
{
return _client.GetHeaderValue(control);
}

/// <summary>
/// Gets the value of a Boolean Item from the header
/// </summary>
/// <param name="control">The boolean field you want to Get.</param>
/// <example>xrmApp.Entity.GetHeaderValue(new BooleanItem { Name = "preferredcontactmethodcode"}); </example>
public bool GetHeaderValue(BooleanItem control)
{
return _client.GetHeaderValue(control);
}

/// <summary>
/// Gets the value of a field from the header
Expand Down Expand Up @@ -185,6 +195,15 @@ public string GetValue(OptionSet optionSet)
return _client.GetValue(optionSet);
}

/// <summary>
/// Gets the value of a Boolean Item.
/// </summary>
/// <param name="option">The boolean field name.</param>
public bool GetValue(BooleanItem option)
{
return _client.GetValue(option);
}

/// <summary>
/// Gets the value of a MultiValueOptionSet.
/// </summary>
Expand Down Expand Up @@ -283,6 +302,15 @@ public void SetHeaderValue(OptionSet control)
_client.SetHeaderValue(control);
}

/// <summary>
/// Sets the value of a BooleanItem in the header
/// </summary>
/// <param name="control">The boolean field you want to set.</param>
public void SetHeaderValue(BooleanItem control)
{
_client.SetHeaderValue(control);
}

/// <summary>
/// Sets the value of a field
/// </summary>
Expand Down Expand Up @@ -314,10 +342,10 @@ public void SetValue(OptionSet optionSet)
/// <summary>
/// Sets the value of a Boolean Item.
/// </summary>
/// <param name="option">The option you want to set.</param>
public void SetValue(BooleanItem optionSet)
/// <param name="option">The boolean field name.</param>
public void SetValue(BooleanItem option)
{
_client.SetValue(optionSet);
_client.SetValue(option);
}

/// <summary>
Expand Down
122 changes: 114 additions & 8 deletions Microsoft.Dynamics365.UIAutomation.Api.UCI/WebClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1669,27 +1669,62 @@ public BrowserCommandResult<bool> SetValue(OptionSet option)
/// <summary>
/// Sets the value of a Boolean Item.
/// </summary>
/// <param name="option">The option you want to set.</param>
/// <example>xrmBrowser.Entity.SetValue(new OptionSet { Name = "preferredcontactmethodcode", Value = "Email" });</example>
/// <param name="option">The boolean field name.</param>
/// <example>xrmApp.Entity.SetValue(new BooleanItem { Name = "donotemail", Value = true });</example>
public BrowserCommandResult<bool> SetValue(BooleanItem option)
{
return this.Execute(GetOptions($"Set BooleanItem Value: {option.Name}"), driver =>
{
var fieldContainer = driver.WaitUntilAvailable(By.XPath(AppElements.Xpath[AppReference.Entity.TextFieldContainer].Replace("[NAME]", option.Name)));
if (option.Value)
var hasRadio = fieldContainer.HasElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldRadioContainer].Replace("[NAME]", option.Name)));
var hasCheckbox = fieldContainer.HasElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldCheckbox].Replace("[NAME]", option.Name)));
var hasList = fieldContainer.HasElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldList].Replace("[NAME]", option.Name)));
if (hasRadio)
{
if (!fieldContainer.Selected)
var trueRadio = fieldContainer.FindElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldRadioTrue].Replace("[NAME]", option.Name)));
var falseRadio = fieldContainer.FindElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldRadioFalse].Replace("[NAME]", option.Name)));
if (option.Value && bool.Parse(falseRadio.GetAttribute("aria-checked")) || !option.Value && bool.Parse(trueRadio.GetAttribute("aria-checked")))
{
fieldContainer.Click();
driver.ClickWhenAvailable(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldRadioContainer].Replace("[NAME]", option.Name)));
}
}
else
else if (hasCheckbox)
{
if (fieldContainer.Selected)
var checkbox = fieldContainer.FindElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldCheckbox].Replace("[NAME]", option.Name)));
if (option.Value && !checkbox.Selected || !option.Value && checkbox.Selected)
{
fieldContainer.Click();
driver.ClickWhenAvailable(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldCheckboxContainer].Replace("[NAME]", option.Name)));
}
}
else if (hasList)
{
var list = fieldContainer.FindElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldList].Replace("[NAME]", option.Name)));
var options = list.FindElements(By.TagName("option"));
var selectedOption = options.FirstOrDefault(a => a.HasAttribute("data-selected") && bool.Parse(a.GetAttribute("data-selected")));
var unselectedOption = options.FirstOrDefault(a => !a.HasAttribute("data-selected"));
var trueOptionSelected = false;
if (selectedOption != null)
{
trueOptionSelected = selectedOption.GetAttribute("value") == "1";
}
if (option.Value && !trueOptionSelected || !option.Value && trueOptionSelected)
{
if (unselectedOption != null)
{
driver.ClickWhenAvailable(By.Id(unselectedOption.GetAttribute("id")));
}
}
}
else
throw new InvalidOperationException($"Field: {option.Name} Does not exist");
return true;
});
}
Expand Down Expand Up @@ -1961,6 +1996,53 @@ internal BrowserCommandResult<string> GetValue(OptionSet option)
});
}

/// <summary>
/// Sets the value of a Boolean Item.
/// </summary>
/// <param name="option">The boolean field name.</param>
/// <example>xrmApp.Entity.GetValue(new BooleanItem { Name = "creditonhold" });</example>
internal BrowserCommandResult<bool> GetValue(BooleanItem option)
{
return this.Execute($"Get BooleanItem Value: {option.Name}", driver =>
{
var check = false;
var fieldContainer = driver.WaitUntilAvailable(By.XPath(AppElements.Xpath[AppReference.Entity.TextFieldContainer].Replace("[NAME]", option.Name)));
var hasRadio = fieldContainer.HasElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldRadioContainer].Replace("[NAME]", option.Name)));
var hasCheckbox = fieldContainer.HasElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldCheckbox].Replace("[NAME]", option.Name)));
var hasList = fieldContainer.HasElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldList].Replace("[NAME]", option.Name)));
if (hasRadio)
{
var trueRadio = fieldContainer.FindElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldRadioTrue].Replace("[NAME]", option.Name)));
check = bool.Parse(trueRadio.GetAttribute("aria-checked"));
}
else if (hasCheckbox)
{
var checkbox = fieldContainer.FindElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldCheckbox].Replace("[NAME]", option.Name)));
check = bool.Parse(checkbox.GetAttribute("aria-checked"));
}
else if (hasList)
{
var list = fieldContainer.FindElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityBooleanFieldList].Replace("[NAME]", option.Name)));
var options = list.FindElements(By.TagName("option"));
var selectedOption = options.FirstOrDefault(a => a.HasAttribute("data-selected") && bool.Parse(a.GetAttribute("data-selected")));
if (selectedOption != null)
{
check = int.Parse(selectedOption.GetAttribute("value")) == 1;
}
}
else
throw new InvalidOperationException($"Field: {option.Name} Does not exist");
return check;
});
}

/// <summary>
/// Gets the value from the multselect type control
/// </summary>
Expand Down Expand Up @@ -2174,6 +2256,17 @@ internal BrowserCommandResult<string> GetHeaderValue(OptionSet control)
});
}

internal BrowserCommandResult<bool> GetHeaderValue(BooleanItem control)
{
return this.Execute(GetOptions($"Get Header BooleanItem Value {control}"), driver =>
{
if (!driver.HasElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityHeader])))
throw new NotFoundException("Unable to find header on the form");
return GetValue(control);
});
}

internal BrowserCommandResult<string> GetStatusFromFooter()
{
return this.Execute(GetOptions($"Get Status value from footer"), driver =>
Expand Down Expand Up @@ -2245,6 +2338,19 @@ internal BrowserCommandResult<bool> SetHeaderValue(OptionSet control)
});
}

internal BrowserCommandResult<bool> SetHeaderValue(BooleanItem control)
{
return this.Execute(GetOptions($"Set Header BooleanItem Value {control.Name}"), driver =>
{
if (!driver.HasElement(By.XPath(AppElements.Xpath[AppReference.Entity.EntityHeader])))
throw new NotFoundException("Unable to find header on the form");
SetValue(control);
return true;
});
}

internal BrowserCommandResult<bool> ClearValue(string fieldName)
{
return this.Execute(GetOptions($"Clear Field {fieldName}"), driver =>
Expand Down
20 changes: 20 additions & 0 deletions Microsoft.Dynamics365.UIAutomation.Api/DTOs/ElementReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,20 +139,30 @@ public static class Elements
{ "Entity_FieldContainer" , "//div[contains(@id,'[NAME]')]"},
{ "Entity_TextFieldContainer" , "//div[@id=\"[NAME]\"]" },
{ "Entity_CheckboxFieldContainer" , "//div[@id=\"[NAME]\"]" },
{ "Entity_TwoOptionFieldList", "//select[@id=\"[NAME]_i\"]" },
{ "Entity_TwoOptionFieldListOption", "//select[@id=\"[NAME]_i\"]//option[@value=\"[VALUE]\"]" },
{ "Entity_TwoOptionFieldTd", "//td[@id=\"[NAME]_d\"]" },
{ "Entity_TwoOptionFieldCheckbox", "//input[@id=\"[NAME]_i\"]" },
{ "Entity_OptionSetFieldContainer" , "//div[@id=\"[NAME]\"]" },
{ "Entity_LookupFieldContainer" , "//div[@id=\"[NAME]\"]" },
{ "Entity_DateFieldContainer" , "//div[@id=\"[NAME]\"]" },
{ "Entity_DateFieldInput" , "//input[@id=\"[NAME]_iDateInput\"]" },
{ "Entity_GetLookupSearchIcon" , "//div[@id=\"[NAME]_lookupSearchIconDiv\"]" },
{ "Entity_Header_TextFieldContainer" , "//div[@id=\"header_[NAME]\"]" },
{ "Entity_Header_CheckboxFieldContainer" , "//div[@id=\"header_[NAME]\"]" },
{ "Entity_Header_TwoOptionFieldList", "//select[@id=\"header_[NAME]_i\"]" },
{ "Entity_Header_TwoOptionFieldListOption", "//select[@id=\"header_[NAME]_i\"]//option[@value=\"[VALUE]\"]" },
{ "Entity_Header_TwoOptionFieldDiv", "//div[@id=\"header_[NAME]_d\"]" },
{ "Entity_Header_TwoOptionFieldCheckbox", "//input[@id=\"header_[NAME]_i\"]" },
{ "Entity_Header_OptionSetFieldContainer" , "//div[@id=\"header_[NAME]\"]" },
{ "Entity_Header_LookupFieldContainer" , "//div[@id=\"header_[NAME]\"]" },
{ "Entity_Header_DateFieldContainer" , "//div[@id=\"header_[NAME]\"]" },
{ "Entity_Header_DateFieldInput" , "//input[@id=\"header_[NAME]_iDateInput\"]" },
{ "Entity_Header_GetLookupSearchIcon" , "//div[@id=\"header_[NAME]_lookupSearchIconDiv\"]" },
{ "Entity_Footer_TextFieldContainer" , "//div[@id=\"footer_[NAME]\"]" },
{ "Entity_Footer_CheckboxFieldContainer" , "//div[@id=\"footer_[NAME]\"]" },
{ "Entity_Footer_TwoOptionFieldTd", "//td[@id=\"footer_[NAME]_d\"]" },
{ "Entity_Footer_TwoOptionFieldCheckbox", "//input[@id=\"footer_[NAME]_i\"]" },
{ "Entity_Footer_OptionSetFieldContainer" , "//div[@id=\"footer_[NAME]\"]" },
{ "Entity_Footer_LookupFieldContainer" , "//div[@id=\"footer_[NAME]\"]" },
{ "Entity_Footer_DateFieldContainer" , "//div[@id=\"footer_[NAME]\"]" },
Expand Down Expand Up @@ -641,20 +651,30 @@ public static class Entity
public static string FieldContainer = "Entity_FieldContainer";
public static string TextFieldContainer = "Entity_TextFieldContainer";
public static string CheckboxFieldContainer = "Entity_CheckboxFieldContainer";
public static string TwoOptionFieldList = "Entity_TwoOptionFieldList";
public static string TwoOptionFieldListOption = "Entity_TwoOptionFieldListOption";
public static string TwoOptionFieldTd = "Entity_TwoOptionFieldTd";
public static string TwoOptionFieldCheckbox = "Entity_TwoOptionFieldCheckbox";
public static string OptionSetFieldContainer = "Entity_OptionSetFieldContainer";
public static string LookupFieldContainer = "Entity_LookupFieldContainer";
public static string DateFieldContainer = "Entity_DateFieldContainer";
public static string DateFieldInput = "Entity_DateFieldInput";
public static string GetLookupSearchIcon = "Entity_GetLookupSearchIcon";
public static string TextFieldContainer_Header = "Entity_Header_TextFieldContainer";
public static string CheckboxFieldContainer_Header = "Entity_Header_CheckboxFieldContainer";
public static string TwoOptionFieldList_Header = "Entity_Header_TwoOptionFieldList";
public static string TwoOptionFieldListOption_Header = "Entity_Header_TwoOptionFieldListOption";
public static string TwoOptionFieldDiv_Header = "Entity_Header_TwoOptionFieldDiv";
public static string TwoOptionFieldCheckbox_Header = "Entity_Header_TwoOptionFieldCheckbox";
public static string OptionSetFieldContainer_Header = "Entity_Header_OptionSetFieldContainer";
public static string LookupFieldContainer_Header = "Entity_Header_LookupFieldContainer";
public static string DateFieldContainer_Header = "Entity_Header_DateFieldContainer";
public static string DateFieldInput_Header = "Entity_Header_DateFieldInput";
public static string GetLookupSearchIcon_Header = "Entity_Header_GetLookupSearchIcon";
public static string TextFieldContainer_Footer = "Entity_Footer_TextFieldContainer";
public static string CheckboxFieldContainer_Footer = "Entity_Footer_CheckboxFieldContainer";
public static string TwoOptionFieldTd_Footer = "Entity_Footer_TwoOptionFieldTd";
public static string TwoOptionFieldCheckbox_Footer = "Entity_Footer_TwoOptionFieldCheckbox";
public static string OptionSetFieldContainer_Footer = "Entity_Footer_OptionSetFieldContainer";
public static string LookupFieldContainer_Footer = "Entity_Footer_LookupFieldContainer";
public static string DateFieldContainer_Footer = "Entity_Footer_DateFieldContainer";
Expand Down

0 comments on commit 8808642

Please sign in to comment.