Exploring Possibilities
In my pursuit of automating web testing using Selenium and incorporating JavaScript functionality, I encountered an intriguing scenario. Within the string func1
, resides a JS function that, when passed to ExecuteScript(func1)
, yields an array of objects structured as follows: {label:'start', time: 121}
.
The objective now is to transform the outcome of ExecuteScript
into a List<timings>
var result = jsExecutor.ExecuteScript(func1);
var list = (ReadOnlyCollection<object>)result;
var timings = (List<Timing>)list;
An error surfaced:
Cannot convert type 'System.Collections.ObjectModel.ReadOnlyCollection<object>'
to 'System.Collections.Generic.List<CoreConsoleApp.TestExecutions.Timing>'
Behold, func1 in all its glory:
string func1= @"var t = window.performance.timing;
var timings = [];
timings.push({ label: 'navigationStart', time: t.navigationStart });
timings.push({ label: 'PageLoadTime', time: t.loadEventEnd - t.navigationStart });
return timings;" // The outcome is an array of JS objects
Highlighted below is a snippet concerning the Selenium aspect
public struct Timing
{
public string label;
public int time;
}
using (var driver = new FirefoxDriver())
{
...
var jsExecutor = (IJavaScriptExecutor)driver;
var result = jsExecutor.ExecuteScript(func1);
var list = (ReadOnlyCollection<object>)result;
}
Pondering Queries
According to the Selenium documentation, ExecuteScript endeavors to present a List for an array. Func1 should return an array composed of {label: string, time: number}
, making it relatively straightforward to transition from
var list = (ReadOnlyCollection<object>)result
to List<string,int> timings = (List<timings>)list;
- How can I proficiently convert 'System.Collections.ObjectModel.ReadOnlyCollection' into a List?
Additional Insights
To initiate Firefox, employ var driver = new FirefoxDriver()
, launch a designated URL via driver.Navigate().GoToUrl(url);
, locate a specific button with
IWebElement button = driver.FindElement(By.Name("btnK"));
, submit the form through button.Submit();
. Post submission, trigger JavaScript execution using ExecuteScript(func1)
followed by displaying the outcome on the console.
All aforementioned steps operate smoothly. However, challenge arises when attempting to convert the JavaScript output into a list of C# objects.
Hence, a workaround ensues:
var result = jsExecutor.ExecuteScript(func1);
var list = (ReadOnlyCollection<object>)result;
foreach (object item in list)
{
var timing = (Dictionary<string, object>)item;
foreach(KeyValuePair<string, object> kvp in timing)
{
Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
}
}
This method yields:
Key = label, Value = navigationStart
Key = time, Value = 1529720672670
Key = label, Value = PageLoadTime
Key = time, Value = 1194
Key = label, Value = DOMContentLoadedTime
Key = time, Value = 589
Key = label, Value = ResponseTime