diff --git a/Microsoft.Dynamics365.UIAutomation.Api.UCI/DTO/AppElementReference.cs b/Microsoft.Dynamics365.UIAutomation.Api.UCI/DTO/AppElementReference.cs index 6626a0dd..1300ce64 100644 --- a/Microsoft.Dynamics365.UIAutomation.Api.UCI/DTO/AppElementReference.cs +++ b/Microsoft.Dynamics365.UIAutomation.Api.UCI/DTO/AppElementReference.cs @@ -299,8 +299,8 @@ public static class AppElements { "Nav_SitemapMenuItems", "//li[contains(@data-id,'sitemap-entity')]"}, { "Nav_SitemapSwitcherButton", "//button[contains(@data-id,'sitemap-areaSwitcher-expand-btn')]"}, { "Nav_SitemapSwitcherFlyout","//div[contains(@data-lp-id,'sitemap-area-switcher-flyout')]"}, - { "Nav_UCIAppContainer","//div[contains(@id,'AppLandingPageContentContainer')]"}, - { "Nav_UCIAppTile", ".//a[contains(@aria-label,'[NAME]')]"}, + { "Nav_UCIAppContainer","//div[@id='AppLandingPageContentContainer']"}, + { "Nav_UCIAppTile", "//div[@data-type='app-title' and @title='[NAME]']"}, //Grid diff --git a/Microsoft.Dynamics365.UIAutomation.Api.UCI/Elements/Dialog.cs b/Microsoft.Dynamics365.UIAutomation.Api.UCI/Elements/Dialog.cs index 4844d809..fe59c3fa 100644 --- a/Microsoft.Dynamics365.UIAutomation.Api.UCI/Elements/Dialog.cs +++ b/Microsoft.Dynamics365.UIAutomation.Api.UCI/Elements/Dialog.cs @@ -58,7 +58,7 @@ public void CloseOpportunity(double revenue, DateTime closeDate, string descript /// /// Enum used to assign record to user or team /// Name of the user or team to assign to - public void Assign(Dialogs.AssignTo to, string userOrTeamName = "") + public void Assign(AssignTo to, string userOrTeamName = null) { _client.AssignDialog(to, userOrTeamName); } diff --git a/Microsoft.Dynamics365.UIAutomation.Api.UCI/WebClient.cs b/Microsoft.Dynamics365.UIAutomation.Api.UCI/WebClient.cs index 2ef226b9..f4efd7be 100644 --- a/Microsoft.Dynamics365.UIAutomation.Api.UCI/WebClient.cs +++ b/Microsoft.Dynamics365.UIAutomation.Api.UCI/WebClient.cs @@ -12,6 +12,7 @@ using System.Security; using System.Threading; using System.Web; +using OpenQA.Selenium.Interactions; using OtpNet; namespace Microsoft.Dynamics365.UIAutomation.Api.UCI @@ -49,7 +50,7 @@ internal BrowserCommandResult InitializeModes() if (Browser.Options.UCITestMode) queryParams += ",testmode=true"; if (Browser.Options.UCIPerformanceMode) queryParams += "&perf=true"; - if (!uri.Contains(queryParams) && !uri.Contains(System.Web.HttpUtility.UrlEncode(queryParams))) + if (!uri.Contains(queryParams) && !uri.Contains(HttpUtility.UrlEncode(queryParams))) { var testModeUri = uri + queryParams; @@ -66,37 +67,23 @@ internal BrowserCommandResult InitializeModes() public string[] OnlineDomains { get; set; } #region PageWaits - - internal void WaitForLoginPage() - { - IWebDriver driver = this.Browser.Driver; - - driver.WaitUntilVisible(By.XPath(Elements.Xpath[Reference.Login.CrmMainPage]) - , TimeSpan.FromSeconds(60), - e => - { - //determine if we landed on the Unified Client Main page - if (driver.HasElement(By.XPath(Elements.Xpath[Reference.Login.CrmUCIMainPage]))) - { - driver.WaitForPageToLoad(); - driver.WaitForTransaction(); - } - else //else we landed on the Web Client main page or app picker page - SwitchToDefaultContent(driver); - }, - "Login page failed." - ); - } - - internal void WaitForMainPage() - { - IWebDriver driver = this.Browser.Driver; - driver.WaitUntilVisible(By.XPath(Elements.Xpath[Reference.Login.CrmMainPage])); - driver.WaitForPageToLoad(); - if (driver.HasElement(By.XPath(Elements.Xpath[Reference.Login.CrmUCIMainPage]))) - { - driver.WaitForTransaction(); - } + internal bool WaitForMainPage(TimeSpan timeout, string errorMessage) + => WaitForMainPage(timeout, null, () => throw new InvalidOperationException(errorMessage)); + + internal bool WaitForMainPage(TimeSpan? timeout = null, Action successCallback = null, Action failureCallback = null) + { + IWebDriver driver = Browser.Driver; + timeout = timeout ?? Constants.DefaultTimeout; + successCallback = successCallback ?? ( + _ => { + bool isUCI = driver.HasElement(By.XPath(Elements.Xpath[Reference.Login.CrmUCIMainPage])); + if (isUCI) + driver.WaitForTransaction(); + }); + + var xpathToMainPage = By.XPath(Elements.Xpath[Reference.Login.CrmMainPage]); + var element = driver.WaitUntilVisible(xpathToMainPage, timeout, successCallback, failureCallback); + return element != null; } #endregion @@ -132,7 +119,7 @@ private LoginResult Login(IWebDriver driver, Uri uri, SecureString username, Sec bool success = EnterUserName(driver, username); if (!success) { - var isUserAlreadyLogged = IsUserAlreadyLogged(driver); + var isUserAlreadyLogged = IsUserAlreadyLogged(); if (isUserAlreadyLogged) { SwitchToDefaultContent(driver); @@ -165,21 +152,23 @@ private LoginResult Login(IWebDriver driver, Uri uri, SecureString username, Sec ThinkTime(1000); } - EnterOneTimeCode(driver, mfaSecrectKey); - - ClickStaySignedIn(driver); - - ThinkTime(1000); + int attempts = 0; + bool entered; + do + { + entered = EnterOneTimeCode(driver, mfaSecrectKey); + success = ClickStaySignedIn(driver) || IsUserAlreadyLogged(); + attempts++; + } + while (!success && attempts <= Constants.DefaultRetryAttempts); // retry to enter the otc-code, if its fail & it is requested again + + if (entered && !success) + throw new InvalidOperationException("Somethig got wrong entering the OTC. Please check the MFA-SecrectKey in configuration."); - return LoginResult.Success; + return success ? LoginResult.Success : LoginResult.Failure; } - private static bool IsUserAlreadyLogged(IWebDriver driver) - { - var xpathToMainPage = By.XPath(Elements.Xpath[Reference.Login.CrmMainPage]); - bool result = driver.HasElement(xpathToMainPage); - return result; - } + private bool IsUserAlreadyLogged() => WaitForMainPage(2.Seconds()); private static string GenerateOneTimeCode(SecureString mfaSecrectKey) { @@ -213,41 +202,39 @@ private static void EnterPassword(IWebDriver driver, SecureString password) input.Submit(); } - private void EnterOneTimeCode(IWebDriver driver, SecureString mfaSecrectKey) + private bool EnterOneTimeCode(IWebDriver driver, SecureString mfaSecrectKey) { - int attempts = 0; - while (true) + try { - try - { - IWebElement input = GetOtcInput(driver); - if (input != null) - { - var oneTimeCode = GenerateOneTimeCode(mfaSecrectKey); - input.SendKeys(oneTimeCode); - input.Submit(); - return; - } - } - catch (Exception e) - { - Trace.TraceInformation($"An Error ocur entering OTC. Attempt {attempts} of {Constants.DefaultRetryAttempts}. Exception: {e}"); - if (attempts >= Constants.DefaultRetryAttempts) - throw; - } - attempts++; - ThinkTime(Constants.DefaultRetryDelay); + IWebElement input = GetOtcInput(driver); // wait for the dialog, even if key is null, to print the right error + if (input == null) + return true; + + if (mfaSecrectKey == null) + throw new InvalidOperationException("The application is wait for the OTC but your MFA-SecrectKey is not set. Please check your configuration."); + + var oneTimeCode = GenerateOneTimeCode(mfaSecrectKey); + SetInputValue(driver, input, oneTimeCode, 1.Seconds()); + input.Submit(); + return true; // input found & code was entered + } + catch (Exception e) + { + var message = $"An Error occur entering OTC. Exception: {e.Message}"; + Trace.TraceInformation(message); + throw new InvalidOperationException(message, e); } } + private static IWebElement GetOtcInput(IWebDriver driver) => driver.WaitUntilAvailable(By.XPath(Elements.Xpath[Reference.Login.OneTimeCode]), TimeSpan.FromSeconds(2)); - private static void ClickStaySignedIn(IWebDriver driver) + private static bool ClickStaySignedIn(IWebDriver driver) { var xpath = By.XPath(Elements.Xpath[Reference.Login.StaySignedIn]); - driver.WaitUntilVisible(xpath, new TimeSpan(0, 0, 5), - e => driver.ClickWhenAvailable(xpath)); + var element = driver.ClickIfVisible(xpath, 5.Seconds()); + return element != null; } private static void SwitchToDefaultContent(IWebDriver driver) @@ -271,7 +258,22 @@ internal BrowserCommandResult PassThroughLogin(Uri uri) { driver.Navigate().GoToUrl(uri); - WaitForLoginPage(); + WaitForMainPage(60.Seconds(), + _ => + { + //determine if we landed on the Unified Client Main page + var isUCI = driver.HasElement(By.XPath(Elements.Xpath[Reference.Login.CrmUCIMainPage])); + if (isUCI) + { + driver.WaitForPageToLoad(); + driver.WaitForTransaction(); + } + else + //else we landed on the Web Client main page or app picker page + SwitchToDefaultContent(driver); + }, + () => new InvalidOperationException("Load Main Page Fail.") + ); return LoginResult.Success; }); @@ -293,7 +295,7 @@ public void ADFSLoginAction(LoginRedirectEventArgs args) //Insert any additional code as required for the SSO scenario //Wait for CRM Page to load - driver.WaitUntilVisible(By.XPath(Elements.Xpath[Reference.Login.CrmMainPage]), TimeSpan.FromSeconds(60), "Login page failed."); + WaitForMainPage(TimeSpan.FromSeconds(60), "Login page failed."); SwitchToMainFrame(driver); } @@ -323,7 +325,7 @@ public void MSFTLoginAction(LoginRedirectEventArgs args) //Insert any additional code as required for the SSO scenario //Wait for CRM Page to load - driver.WaitUntilVisible(By.XPath(Elements.Xpath[Reference.Login.CrmMainPage]), TimeSpan.FromSeconds(60), "Login page failed."); + WaitForMainPage(TimeSpan.FromSeconds(60), "Login page failed."); SwitchToMainFrame(driver); } @@ -337,12 +339,14 @@ internal BrowserCommandResult OpenApp(string appName, int thinkTime = Cons return Execute(GetOptions($"Open App {appName}"), driver => { + driver.WaitForPageToLoad(); driver.SwitchTo().DefaultContent(); //Handle left hand Nav in Web Client - var success = TryOpenAppFromMenu(driver, appName, AppReference.Navigation.WebAppMenuButton) || - TryOpenAppFromMenu(driver, appName, AppReference.Navigation.UCIAppMenuButton) || - TryToClickInAppTile(appName, driver); + var success = TryToClickInAppTile(appName, driver) || + TryOpenAppFromMenu(driver, appName, AppReference.Navigation.WebAppMenuButton) || + TryOpenAppFromMenu(driver, appName, AppReference.Navigation.UCIAppMenuButton); + if (!success) throw new InvalidOperationException($"App Name {appName} not found."); @@ -355,36 +359,26 @@ internal BrowserCommandResult OpenApp(string appName, int thinkTime = Cons private bool TryOpenAppFromMenu(IWebDriver driver, string appName, string appMenuButton) { - try - { - var xpathToAppMenu = By.XPath(AppElements.Xpath[appMenuButton]); - bool found = driver.TryFindElement(xpathToAppMenu, out var appMenu); - if (found) - { - appMenu.Click(true); - OpenAppFromMenu(driver, appName); - } - - return found; - } - catch (Exception e) - { - throw new InvalidOperationException($"App Button {appMenuButton} not found.", e); - } + bool found = false; + var xpathToAppMenu = By.XPath(AppElements.Xpath[appMenuButton]); + driver.WaitUntilClickable(xpathToAppMenu, TimeSpan.FromSeconds(5), + appMenu => + { + appMenu.Click(true); + OpenAppFromMenu(driver, appName); + found = true; + }); + return found; } internal void OpenAppFromMenu(IWebDriver driver, string appName) { var container = driver.WaitUntilAvailable(By.XPath(AppElements.Xpath[AppReference.Navigation.AppMenuContainer])); - - var buttons = container.FindElements(By.TagName("button")); - - var button = buttons.FirstOrDefault(x => x.Text.Trim() == appName); - - if (button != null) - button.Click(true); - else - throw new InvalidOperationException($"App Name {appName} not found."); + var xpathToButton = "//nav[@aria-hidden='false']//button//*[text()='[TEXT]']".Replace("[TEXT]", appName); + container.ClickWhenAvailable(By.XPath(xpathToButton), + TimeSpan.FromSeconds(1), + $"App Name {appName} not found." + ); driver.WaitUntilVisible(By.XPath(AppElements.Xpath[AppReference.Application.Shell])); driver.WaitUntilVisible(By.XPath(AppElements.Xpath[AppReference.Navigation.SiteMapLauncherButton])); @@ -392,15 +386,33 @@ internal void OpenAppFromMenu(IWebDriver driver, string appName) private static bool TryToClickInAppTile(string appName, IWebDriver driver) { - //Switch to frame 0 - driver.SwitchTo().Frame(0); - IWebElement tileContainer; - bool success = driver.TryFindElement(By.XPath(AppElements.Xpath[AppReference.Navigation.UCIAppContainer]), out tileContainer); - if (success) - { - var appTile = tileContainer.FindElement(By.XPath(AppElements.Xpath[AppReference.Navigation.UCIAppTile].Replace("[NAME]", appName))); - appTile.Click(true); - } + string message = null; + driver.WaitUntil( + d => + { + try + { + driver.SwitchTo().Frame("AppLandingPage"); + } + catch (NoSuchFrameException ex) + { + message = $"Frame AppLandingPage is not loaded. Exception: {ex.Message}"; + Trace.TraceWarning(message); + return false; + } + return true; + }, + TimeSpan.FromSeconds(30), + failureCallback: () => throw new InvalidOperationException(message) + ); + + var xpathToAppContainer = By.XPath(AppElements.Xpath[AppReference.Navigation.UCIAppContainer]); + var xpathToappTile = By.XPath(AppElements.Xpath[AppReference.Navigation.UCIAppTile].Replace("[NAME]", appName)); + + bool success = false; + driver.WaitUntilVisible(xpathToAppContainer, TimeSpan.FromSeconds(5), + appContainer => success = appContainer.ClickWhenAvailable(xpathToappTile, TimeSpan.FromSeconds(5)) != null + ); return success; } @@ -901,56 +913,47 @@ internal BrowserCommandResult ConfirmationDialog(bool ClickConfirmButton) }); } - internal BrowserCommandResult AssignDialog(Dialogs.AssignTo to, string userOrTeamName) + internal BrowserCommandResult AssignDialog(Dialogs.AssignTo to, string userOrTeamName = null) { + userOrTeamName = userOrTeamName?.Trim() ?? string.Empty; return this.Execute(GetOptions($"Assign to User or Team Dialog"), driver => { var inlineDialog = this.SwitchToDialog(); - if (inlineDialog) - { - if (to != Dialogs.AssignTo.Me) - { - //Click the Option to Assign to User Or Team - driver.WaitUntilClickable(By.XPath(AppElements.Xpath[AppReference.Dialogs.AssignDialogToggle])); - - var toggleButton = driver.WaitUntilAvailable(By.XPath(AppElements.Xpath[AppReference.Dialogs.AssignDialogToggle]), "Me/UserTeam toggle button unavailable"); - if (toggleButton.Text == "Me") - toggleButton.Click(); - - //Set the User Or Team - var userOrTeamField = driver.WaitUntilAvailable(By.XPath(AppElements.Xpath[AppReference.Entity.TextFieldLookup]), "User field unavailable"); - - if (userOrTeamField.FindElements(By.TagName("input")).Count > 0) - { - var input = userOrTeamField.FindElement(By.TagName("input")); - if (input != null) - { - input.Click(); - - driver.WaitForTransaction(); - - input.SendKeys(userOrTeamName, true); - } - } - - //Pick the User from the list - driver.WaitUntilVisible(By.XPath(AppElements.Xpath[AppReference.Dialogs.AssignDialogUserTeamLookupResults])); - - driver.WaitForTransaction(); + if (!inlineDialog) + return false; - var container = driver.FindElement(By.XPath(AppElements.Xpath[AppReference.Dialogs.AssignDialogUserTeamLookupResults])); - var records = container.FindElements(By.TagName("li")); - foreach (var record in records) - { - if (record.Text.StartsWith(userOrTeamName, StringComparison.OrdinalIgnoreCase)) - record.Click(true); - } - } + //Click the Option to Assign to User Or Team + var xpathToToggleButton = By.XPath(AppElements.Xpath[AppReference.Dialogs.AssignDialogToggle]); + var toggleButton = driver.WaitUntilClickable(xpathToToggleButton, "Me/UserTeam toggle button unavailable"); - //Click Assign - var okButton = driver.FindElement(By.XPath(AppElements.Xpath[AppReference.Dialogs.AssignDialogOKButton])); - okButton.Click(true); + if (to == Dialogs.AssignTo.Me) + { + if (toggleButton.Text != "Me") + toggleButton.Click(); } + else + { + if (toggleButton.Text == "Me") + toggleButton.Click(); + + //Set the User Or Team + var userOrTeamField = driver.WaitUntilAvailable(By.XPath(AppElements.Xpath[AppReference.Entity.TextFieldLookup]), "User field unavailable"); + var input = userOrTeamField.ClickWhenAvailable(By.TagName("input"), "User field unavailable"); + input.SendKeys(userOrTeamName, true); + + ThinkTime(2000); + + //Pick the User from the list + var container = driver.WaitUntilVisible(By.XPath(AppElements.Xpath[AppReference.Dialogs.AssignDialogUserTeamLookupResults])); + container.WaitUntil( + c => c.FindElements(By.TagName("li")).FirstOrDefault(r => r.Text.StartsWith(userOrTeamName, StringComparison.OrdinalIgnoreCase)), + successCallback: e => e.Click(true), + failureCallback: () => throw new InvalidOperationException($"None {to} found which match with '{userOrTeamName}'")); + } + + //Click Assign + driver.ClickWhenAvailable(By.XPath(AppElements.Xpath[AppReference.Dialogs.AssignDialogOKButton]), TimeSpan.FromSeconds(5), + "Unable to click the OK button in the assign dialog"); return true; }); @@ -1903,6 +1906,19 @@ internal BrowserCommandResult SetValue(string field, string value) }); } + private void SetInputValue(IWebDriver driver, IWebElement input, string value, TimeSpan? thinktime = null) + { + input.SendKeys(Keys.Control + "a"); + input.SendKeys(Keys.Backspace); + driver.WaitForTransaction(); + + if (string.IsNullOrWhiteSpace(value)) + return; + + input.SendKeys(value, true); + driver.WaitForTransaction(); + ThinkTime(thinktime ?? 3.Seconds()); + } /// /// Sets the value of a Lookup, Customer, Owner or ActivityParty Lookup which accepts only a single value. /// @@ -2223,6 +2239,7 @@ private void TrySetDateValue(IWebDriver driver, IWebElement dateField, string da failureCallback: () => throw new InvalidOperationException($"Timeout after 10 seconds. Expected: {date}. Actual: {dateField.GetAttribute("value")}") ); } + private void ClearFieldValue(IWebElement field) { if (field.GetAttribute("value").Length > 0) @@ -2230,6 +2247,7 @@ private void ClearFieldValue(IWebElement field) field.SendKeys(Keys.Control + "a"); field.SendKeys(Keys.Backspace); } + ThinkTime(500); } @@ -2637,7 +2655,7 @@ internal BrowserCommandResult GetValue(MultiValueOptionSet expandCollapseButtons.First().Click(true); } - var returnValue = new MultiValueOptionSet { Name = option.Name }; + var returnValue = new MultiValueOptionSet {Name = option.Name}; xpath = AppElements.Xpath[AppReference.MultiSelect.SelectedRecordLabel].Replace("[NAME]", Elements.ElementId[option.Name]); var labelItems = driver.FindElements(By.XPath(xpath)); @@ -2909,7 +2927,7 @@ internal BrowserCommandResult GetHeaderValue(BooleanItem control) { var xpathToContainer = AppElements.Xpath[AppReference.Entity.Header.DateTimeFieldContainer].Replace("[NAME]", control.Name); return Execute(GetOptions($"Get Header DateTime Value {control.Name}"), - driver => ExecuteInHeaderContainer(driver, xpathToContainer, + driver => ExecuteInHeaderContainer(driver, xpathToContainer, container => TryGetValue(driver, container, control))); } @@ -4151,7 +4169,7 @@ internal BrowserCommandResult SelectDashboard(string dashboardName, int th internal void EnablePerformanceCenter() { - Browser.Driver.Navigate().GoToUrl(string.Format("{0}&perf=true", Browser.Driver.Url)); + Browser.Driver.Navigate().GoToUrl($"{Browser.Driver.Url}&perf=true"); Browser.Driver.WaitForPageToLoad(); Browser.Driver.WaitForTransaction(); } @@ -4163,6 +4181,11 @@ internal void ThinkTime(int milliseconds) Browser.ThinkTime(milliseconds); } + internal void ThinkTime(TimeSpan timespan) + { + ThinkTime((int)timespan.TotalMilliseconds); + } + internal void Dispose() { Browser.Dispose(); diff --git a/Microsoft.Dynamics365.UIAutomation.Api.UCI/XrmApp.cs b/Microsoft.Dynamics365.UIAutomation.Api.UCI/XrmApp.cs index 7dfd17fb..31192c13 100644 --- a/Microsoft.Dynamics365.UIAutomation.Api.UCI/XrmApp.cs +++ b/Microsoft.Dynamics365.UIAutomation.Api.UCI/XrmApp.cs @@ -43,6 +43,11 @@ public void ThinkTime(int milliseconds) { _client.ThinkTime(milliseconds); } + public void ThinkTime(TimeSpan timespan) + { + _client.ThinkTime((int)timespan.TotalMilliseconds); + } + public void Dispose() { _client?.Dispose(); diff --git a/Microsoft.Dynamics365.UIAutomation.Browser/Extensions/SeleniumExtensions.cs b/Microsoft.Dynamics365.UIAutomation.Browser/Extensions/SeleniumExtensions.cs index 27ea225b..448df279 100644 --- a/Microsoft.Dynamics365.UIAutomation.Browser/Extensions/SeleniumExtensions.cs +++ b/Microsoft.Dynamics365.UIAutomation.Browser/Extensions/SeleniumExtensions.cs @@ -7,6 +7,7 @@ using OpenQA.Selenium.Support.Events; using OpenQA.Selenium.Support.UI; using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; diff --git a/Microsoft.Dynamics365.UIAutomation.Browser/Extensions/TimeExtensions.cs b/Microsoft.Dynamics365.UIAutomation.Browser/Extensions/TimeExtensions.cs new file mode 100644 index 00000000..78fdafd0 --- /dev/null +++ b/Microsoft.Dynamics365.UIAutomation.Browser/Extensions/TimeExtensions.cs @@ -0,0 +1,13 @@ +// Created by: Rodriguez Mustelier Angel (rodang) +// Modify On: 2020-02-09 14:05 + +using System; + +namespace Microsoft.Dynamics365.UIAutomation.Browser +{ + public static class TimeExtensions + { + public static TimeSpan Seconds(this int value) + => TimeSpan.FromSeconds(value); + } +} \ No newline at end of file diff --git a/Microsoft.Dynamics365.UIAutomation.Browser/Microsoft.Dynamics365.UIAutomation.Browser.csproj b/Microsoft.Dynamics365.UIAutomation.Browser/Microsoft.Dynamics365.UIAutomation.Browser.csproj index ee96443d..e8422a04 100644 --- a/Microsoft.Dynamics365.UIAutomation.Browser/Microsoft.Dynamics365.UIAutomation.Browser.csproj +++ b/Microsoft.Dynamics365.UIAutomation.Browser/Microsoft.Dynamics365.UIAutomation.Browser.csproj @@ -80,6 +80,7 @@ + diff --git a/Microsoft.Dynamics365.UIAutomation.Sample/UCI/CommandBar/AssignAccount.cs b/Microsoft.Dynamics365.UIAutomation.Sample/UCI/CommandBar/AssignAccount.cs index ed719eaf..ccd325a2 100644 --- a/Microsoft.Dynamics365.UIAutomation.Sample/UCI/CommandBar/AssignAccount.cs +++ b/Microsoft.Dynamics365.UIAutomation.Sample/UCI/CommandBar/AssignAccount.cs @@ -3,6 +3,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Dynamics365.UIAutomation.Api.UCI; +using Microsoft.Dynamics365.UIAutomation.Browser; namespace Microsoft.Dynamics365.UIAutomation.Sample.UCI @@ -25,9 +26,22 @@ public void UCITestAssignAccount() _xrmApp.ThinkTime(2000); + string name = _xrmApp.Entity.GetHeaderValue(new LookupItem{ Name = "ownerid" }); + Assert.IsNotNull(name); + _xrmApp.CommandBar.ClickCommand("Assign"); + _xrmApp.Dialogs.Assign(Dialogs.AssignTo.User, name); + } - _xrmApp.Dialogs.Assign(Dialogs.AssignTo.User, "Grant"); + [TestMethod] + public void UCITestAssignAccount_ToMe() + { + _xrmApp.Grid.OpenRecord(0); + + _xrmApp.ThinkTime(2000); + + _xrmApp.CommandBar.ClickCommand("Assign"); + _xrmApp.Dialogs.Assign(Dialogs.AssignTo.Me); } } } diff --git a/Microsoft.Dynamics365.UIAutomation.Sample/UCI/Login/Login.cs b/Microsoft.Dynamics365.UIAutomation.Sample/UCI/Login/Login.cs index 212e42b3..514919b8 100644 --- a/Microsoft.Dynamics365.UIAutomation.Sample/UCI/Login/Login.cs +++ b/Microsoft.Dynamics365.UIAutomation.Sample/UCI/Login/Login.cs @@ -20,7 +20,7 @@ public void MultiFactorLogin() _xrmApp.CommandBar.ClickCommand("New"); - _xrmApp.Entity.SetValue("name", _timed("Test API Account")); + _xrmApp.Entity.SetValue("name", "Test API Account"); _xrmApp.Entity.SetValue("telephone1", "555-555-5555"); } } diff --git a/Microsoft.Dynamics365.UIAutomation.Sample/UCI/TestsBase.cs b/Microsoft.Dynamics365.UIAutomation.Sample/UCI/TestsBase.cs index 10a40bd5..8e731c0d 100644 --- a/Microsoft.Dynamics365.UIAutomation.Sample/UCI/TestsBase.cs +++ b/Microsoft.Dynamics365.UIAutomation.Sample/UCI/TestsBase.cs @@ -22,8 +22,16 @@ public class TestsBase public virtual void InitTest() { - CreateApp(); - NavigateToHomePage(); + try + { + CreateApp(); + NavigateToHomePage(); + } + catch + { + CloseApp(); + throw; + } } public virtual void FinishTest()