diff --git a/Microsoft.Dynamics365.UIAutomation.Api.UCI/Properties/AssemblyInfo.cs b/Microsoft.Dynamics365.UIAutomation.Api.UCI/Properties/AssemblyInfo.cs index 30d5c6fa..daf3eb74 100644 --- a/Microsoft.Dynamics365.UIAutomation.Api.UCI/Properties/AssemblyInfo.cs +++ b/Microsoft.Dynamics365.UIAutomation.Api.UCI/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // 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.21191.0750")] -[assembly: AssemblyFileVersion("1.0.21191.0750")] +[assembly: AssemblyVersion("1.0.21208.0840")] +[assembly: AssemblyFileVersion("1.0.21208.0840")] diff --git a/Microsoft.Dynamics365.UIAutomation.Api.UCI/WebClient.cs b/Microsoft.Dynamics365.UIAutomation.Api.UCI/WebClient.cs index 63d69746..718d3791 100644 --- a/Microsoft.Dynamics365.UIAutomation.Api.UCI/WebClient.cs +++ b/Microsoft.Dynamics365.UIAutomation.Api.UCI/WebClient.cs @@ -9,8 +9,10 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Collections.Specialized; using System.Diagnostics; using System.Linq; +using System.Resources; using System.Security; using System.Threading; using System.Web; @@ -49,26 +51,50 @@ internal BrowserCommandResult InitializeModes() // Wait for main page to load before attempting this. If you don't do this it might still be authenticating and the URL will be wrong WaitForMainPage(); - var uri = driver.Url; - var queryParams = "&flags=easyreproautomation=true"; - - if (Browser.Options.UCITestMode) queryParams += ",testmode=true"; - if (Browser.Options.UCIPerformanceMode) queryParams += "&perf=true"; - - if (!uri.Contains(queryParams) && !uri.Contains(HttpUtility.UrlEncode(queryParams))) + string uri = driver.Url; + if (string.IsNullOrEmpty(uri)) + return false; + + var prevQuery = GetUrlQueryParams(uri); + bool requireRedirect = false; + string queryParams = ""; + if (prevQuery.Get("flags") == null) { - var testModeUri = uri + queryParams; + queryParams+= "&flags=easyreproautomation=true"; + if (Browser.Options.UCITestMode) + queryParams += ",testmode=true"; + requireRedirect = true; + } - driver.Navigate().GoToUrl(testModeUri); + if (Browser.Options.UCIPerformanceMode && prevQuery.Get("perf") == null) + { + queryParams += "&perf=true"; + requireRedirect = true; } + if (!requireRedirect) + return true; + + var testModeUri = uri + queryParams; + driver.Navigate().GoToUrl(testModeUri); + // Again wait for loading WaitForMainPage(); - return true; }); } + private NameValueCollection GetUrlQueryParams(string url) + { + if (string.IsNullOrEmpty(url)) + return null; + + Uri uri = new Uri(url); + var query = uri.Query.ToLower(); + NameValueCollection result = HttpUtility.ParseQueryString(query); + return result; + } + public string[] OnlineDomains { get; set; } @@ -179,7 +205,7 @@ private LoginResult Login(IWebDriver driver, Uri uri, SecureString username, Sec return success ? LoginResult.Success : LoginResult.Failure; } - private bool IsUserAlreadyLogged() => WaitForMainPage(10.Seconds()); + private bool IsUserAlreadyLogged() => WaitForMainPage(2.Seconds()); private static string GenerateOneTimeCode(SecureString mfaSecretKey) { @@ -244,7 +270,7 @@ private static IWebElement GetOtcInput(IWebDriver driver) private static bool ClickStaySignedIn(IWebDriver driver) { var xpath = By.XPath(Elements.Xpath[Reference.Login.StaySignedIn]); - var element = driver.ClickIfVisible(xpath, 5.Seconds()); + var element = driver.ClickIfVisible(xpath, 2.Seconds()); return element != null; } @@ -283,7 +309,7 @@ internal BrowserCommandResult PassThroughLogin(Uri uri) //else we landed on the Web Client main page or app picker page SwitchToDefaultContent(driver); }, - () => new InvalidOperationException("Load Main Page Fail.") + () => throw new InvalidOperationException("Load Main Page Fail.") ); return LoginResult.Success; @@ -364,28 +390,20 @@ internal BrowserCommandResult OpenApp(string appName, int thinkTime = Cons { driver.WaitForPageToLoad(); driver.SwitchTo().DefaultContent(); - var success = false; - //Handle left hand Nav in Web Client - if (!driver.Url.Contains("appid")) - { + + var query = GetUrlQueryParams(driver.Url); + bool isSomeAppOpen = query.Get("appid") != null || query.Get("app") != null; + + bool success = false; + if (!isSomeAppOpen) success = TryToClickInAppTile(appName, driver); - } - - else if (driver.Url.Contains("forceUCI=1")) - { - success = TryOpenAppFromMenu(driver, appName, AppReference.Navigation.UCIAppMenuButton); - } else - { - success = TryOpenAppFromMenu(driver, appName, AppReference.Navigation.WebAppMenuButton); - } - + success = TryOpenAppFromMenu(driver, appName, AppReference.Navigation.UCIAppMenuButton) || + TryOpenAppFromMenu(driver, appName, AppReference.Navigation.WebAppMenuButton); if (!success) throw new InvalidOperationException($"App Name {appName} not found."); - - Thread.Sleep(1000); - WaitForMainPage(); + InitializeModes(); // Wait for app page elements to be visible (shell and sitemapLauncherButton) @@ -397,7 +415,7 @@ internal BrowserCommandResult OpenApp(string appName, int thinkTime = Cons if (!success) throw new InvalidOperationException($"App '{appName}' was found but app page was not loaded."); - return success; + return true; }); } @@ -405,7 +423,7 @@ private bool TryOpenAppFromMenu(IWebDriver driver, string appName, string appMen { bool found = false; var xpathToAppMenu = By.XPath(AppElements.Xpath[appMenuButton]); - driver.WaitUntilClickable(xpathToAppMenu, TimeSpan.FromSeconds(5), + driver.WaitUntilClickable(xpathToAppMenu, 5.Seconds(), appMenu => { appMenu.Click(true); @@ -447,7 +465,7 @@ private static bool TryToClickInAppTile(string appName, IWebDriver driver) } return true; }, - TimeSpan.FromSeconds(30) + 5.Seconds() ); var xpathToAppContainer = By.XPath(AppElements.Xpath[AppReference.Navigation.UCIAppContainer]); diff --git a/Microsoft.Dynamics365.UIAutomation.Sample/UCI/Login/Login.cs b/Microsoft.Dynamics365.UIAutomation.Sample/UCI/Login/Login.cs index 6901b3af..3e2353c8 100644 --- a/Microsoft.Dynamics365.UIAutomation.Sample/UCI/Login/Login.cs +++ b/Microsoft.Dynamics365.UIAutomation.Sample/UCI/Login/Login.cs @@ -11,17 +11,38 @@ public class Login : TestsBase [TestCleanup] public override void FinishTest() => base.FinishTest(); - public override void NavigateToHomePage() => NavigateTo(UCIAppName.Sales, "Sales", "Accounts"); - [TestMethod] public void MultiFactorLogin() { - _xrmApp.Grid.SwitchView("All Accounts"); + trace.Log("Login success"); + } + + [TestMethod] + public void MultiFactorLogin_NavigateToApp() + { + trace.Log("Login success"); + NavigateTo(UCIAppName.Sales); + } + + [TestMethod] + public void MultiFactorLogin_NavigateToApp_CustomerService() + { + trace.Log("Login success"); + + NavigateTo(UCIAppName.CustomerService); + trace.Log("Open Customer Service Success"); + } - _xrmApp.CommandBar.ClickCommand("New"); + [TestMethod] + public void MultiFactorLogin_NavigateToApp_ChangeApp() + { + trace.Log("Login success"); + NavigateTo(UCIAppName.Sales); - _xrmApp.Entity.SetValue("name", "Test API Account" + TestSettings.GetRandomString(5,5) ); - _xrmApp.Entity.SetValue("telephone1", "555-555-5555"); + trace.Log("Open Sales Success"); + + NavigateTo(UCIAppName.CustomerService); + trace.Log("Open Customer Service Success"); } } } \ No newline at end of file