Skip to content

Commit

Permalink
fix: GetUser returning wrong users for alias (#89)
Browse files Browse the repository at this point in the history
* fix: GetUser(string alias) not returning new users

The default behaviour wasn't returning a user for the given alias when `currentUser` was `true`. It would also cycle users when requesting the same alias in a single scenario with `currentUser` was set to `true` if the calls were separated by a call for another alias.

* fix: exceptions creating base profiles

Depending on the test runner, this code would fail. Synchronisation also needs to happen across processes in the case where build agents are running multiple test runs concurrently.

* fix: CurrentUsers occasionally `null`

Co-authored-by: Max Ewing <max.ewing@outlook.com>
  • Loading branch information
Alex Bance and ewingjm committed Jun 25, 2021
1 parent 26ed97f commit 2f7a932
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Threading;
using YamlDotNet.Serialization;

/// <summary>
Expand All @@ -19,8 +18,9 @@ public class TestConfiguration

private const string GetUserException = "Unable to retrieve user configuration. Please ensure a user with the given alias exists in the config.";

private static readonly Dictionary<string, UserConfiguration> CurrentUsers = new Dictionary<string, UserConfiguration>();

private readonly object userEnumeratorsLock = new object();
private readonly ThreadLocal<UserConfiguration> currentUser = new ThreadLocal<UserConfiguration>();
private Dictionary<string, IEnumerator<UserConfiguration>> userEnumerators;
private string profilesBasePath;

Expand Down Expand Up @@ -107,9 +107,9 @@ public Uri GetTestUrl()
/// <returns>The user configuration.</returns>
public UserConfiguration GetUser(string userAlias, bool useCurrentUser = true)
{
if (useCurrentUser && this.currentUser.Value != null)
if (useCurrentUser && CurrentUsers.ContainsKey(userAlias))
{
return this.currentUser.Value;
return CurrentUsers[userAlias];
}

try
Expand All @@ -124,15 +124,30 @@ public UserConfiguration GetUser(string userAlias, bool useCurrentUser = true)
aliasEnumerator.MoveNext();
}

this.currentUser.Value = aliasEnumerator.Current;
if (CurrentUsers.ContainsKey(userAlias))
{
CurrentUsers[userAlias] = aliasEnumerator.Current;
}
else
{
CurrentUsers.Add(userAlias, aliasEnumerator.Current);
}
}
}
catch (Exception ex)
{
throw new ConfigurationErrorsException($"{GetUserException} User: {userAlias}", ex);
}

return this.currentUser.Value;
return CurrentUsers[userAlias];
}

/// <summary>
/// Called internally between scenarios to reset thread state.
/// </summary>
internal void Flush()
{
CurrentUsers.Clear();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
{
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Capgemini.PowerApps.SpecFlowBindings.Configuration;
using Capgemini.PowerApps.SpecFlowBindings.Steps;
using Microsoft.Dynamics365.UIAutomation.Api.UCI;
using Microsoft.Dynamics365.UIAutomation.Browser;
using TechTalk.SpecFlow;

/// <summary>
Expand All @@ -31,17 +31,39 @@ public static void BaseProfileSetup()
var profileDirectory = UserProfileDirectories[username];
var baseDirectory = Path.Combine(profileDirectory, "base");
Directory.CreateDirectory(baseDirectory);
// SpecFlow isolation settings may run scenarios in different processes or AppDomains and [BeforeTestRun] runs per thread. Lock statement insufficient.
using (var mutex = new Mutex(true, $"{nameof(BaseProfileSetup)}-{username}", out var createdNew))
{
if (!createdNew)
{
mutex.WaitOne();
}
var userBrowserOptions = (BrowserOptionsWithProfileSupport)TestConfig.BrowserOptions.Clone();
userBrowserOptions.ProfileDirectory = baseDirectory;
userBrowserOptions.Headless = true;
if (Directory.Exists(baseDirectory))
{
mutex.ReleaseMutex();
return;
}
var webClient = new WebClient(userBrowserOptions);
using (new XrmApp(webClient))
{
var user = TestConfig.Users.First(u => u.Username == username);
LoginSteps.Login(webClient.Browser.Driver, TestConfig.GetTestUrl(), user.Username, user.Password);
try
{
Directory.CreateDirectory(baseDirectory);
var userBrowserOptions = (BrowserOptionsWithProfileSupport)TestConfig.BrowserOptions.Clone();
userBrowserOptions.ProfileDirectory = baseDirectory;
userBrowserOptions.Headless = true;
var webClient = new WebClient(userBrowserOptions);
using (new XrmApp(webClient))
{
var user = TestConfig.Users.First(u => u.Username == username);
LoginSteps.Login(webClient.Browser.Driver, TestConfig.GetTestUrl(), user.Username, user.Password);
}
}
finally
{
mutex.ReleaseMutex();
}
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ protected static void Quit()
xrmApp = null;
client = null;
testDriver = null;
testConfig?.Flush();

if (!string.IsNullOrEmpty(currentProfileDirectory) && Directory.Exists(currentProfileDirectory))
{
Expand Down

0 comments on commit 2f7a932

Please sign in to comment.