diff --git a/dotnet/src/webdriver/InitializationScript.cs b/dotnet/src/webdriver/InitializationScript.cs
index 0fa30bbfded79..eaf29bb9438c0 100644
--- a/dotnet/src/webdriver/InitializationScript.cs
+++ b/dotnet/src/webdriver/InitializationScript.cs
@@ -41,6 +41,28 @@ public class InitializationScript
///
public string ScriptSource { get; internal set; }
+ ///
+ /// Indicates whether the current is equal to another of the same type.
+ ///
+ /// An to compare with this .
+ /// if the current is equal to the other parameter; otherwise, .
+ public override bool Equals(object obj)
+ {
+ return obj is InitializationScript other && this.ScriptId == other.ScriptId && this.ScriptName == other.ScriptName && this.ScriptSource == other.ScriptSource;
+ }
+
+ ///
+ /// Serves as a hash function for a particular .
+ ///
+ /// A hash code for the current .
+ public override int GetHashCode()
+ {
+ int result = this.ScriptId.GetHashCode();
+ result = (31 * result) + this.ScriptName.GetHashCode();
+ result = (31 * result) + this.ScriptSource.GetHashCode();
+ return result;
+ }
+
///
/// Returns a string that represents the current object.
///
diff --git a/dotnet/src/webdriver/JavaScriptEngine.cs b/dotnet/src/webdriver/JavaScriptEngine.cs
index 4bd4fe4676eb4..8ea7018530294 100644
--- a/dotnet/src/webdriver/JavaScriptEngine.cs
+++ b/dotnet/src/webdriver/JavaScriptEngine.cs
@@ -40,7 +40,7 @@ public class JavaScriptEngine : IJavaScriptEngine
private Lazy session;
private Dictionary initializationScripts = new Dictionary();
private Dictionary pinnedScripts = new Dictionary();
- private List bindings = new List();
+ private HashSet bindings = new HashSet();
private bool isEnabled = false;
private bool isDisposed = false;
@@ -271,7 +271,7 @@ public async Task UnpinScript(PinnedScript script)
/// A task that represents the asynchronous operation.
public async Task AddScriptCallbackBinding(string bindingName)
{
- if (this.bindings.Contains(bindingName))
+ if (!this.bindings.Add(bindingName))
{
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "A binding named {0} has already been added", bindingName));
}
@@ -288,7 +288,7 @@ public async Task AddScriptCallbackBinding(string bindingName)
public async Task RemoveScriptCallbackBinding(string bindingName)
{
await this.session.Value.Domains.JavaScript.RemoveBinding(bindingName).ConfigureAwait(false);
- this.bindings.Remove(bindingName);
+ _ = this.bindings.Remove(bindingName);
}
///
diff --git a/dotnet/test/common/ExecutingJavascriptTest.cs b/dotnet/test/common/ExecutingJavascriptTest.cs
index d5b239a9cf206..32cfbbccb08ef 100644
--- a/dotnet/test/common/ExecutingJavascriptTest.cs
+++ b/dotnet/test/common/ExecutingJavascriptTest.cs
@@ -480,7 +480,7 @@ public void ShouldBeAbleToExecuteABigChunkOfJavascriptCode()
[IgnoreBrowser(Selenium.Browser.Safari, "Safari does not support Chrome DevTools Protocol")]
public async Task ShouldBeAbleToPinJavascriptCodeAndExecuteRepeatedly()
{
- IJavaScriptEngine jsEngine = new JavaScriptEngine(driver);
+ using IJavaScriptEngine jsEngine = new JavaScriptEngine(driver);
driver.Url = xhtmlTestPage;
@@ -500,6 +500,107 @@ public async Task ShouldBeAbleToPinJavascriptCodeAndExecuteRepeatedly()
Throws.TypeOf());
}
+ [Test]
+ [NeedsFreshDriver(IsCreatedAfterTest = true)]
+ [IgnoreBrowser(Selenium.Browser.IE, "IE does not support Chrome DevTools Protocol")]
+ [IgnoreBrowser(Selenium.Browser.Firefox, "Firefox does not support Chrome DevTools Protocol")]
+ [IgnoreBrowser(Selenium.Browser.Safari, "Safari does not support Chrome DevTools Protocol")]
+ public async Task ShouldBeAbleToAddInitializationScriptAndExecuteOnNewDocument()
+ {
+ const string ScriptValue = "alert('notice')";
+ const string ScriptName = "AlertScript";
+
+ using IJavaScriptEngine jsEngine = new JavaScriptEngine(driver);
+
+ var initScript = await jsEngine.AddInitializationScript(ScriptName, ScriptValue);
+
+ Assert.That(initScript, Is.Not.Null);
+ Assert.That(initScript.ScriptSource, Is.EqualTo(ScriptValue));
+ Assert.That(initScript.ScriptName, Is.EqualTo(ScriptName));
+ Assert.That(initScript.ScriptId, Is.Not.Null);
+
+ await jsEngine.StartEventMonitoring();
+
+ driver.Navigate().Refresh();
+ driver.SwitchTo().Alert().Accept();
+
+ Assert.That(jsEngine.InitializationScripts, Does.Contain(initScript));
+ await jsEngine.RemoveInitializationScript(ScriptName);
+
+ driver.Navigate().Refresh();
+ Assert.That(() => driver.SwitchTo().Alert().Accept(), Throws.TypeOf());
+
+ Assert.That(jsEngine.InitializationScripts, Does.Not.Contain(initScript));
+
+ await jsEngine.AddInitializationScript(ScriptName, ScriptValue);
+
+ driver.Navigate().Refresh();
+ driver.SwitchTo().Alert().Accept();
+ Assert.That(jsEngine.InitializationScripts, Does.Contain(initScript));
+
+ await jsEngine.ClearInitializationScripts();
+
+ driver.Navigate().Refresh();
+ Assert.That(() => driver.SwitchTo().Alert().Accept(), Throws.TypeOf());
+ Assert.That(jsEngine.InitializationScripts, Is.Empty);
+
+ await jsEngine.AddInitializationScript(ScriptName, ScriptValue);
+ driver.Navigate().Refresh();
+ driver.SwitchTo().Alert().Accept();
+
+ await jsEngine.ClearAll();
+ driver.Navigate().Refresh();
+ Assert.That(() => driver.SwitchTo().Alert().Accept(), Throws.TypeOf());
+ Assert.That(jsEngine.InitializationScripts, Is.Empty);
+ }
+
+ [Test]
+ [NeedsFreshDriver(IsCreatedAfterTest = true)]
+ [IgnoreBrowser(Selenium.Browser.IE, "IE does not support Chrome DevTools Protocol")]
+ [IgnoreBrowser(Selenium.Browser.Firefox, "Firefox does not support Chrome DevTools Protocol")]
+ [IgnoreBrowser(Selenium.Browser.Safari, "Safari does not support Chrome DevTools Protocol")]
+ public async Task ShouldBeAbleToAddAndRemoveScriptCallbackBinding()
+ {
+ const string ScriptValue = "alert('Hello world')";
+ const string ScriptName = "alert";
+
+ using IJavaScriptEngine jsEngine = new JavaScriptEngine(driver);
+
+ var executedBindings = new List();
+ jsEngine.JavaScriptCallbackExecuted += AddToList;
+ await jsEngine.AddInitializationScript(ScriptName, ScriptValue);
+ await jsEngine.StartEventMonitoring();
+
+ driver.Navigate().Refresh();
+ driver.SwitchTo().Alert().Accept();
+
+ await jsEngine.AddScriptCallbackBinding(ScriptName);
+
+ driver.Navigate().Refresh();
+ Assert.That(() => driver.SwitchTo().Alert().Accept(), Throws.TypeOf());
+
+ Assert.That(executedBindings, Does.Contain(ScriptName));
+ int oldCount = executedBindings.Count;
+ driver.Navigate().Refresh();
+
+ Assert.That(executedBindings, Has.Count.GreaterThan(oldCount));
+ Assert.That(jsEngine.ScriptCallbackBindings, Does.Contain(ScriptName));
+ oldCount = executedBindings.Count;
+
+ await jsEngine.RemoveScriptCallbackBinding(ScriptName);
+ Assert.That(jsEngine.ScriptCallbackBindings, Is.Empty);
+ await jsEngine.AddScriptCallbackBinding(ScriptName);
+ Assert.That(jsEngine.ScriptCallbackBindings, Does.Contain(ScriptName));
+ await jsEngine.ClearScriptCallbackBindings();
+ Assert.That(jsEngine.ScriptCallbackBindings, Is.Empty);
+
+ jsEngine.JavaScriptCallbackExecuted -= AddToList;
+ driver.Navigate().Refresh();
+ Assert.That(executedBindings, Has.Count.EqualTo(oldCount));
+
+ void AddToList(object sender, JavaScriptCallbackExecutedEventArgs e) => executedBindings.Add(e.BindingName);
+ }
+
[Test]
public void ShouldBeAbleToExecuteScriptAndReturnElementsList()
{