It’s been great attending Ali Youssefi’s EasyRepro workshop this week (and it’s also been great to be invited into those workshops by the client to start with). That’s a nice workshop which will get you through the basics of Easy Repro (and some of the related things you may need to keep in mind) – we are not supposed to share workshop materials, but, well, you might still want to see all of the EasyRepro videos Ali has on Youtube:
https://www.youtube.com/results?search_query=Ali+Youssefi+easyrepro
Either way, that’s been a great opportunity for me to dig a little deeper into how EasyRepro works, what’s doable and what’s not.
On the high level, I wrote about Easy Repro before:
https://www.itaintboring.com/dynamics-crm/easy-repro-what-is-it/
All of that still stands, so, in this post, I am just going to dig into a few areas where I had problems with Easy Repro this week.
1. Invoking “New” lookup action
It seems easy to do, since you just need to call xrmApp.Lookup.New()
However, xrmApp has a few properties which are only applicable in the context:
- Lookup
- QuickCreate
- Grid
- Entity
And there are, probably, a few more.
What this means is that those properties of xrmApp make (or do not make) sense depending on what’s currently happening in the model-driven application. For example, when a quick create form is visible, xrmApp.QuickCreate will allow access to that form. When a lookup is “selected”, we can access that lookup through xrmApp.Lookup, and, therefore, we can initiate new record creation in the user-interface using xrmApp.Lookup.New() method.
Which means that in order to use New, you have to somehow select the lookup first. So you could, for example, do this:
LookupItem liContact = new LookupItem()
{
Name = “ita_contact”
};
xrmApp.Entity.SelectLookup(liContact);
xrmApp.Lookup.New();
And, along the way, if your lookup is polymorphic (it’s a customer, for example), you may need to call SelectRelatedEntity before calling “New”:
xrmApp.Lookup.SelectRelatedEntity(“Contacts”);
2. “You might want to close “Unsaved changes” popup automatically in your tests
The function below will click “Discard changes” button (although, you might want to update it so it uses “Save and continue” instead). Normally, you would call this function in those places where you would expect “Unsaved changes” dialog to pop up:
public bool DiscardChangesIfPresent()
{
try
{
var cancelButton = _client.Browser.Driver.FindElement(By.XPath(“//*[@id=\”cancelButton\”]”));
if (cancelButton != null)
{
cancelButton.Click();
_client.Browser.Driver.WaitForTransaction();
return true;
}
}
catch
{
return false;
}
return false;
}
3. Updating two lookup fields in a sequence
It seems that, sometimes, you may have to “focus out” of the lookup before switching to another lookup. For example, I’ve been having problems with the code below:
LookupItem li = new LookupItem()
{
Name = “<column_name>”,
Value = “<column_value>”,
Index = 0
};
xrmApp.Entity.SetValue(li);
xrmApp.ThinkTime(2000);
<SEE EXPLANATION BELOW FOR AN EXTRA LINE HERE>
LookupItem liContact = new LookupItem()
{
Name = “<another_column_name>”
};
xrmApp.Entity.SelectLookup(liContact);
xrmApp.Lookup.New();
You can see how that code is setting value of the first lookup, and, then, it immediately proceeds to create “new” record for another lookup. Or, at least, that’s the intent. Instead of that, though, “New” method gets called on the first lookup somehow.
It seems all we need to do is add an extra line to select another element on the form (sort of to “focus out”). There are, probably, other ways to do it, but here is what worked for me:
xrmApp.Entity.SelectTab(“General”);
Once I added this line right where the placeholder is in the code above, everything started to work properly.
4. Killing chromedriver and related chrome.exe processes
If you tend to terminate test debugging in Visual Studio, and if you are using Chrome there, you will inevitably end up with chromedriver.exe and chrome.exe processes stuck in memory, so you will either have to keep terminating them from the task manager, or you could make your life a little easier using some kind of script/tool. Here is a powershell script that might do the trick:
function Kill-Tree {
Param(
[int]$ppid,
[bool]$recursive
)
if($recursive -eq $true){
Get-CimInstance Win32_Process | Where-Object { $_.ParentProcessId -eq $ppid -and $_.Name -eq “chrome.exe”} | ForEach-Object { Kill-Tree $_.ProcessId $false }
}
Stop-Process -Id $ppid
}
Get-Process -Name chromedriver | ForEach-Object -Process{
Kill-Tree $_.Id $true
}
For Edge, FireFox, and other browsers, you might need to adjust the script above.