diff --git a/.github/workflows/crossBrowserTesting.yml b/.github/workflows/crossBrowserTesting.yml
index 4fe2994a..89ebf10e 100644
--- a/.github/workflows/crossBrowserTesting.yml
+++ b/.github/workflows/crossBrowserTesting.yml
@@ -1,5 +1,9 @@
name: Cross-browser testing
+concurrency:
+ group: ${{ github.workflow }}
+ cancel-in-progress: false
+
on:
push:
branches: [ "master" ]
diff --git a/CSF.Screenplay.Reqnroll/EnumerableResolutionAdapter.cs b/CSF.Screenplay.Reqnroll/EnumerableResolutionAdapter.cs
new file mode 100644
index 00000000..3aff893a
--- /dev/null
+++ b/CSF.Screenplay.Reqnroll/EnumerableResolutionAdapter.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+#if SPECFLOW
+using BoDi;
+#else
+using Reqnroll.BoDi;
+#endif
+
+namespace CSF.Screenplay
+{
+ ///
+ /// Adapter class which - when added to DI - permits the BoDi DI container to resolve arbitrary of
+ /// service instances.
+ ///
+ ///
+ ///
+ /// The BoDi DI container which is included in Reqnroll/SpecFlow does not fully support the functionality of Microsoft's DI standard.
+ /// Notably, it cannot natively resolve an , where type T is a service type which may have multiple implementations
+ /// added to/registered with the container.
+ /// BoDi does have conceptually identical functionality, in its function.
+ ///
+ ///
+ /// The purpose of this type is to provide a mechanism by which BoDi may resolve enumerables of service types.
+ /// This class wraps an instance of and - in its method - redirects to the
+ /// method.
+ ///
+ ///
+ /// The limitation of this type (as a workaround) is that this type must be added to the container manually for each
+ /// type which could be resolved from the container.
+ ///
+ ///
+ public class EnumerableResolutionAdapter : IEnumerable where T : class
+ {
+ readonly IObjectContainer container;
+
+ ///
+ public IEnumerator GetEnumerator()
+ {
+ var allOptions = container.ResolveAll();
+ return allOptions.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// The BoDi object container.
+ /// is null .
+ public EnumerableResolutionAdapter(IObjectContainer container)
+ {
+ this.container = container ?? throw new ArgumentNullException(nameof(container));
+ }
+ }
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Reqnroll/ObjectContainerExtensions.cs b/CSF.Screenplay.Reqnroll/ObjectContainerExtensions.cs
new file mode 100644
index 00000000..b1453e7c
--- /dev/null
+++ b/CSF.Screenplay.Reqnroll/ObjectContainerExtensions.cs
@@ -0,0 +1,46 @@
+using System;
+#if SPECFLOW
+using BoDi;
+#else
+using Reqnroll.BoDi;
+#endif
+using Microsoft.Extensions.DependencyInjection;
+
+namespace CSF.Screenplay
+{
+ ///
+ /// Extension methods for the Reqnroll/SpecFlow "BoDi" DI container.
+ ///
+ public static class ObjectContainerExtensions
+ {
+ ///
+ /// Gets an adapter object which permits limited use of the BoDi as if it were an
+ /// .
+ ///
+ ///
+ ///
+ /// Note that this is an imperfect solution. The BoDi container shipped with Reqnroll/SpecFlow does not support all the functionality
+ /// which is expected from . Many methods of the returned object will throw
+ /// if attempts are made to use them (a known LSP violation). Additionally, not all service collection DI behaviour will operate in the same
+ /// manner when using this adapter. In short "your mileage may vary".
+ ///
+ ///
+ /// However, for the most simple of usages, this enables the use of "Add to DI" logic which has been crafted for service collection,
+ /// in such a way that services may be added to the BoDi container without additional logic.
+ ///
+ ///
+ /// A Reqnroll/SpecFlow BoDi DI container.
+ /// An adapter object which implements some of the functionality of
+ public static IServiceCollection ToServiceCollection(this IObjectContainer bodiContainer)
+ => new ServiceCollectionAdapter(bodiContainer);
+
+ ///
+ /// Gets an adapter object which permits the use of the BoDi as if it were an
+ /// .
+ ///
+ /// A Reqnroll/SpecFlow BoDi DI container.
+ /// An adapter object which implements the functionality of
+ public static IServiceProvider ToServiceProvider(this IObjectContainer bodiContainer)
+ => new ServiceProviderAdapter(bodiContainer);
+ }
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Reqnroll/PerformanceProviderFactory.cs b/CSF.Screenplay.Reqnroll/PerformanceProviderFactory.cs
new file mode 100644
index 00000000..fe46efd8
--- /dev/null
+++ b/CSF.Screenplay.Reqnroll/PerformanceProviderFactory.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Concurrent;
+using CSF.Screenplay.Performances;
+using Microsoft.Extensions.DependencyInjection;
+#if SPECFLOW
+using TechTalk.SpecFlow;
+#else
+using Reqnroll;
+#endif
+
+namespace CSF.Screenplay
+{
+ ///
+ /// Factory type for instances of .
+ ///
+ public class PerformanceProviderFactory
+ {
+ readonly ConcurrentDictionary featureContextIds = new ConcurrentDictionary();
+ readonly ConcurrentDictionary scenarioContextIds = new ConcurrentDictionary();
+
+ ///
+ /// Gets an instance of for the specified service provider.
+ ///
+ /// A service provider
+ /// A .
+ public PerformanceProvider GetPerformanceContainer(IServiceProvider services)
+ {
+ var performance = new Performance(services, new [] { GetFeatureIdAndName(services), GetScenarioIdAndName(services) });
+ var performanceContainer = new PerformanceProvider();
+ performanceContainer.SetCurrentPerformance(performance);
+ return performanceContainer;
+ }
+
+ IdentifierAndName GetFeatureIdAndName(IServiceProvider services)
+ {
+ var featureInfo = services.GetRequiredService();
+ return new IdentifierAndName(GetFeatureId(featureInfo).ToString(),
+ featureInfo.Title,
+ true);
+ }
+
+ Guid GetFeatureId(FeatureInfo featureContext) => featureContextIds.GetOrAdd(featureContext, _ => Guid.NewGuid());
+
+ IdentifierAndName GetScenarioIdAndName(IServiceProvider services)
+ {
+ var featureInfo = services.GetRequiredService();
+ var scenarioInfo = services.GetRequiredService();
+ return new IdentifierAndName(GetScenarioId(featureInfo, scenarioInfo).ToString(),
+ scenarioInfo.Title,
+ true);
+ }
+
+ Guid GetScenarioId(FeatureInfo featureInfo, ScenarioInfo scenarioInfo)
+ => scenarioContextIds.GetOrAdd(new ScenarioAndFeatureInfoKey(scenarioInfo, featureInfo), _ => Guid.NewGuid());
+
+ }
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Reqnroll/ScreenplayPlugin.cs b/CSF.Screenplay.Reqnroll/ScreenplayPlugin.cs
index 13b5c0d6..1158cd2e 100644
--- a/CSF.Screenplay.Reqnroll/ScreenplayPlugin.cs
+++ b/CSF.Screenplay.Reqnroll/ScreenplayPlugin.cs
@@ -3,6 +3,8 @@
using System.Reflection;
using CSF.Screenplay.Actors;
using CSF.Screenplay.Performances;
+using Microsoft.Extensions.DependencyInjection;
+
#if SPECFLOW
using BoDi;
using TechTalk.SpecFlow;
@@ -31,7 +33,7 @@ namespace CSF.Screenplay
///
///
/// This may be easily worked-around, though. If you are using a third-party DI plugin then do not use this plugin.
- /// Instead use the
+ /// Instead use the
/// method to add Screenplay to that third-party DI system, when customising the dependency registrations.
/// Adding Screenplay in that way is equivalent to the work done by this plugin.
///
@@ -46,8 +48,6 @@ namespace CSF.Screenplay
public class ScreenplayPlugin : IRuntimePlugin
{
readonly object syncRoot = new object();
- readonly ConcurrentDictionary featureContextIds = new ConcurrentDictionary();
- readonly ConcurrentDictionary scenarioContextIds = new ConcurrentDictionary();
bool initialised;
@@ -104,50 +104,28 @@ void OnCustomizeGlobalDependencies(object sender, CustomizeGlobalDependenciesEve
{
if (initialised) return;
- var container = args.ObjectContainer;
- var serviceCollection = new ServiceCollectionAdapter(container);
- serviceCollection.AddScreenplay();
- container.RegisterFactoryAs(c => new ServiceProviderAdapter(c));
- Screenplay = container.Resolve();
+ var boDiContainer = args.ObjectContainer;
+ var services = new ServiceCollectionAdapter(boDiContainer);
+ services.AddScreenplayPlugin();
+ boDiContainer.RegisterFactoryAs(c => c.ToServiceProvider());
+ Screenplay = boDiContainer.Resolve();
initialised = true;
}
}
- void OnCustomizeScenarioDependencies(object sender, CustomizeScenarioDependenciesEventArgs args)
- {
- var container = args.ObjectContainer;
- var services = new ServiceProviderAdapter(container);
- container.RegisterInstanceAs(services);
- var performance = new Performance(services, new [] { GetFeatureIdAndName(container), GetScenarioIdAndName(container) });
- var performanceContainer = new PerformanceProvider();
- performanceContainer.SetCurrentPerformance(performance);
- container.RegisterInstanceAs(performanceContainer);
- container.RegisterFactoryAs(c => c.Resolve().GetCurrentPerformance());
-
- container.RegisterFactoryAs(c => new Cast(c.Resolve(), c.Resolve().PerformanceIdentity));
- container.RegisterTypeAs();
- }
-
- IdentifierAndName GetFeatureIdAndName(IObjectContainer container)
+ static void OnCustomizeScenarioDependencies(object sender, CustomizeScenarioDependenciesEventArgs args)
{
- var featureInfo = container.Resolve();
- return new IdentifierAndName(GetFeatureId(featureInfo).ToString(),
- featureInfo.Title,
- true);
- }
+ var boDiContainer = args.ObjectContainer;
+ var services = boDiContainer.ToServiceProvider();
+ boDiContainer.RegisterInstanceAs(services);
- Guid GetFeatureId(FeatureInfo featureContext) => featureContextIds.GetOrAdd(featureContext, _ => Guid.NewGuid());
-
- IdentifierAndName GetScenarioIdAndName(IObjectContainer container)
- {
- var featureInfo = container.Resolve();
- var scenarioInfo = container.Resolve();
- return new IdentifierAndName(GetScenarioId(featureInfo, scenarioInfo).ToString(),
- scenarioInfo.Title,
- true);
+ var serviceCollection = boDiContainer.ToServiceCollection();
+ serviceCollection
+ .AddSingleton(s => s.GetRequiredService().GetPerformanceContainer(s))
+ .AddSingleton(s => s.GetRequiredService().GetCurrentPerformance())
+ .AddSingleton(s => new Cast(s, s.GetRequiredService().PerformanceIdentity))
+ .AddSingleton();
}
- Guid GetScenarioId(FeatureInfo featureInfo, ScenarioInfo scenarioInfo)
- => scenarioContextIds.GetOrAdd(new ScenarioAndFeatureInfoKey(scenarioInfo, featureInfo), _ => Guid.NewGuid());
}
}
diff --git a/CSF.Screenplay.Reqnroll/ServiceCollectionAdapter.cs b/CSF.Screenplay.Reqnroll/ServiceCollectionAdapter.cs
index 11b40faf..6e7d8d64 100644
--- a/CSF.Screenplay.Reqnroll/ServiceCollectionAdapter.cs
+++ b/CSF.Screenplay.Reqnroll/ServiceCollectionAdapter.cs
@@ -30,7 +30,6 @@ public class ServiceCollectionAdapter : IServiceCollection
// not actually bypassing accessibility.
#pragma warning disable S3011
static readonly MethodInfo
- OpenGenericRegisterType = typeof(ServiceCollectionAdapter).GetMethod(nameof(RegisterType), BindingFlags.Instance | BindingFlags.NonPublic),
OpenGenericRegisterInstance = typeof(ServiceCollectionAdapter).GetMethod(nameof(RegisterInstance), BindingFlags.Instance | BindingFlags.NonPublic),
OpenGenericRegisterFactory = typeof(ServiceCollectionAdapter).GetMethod(nameof(RegisterFactory), BindingFlags.Instance | BindingFlags.NonPublic);
#pragma warning restore S3011
@@ -89,12 +88,12 @@ public void Add(ServiceDescriptor item)
else if (item.ImplementationInstance != null)
OpenGenericRegisterInstance.MakeGenericMethod(item.ServiceType).Invoke(this, new[] { item });
else
- OpenGenericRegisterType.MakeGenericMethod(item.ServiceType, item.ImplementationType).Invoke(this, Array.Empty());
+ RegisterTypeNonGeneric(item.ServiceType, item.ImplementationType);
}
- void RegisterType() where TImpl : class,TSvc
+ void RegisterTypeNonGeneric(Type service, Type implementation)
{
- wrapped.RegisterTypeAs();
+ ((ObjectContainer) wrapped).RegisterTypeAs(implementation, service);
}
void RegisterInstance(ServiceDescriptor item) where T : class
@@ -104,7 +103,7 @@ void RegisterInstance(ServiceDescriptor item) where T : class
void RegisterFactory(ServiceDescriptor item) where T : class
{
- wrapped.RegisterFactoryAs(objectContainer => (T) item.ImplementationFactory(new ServiceProviderAdapter(objectContainer)));
+ wrapped.RegisterFactoryAs(objectContainer => (T) item.ImplementationFactory(objectContainer.ToServiceProvider()));
}
///
diff --git a/CSF.Screenplay.Reqnroll/ServiceCollectionExtensions.cs b/CSF.Screenplay.Reqnroll/ServiceCollectionExtensions.cs
new file mode 100644
index 00000000..bae7d395
--- /dev/null
+++ b/CSF.Screenplay.Reqnroll/ServiceCollectionExtensions.cs
@@ -0,0 +1,66 @@
+using System.Collections.Generic;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+
+namespace CSF.Screenplay
+{
+ ///
+ /// Extension methods for .
+ ///
+ public static class ServiceCollectionExtensions
+ {
+ ///
+ /// Adds to the DI container for the service type .
+ ///
+ ///
+ ///
+ /// This is required to work around a limitation of the BoDi DI container which ships with Reqnroll/SpecFlow.
+ /// See for more information.
+ ///
+ ///
+ /// The service type for which to add the adapter
+ /// A service collection
+ /// The same service collection, so calls may be chained
+ public static IServiceCollection AddEnumerableAdapter(this IServiceCollection services) where TService : class
+ => services.AddTransient, EnumerableResolutionAdapter>();
+
+ ///
+ /// Adds enumerable adapters for service types which are required in order to enable
+ /// the Microsoft Options Pattern with the specified options type.
+ ///
+ ///
+ ///
+ /// This is required to work around a limitation of the BoDi DI container which ships with Reqnroll/SpecFlow.
+ /// See for more information.
+ ///
+ ///
+ /// Use of the options pattern requires the resolution of three enumerable types: ,
+ /// and . This method uses
+ /// for each of those types.
+ ///
+ ///
+ /// The options type
+ /// A service collection
+ /// The same service collection, so calls may be chained
+ public static IServiceCollection AddOptionsAdapters(this IServiceCollection services) where TOptions : class
+ {
+ return services
+ .AddEnumerableAdapter>()
+ .AddEnumerableAdapter>()
+ .AddEnumerableAdapter>();
+ }
+
+ ///
+ /// Adds the services to DI which are required to use the Reqnroll/SpecFlow plugin.
+ ///
+ /// A service collection
+ /// The same service collection, so calls may be chained
+ public static IServiceCollection AddScreenplayPlugin(this IServiceCollection services)
+ {
+ return services
+ .AddScreenplay()
+ .AddOptionsAdapters()
+ .AddSingleton();
+ }
+ }
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium/Actions/SetTheElementValue.cs b/CSF.Screenplay.Selenium/Actions/SetTheElementValue.cs
new file mode 100644
index 00000000..9169abbe
--- /dev/null
+++ b/CSF.Screenplay.Selenium/Actions/SetTheElementValue.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using CSF.Screenplay.Selenium.Elements;
+using OpenQA.Selenium;
+using static CSF.Screenplay.Selenium.PerformableBuilder;
+
+namespace CSF.Screenplay.Selenium.Actions
+{
+ ///
+ /// An action that sets the value of a web element using JavaScript.
+ ///
+ public class SetTheElementValue : ISingleElementPerformable
+ {
+ readonly object value;
+ readonly bool simulateInteractiveSet;
+
+ ///
+ public ReportFragment GetReportFragment(Actor actor, Lazy element, IFormatsReportFragment formatter)
+ {
+ return simulateInteractiveSet
+ ? formatter.Format("{Actor} uses JavaScript to simulate setting the value of {Element} to {Value} interactively", actor, element.Value, value)
+ : formatter.Format("{Actor} uses JavaScript to set the value of {Element} to {Value}", actor, element.Value, value);
+ }
+
+ ///
+ public ValueTask PerformAsAsync(ICanPerform actor, IWebDriver webDriver, Lazy element, CancellationToken cancellationToken = default)
+ {
+ return simulateInteractiveSet
+ ? actor.PerformAsync(ExecuteAScript(Scripts.SetElementValueSimulatedInteractively, element.Value.WebElement, value), cancellationToken)
+ : actor.PerformAsync(ExecuteAScript(Scripts.SetElementValue, element.Value.WebElement, value), cancellationToken);
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The value to set on the element.
+ /// If then the JavaScript will fire UI events to simulate having set the element interactively
+ public SetTheElementValue(object value, bool simulateInteractiveSet)
+ {
+ this.value = value;
+ this.simulateInteractiveSet = simulateInteractiveSet;
+ }
+ }
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium/BrowserQuirks.cs b/CSF.Screenplay.Selenium/BrowserQuirks.cs
new file mode 100644
index 00000000..5408b388
--- /dev/null
+++ b/CSF.Screenplay.Selenium/BrowserQuirks.cs
@@ -0,0 +1,84 @@
+using System.Collections.Generic;
+using CSF.Extensions.WebDriver.Quirks;
+
+namespace CSF.Screenplay.Selenium
+{
+ ///
+ /// Static class which holds known browser quirks information.
+ ///
+ public static class BrowserQuirks
+ {
+ ///
+ /// Gets the name of a browser quirk which means that a Web Driver cannot set the value of an <input type="date"> using
+ /// "Send Keys".
+ ///
+ ///
+ ///
+ /// Date input fields have patchy support amongst browsers and web drivers. The UI which appears in order to set a date often responds
+ /// poorly to typing a new date manually. Additionally, the calendar UI which most browsers will render is not built from HTML elements
+ /// and thus cannot be interacted with in the traditional way, by Web Drivers. Thus, if we cannot 'type' a new date and cannot interact
+ /// by clicking on the calendar, all that remains is to use a JavaScript workaround to set the date.
+ ///
+ ///
+ public static readonly string CannotSetInputTypeDateWithSendKeys = "CannotSetInputTypeDateWithSendKeys";
+
+ ///
+ /// Gets the name of a browser quirk which means that - after navigation to a different page - the browser must be instructed to wait
+ /// until the following page document is ready.
+ ///
+ ///
+ ///
+ /// Most Web Driver implementations, without this quirk, automatically wait for the 'incoming' page (in traditional web document
+ /// navigation) to be ready before they attempt to interact with it. That is - if the "document ready" event has not yet occurred,
+ /// they will continue waiting. Some browsers/web drivers (those with this quirk) need to be instructed to wait for that ready-state,
+ /// or else they are liable to attempt to interact with a page which is not yet fully loaded.
+ ///
+ ///
+ /// Note that this only applies to traditional web navigation. It does not apply to navigating SPA-type apps.
+ ///
+ ///
+ public static readonly string NeedsToWaitAfterPageLoad = "NeedsToWaitAfterPageLoad";
+
+ ///
+ /// Gets hard-coded information about known browser quirks.
+ ///
+ ///
+ ///
+ /// This information ships with CSF.Screenplay.Selenium. It may be overridden by user-supplied configuration, should
+ /// things change in the future. See the
+ /// browser quirks reference material for more information.
+ ///
+ ///
+ /// Quirks data, about the peculiarities of specific browsers.
+ public static QuirksData GetQuirksData()
+ {
+ return new QuirksData
+ {
+ Quirks = new Dictionary
+ {
+ {
+ CannotSetInputTypeDateWithSendKeys,
+ new BrowserInfoCollection
+ {
+ AffectedBrowsers = new HashSet
+ {
+ new BrowserInfo { Name = "firefox" },
+ new BrowserInfo { Name = "safari" },
+ }
+ }
+ },
+ {
+ NeedsToWaitAfterPageLoad,
+ new BrowserInfoCollection
+ {
+ AffectedBrowsers = new HashSet
+ {
+ new BrowserInfo { Name = "safari" },
+ }
+ }
+ }
+ }
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium/Builders/SetTheValueBuilder.cs b/CSF.Screenplay.Selenium/Builders/SetTheValueBuilder.cs
new file mode 100644
index 00000000..e565b99c
--- /dev/null
+++ b/CSF.Screenplay.Selenium/Builders/SetTheValueBuilder.cs
@@ -0,0 +1,72 @@
+using CSF.Screenplay.Performables;
+using CSF.Screenplay.Selenium.Actions;
+using CSF.Screenplay.Selenium.Elements;
+
+namespace CSF.Screenplay.Selenium
+{
+ ///
+ /// Builds actions for setting values in Selenium web elements.
+ ///
+ public class SetTheValueBuilder: IGetsPerformable, SetTheValueBuilder.IChoosesValue
+ {
+ readonly ITarget target;
+ object value;
+
+ ///
+ public SetTheValueBuilder To(object value)
+ {
+ this.value = value;
+ return this;
+ }
+
+ ///
+ /// Gets a performable which, whilst setting the value programatically, attempts to simulate setting it interactively in the browser.
+ ///
+ ///
+ ///
+ /// Use this method to work around limitations in the web browser/WebDriver, as it is an imperfect solution.
+ /// When this method is used, it configures the performable to use JavaScript which will not only update the value of the
+ /// specified element. It will additionally trigger HTML/JavaScript events upon the element such as focus ,
+ /// input , change and blur in an attempt to simulate an interactive change.
+ ///
+ ///
+ /// The reason for this is that client web page functionality may be listening to these events and would be exercised if
+ /// the element value were updated by a human being interacting with the web page. However when JS is used to update the value,
+ /// those events are not fired. This method fires the events artificially.
+ ///
+ ///
+ /// A performable
+ public IPerformable AsIfSetInteractively() => SingleElementPerformableAdapter.From(new SetTheElementValue(value, true), target);
+
+ IPerformable IGetsPerformable.GetPerformable()
+ => SingleElementPerformableAdapter.From(new SetTheElementValue(value, false), target);
+
+ ///
+ /// Initializes a new instance of the class with the specified target.
+ ///
+ /// The target web element for which to build value-setting actions.
+ public SetTheValueBuilder(ITarget target)
+ {
+ this.target = target ?? throw new System.ArgumentNullException(nameof(target));
+ }
+
+ ///
+ /// An object from which a consumer may choose a value to set into the element.
+ ///
+ public interface IChoosesValue
+ {
+ ///
+ /// Gets a builder for a performable which sets the target element to the value specified in this method.
+ ///
+ ///
+ ///
+ /// If you are using this method to update the value of an element because you are working around a limitation in a web browser/
+ /// WebDriver, then strongly consider following it with .
+ ///
+ ///
+ /// The new value for the element
+ /// A builder for a performable
+ SetTheValueBuilder To(object value);
+ }
+ }
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj
index a7318f27..501569e8 100644
--- a/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj
+++ b/CSF.Screenplay.Selenium/CSF.Screenplay.Selenium.csproj
@@ -21,12 +21,13 @@
-
+
+
diff --git a/CSF.Screenplay.Selenium/PerformableBuilder.elementPerformables.cs b/CSF.Screenplay.Selenium/PerformableBuilder.elementPerformables.cs
index add96cb2..d3dfbe82 100644
--- a/CSF.Screenplay.Selenium/PerformableBuilder.elementPerformables.cs
+++ b/CSF.Screenplay.Selenium/PerformableBuilder.elementPerformables.cs
@@ -160,5 +160,19 @@ public static FromTargetActionBuilder SelectTheOptionWithValue(string optionValu
/// The target element whose contents will be cleared.
/// A performable action
public static IPerformable ClearTheContentsOf(ITarget target) => SingleElementPerformableAdapter.From(new ClearTheContents(), target);
+
+ ///
+ /// Gets a builder for an action which sets the value of an element programatically, using JavaScript.
+ ///
+ ///
+ ///
+ /// It is advised to use this technique and others like it sparingly, particularly when using Screenplay/Selenium for testing. Whilst
+ /// it is possible to set values and update the web page's state via JavaScript, this does not properly mimic the manner in which a real
+ /// human being would interact with the page.
+ ///
+ ///
+ /// The target HTML element, to have its value updated.
+ /// A builder with which to choose the new value
+ public static SetTheValueBuilder.IChoosesValue SetTheValueOf(ITarget target) => new SetTheValueBuilder(target);
}
}
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium/Resources/ScriptResources.cs b/CSF.Screenplay.Selenium/Resources/ScriptResources.cs
index f111198b..37848a88 100644
--- a/CSF.Screenplay.Selenium/Resources/ScriptResources.cs
+++ b/CSF.Screenplay.Selenium/Resources/ScriptResources.cs
@@ -12,6 +12,13 @@ static class ScriptResources
/// Gets a short JavaScript for .
internal static string ClearLocalStorage => resourceManager.GetString("ClearLocalStorage");
+ /// Gets a short JavaScript that returns the value of document.readyState .
internal static string GetDocReadyState => resourceManager.GetString("GetDocReadyState");
+
+ /// Gets a short JavaScript which sets the value of an HTML element.
+ internal static string SetElementValue => resourceManager.GetString("SetElementValue");
+
+ /// Gets a short JavaScript which sets the value of an HTML element in a way that simulates updating the element interactively.
+ internal static string SetElementValueSimulatedInteractively => resourceManager.GetString("SetElementValueSimulatedInteractively");
}
}
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium/Resources/ScriptResources.restext b/CSF.Screenplay.Selenium/Resources/ScriptResources.restext
index 782ae2a4..c1dc8bca 100644
--- a/CSF.Screenplay.Selenium/Resources/ScriptResources.restext
+++ b/CSF.Screenplay.Selenium/Resources/ScriptResources.restext
@@ -1,2 +1,4 @@
ClearLocalStorage = localStorage.clear()
-GetDocReadyState = return document.readyState
\ No newline at end of file
+GetDocReadyState = return document.readyState
+SetElementValue = arguments[0].value = arguments[1]
+SetElementValueSimulatedInteractively = ((el, v) => {const d = (e, n) => e.dispatchEvent(new Event(n, {bubbles: true}));d(el, 'focus');el.value = v;d(el, 'input');d(el, 'change');d(el, 'blur');})(arguments[0], arguments[1])
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium/Scripts.cs b/CSF.Screenplay.Selenium/Scripts.cs
index e9382f0f..0077c854 100644
--- a/CSF.Screenplay.Selenium/Scripts.cs
+++ b/CSF.Screenplay.Selenium/Scripts.cs
@@ -15,7 +15,6 @@ public static class Scripts
///
/// Gets a which clears the Local Storage of the browser, for the current domain.
///
- /// A named script.
public static NamedScript ClearLocalStorage
=> new NamedScript(Resources.ScriptResources.ClearLocalStorage, "clear the local storage");
@@ -28,5 +27,17 @@ public static NamedScript ClearLocalStorage
///
public static NamedScriptWithResult GetTheDocumentReadyState
=> new NamedScriptWithResult(Resources.ScriptResources.GetDocReadyState, "get the readiness of the current page");
+
+ ///
+ /// Gets a which sets the value of a specified HTML element.
+ ///
+ public static NamedScript SetElementValue
+ => new NamedScript(Resources.ScriptResources.SetElementValue, "set the element's value");
+
+ ///
+ /// Gets a which sets the value of a specified HTML element, simulating setting it interactively.
+ ///
+ public static NamedScript SetElementValueSimulatedInteractively
+ => new NamedScript(Resources.ScriptResources.SetElementValueSimulatedInteractively, "simulate setting the element's value interactively");
}
}
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium/ServiceCollectionExtensions.cs b/CSF.Screenplay.Selenium/ServiceCollectionExtensions.cs
new file mode 100644
index 00000000..f46a8ad9
--- /dev/null
+++ b/CSF.Screenplay.Selenium/ServiceCollectionExtensions.cs
@@ -0,0 +1,33 @@
+using CSF.Extensions.WebDriver;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace CSF.Screenplay.Selenium
+{
+ ///
+ /// Extension methods for .
+ ///
+ public static class ServiceCollectionExtensions
+ {
+ ///
+ /// Adds the required services to the service collection, so that performances may incorporate Selenium-based performables
+ /// and abilities.
+ ///
+ /// The service collection
+ /// The same service collection, so calls may be chained.
+ public static IServiceCollection AddSelenium(this IServiceCollection services)
+ {
+ services.AddWebDriverFactory();
+ services.AddWebDriverQuirks(BrowserQuirks.GetQuirksData());
+
+ services.AddTransient();
+ services.AddTransient();
+ services.Configure(o =>
+ {
+ o.ValueFormatters.Add(typeof(Reporting.OptionsFormatter));
+ o.ValueFormatters.Add(typeof(Reporting.ScreenshotFormatter));
+ });
+
+ return services;
+ }
+ }
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium/Tasks/ClickAndWaitForDocumentReady.cs b/CSF.Screenplay.Selenium/Tasks/ClickAndWaitForDocumentReady.cs
index 69aaf007..61467e5c 100644
--- a/CSF.Screenplay.Selenium/Tasks/ClickAndWaitForDocumentReady.cs
+++ b/CSF.Screenplay.Selenium/Tasks/ClickAndWaitForDocumentReady.cs
@@ -19,6 +19,7 @@ namespace CSF.Screenplay.Selenium.Tasks
/// subsequent performables are executed.
///
///
+ ///
public class ClickAndWaitForDocumentReady : ISingleElementPerformable
{
const string COMPLETE_READY_STATE = "complete";
@@ -35,6 +36,8 @@ public ReportFragment GetReportFragment(Actor actor, Lazy eleme
public async ValueTask PerformAsAsync(ICanPerform actor, IWebDriver webDriver, Lazy element, CancellationToken cancellationToken = default)
{
await actor.PerformAsync(ClickOn(element.Value), cancellationToken);
+ if(!webDriver.HasQuirk(BrowserQuirks.NeedsToWaitAfterPageLoad)) return;
+
await actor.PerformAsync(WaitUntil(ElementIsStale(element.Value.WebElement))
.ForAtMost(waitTimeout)
.Named($"{element.Value.Name} is no longer on the page"),
diff --git a/CSF.Screenplay.Selenium/Tasks/EnterTheDate.cs b/CSF.Screenplay.Selenium/Tasks/EnterTheDate.cs
index f16af502..8cbb9bc6 100644
--- a/CSF.Screenplay.Selenium/Tasks/EnterTheDate.cs
+++ b/CSF.Screenplay.Selenium/Tasks/EnterTheDate.cs
@@ -4,6 +4,7 @@
using System.Threading;
using System.Threading.Tasks;
using CSF.Screenplay.Selenium.Elements;
+using OpenQA.Selenium;
using static CSF.Screenplay.Selenium.PerformableBuilder;
namespace CSF.Screenplay.Selenium.Actions
@@ -45,9 +46,15 @@ public class EnterTheDate : IPerformable, ICanReport
string FormatDate() => date.HasValue ? date.Value.ToString(GetShortDatePattern()) : null;
+ string FormatDateAsIso() => date.HasValue ? date.Value.ToString("yyyy-MM-dd") : null;
+
///
public ValueTask PerformAsAsync(ICanPerform actor, CancellationToken cancellationToken = default)
{
+ var browseTheWeb = actor.GetAbility();
+ if(browseTheWeb.WebDriver.HasQuirk(BrowserQuirks.CannotSetInputTypeDateWithSendKeys))
+ return actor.PerformAsync(SetTheValueOf(target).To(FormatDateAsIso()).AsIfSetInteractively(), cancellationToken);
+
if(!date.HasValue)
return actor.PerformAsync(ClearTheContentsOf(target), cancellationToken);
diff --git a/CSF.Screenplay/CSF.Screenplay.csproj b/CSF.Screenplay/CSF.Screenplay.csproj
index 839babe6..061a62ad 100644
--- a/CSF.Screenplay/CSF.Screenplay.csproj
+++ b/CSF.Screenplay/CSF.Screenplay.csproj
@@ -11,7 +11,9 @@
-
+
+
+
diff --git a/CSF.Screenplay/IGetsScreenplay.cs b/CSF.Screenplay/IGetsScreenplay.cs
index a2cb6d2a..c7fe77b2 100644
--- a/CSF.Screenplay/IGetsScreenplay.cs
+++ b/CSF.Screenplay/IGetsScreenplay.cs
@@ -13,7 +13,7 @@ namespace CSF.Screenplay
///
/// Types which implement this interface need only implement the method, which should build
/// and return a Screenplay instance. Developers are advised to use
- ///
+ ///
/// to create and return the Screenplay.
///
///
@@ -45,7 +45,7 @@ public interface IGetsScreenplay
///
///
/// Implementors should create and return a new instance from this method; they are strongly urged
- /// to consider the use of
+ /// to consider the use of
/// for this purpose.
/// As well as the creation of the Screenplay instance itself, they should also add to the service collection any
/// services which relate to .
diff --git a/CSF.Screenplay/Reporting/ReportPathProvider.cs b/CSF.Screenplay/Reporting/ReportPathProvider.cs
index 7d365152..eb378b9d 100644
--- a/CSF.Screenplay/Reporting/ReportPathProvider.cs
+++ b/CSF.Screenplay/Reporting/ReportPathProvider.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using Microsoft.Extensions.Options;
namespace CSF.Screenplay.Reporting
{
@@ -22,7 +23,7 @@ namespace CSF.Screenplay.Reporting
///
public class ReportPathProvider : IGetsReportPath
{
- readonly ScreenplayOptions screenplayOptions;
+ readonly IOptions screenplayOptions;
readonly ITestsPathForWritePermissions permissionsTester;
bool hasCachedReportPath;
@@ -47,15 +48,15 @@ public string GetReportPath()
/// if reporting should be enabled; if not.
bool ShouldEnableReporting(out string reportPath)
{
- if (string.IsNullOrWhiteSpace(screenplayOptions.ReportPath))
+ if (string.IsNullOrWhiteSpace(screenplayOptions.Value.ReportPath))
{
reportPath = null;
return false;
}
- reportPath = Path.IsPathRooted(screenplayOptions.ReportPath)
- ? screenplayOptions.ReportPath
- : Path.Combine(Environment.CurrentDirectory, screenplayOptions.ReportPath);
+ reportPath = Path.IsPathRooted(screenplayOptions.Value.ReportPath)
+ ? screenplayOptions.Value.ReportPath
+ : Path.Combine(Environment.CurrentDirectory, screenplayOptions.Value.ReportPath);
return permissionsTester.HasWritePermission(reportPath);
}
@@ -64,10 +65,10 @@ bool ShouldEnableReporting(out string reportPath)
///
/// The screenplay options.
/// The permissions tester.
- public ReportPathProvider(ScreenplayOptions screenplayOptions, ITestsPathForWritePermissions permissionsTester)
+ public ReportPathProvider(IOptions screenplayOptions, ITestsPathForWritePermissions permissionsTester)
{
- this.screenplayOptions = screenplayOptions ?? throw new System.ArgumentNullException(nameof(screenplayOptions));
- this.permissionsTester = permissionsTester ?? throw new System.ArgumentNullException(nameof(permissionsTester));
+ this.screenplayOptions = screenplayOptions ?? throw new ArgumentNullException(nameof(screenplayOptions));
+ this.permissionsTester = permissionsTester ?? throw new ArgumentNullException(nameof(permissionsTester));
}
}
}
\ No newline at end of file
diff --git a/CSF.Screenplay/Screenplay.cs b/CSF.Screenplay/Screenplay.cs
index 35881e37..ae4213b4 100644
--- a/CSF.Screenplay/Screenplay.cs
+++ b/CSF.Screenplay/Screenplay.cs
@@ -5,6 +5,7 @@
using CSF.Screenplay.Performables;
using CSF.Screenplay.Performances;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
using AsyncPerformanceLogic = System.Func>;
namespace CSF.Screenplay
@@ -25,10 +26,10 @@ namespace CSF.Screenplay
///
///
/// It is recommended to create instances of this type by adding Screenplay to a dependency injection
- /// via the extension method
+ /// via the extension method
/// and then resolving an instance of this class from the service provider.
/// Alternatively, if you do not wish to configure a service collection manually and just want an instance of this type then
- /// use the static method.
+ /// use the static method.
///
///
/// The Screenplay object is used to create instances of via its .
@@ -46,8 +47,8 @@ public sealed class Screenplay : IHasServiceProvider
/// Screenplay has begun.
public void BeginScreenplay()
{
- var config = ServiceProvider.GetRequiredService();
- foreach (var callback in config.OnBeginScreenplayActions)
+ var config = ServiceProvider.GetRequiredService>();
+ foreach (var callback in config.Value.OnBeginScreenplayActions)
callback(ServiceProvider);
ServiceProvider.GetRequiredService().InvokeScreenplayStarted();
@@ -59,8 +60,8 @@ public void CompleteScreenplay()
{
ServiceProvider.GetRequiredService().InvokeScreenplayEnded();
- var config = ServiceProvider.GetRequiredService();
- foreach (var callback in config.OnEndScreenplayActions)
+ var config = ServiceProvider.GetRequiredService>();
+ foreach (var callback in config.Value.OnEndScreenplayActions)
callback(ServiceProvider);
}
@@ -135,8 +136,8 @@ public void CompleteScreenplay()
///
///
/// It is unlikely that developers should be executing this constructor directly. Consider using the static factory method
- /// . Alternatively, add Screenplay to an using
- /// and then resolve an instance of
+ /// . Alternatively, add Screenplay to an using
+ /// and then resolve an instance of
/// this class from the service provider built from that service collection.
///
///
@@ -158,17 +159,15 @@ public Screenplay(IServiceProvider serviceProvider)
///
///
/// If you already have an and you wish to integrate Screenplay into it, then use the extension method
- /// instead.
+ /// instead.
///
///
/// An optional action which permits further customization of the service collection that is implicitly created by this method.
- /// An optional action to configure the which is created by this method.
/// A Screenplay instance created from a new service collection.
- public static Screenplay Create(Action serviceCollectionCustomisations = null,
- Action options = null)
+ public static Screenplay Create(Action serviceCollectionCustomisations = null)
{
var services = new ServiceCollection();
- services.AddScreenplay(options);
+ services.AddScreenplay();
serviceCollectionCustomisations?.Invoke(services);
var serviceProvider = services.BuildServiceProvider();
return serviceProvider.GetRequiredService();
diff --git a/CSF.Screenplay/ScreenplayOptions.cs b/CSF.Screenplay/ScreenplayOptions.cs
index ed22076e..649d7c77 100644
--- a/CSF.Screenplay/ScreenplayOptions.cs
+++ b/CSF.Screenplay/ScreenplayOptions.cs
@@ -18,6 +18,11 @@ namespace CSF.Screenplay
/// the appropriate methods/logic to register the neccesary services for Options.
/// This is why this object uses a somewhat homebrew version of options, without making use of the official libraries.
///
+ ///
+ /// Reqnroll is presently investigating replacing the BoDi container, and if it is someday replaced by MSDI, then
+ /// issue #292 is available to make that switch
+ /// to the options pattern /
+ ///
///
public sealed class ScreenplayOptions
{
diff --git a/CSF.Screenplay/ScreenplayServiceCollectionExtensions.cs b/CSF.Screenplay/ScreenplayServiceCollectionExtensions.cs
index 2ba67f0d..7264a480 100644
--- a/CSF.Screenplay/ScreenplayServiceCollectionExtensions.cs
+++ b/CSF.Screenplay/ScreenplayServiceCollectionExtensions.cs
@@ -7,6 +7,7 @@
using CSF.Screenplay.Reporting;
using CSF.Screenplay.ReportModel;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
namespace CSF.Screenplay
{
@@ -22,65 +23,62 @@ public static class ScreenplayServiceCollectionExtensions
///
/// Use this method to add Screenplay to an existing service collection; if you just want an instance of
/// and do not care for integrating it with a service collection of your own then consider the convenience method
- /// .
- ///
- ///
- /// If you choose to provide any configuration via the parameter, do not 'capture' the
- /// object outside the closure. This object is added to dependency injection as a singleton, and so if it is modified outside of
- /// this configuration action then the integrity of the Screenplay dependency injection may be compromised.
+ /// .
///
///
/// An
- /// An optional configuration action, used to configure Screenplay in DI
/// The service collection, so that calls may be chained
/// If is .
- public static IServiceCollection AddScreenplay(this IServiceCollection services, Action options = null)
+ public static IServiceCollection AddScreenplay(this IServiceCollection services)
{
if (services is null)
throw new ArgumentNullException(nameof(services));
- var optionsModel = new ScreenplayOptions();
- options?.Invoke(optionsModel);
- var eventBus = new PerformanceEventBus();
- optionsModel.PerformanceEventsConfig?.Invoke(eventBus);
-
- services.AddSingleton();
- services.AddSingleton(eventBus);
- services.AddSingleton(s => s.GetRequiredService());
- services.AddSingleton(s => s.GetRequiredService());
- services.AddSingleton(optionsModel);
- services.AddSingleton(s => s.GetRequiredService().ValueFormatters);
- services.AddSingleton();
- services.AddSingleton();
- services.AddSingleton(s =>
- {
- var reportPath = s.GetRequiredService().GetReportPath();
- if(reportPath is null) return new NoOpReporter();
-
- var stream = File.Create(reportPath);
- return ActivatorUtilities.CreateInstance(s, stream);
- });
+ services
+ .AddOptions()
+ .Configure((ScreenplayOptions o, PerformanceEventBus eventBus) => o.PerformanceEventsConfig?.Invoke(eventBus));
+
+ services
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton(s => s.GetRequiredService())
+ .AddSingleton(s => s.GetRequiredService())
+ .AddSingleton(s => s.GetRequiredService>().Value.ValueFormatters)
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton(s =>
+ {
+ var reportPath = s.GetRequiredService().GetReportPath();
+ if(reportPath is null) return new NoOpReporter();
+
+ var stream = File.Create(reportPath);
+ return ActivatorUtilities.CreateInstance(s, stream);
+ });
- services.AddScoped(s => new Cast(s, s.GetRequiredService().PerformanceIdentity));
- services.AddScoped();
- services.AddScoped();
- services.AddScoped(s => s.GetRequiredService().GetCurrentPerformance());
- services.AddScoped();
+ services
+ .AddScoped(s => new Cast(s, s.GetRequiredService().PerformanceIdentity))
+ .AddScoped()
+ .AddScoped()
+ .AddScoped(s => s.GetRequiredService().GetCurrentPerformance())
+ .AddScoped();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient();
- services.AddTransient, PerformanceReportBuilder>>(s =>
- {
- return idsAndNames => ActivatorUtilities.CreateInstance(s, idsAndNames);
- });
- services.AddTransient();
- foreach(var type in optionsModel.ValueFormatters)
- services.AddTransient(type);
+ services
+ .AddTransient()
+ .AddTransient()
+ .AddTransient()
+ .AddTransient()
+ .AddTransient()
+ .AddTransient()
+ .AddTransient()
+ .AddTransient, PerformanceReportBuilder>>(s =>
+ {
+ return idsAndNames => ActivatorUtilities.CreateInstance(s, idsAndNames);
+ })
+ .AddTransient()
+ .AddTransient()
+ .AddTransient()
+ .AddTransient()
+ .AddTransient();
return services;
}
diff --git a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/AppleSafari.flags.json b/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/AppleSafari.flags.json
deleted file mode 100644
index 286888f1..00000000
--- a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/AppleSafari.flags.json
+++ /dev/null
@@ -1,15 +0,0 @@
-[
- {
- "browserName": "Safari",
- "flags": [
- ],
- },
- {
- "browserName": "Safari",
- "minVersion": "11",
- "flags": [
- "HtmlElements.Select.RequiresUpdatesViaJavaScriptWorkaround",
- ],
- },
-]
-
diff --git a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/GoogleChrome.flags.json b/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/GoogleChrome.flags.json
deleted file mode 100644
index b62dc273..00000000
--- a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/GoogleChrome.flags.json
+++ /dev/null
@@ -1,8 +0,0 @@
-[
- {
- "browserName": "Chrome",
- "flags": [
- "HtmlElements.InputTypeDate.RequiresEntryUsingLocaleFormat",
- ],
- },
-]
\ No newline at end of file
diff --git a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/InternetExplorer.flags.json b/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/InternetExplorer.flags.json
deleted file mode 100644
index f92a921c..00000000
--- a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/InternetExplorer.flags.json
+++ /dev/null
@@ -1,7 +0,0 @@
-[
- {
- "browserName": [ "InternetExplorer", "Internet Explorer" ],
- "flags": [
- ],
- },
-]
\ No newline at end of file
diff --git a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/MicrosoftEdge.flags.json b/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/MicrosoftEdge.flags.json
deleted file mode 100644
index d9fd8749..00000000
--- a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/MicrosoftEdge.flags.json
+++ /dev/null
@@ -1,10 +0,0 @@
-[
- {
- "browserName": "MicrosoftEdge",
- "flags": [
- "Browser.CannotClearDomainCookies",
- "HtmlElements.SelectMultiple.RequiresCtrlClickToToggleOptionSelection",
- "HtmlElements.InputTypeDate.RequiresInputViaJavaScriptWorkaround",
- ],
- },
-]
\ No newline at end of file
diff --git a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/MozillaFirefox.flags.json b/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/MozillaFirefox.flags.json
deleted file mode 100644
index c8e38046..00000000
--- a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/MozillaFirefox.flags.json
+++ /dev/null
@@ -1,8 +0,0 @@
-[
- {
- "browserName": "Firefox",
- "flags": [
- "HtmlElements.InputTypeDate.RequiresInputViaJavaScriptWorkaround"
- ],
- },
-]
diff --git a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.Browser.cs b/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.Browser.cs
deleted file mode 100644
index b1cef97f..00000000
--- a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.Browser.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-
-namespace CSF.Screenplay.Selenium
-{
- public static partial class Flags
- {
- ///
- /// Flags relating to the web browser itself, such as management of cookies.
- ///
- public static class Browser
- {
- ///
- /// Indicates that the web driver is incapable of clearing the cookies for the current domain.
- ///
- ///
- ///
- /// The current domain is the domain for the page upon which the web driver is currently viewing.
- ///
- ///
- public static readonly string CannotClearDomainCookies = "Browser.CannotClearDomainCookies";
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.HtmlElements.cs b/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.HtmlElements.cs
deleted file mode 100644
index 3be266d8..00000000
--- a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.HtmlElements.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using System;
-namespace CSF.Screenplay.Selenium
-{
- public static partial class Flags
- {
- ///
- /// Flags relating to specific HTML elements.
- ///
- public static class HtmlElements
- {
- ///
- /// Flags relating to HTML <input type="date"> elements.
- ///
- public static class InputTypeDate
- {
- ///
- /// Indicates that the web driver may be used to enter a date using a format that conforms to the web browser's
- /// current locale setting.
- ///
- public static readonly string RequiresEntryUsingLocaleFormat = "HtmlElements.InputTypeDate.RequiresEntryUsingLocaleFormat";
-
- ///
- /// Indicates that the web driver must use a JavaScript workaround to set the date, because it is impossible to do so
- /// by typing keys.
- ///
- public static readonly string RequiresInputViaJavaScriptWorkaround = "HtmlElements.InputTypeDate.RequiresInputViaJavaScriptWorkaround";
- }
-
- ///
- /// Flags relating to HTML <select multiple> elements.
- ///
- public static class SelectMultiple
- {
- ///
- /// Indicates that the web driver must send Ctrl+Click in order to toggle the selection of a single
- /// option within the select element. Without Ctrl, the click is interpreted as "change entire selection to just
- /// the one option clicked".
- ///
- public static readonly string RequiresCtrlClickToToggleOptionSelection = "HtmlElements.SelectMultiple.RequiresCtrlClickToToggleOptionSelection";
- }
-
- ///
- /// Flags relating to HTML <select> elements.
- ///
- public static class Select
- {
- ///
- /// Indicates that the browser requires a JavaScript workaround in order to change the selection state
- /// of an HTML <select> element.
- ///
- public static readonly string RequiresUpdatesViaJavaScriptWorkaround = "HtmlElements.Select.RequiresUpdatesViaJavaScriptWorkaround";
- }
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.cs b/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.cs
deleted file mode 100644
index 2a0f2e1c..00000000
--- a/Old/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System;
-namespace CSF.Screenplay.Selenium
-{
- ///
- /// A catalogue of the the various browser flags of which this library is aware.
- ///
- public static partial class Flags
- {
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/ArgumentsArrayValidator.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/ArgumentsArrayValidator.cs
deleted file mode 100644
index 06e95245..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/ArgumentsArrayValidator.cs
+++ /dev/null
@@ -1,57 +0,0 @@
-//
-// ArgumentsArrayValidator.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.StoredScripts;
-
-namespace CSF.Screenplay.Selenium.ScriptResources
-{
- ///
- /// A stored JavaScript which validates a collection of arguments passed as an array.
- ///
- public class ArgumentsArrayValidator : ScriptResource
- {
- const string EntryPointNameConst = "validateArgumentsArray";
-
- ///
- /// Gets the name of the entry point for this script (which differs from the default).
- ///
- /// The name of the entry point.
- public static string EntryPointName => EntryPointNameConst;
-
- ///
- /// Gets the name of this script.
- ///
- /// The name.
- public override string Name => "a JavaScript which validates function arguments arrays";
-
- ///
- /// Gets the name of the entry point to the script - this is the function exposed by
- /// .
- ///
- /// The name of the entry point function.
- public override string GetEntryPointName() => EntryPointName;
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/ArgumentsArrayValidator.js b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/ArgumentsArrayValidator.js
deleted file mode 100644
index 6b653445..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/ArgumentsArrayValidator.js
+++ /dev/null
@@ -1,87 +0,0 @@
-var argumentsArrayValidator = function()
-{
- 'use strict';
-
- function getLengthParams(min, max)
- {
- if(typeof min === 'number' && max === undefined)
- {
- return {
- count: min,
- validateCount: true,
- };
- }
-
- var minCount, validateMinCount = false, maxCount, validateMaxCount = false;
-
- if(typeof min === 'number')
- {
- minCount = min;
- validateMinCount = true;
- }
-
- if(typeof max === 'number')
- {
- maxCount = max;
- validateMaxCount = true;
- }
-
- return {
- min: minCount,
- validateMin: validateMinCount,
- max: maxCount,
- validateMax: validateMaxCount,
- validateCount: false,
- };
- }
-
- function validateType(argsArray)
- {
- if(!argsArray) throw new Error('Arguments must be a non-null array.');
- if(!(argsArray instanceof Array)) throw new Error('Arguments must be an array.');
- }
-
- function validateLength(argsArray, lengthParams)
- {
- if(lengthParams.validateCount && argsArray.length !== lengthParams.count)
- throw new Error('Arguments array must contain precisely ' + lengthParams.count + ' item(s).');
-
- if(lengthParams.validateMin && argsArray.length < lengthParams.min)
- throw new Error('Arguments array must contain at least ' + lengthParams.min + ' item(s).');
-
- if(lengthParams.validateMax && argsArray.length > lengthParams.max)
- throw new Error('Arguments array must contain no more than ' + lengthParams.max + ' item(s).');
- }
-
- function validate(argsArray, min, max)
- {
- validateType(argsArray);
- var lengthParams = getLengthParams(min, max);
- validateLength(argsArray, lengthParams);
-
- return true;
- }
-
- function selfValidate(argsArray, min, max)
- {
- try
- {
- return validate(argsArray, min, max);
- }
- catch(e) { throw new Error('The call to \'validateArgumentsArray\' raised an error: ' + e.message); }
- }
-
- return {
- validate: validate,
- selfValidate: selfValidate,
- };
-}();
-
-function validateArgumentsArray(argsArray)
-{
- 'use strict';
-
- validator.selfValidate(argsArray, 1, 3);
- var arrayToValidate = argsArray[0], min = argsArray[1], max = argsArray[2];
- return validator.validate(arrayToValidate, min, max);
-}
\ No newline at end of file
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetALocalisedDate.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetALocalisedDate.cs
deleted file mode 100644
index 8cb0206f..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetALocalisedDate.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// GetALocalisedDate.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.StoredScripts;
-
-namespace CSF.Screenplay.Selenium.ScriptResources
-{
- ///
- /// Script resource for getting a localised date string
- ///
- public class GetALocalisedDate : ScriptResource
- {
- readonly ScriptResource argsValidator;
-
- ///
- /// Gets the name of this script.
- ///
- /// The name.
- public override string Name => "a JavaScript which converts a date to a locale-formatted string";
-
- ///
- /// Gets a collection of scripts which the current script instance depends upon.
- ///
- /// The dependencies.
- protected override ScriptResource[] GetDependencies() => new [] { argsValidator };
-
- ///
- /// Initializes a new instance of the class.
- ///
- public GetALocalisedDate() : this(null) {}
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Arguments validator.
- public GetALocalisedDate(ScriptResource argsValidator)
- {
- this.argsValidator = argsValidator ?? new ArgumentsArrayValidator();
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetALocalisedDate.js b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetALocalisedDate.js
deleted file mode 100644
index 9456b68c..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetALocalisedDate.js
+++ /dev/null
@@ -1,17 +0,0 @@
-function executeScript(argsArray) {
- 'use strict';
-
- argumentsArrayValidator.validate(argsArray, 3);
-
- var
- year = argsArray[0],
- month = argsArray[1],
- day = argsArray[2],
- theDate;
-
- if(typeof year !== 'number' || typeof month !== 'number' || typeof day !== 'number')
- throw new Error('The supplied year, month and day must all be numbers.');
-
- theDate = new Date(year, month, day);
- return theDate.toLocaleDateString();
-}
\ No newline at end of file
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetDocumentReadyState.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetDocumentReadyState.cs
deleted file mode 100644
index bff50835..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetDocumentReadyState.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// GetDocumentReadyState.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.StoredScripts;
-
-namespace CSF.Screenplay.Selenium.ScriptResources
-{
- ///
- /// Script resource for getting the document ready state.
- ///
- public class GetDocumentReadyState : ScriptResource
- {
- ///
- /// Gets the name of this script.
- ///
- /// The name.
- public override string Name => "a JavaScript which gets the current web page's ready-state";
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetDocumentReadyState.js b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetDocumentReadyState.js
deleted file mode 100644
index b8953856..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetDocumentReadyState.js
+++ /dev/null
@@ -1,4 +0,0 @@
-function executeScript(argsArray) {
- 'use strict';
- return document.readyState;
-}
\ No newline at end of file
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementAttribute.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementAttribute.cs
deleted file mode 100644
index 93126cf8..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementAttribute.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// SetAnElementAttribute.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.StoredScripts;
-
-namespace CSF.Screenplay.Selenium.ScriptResources
-{
- ///
- /// Script resource for setting an attribute upon an element.
- ///
- public class SetAnElementAttribute : ScriptResource
- {
- ///
- /// Gets the name of this script.
- ///
- /// The name.
- public override string Name => "a JavaScript which sets an attribute upon an element";
-
- ///
- /// Gets a collection of scripts which the current script instance depends upon.
- ///
- /// The dependencies.
- protected override ScriptResource[] GetDependencies() => new [] { new ArgumentsArrayValidator() };
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementAttribute.js b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementAttribute.js
deleted file mode 100644
index 79c5f7e9..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementAttribute.js
+++ /dev/null
@@ -1,24 +0,0 @@
-function executeScript(argsArray)
-{
- 'use strict';
-
- argumentsArrayValidator.validate(argsArray, 3);
-
- var htmlElement = argsArray[0], attributeName = argsArray[1], newValue = argsArray[2];
-
- function validateElement(element)
- {
- if(element === null || element === undefined)
- throw new Error('You must provide an HTML element object.');
- if(!(element instanceof HTMLElement))
- throw new Error('The element must be an HTML element.');
- }
-
- validateElement(htmlElement);
- if(newValue === null)
- htmlElement.removeAttribute(attributeName);
- else
- htmlElement.setAttribute(attributeName, newValue);
-
- return true;
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementValue.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementValue.cs
deleted file mode 100644
index 3b9279da..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementValue.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// SetAnElementValue.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.StoredScripts;
-
-namespace CSF.Screenplay.Selenium.ScriptResources
-{
- ///
- /// A stored JavaScript which sets the value of an HTML element and then triggers the 'change' event for that element.
- ///
- public class SetAnElementValue : ScriptResource
- {
- readonly ScriptResource argsValidator;
-
- ///
- /// Gets the name of this script.
- ///
- /// The name.
- public override string Name => "a JavaScript to set the value of an HTML element";
-
- ///
- /// Gets a collection of scripts which the current script instance depends upon.
- ///
- /// The dependencies.
- protected override ScriptResource[] GetDependencies() => new [] { argsValidator };
-
- ///
- /// Initializes a new instance of the class.
- ///
- public SetAnElementValue() : this(null) {}
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Arguments validator.
- public SetAnElementValue(ScriptResource argsValidator)
- {
- this.argsValidator = argsValidator ?? new ArgumentsArrayValidator();
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementValue.js b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementValue.js
deleted file mode 100644
index d93f5b4f..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementValue.js
+++ /dev/null
@@ -1,36 +0,0 @@
-function executeScript(argsArray)
-{
- 'use strict';
-
- argumentsArrayValidator.validate(argsArray, 2);
-
- var htmlElement = argsArray[0], newValue = argsArray[1];
-
- function validateElement(element)
- {
- if(element === null || element === undefined)
- throw new Error('You must provide an HTML element object.');
- if(!(element instanceof HTMLElement))
- throw new Error('The element must be an HTML element.');
- if(element.value === undefined)
- throw new Error('The element must have a \'value\' property.');
- }
-
- function setValue(element, val)
- {
- element.value = val;
- }
-
- function triggerChangeEvent(element)
- {
- var ev = document.createEvent('Event');
- ev.initEvent('change', true, true);
- element.dispatchEvent(ev);
- }
-
- validateElement(htmlElement);
- setValue(htmlElement, newValue);
- triggerChangeEvent(htmlElement);
-
- return true;
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/UpdateSelectElementSelection.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/UpdateSelectElementSelection.cs
deleted file mode 100644
index ef9a59a6..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/UpdateSelectElementSelection.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-//
-// UpdateSelectElementSelection.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.StoredScripts;
-
-namespace CSF.Screenplay.Selenium.ScriptResources
-{
- ///
- /// A stored JavaScript which sets the selected option(s) for an HTML <select> element.
- ///
- public class UpdateSelectElementSelection : ScriptResource
- {
- ///
- /// Gets the action name for deselecting every option.
- ///
- public static readonly string DeselectAllActionName = "deselectAll";
-
- ///
- /// Gets the action name for selecting an option by its zero-based index.
- ///
- public static readonly string SelectByIndexActionName = "selectByIndex";
-
- ///
- /// Gets the action name for selecting an option by its value.
- ///
- public static readonly string SelectByValueActionName = "selectByValue";
-
- ///
- /// Gets the action name for selecting an option by its displyed text.
- ///
- public static readonly string SelectByTextActionName = "selectByText";
-
- ///
- /// Gets the action name for deselecting an option by its zero-based index.
- ///
- public static readonly string DeselectByIndexActionName = "deselectByIndex";
-
- ///
- /// Gets the action name for deselecting an option by its value.
- ///
- public static readonly string DeselectByValueActionName = "deselectByValue";
-
- ///
- /// Gets the action name for deselecting an option by its displayed text.
- ///
- public static readonly string DeselectByTextActionName = "deselectByText";
-
- ///
- /// Gets the name of this script.
- ///
- /// The name.
- public override string Name => "a JavaScript to set the select options of an HTML element";
-
- ///
- /// Gets a collection of scripts which the current script instance depends upon.
- ///
- /// The dependencies.
- protected override ScriptResource[] GetDependencies() => new [] { new ArgumentsArrayValidator() };
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/UpdateSelectElementSelection.js b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/UpdateSelectElementSelection.js
deleted file mode 100644
index b5650fcb..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/UpdateSelectElementSelection.js
+++ /dev/null
@@ -1,103 +0,0 @@
-function executeScript(argsArray)
-{
- 'use strict';
-
- argumentsArrayValidator.validate(argsArray, 2, 3);
-
- function validateElement(element)
- {
- if(element === null || element === undefined)
- throw new Error('You must provide an HTML element object.');
- if(!(element instanceof HTMLSelectElement))
- throw new Error('The element must be an HTML element.');
- }
-
- var optionUpdater = function()
- {
- function triggerChangeEvent(element)
- {
- var ev = document.createEvent('Event');
- ev.initEvent('change', true, true);
- element.dispatchEvent(ev);
- }
-
- function getOptionByIndex(selectElement, index)
- {
- return selectElement.item(index);
- }
-
- function getOptionByValue(selectElement, value)
- {
- var options = selectElement.options;
- for(var i = 0, len = options.length; i < len; i++)
- if(options[i].value === value) return options[i];
- return null;
- }
-
- function getOptionByText(selectElement, text)
- {
- var options = selectElement.options;
- for(var i = 0, len = options.length; i < len; i++)
- if(options[i].text === text) return options[i];
- return null;
- }
-
- function setSelectedByIndex(selectElement, index, selected)
- {
- var option = getOptionByIndex(selectElement, index);
- return setSelected(selectElement, option, selected);
- }
-
- function setSelectedByValue(selectElement, value, selected)
- {
- var option = getOptionByValue(selectElement, value);
- return setSelected(selectElement, option, selected);
- }
-
- function setSelectedByText(selectElement, text, selected)
- {
- var option = getOptionByText(selectElement, text);
- return setSelected(selectElement, option, selected);
- }
-
- function setSelected(selectElement, option, selected)
- {
- if(!option) return false;
- option.selected = selected;
- triggerChangeEvent(selectElement);
- return true;
- }
-
- function deselectAll(selectElement)
- {
- var options = selectElement.options;
- for(var i = 0, len = options.length; i < len; i++)
- options.item(i).selected = false;
- triggerChangeEvent(selectElement);
- return options.length > 0;
- }
-
- return {
- selectByIndex: function(ele, idx) { return setSelectedByIndex(ele, idx, true); },
- selectByValue: function(ele, val) { return setSelectedByValue(ele, val, true); },
- selectByText: function(ele, txt) { return setSelectedByText(ele, txt, true); },
- deselectByIndex: function(ele, idx) { return setSelectedByIndex(ele, idx, false); },
- deselectByValue: function(ele, val) { return setSelectedByValue(ele, val, false); },
- deselectByText: function(ele, txt) { return setSelectedByText(ele, txt, false); },
- deselectAll: deselectAll,
- };
-
- }();
-
- var
- element = argsArray[0],
- action = argsArray[1],
- value = argsArray[2];
-
- validateElement(element);
-
- if(!optionUpdater.hasOwnProperty(action))
- throw new Error("The action '" + action + "' was not recognised.");
-
- return optionUpdater[action](element, value);
-}
\ No newline at end of file
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ICreatesInvocationScript.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ICreatesInvocationScript.cs
deleted file mode 100644
index 339a9f34..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ICreatesInvocationScript.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// IInvokesScripts.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-namespace CSF.Screenplay.Selenium.StoredScripts
-{
- ///
- /// A service which creates a JavaScript which is used for the purpose of invoking other JavaScripts.
- ///
- public interface ICreatesInvocationScript
- {
- ///
- /// Gets an invocation script for the given entry point name.
- ///
- /// The invocation script.
- /// The name of the entry point which should be invoked.
- string GetScript(string entryPoint);
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/IProvidesScript.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/IProvidesScript.cs
deleted file mode 100644
index 9b0461aa..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/IProvidesScript.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// IStoredScript.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-namespace CSF.Screenplay.Selenium.StoredScripts
-{
- ///
- /// A service which provides a JavaScript fragment with a named entry point.
- ///
- public interface IProvidesScript
- {
- ///
- /// Gets the name of this script.
- ///
- /// The name.
- string Name { get; }
-
- ///
- /// Gets a JavaScript which includes a named function. The name of that function is exposed via
- /// .
- ///
- /// The script.
- string GetScript();
-
- ///
- /// Gets the name of the entry point to the script - this is the function exposed by .
- ///
- /// The name of the entry point function.
- string GetEntryPointName();
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/IRunsScripts.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/IRunsScripts.cs
deleted file mode 100644
index 244a2c2c..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/IRunsScripts.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// IRunsStoredScripts.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using OpenQA.Selenium;
-
-namespace CSF.Screenplay.Selenium.StoredScripts
-{
- ///
- /// A service which executes JavaScripts using given parameters.
- ///
- public interface IRunsScripts
- {
- ///
- /// Executes the script exposed by the given script provider and returns the result.
- ///
- /// The script result.
- /// A JavaScript provider.
- /// A web driver.
- /// The script arguments.
- object ExecuteScript(IProvidesScript script, IWebDriver webDriver, params object[] arguments);
-
- ///
- /// Executes the script and returns the result.
- ///
- /// The script result.
- /// A JavaScript.
- /// A web driver.
- /// The script arguments.
- object ExecuteScript(string script, IWebDriver webDriver, params object[] arguments);
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptInvokerFactory.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptInvokerFactory.cs
deleted file mode 100644
index c3776f33..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptInvokerFactory.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// ArgumentsArrayConverter.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-namespace CSF.Screenplay.Selenium.StoredScripts
-{
- ///
- /// A special stored JavaScript which is used to invoke other JavaScripts.
- ///
- public class ScriptInvokerFactory : ICreatesInvocationScript
- {
- readonly ScriptResourceLoader loader;
-
- ///
- /// Gets an invocation script for the given entry point name.
- ///
- /// The invocation script.
- /// The name of the entry point which should be invoked.
- public string GetScript(string entryPoint)
- {
- var invokerService = loader.GetScriptFor();
- var invocationLine = GetInvocationLine(entryPoint);
-
- return String.Concat(invokerService, Environment.NewLine, invocationLine);
- }
-
- string GetInvocationLine(string entryPoint)
- => $"return invoker.invoke({entryPoint}, arguments);";
-
- ///
- /// Initializes a new instance of the class.
- ///
- public ScriptInvokerFactory()
- {
- loader = new ScriptResourceLoader();
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptInvokerFactory.js b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptInvokerFactory.js
deleted file mode 100644
index 689a2f9b..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptInvokerFactory.js
+++ /dev/null
@@ -1,24 +0,0 @@
-var invoker = function()
-{
- 'use strict';
-
- function validateEntryPoint(entryPoint)
- {
- if(!entryPoint || typeof entryPoint !== 'function')
- throw new Error('The script entry-point must be a function');
- }
-
- function getArgumentsObjectAsArray(argumentsObject)
- {
- return Array.prototype.slice.call(argumentsObject);
- }
-
- function invoke(entryPoint, argumentsObject)
- {
- validateEntryPoint(entryPoint);
- var args = getArgumentsObjectAsArray(argumentsObject);
- return entryPoint(args);
- }
-
- return { invoke: invoke };
-}();
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptResource.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptResource.cs
deleted file mode 100644
index 2f511b50..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptResource.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-//
-// ScriptResource.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using System.Linq;
-
-namespace CSF.Screenplay.Selenium.StoredScripts
-{
- ///
- /// Abstract implementation of for a JavaScript which is stored as an embedded resource.
- ///
- public abstract class ScriptResource : IProvidesScript
- {
- internal const string
- DefaultEntryPointName = "executeScript";
- readonly ScriptResourceLoader scriptLoader;
-
- ///
- /// Gets the name of this script.
- ///
- /// The name.
- public virtual string Name => GetType().Name;
-
- ///
- /// Gets the name of the entry point to the script - this is the function exposed by
- /// .
- ///
- /// The name of the entry point function.
- public virtual string GetEntryPointName() => DefaultEntryPointName;
-
- ///
- /// Gets a JavaScript which includes a named function. The name of that function is exposed via
- /// .
- ///
- /// The script.
- public virtual string GetScript() => CombineScripts(this, GetDependencies());
-
- ///
- /// Gets the script fragment as a named function (without any dependency scripts, if any).
- /// The name of that function is exposed via
- /// .
- ///
- /// The current script.
- protected virtual string GetScriptWithoutDependencies() => scriptLoader.GetScriptFor(GetType());
-
- ///
- /// Gets a collection of scripts which the current script instance depends upon.
- ///
- /// The dependencies.
- protected virtual ScriptResource[] GetDependencies() => new ScriptResource[0];
-
- ///
- /// Combines the given script (which provides an entry point) with other scripts, creating one long script.
- ///
- /// The scripts.
- /// Entry point provider.
- /// Scripts.
- protected string CombineScripts(ScriptResource entryPointProvider, params ScriptResource[] scripts)
- {
- if(entryPointProvider == null)
- throw new ArgumentNullException(nameof(entryPointProvider));
- if(scripts == null)
- throw new ArgumentNullException(nameof(scripts));
-
- var scriptsToCombine = scripts
- .Select(x => x.GetScript())
- .Union(new [] { entryPointProvider.GetScriptWithoutDependencies() })
- .ToArray();
-
- return String.Join(Environment.NewLine, scriptsToCombine);
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public ScriptResource()
- {
- scriptLoader = new ScriptResourceLoader();
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptResourceLoader.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptResourceLoader.cs
deleted file mode 100644
index 55b0f44d..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptResourceLoader.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// ScriptResourceLoader.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Reflection;
-
-namespace CSF.Screenplay.Selenium.StoredScripts
-{
- ///
- /// Loads a string manifest resource representing a JavaScript which matches the name of a System.Type .
- ///
- public class ScriptResourceLoader
- {
- ///
- /// Gets the JavaScript for the given type.
- ///
- /// The JavaScript resource.
- /// The type for which to load script.
- public string GetScriptFor()
- => GetScriptFor(typeof(T));
-
- ///
- /// Gets the JavaScript for the given type.
- ///
- /// The JavaScript resource.
- /// The type for which to load script.
- public string GetScriptFor(Type type)
- {
- if(type == null)
- throw new ArgumentNullException(nameof(type));
-
- var scriptAssembly = type.Assembly;
-
- return scriptAssembly.GetManifestResourceText(type, $"{type.Name}.js");
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptRunner.cs b/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptRunner.cs
deleted file mode 100644
index 769d54ff..00000000
--- a/Old/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/StoredScripts/ScriptRunner.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-//
-// ScriptRunner.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using OpenQA.Selenium;
-
-namespace CSF.Screenplay.Selenium.StoredScripts
-{
- ///
- /// Default implementation of
- ///
- public class ScriptRunner : IRunsScripts
- {
- readonly ICreatesInvocationScript invoker;
-
- ///
- /// Executes the script and returns the result.
- ///
- /// The script result.
- /// A JavaScript.
- /// A web driver.
- /// The script arguments.
- public object ExecuteScript(string script, IWebDriver webDriver, params object[] arguments)
- {
- if(script == null)
- throw new ArgumentNullException(nameof(script));
- if(webDriver == null)
- throw new ArgumentNullException(nameof(webDriver));
-
- var javaScriptRunner = GetJavaScriptExecutor(webDriver);
- return javaScriptRunner.ExecuteScript(script, arguments);
- }
-
- ///
- /// Executes the script exposed by the given script provider and returns the result.
- ///
- /// The script result.
- /// A JavaScript provider.
- /// A web driver.
- /// The script arguments.
- public object ExecuteScript(IProvidesScript script, IWebDriver webDriver, params object[] arguments)
- {
- if(script == null)
- throw new ArgumentNullException(nameof(script));
- if(webDriver == null)
- throw new ArgumentNullException(nameof(webDriver));
-
- var scriptBody = GetScriptBodyWithInvoker(script);
- return ExecuteScript(scriptBody, webDriver, arguments);
- }
-
- string GetScriptBodyWithInvoker(IProvidesScript script)
- {
- var scriptBody = script.GetScript();
- var invokerBody = invoker.GetScript(script.GetEntryPointName());
-
- return String.Concat(scriptBody, Environment.NewLine, invokerBody);
- }
-
- IJavaScriptExecutor GetJavaScriptExecutor(IWebDriver driver)
- {
- var jsDriver = driver as IJavaScriptExecutor;
-
- if(jsDriver == null)
- throw new ArgumentException($"The {nameof(IWebDriver)} must support the execution of JavaScript.", nameof(driver));
-
- return jsDriver;
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public ScriptRunner() : this(null) {}
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// A JavaScript which invokes other scripts via their named entry points.
- public ScriptRunner(ICreatesInvocationScript invoker)
- {
- this.invoker = invoker ?? new ScriptInvokerFactory();
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Actions/TargetNotFoundTests.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Actions/TargetNotFoundTests.cs
deleted file mode 100644
index c2b62286..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Actions/TargetNotFoundTests.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using System;
-using CSF.Screenplay.Actors;
-using CSF.Screenplay.NUnit;
-using CSF.Screenplay.Selenium.Abilities;
-using CSF.Screenplay.Selenium.Builders;
-using CSF.Screenplay.Selenium.Models;
-using CSF.Screenplay.Selenium.Tests.Pages;
-using NUnit.Framework;
-using static CSF.Screenplay.StepComposer;
-
-namespace CSF.Screenplay.Selenium.Tests.Actions
-{
- [TestFixture]
- [Description("Behaviours when a target is not found for a desired action")]
- public class TargetNotFoundTests
- {
- [Test,Screenplay]
- [Description("Attempting to click on a link which does not exist raises an appropriate 'target not found' exception.")]
- public void Click_on_non_existent_element_raises_TargetNotFoundException(ICast cast, BrowseTheWeb browseTheWeb)
- {
- var joe = cast.Get("Joe");joe.IsAbleTo(browseTheWeb);
-
- Given(joe).WasAbleTo(OpenTheirBrowserOn.ThePage());
-
- Assert.That(() => When(joe).AttemptsTo(Click.On(ListsPage.ListOfItems)),
- Throws.TypeOf());
- }
-
- [Test,Screenplay]
- [Description("When a 'target not found' exception is raised, it should have a name which matches the missing target.")]
- public void TargetNotFoundException_raised_has_correct_target_name(ICast cast, BrowseTheWeb browseTheWeb)
- {
- var joe = cast.Get("Joe");joe.IsAbleTo(browseTheWeb);
-
- Given(joe).WasAbleTo(OpenTheirBrowserOn.ThePage());
-
- IHasTargetName target = null;
- try
- {
- When(joe).AttemptsTo(Click.On(ListsPage.ListOfItems));
- Assert.Fail("The action should raise an exception.");
- }
- catch(TargetNotFoundException ex)
- {
- target = ex.Target;
- }
- catch(Exception ex)
- {
- Assert.Fail($"Wrong exception type caught. Expected {nameof(TargetNotFoundException)}, got:\n{ex.ToString()}");
- }
-
- Assert.That(target, Is.Not.Null, "Target should not be null.");
- Assert.That(target.GetName(), Is.EqualTo(ListsPage.ListOfItems.GetName()), "Target has the correct name");
- }
-
- [Test,Screenplay]
- [Description("A 'target not found' exception should include the target name in its report when the target is provided.")]
- public void TargetNotFoundException_includes_target_name_in_report(ICast cast, BrowseTheWeb browseTheWeb)
- {
- var joe = cast.Get("Joe");joe.IsAbleTo(browseTheWeb);
- var ex = new TargetNotFoundException() { Target = ListsPage.ListOfItems };
-
- var result = ex.GetReport(joe);
-
- Assert.That(result, Is.EqualTo("Joe cannot see the list of items on the screen."));
- }
-
- [Test,Screenplay]
- [Description("A 'target not found' exception should include the target name in its report when the target is provided.")]
- public void TargetNotFoundException_can_create_a_report_without_target(ICast cast, BrowseTheWeb browseTheWeb)
- {
- var joe = cast.Get("Joe");joe.IsAbleTo(browseTheWeb);
- var ex = new TargetNotFoundException();
-
- var result = ex.GetReport(joe);
-
- Assert.That(result, Is.EqualTo("Joe cannot see the required element on the screen."));
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/DateInputPage.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Pages/DateInputPage.cs
deleted file mode 100644
index cfd399f6..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/DateInputPage.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// DateInputPage.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Tests.Pages
-{
- public class DateInputPage : Page
- {
- public override string GetName() => "the date-input page";
-
- public override IUriProvider GetUriProvider() => new AppUri("DateInput");
-
- public static ILocatorBasedTarget DateInput = new ElementId("DateInput", "the date input field");
-
- public static ILocatorBasedTarget DateOutput = new ElementId("DateOutput", "the date display");
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/ElementsWithAttributesPage.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Pages/ElementsWithAttributesPage.cs
deleted file mode 100644
index db45f496..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/ElementsWithAttributesPage.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// ElementsWithAttributesPage.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Tests.Pages
-{
- public class ElementsWithAttributesPage : Page
- {
- public override string GetName() => "the elements-with-attributes page";
-
- public override IUriProvider GetUriProvider() => new AppUri("ElementsWithAttributes");
-
- public static ILocatorBasedTarget DivWithClass = new ElementId("DivWithClass", "a div with a class attribute");
-
- public static ILocatorBasedTarget ClassOutput = new ElementId("DisplayDivClass", "the displayed class");
-
- public static ILocatorBasedTarget DateInput = new ElementId("DateInput", "the date input field");
-
- public static ILocatorBasedTarget DateOutput = new ElementId("DisplayDateReadonly", "the displayed date-readonly attribute");
-
- public static ILocatorBasedTarget TextInput = new ElementId("TextInput", "the text input field");
-
- public static ILocatorBasedTarget TextOutput = new ElementId("DisplayTextReadonly", "the displayed text-readonly attribute");
-
- public static ILocatorBasedTarget TextPlaceholder = new ElementId("DisplayTextPlaceholder", "the displayed text-placeholder attribute");
-
- public static ILocatorBasedTarget GetOutputButton = new ElementId("GetOutput", "the button which refreshes the outputs");
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/HomePage.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Pages/HomePage.cs
deleted file mode 100644
index 659b338b..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/HomePage.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Tests.Pages
-{
- public class HomePage : Page
- {
- public override string GetName() => "the app home page";
-
- public override IUriProvider GetUriProvider() => new AppUri("Home");
-
- public static ITarget SecondPageLink => new ClassName("second_page_link", "the hyperlink to page two");
-
- public static ITarget SlowLoadingLink => new ElementId("load_in_2_seconds", "the link to reload with a 2-second delay");
-
- public static ITarget LoadDelay => new ElementId("load_delay", "the readout of the page-load delay");
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/ListsPage.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Pages/ListsPage.cs
deleted file mode 100644
index f1ba4403..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/ListsPage.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// ListsPage.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Tests.Pages
-{
- public class ListsPage : Page
- {
- public override string GetName() => "the lists testing page";
-
- public override IUriProvider GetUriProvider() => new AppUri("Lists");
-
- public static ITarget SingleSelectionList => new CssSelector("#single_selection", "the single selection list");
-
- public static ITarget SingleSelectionValue => new CssSelector("#single_selected_value", "the single-selection value");
-
- public static ITarget MultiSelectionList => new CssSelector("#multiple_selection", "the multi selection list");
-
- public static ITarget MultiSelectionValue => new CssSelector("#multiple_selected_value", "the multi-selection value");
-
- public static ITarget ListOfItems => new CssSelector("#list_of_items", "the list of items");
-
- public static ILocatorBasedTarget ItemsInTheList => new CssSelector("#list_of_items li", "items in the list");
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/PageThree.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Pages/PageThree.cs
deleted file mode 100644
index 9d71c802..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/PageThree.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Tests.Pages
-{
- public class PageThree : Page
- {
- public override string GetName() => "page three";
-
- public override IUriProvider GetUriProvider() => new AppUri("PageThree");
-
- public static ITarget DelayedButtonOne => new CssSelector("#delay_click_one", "the first delay button");
-
- public static ITarget DelayedLinkOne => new CssSelector("#delay_appear_target_one .appeared", "the first delay-appearance link");
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/PageTwo.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Pages/PageTwo.cs
deleted file mode 100644
index ee3ed9b2..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/PageTwo.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Tests.Pages
-{
- public class PageTwo : Page
- {
- public override string GetName() => "the second page";
-
- public override IUriProvider GetUriProvider() => new AppUri("PageTwo");
-
- public static ILocatorBasedTarget SpecialInputField => new CssSelector(".special_text input", "the special input field");
-
- public static ITarget SecondTextbox => new CssSelector(".second_textbox input", "the second text box");
-
- public static ITarget TheDynamicTextArea => new ElementId("dynamic_value", "the dynamic value");
-
- public static ITarget JavaScriptResult => new ElementId("ScriptOutput", "the Javascript output");
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/ReadElementsPage.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Pages/ReadElementsPage.cs
deleted file mode 100644
index 269d69c3..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/ReadElementsPage.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// InputPage.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Tests.Pages
-{
- public class ReadElementsPage : Page
- {
- public override string GetName() => "the page for testing reading HTML elements";
-
- public override IUriProvider GetUriProvider() => new AppUri("ReadElements");
-
- public static ITarget ImportantString => new ElementId("important_string", "the string element");
-
- public static ITarget ImportantNumber => new ElementId("important_number", "the numeric element");
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/ScriptTestingHarness.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Pages/ScriptTestingHarness.cs
deleted file mode 100644
index 7881c6af..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Pages/ScriptTestingHarness.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// ScriptTestingHarness.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.Models;
-using CSF.Screenplay.Selenium.StoredScripts;
-
-namespace CSF.Screenplay.Selenium.Tests.Pages
-{
- public class ScriptTestingHarness : Page
- {
- readonly IProvidesScript scriptProvider;
-
- public override string GetName() => $"the Jasmine test harness for {scriptProvider.Name}";
-
- public override IUriProvider GetUriProvider()
- => new AppUri($"StoredScriptTest/Index/{scriptProvider.GetType().Name}");
-
- public static ILocatorBasedTarget TheResultsBar
- => new CssSelector(".jasmine_html-reporter .jasmine-bar", "the Jasmine results bar");
-
- public ScriptTestingHarness(IProvidesScript scriptProvider)
- {
- if(scriptProvider == null)
- throw new ArgumentNullException(nameof(scriptProvider));
-
- this.scriptProvider = scriptProvider;
- }
-
- public static ScriptTestingHarness For() where TScript : IProvidesScript, new()
- => new ScriptTestingHarness(new TScript());
-
- public static ScriptTestingHarness For(Type scriptType)
- => new ScriptTestingHarness((IProvidesScript) Activator.CreateInstance(scriptType));
-
- public static ScriptTestingHarness For(IProvidesScript script)
- => new ScriptTestingHarness(script);
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/ScriptResources/SetAnAttributeValueTests.cs b/Old/CSF.Screenplay.Selenium.Tests_old/ScriptResources/SetAnAttributeValueTests.cs
deleted file mode 100644
index 912c9324..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/ScriptResources/SetAnAttributeValueTests.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// SetAnAttributeValueTests.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.NUnit;
-using CSF.Screenplay.Selenium.Builders;
-using CSF.Screenplay.Selenium.Tests.Pages;
-using CSF.Screenplay.Selenium.Tests.Personas;
-using FluentAssertions;
-using NUnit.Framework;
-using static CSF.Screenplay.StepComposer;
-
-namespace CSF.Screenplay.Selenium.Tests.ScriptResources
-{
- [TestFixture,Description("Setting the value of an attribute using JavaScript")]
- public class SetAnAttributeValueTests
- {
- [Test,Screenplay,Description("Removing an attribute should result in successful removal")]
- public void Removing_an_attribute_should_remove_it(ICast cast)
- {
- var joe = cast.Get();
-
- Given(joe).WasAbleTo(OpenTheirBrowserOn.ThePage());
- var element = Given(joe).WasAbleTo(Get.TheElement(ElementsWithAttributesPage.TextInput));
-
- When(joe).AttemptsTo(Execute.JavaScript.WhichRemovesTheAttribute("readonly").From(element));
- When(joe).AttemptsTo(Click.On(ElementsWithAttributesPage.GetOutputButton));
-
- Then(joe).ShouldSee(TheText.Of(ElementsWithAttributesPage.TextOutput)).Should().Be(String.Empty);
- }
-
- [Test,Screenplay,Description("Removing an unrelated attribute should not affect the original")]
- public void Removing_a_disabled_attribute_should_not_the_readonly_attribute(ICast cast)
- {
- var joe = cast.Get();
-
- Given(joe).WasAbleTo(OpenTheirBrowserOn.ThePage());
- var element = Given(joe).WasAbleTo(Get.TheElement(ElementsWithAttributesPage.TextInput));
-
- When(joe).AttemptsTo(Execute.JavaScript.WhichRemovesTheAttribute("disabled").From(element));
- When(joe).AttemptsTo(Click.On(ElementsWithAttributesPage.GetOutputButton));
-
- Then(joe).ShouldSee(TheText.Of(ElementsWithAttributesPage.TextOutput)).Should().Be("readonly");
- }
-
- [Test,Screenplay,Description("Setting a previously-unset attribute should update its value")]
- public void Editing_an_attribute_should_set_it_to_the_new_value(ICast cast)
- {
- var joe = cast.Get();
-
- Given(joe).WasAbleTo(OpenTheirBrowserOn.ThePage());
- var element = Given(joe).WasAbleTo(Get.TheElement(ElementsWithAttributesPage.TextInput));
-
- When(joe).AttemptsTo(Execute.JavaScript.WhichSetsTheAttribute("placeholder").For(element).To("New placeholder"));
- When(joe).AttemptsTo(Click.On(ElementsWithAttributesPage.GetOutputButton));
-
- Then(joe).ShouldSee(TheText.Of(ElementsWithAttributesPage.TextPlaceholder)).Should().Be("New placeholder");
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/ScriptResources/SetAnElementValueTests.cs b/Old/CSF.Screenplay.Selenium.Tests_old/ScriptResources/SetAnElementValueTests.cs
deleted file mode 100644
index 2e744bf2..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/ScriptResources/SetAnElementValueTests.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// SetAnElementValueTests.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.NUnit;
-using CSF.Screenplay.Selenium.Builders;
-using CSF.Screenplay.Selenium.Tests.Pages;
-using CSF.Screenplay.Selenium.Tests.Personas;
-using FluentAssertions;
-using NUnit.Framework;
-using static CSF.Screenplay.StepComposer;
-
-namespace CSF.Screenplay.Selenium.Tests.ScriptResources
-{
- [TestFixture]
- [Description("The SetAnElementValue stored JavaScript")]
- public class SetAnElementValueTests
- {
- [Test,Screenplay,Description("Executing the script successfully sets the value of the element")]
- public void Executing_the_script_successfully_sets_the_value(ICast cast)
- {
- var joe = cast.Get();
-
- Given(joe).WasAbleTo(OpenTheirBrowserOn.ThePage());
- var theElement = Given(joe).WasAbleTo(Get.TheElement(PageTwo.SpecialInputField));
-
- When(joe).AttemptsTo(Execute.JavaScript.WhichSetsTheValueOf(theElement).To("The right value"));
-
- Then(joe).ShouldSee(TheText.Of(PageTwo.TheDynamicTextArea)).Should().Be("different value");
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/SampleScript.cs b/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/SampleScript.cs
deleted file mode 100644
index 96426a1e..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/SampleScript.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// SampleScript.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.StoredScripts;
-
-namespace CSF.Screenplay.Selenium.Tests.StoredScripts
-{
- public class SampleScript : ScriptResource
- {
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/SampleScript.js b/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/SampleScript.js
deleted file mode 100644
index 02f5bb61..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/SampleScript.js
+++ /dev/null
@@ -1,4 +0,0 @@
-function executeScript(argsArray)
-{
- window.console.log('Test');
-}
\ No newline at end of file
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/ScriptResourceTests.cs b/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/ScriptResourceTests.cs
deleted file mode 100644
index 86d9d9a7..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/ScriptResourceTests.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// ScriptResourceTests.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using NUnit.Framework;
-
-namespace CSF.Screenplay.Selenium.Tests.StoredScripts
-{
- [TestFixture]
- public class ScriptResourceTests
- {
- [Test]
- public void Sample_Script_has_correct_script_body()
- {
- // Arrange
- var expectedScript = @"function executeScript(argsArray)
-{
- window.console.log('Test');
-}";
- var sut = new SampleScript();
-
- // Act
- var actualScript = sut.GetScript();
-
- // Assert
- Assert.That(actualScript, Is.EqualTo(expectedScript));
- }
-
- [Test]
- public void Sample_Script_has_correct_entry_point_name()
- {
- // Arrange
- var expectedName = @"executeScript";
- var sut = new SampleScript();
-
- // Act
- var actualName = sut.GetEntryPointName();
-
- // Assert
- Assert.That(actualName, Is.EqualTo(expectedName));
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/ScriptRunnerTests.cs b/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/ScriptRunnerTests.cs
deleted file mode 100644
index 6c39d2cc..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/ScriptRunnerTests.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-//
-// ScriptRunnerTests.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.StoredScripts;
-using Moq;
-using NUnit.Framework;
-using OpenQA.Selenium;
-
-namespace CSF.Screenplay.Selenium.Tests.StoredScripts
-{
- [TestFixture]
- public class ScriptRunnerTests
- {
- [Test]
- public void ExecuteScript_passes_correct_script_to_webdriver()
- {
- // Arrange
- var script = Mock.Of();
- var driver = new Mock();
- driver.As();
- var invoker = Mock.Of(x => x.GetScript(It.IsAny()) == "return fooBar(argsArray);");
- var sut = new ScriptRunner(invoker);
-
- Mock.Get(script).Setup(x => x.GetScript()).Returns("function fooBar(argsArray) {}");
- Mock.Get(script).Setup(x => x.GetEntryPointName()).Returns("fooBar");
-
- var expectedExecutedScript = @"function fooBar(argsArray) {}
-return fooBar(argsArray);";
-
- // Act
- sut.ExecuteScript(script, driver.Object);
-
- // Assert
- driver
- .As()
- .Verify(x => x.ExecuteScript(expectedExecutedScript), Times.Once);
- }
-
- [Test]
- public void ExecuteScript_passes_correct_script_arguments_to_webdriver()
- {
- // Arrange
- var script = Mock.Of();
- var driver = new Mock();
- driver.As();
- var invoker = Mock.Of(x => x.GetScript(It.IsAny()) == String.Empty);
- var sut = new ScriptRunner(invoker);
-
- Mock.Get(script).Setup(x => x.GetScript()).Returns(String.Empty);
- Mock.Get(script).Setup(x => x.GetEntryPointName()).Returns(String.Empty);
-
- // Act
- sut.ExecuteScript(script, driver.Object, 1, 2, "three");
-
- // Assert
- driver
- .As()
- .Verify(x => x.ExecuteScript(It.IsAny(), 1, 2, "three"), Times.Once);
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/TestAllScriptsViaTestingHarness.cs b/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/TestAllScriptsViaTestingHarness.cs
deleted file mode 100644
index 4455e0c4..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/StoredScripts/TestAllScriptsViaTestingHarness.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// TestAllScriptsViaTestingHarness.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using CSF.Screenplay.NUnit;
-using CSF.Screenplay.Selenium.Tests.Personas;
-using CSF.Screenplay.Selenium.Tests.Tasks;
-using NUnit.Framework;
-using static CSF.Screenplay.StepComposer;
-
-namespace CSF.Screenplay.Selenium.Tests.StoredScripts
-{
- [TestFixture]
- [Description("The JavaScripts in the CSF.Screenplay.Selenium.JavaScriptWorkarounds project")]
- public class TestAllScriptsViaTestingHarness
- {
- [Test,Screenplay]
- [Description("Every script should pass a Jasmine test suite")]
- public void Every_script_in_the_main_assembly_must_pass_its_Jasmine_test_suite(ICast cast)
- {
- /* Please note that this single test scenario will test every available script using all of the
- * available Jasmine test suites. Those Jasmine tests themselves are not held within this project.
- *
- * They are all written using JavaScript and are found within the CSF.Screenplay.WebTestWebsite project,
- * at the path:
- * Scripts/script-tests/
- * Each class in the CSF.Screenplay.Selenium.JavaScriptWorkarounds project has its own test suite in that
- * directory, named after the name of its class, with the suffix 'tests.js'.
- *
- * If further JavaScript workarounds are added then each should have its own test suite in that path.
- */
- var joe = cast.Get();
-
- var scriptTypes = Given(joe).Got(AllOfTheExecutableScriptTypes.FromTheMainAssembly());
- var results = When(joe).Gets(AllOfTheScriptTestResults.ForTheScriptTypes(scriptTypes));
- Then(joe).Should(VerifyThatAllOfTheScriptTestsPassed.ForTheResults(results));
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/AllOfTheExecutableScriptTypes.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/AllOfTheExecutableScriptTypes.cs
deleted file mode 100644
index bd41e3ed..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/AllOfTheExecutableScriptTypes.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// GetAllOfTheScriptTypes.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using CSF.Screenplay.Actors;
-using CSF.Screenplay.Performables;
-using CSF.Screenplay.Selenium.ScriptResources;
-using CSF.Screenplay.Selenium.StoredScripts;
-
-namespace CSF.Screenplay.Selenium.Tests.Tasks
-{
- public class AllOfTheExecutableScriptTypes : Question>
- {
- protected override string GetReport(INamed actor)
- => $"{actor.Name} gets all of the executable script provider types from the main assembly.";
-
- protected override IReadOnlyCollection PerformAs(IPerformer actor)
- {
- var assembly = typeof(IProvidesScript).Assembly;
- return assembly.GetExportedTypes().Where(IsExecutableScriptType).ToArray();
- }
-
- bool IsExecutableScriptType(Type type)
- {
- if(!typeof(IProvidesScript).IsAssignableFrom(type)) return false;
- if(!type.IsClass || type.IsAbstract) return false;
- if(typeof(ICreatesInvocationScript).IsAssignableFrom(type)) return false;
- return true;
- }
-
- public static IQuestion> FromTheMainAssembly()
- => new AllOfTheExecutableScriptTypes();
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/AllOfTheScriptTestResults.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/AllOfTheScriptTestResults.cs
deleted file mode 100644
index 2f74dfaf..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/AllOfTheScriptTestResults.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// GetAllOfTheScriptTestResults.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using CSF.Screenplay.Actors;
-using CSF.Screenplay.Performables;
-
-namespace CSF.Screenplay.Selenium.Tests.Tasks
-{
- public class AllOfTheScriptTestResults : Question>
- {
- readonly IReadOnlyCollection types;
-
- protected override string GetReport(INamed actor) => $"{actor.Name} runs all of the Jasmine script tests and gets their results";
-
- protected override IReadOnlyCollection PerformAs(IPerformer actor)
- => GetResults(actor).ToArray();
-
- IEnumerable GetResults(IPerformer actor)
- {
- foreach(var type in types)
- yield return actor.Perform(TestTheStoredScript.OfType(type));
- }
-
- public AllOfTheScriptTestResults(IReadOnlyCollection types)
- {
- if(types == null)
- throw new ArgumentNullException(nameof(types));
-
- this.types = types;
- }
-
- public static IQuestion> ForTheScriptTypes(IReadOnlyCollection types)
- => new AllOfTheScriptTestResults(types);
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/EnterTextIntoThePageTwoInputField.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/EnterTextIntoThePageTwoInputField.cs
deleted file mode 100644
index 461246b3..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/EnterTextIntoThePageTwoInputField.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System;
-using CSF.Screenplay.Actors;
-using CSF.Screenplay.Performables;
-using CSF.Screenplay.Selenium.Builders;
-using CSF.Screenplay.Selenium.Tests.Pages;
-
-namespace CSF.Screenplay.Selenium.Tests.Tasks
-{
- public class EnterTextIntoThePageTwoInputField : Performable
- {
- readonly string text;
-
- protected override string GetReport(INamed actor)
- => $"{actor.Name} enters '{text}' into the input field on page two";
-
- protected override void PerformAs(IPerformer actor)
- {
- actor.Perform(OpenTheirBrowserOn.ThePage());
- actor.Perform(Enter.TheText(text).Into(PageTwo.SpecialInputField));
- }
-
- public EnterTextIntoThePageTwoInputField(string text)
- {
- if(text == null)
- throw new ArgumentNullException(nameof(text));
-
- this.text = text;
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/EnterTheDateTests.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/EnterTheDateTests.cs
deleted file mode 100644
index 0a9145f6..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/EnterTheDateTests.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System;
-using CSF.Screenplay.Actors;
-using CSF.Screenplay.NUnit;
-using CSF.Screenplay.Selenium.Abilities;
-using CSF.Screenplay.Selenium.Builders;
-using CSF.Screenplay.Selenium.Tests.Pages;
-using CSF.Screenplay.Selenium.Tests.Personas;
-using FluentAssertions;
-using NUnit.Framework;
-using static CSF.Screenplay.StepComposer;
-
-namespace CSF.Screenplay.Selenium.Tests.Tasks
-{
- [TestFixture]
- [Description("Entering dates")]
- public class EnterTheDateTests
- {
- [Test,Screenplay]
- [Description("Entering a date into an HTML 5 input field should work cross-browser")]
- public void Enter_TheDate_puts_the_correct_value_into_the_control(ICast cast, BrowseTheWeb browseTheWeb)
- {
- var joe = cast.Get();
-
- var date = new DateTime(2012, 5, 6);
- var expectedString = date.ToString("yyyy-MM-dd");
-
- Given(joe).WasAbleTo(OpenTheirBrowserOn.ThePage());
-
- When(joe).AttemptsTo(Enter.TheDate(date).Into(DateInputPage.DateInput));
-
- Then(joe).ShouldSee(TheText.Of(DateInputPage.DateOutput))
- .Should()
- .Be(expectedString, because: "the displayed date should match");
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/ScriptTestResult.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/ScriptTestResult.cs
deleted file mode 100644
index 46a4371f..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/ScriptTestResult.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// ScriptTestResult.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.StoredScripts;
-
-namespace CSF.Screenplay.Selenium.Tests.Tasks
-{
- public class ScriptTestResult
- {
- public IProvidesScript Script { get; }
-
- public bool Success { get; }
-
- public ScriptTestResult(IProvidesScript script, bool result)
- {
- if(script == null)
- throw new ArgumentNullException(nameof(script));
-
- Script = script;
- Success = result;
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/TestTheStoredScript.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/TestTheStoredScript.cs
deleted file mode 100644
index 7f4ef0a8..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/TestTheStoredScript.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-//
-// TestTheStoredScript.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using System.Text.RegularExpressions;
-using CSF.Screenplay.Actors;
-using CSF.Screenplay.Performables;
-using CSF.Screenplay.Selenium.Builders;
-using CSF.Screenplay.Selenium.StoredScripts;
-using CSF.Screenplay.Selenium.Tests.Pages;
-
-namespace CSF.Screenplay.Selenium.Tests.Tasks
-{
- public class TestTheStoredScript : Question
- {
- const string JasminePassedClassPattern = @"\bjasmine-passed\b";
- static readonly Regex PassMatcher = new Regex(JasminePassedClassPattern, RegexOptions.Compiled);
-
- readonly IProvidesScript script;
-
- protected override string GetReport(INamed actor)
- => $"{actor.Name} gets the result for {script.Name}";
-
- protected override ScriptTestResult PerformAs(IPerformer actor)
- {
- var theTestPage = ScriptTestingHarness.For(script);
- actor.Perform(OpenTheirBrowserOn.ThePage(theTestPage));
-
- actor.Perform(Wait.ForAtMost(5).Seconds().OrUntil(ScriptTestingHarness.TheResultsBar).IsVisible());
-
- var classAttribute = actor.Perform(TheAttribute.Named("class").From(ScriptTestingHarness.TheResultsBar));
- var testsPassed = PassMatcher.IsMatch(classAttribute);
-
- return new ScriptTestResult(script, testsPassed);
- }
-
- public TestTheStoredScript(IProvidesScript script)
- {
- if(script == null)
- throw new ArgumentNullException(nameof(script));
-
- this.script = script;
- }
-
- public static IQuestion OfType(Type scriptType)
- => new TestTheStoredScript(GetTheScript(scriptType));
-
- static IProvidesScript GetTheScript(Type theScriptType)
- => (IProvidesScript) Activator.CreateInstance(theScriptType);
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/VerifyThatAllOfTheScriptTestsPassed.cs b/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/VerifyThatAllOfTheScriptTestsPassed.cs
deleted file mode 100644
index 147ba33f..00000000
--- a/Old/CSF.Screenplay.Selenium.Tests_old/Tasks/VerifyThatAllOfTheScriptTestsPassed.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// VerifyThatAllOfTheScriptTestsPassed.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using CSF.Screenplay.Actors;
-using CSF.Screenplay.Performables;
-using NUnit.Framework;
-
-namespace CSF.Screenplay.Selenium.Tests.Tasks
-{
- public class VerifyThatAllOfTheScriptTestsPassed : Performable
- {
- readonly IReadOnlyCollection results;
-
- protected override string GetReport(INamed actor)
- => $"{actor.Name} verifies that all of the script tests were successful";
-
- protected override void PerformAs(IPerformer actor)
- {
- var failures = results.Where(x => !x.Success).ToArray();
-
- Assert.That(failures,
- Has.Length.Zero,
- "The following scripts failed testing:{0} {1}",
- Environment.NewLine,
- String.Join($"{Environment.NewLine} ", failures.Select(x => x.Script.Name).ToArray()));
- }
-
- public VerifyThatAllOfTheScriptTestsPassed(IReadOnlyCollection results)
- {
- if(results == null)
- throw new ArgumentNullException(nameof(results));
-
- this.results = results;
- }
-
- public static IPerformable ForTheResults(IReadOnlyCollection results)
- => new VerifyThatAllOfTheScriptTestsPassed(results);
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Builders/Clear.cs b/Old/CSF.Screenplay.Selenium_old/Builders/Clear.cs
deleted file mode 100644
index e4c21eec..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Builders/Clear.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System;
-using CSF.Screenplay.Performables;
-using CSF.Screenplay.Selenium.Actions;
-using CSF.Screenplay.Selenium.Models;
-using CSF.Screenplay.Selenium.Tasks;
-
-namespace CSF.Screenplay.Selenium.Builders
-{
- ///
- /// Builds an action which clears contents from editable areas of the page.
- ///
- public class Clear
- {
- ///
- /// Clears the contents of a user-editable HTML element, such as an input element.
- ///
- /// A performable action.
- /// The target from which to clear the value.
- public static IPerformable TheContentsOf(ITarget target)
- => new TargettedAction(target, new ClearTheContents());
-
- ///
- /// Clears the contents of an HTML <input type="date"> element.
- ///
- /// A performable action.
- /// The target from which to clear the date.
- public static IPerformable TheDateFrom(ITarget target)
- => new ClearTheDate(target);
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Builders/Enter.cs b/Old/CSF.Screenplay.Selenium_old/Builders/Enter.cs
deleted file mode 100644
index 3b1f5d4c..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Builders/Enter.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-using CSF.Screenplay.Performables;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Builders
-{
- ///
- /// Builds an action representing an actor entering text into a page element.
- ///
- public class Enter
- {
- readonly string val;
- readonly DateTime? date;
-
- ///
- /// The actor enters the text into a given .
- ///
- /// A performable action instance.
- /// Target.
- public IPerformable Into(ITarget target)
- {
- if(date.HasValue)
- return new Tasks.EnterTheDate(date.Value, target);
-
- return new Actions.TargettedAction(target, new Actions.Enter(val));
- }
-
- ///
- /// Indicates the text that the actor is to enter.
- ///
- /// A builder instance accepting further configuration.
- /// The text to be entered.
- public static Enter TheText(string val)
- {
- return new Enter(val);
- }
-
- ///
- /// Indicates a date that the actor is to enter.
- ///
- /// A builder instance accepting further configuration.
- /// The date to be entered.
- public static Enter TheDate(DateTime date)
- {
- return new Enter(date);
- }
-
- Enter(string val)
- {
- if(val == null)
- throw new ArgumentNullException(nameof(val));
-
- this.val = val;
- }
-
- Enter(DateTime date)
- {
- this.date = date;
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Builders/GetALocalisedDateScriptExtensions.cs b/Old/CSF.Screenplay.Selenium_old/Builders/GetALocalisedDateScriptExtensions.cs
deleted file mode 100644
index 33236362..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Builders/GetALocalisedDateScriptExtensions.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// StoredScriptBuilderExtensions.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.Actions;
-using CSF.Screenplay.Selenium.ScriptResources;
-
-namespace CSF.Screenplay.Selenium.Builders
-{
- ///
- /// Extension methods for a , related to building performables which use the
- /// JavaScript.
- ///
- public static class GetALocalisedDateScriptExtensions
- {
- ///
- /// Gets a performable which represents an invocation of the JavaScript, using the
- /// given parameters.
- ///
- /// The JavaScript question performable.
- /// Builder.
- /// The date.
- public static IPerformableJavaScriptWithResult WhichGetsALocaleFormattedVersionOf(this ExecuteJavaScriptBuilder builder,
- DateTime date)
- {
- if(builder == null)
- throw new ArgumentNullException(nameof(builder));
-
- int
- year = date.Year,
- // Months in JavaScript start with zero, because reasons
- month = date.Month - 1,
- day = date.Day;
-
- return builder.AsPerformableBuilder.BuildQuestion(year, month, day);
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Builders/GetDocumentReadyStateExtensions.cs b/Old/CSF.Screenplay.Selenium_old/Builders/GetDocumentReadyStateExtensions.cs
deleted file mode 100644
index 40c925f1..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Builders/GetDocumentReadyStateExtensions.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// GetDocumentReadyStateExtensions.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.Actions;
-using CSF.Screenplay.Selenium.ScriptResources;
-
-namespace CSF.Screenplay.Selenium.Builders
-{
- ///
- /// Extension methods for a , related to building performables which use the
- /// JavaScript.
- ///
- public static class GetDocumentReadyStateExtensions
- {
- ///
- /// Gets a performable which represents an invocation of the JavaScript.
- ///
- /// The JavaScript question performable.
- /// Builder.
- public static IPerformableJavaScriptWithResult WhichGetsTheDocumentReadyState(this ExecuteJavaScriptBuilder builder)
- {
- if(builder == null)
- throw new ArgumentNullException(nameof(builder));
-
- return builder.AsPerformableBuilder.BuildQuestion();
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Builders/SetAnElementAttributeExtensions.cs b/Old/CSF.Screenplay.Selenium_old/Builders/SetAnElementAttributeExtensions.cs
deleted file mode 100644
index a0fc5011..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Builders/SetAnElementAttributeExtensions.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-//
-// SetAnElementAttributeExtensions.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.Actions;
-using CSF.Screenplay.Selenium.Models;
-using CSF.Screenplay.Selenium.ScriptResources;
-
-namespace CSF.Screenplay.Selenium.Builders
-{
- ///
- /// Extension methods for a , related to building performables which use the
- /// JavaScript.
- ///
- public static class SetAnElementAttributeExtensions
- {
- ///
- /// Gets a performable which represents an invocation of the JavaScript to
- /// remove a given attribute from an element.
- ///
- /// The JavaScript question performable.
- /// Builder.
- /// The attribute name.
- public static RemoveAttributeBuilder WhichRemovesTheAttribute(this ExecuteJavaScriptBuilder builder,
- string name)
- {
- return new RemoveAttributeBuilder(builder, name);
- }
-
- ///
- /// Gets a performable which represents an invocation of the JavaScript to
- /// set a given attribute upon an element to a new value.
- ///
- /// The JavaScript question performable.
- /// Builder.
- /// The attribute name.
- public static ChooseElementBuilder WhichSetsTheAttribute(this ExecuteJavaScriptBuilder builder,
- string name)
- {
- return new ChooseElementBuilder(builder, name);
- }
-
- ///
- /// Builder for an action which removes an attribute.
- ///
- public class RemoveAttributeBuilder
- {
- readonly string attributeName;
- readonly ExecuteJavaScriptBuilder builder;
-
- ///
- /// Choose the element from which to remove the attribute.
- ///
- /// Element.
- public IPerformableJavaScript From(IWebElementAdapter element)
- {
- return builder.AsPerformableBuilder.BuildAction(element.GetUnderlyingElement(),
- attributeName,
- null);
- }
-
- internal RemoveAttributeBuilder(ExecuteJavaScriptBuilder builder, string attributeName)
- {
- if(builder == null)
- throw new ArgumentNullException(nameof(builder));
- if(attributeName == null)
- throw new ArgumentNullException(nameof(attributeName));
-
- this.builder = builder;
- this.attributeName = attributeName;
- }
- }
-
- ///
- /// Builder for an action which alters an attribute value.
- ///
- public class ChooseElementBuilder
- {
- readonly string attributeName;
- readonly ExecuteJavaScriptBuilder builder;
-
- ///
- /// Choose the element for which to set the attribute.
- ///
- /// Element.
- public ChooseNewValueBuilder For(IWebElementAdapter element)
- {
- return new ChooseNewValueBuilder(builder, attributeName, element);
- }
-
- internal ChooseElementBuilder(ExecuteJavaScriptBuilder builder, string attributeName)
- {
- if(builder == null)
- throw new ArgumentNullException(nameof(builder));
- if(attributeName == null)
- throw new ArgumentNullException(nameof(attributeName));
-
- this.builder = builder;
- this.attributeName = attributeName;
- }
- }
-
- ///
- /// Builder for an action which alters an attribute value.
- ///
- public class ChooseNewValueBuilder
- {
- readonly string attributeName;
- readonly ExecuteJavaScriptBuilder builder;
- readonly IWebElementAdapter element;
-
- ///
- /// Choose the new value for the attribute.
- ///
- /// New value.
- public IPerformableJavaScript To(string newValue)
- {
- return builder.AsPerformableBuilder.BuildAction(element.GetUnderlyingElement(),
- attributeName,
- newValue);
- }
-
- internal ChooseNewValueBuilder(ExecuteJavaScriptBuilder builder, string attributeName, IWebElementAdapter element)
- {
- if(element == null)
- throw new ArgumentNullException(nameof(element));
- if(builder == null)
- throw new ArgumentNullException(nameof(builder));
- if(attributeName == null)
- throw new ArgumentNullException(nameof(attributeName));
-
- this.builder = builder;
- this.attributeName = attributeName;
- this.element = element;
- }
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Builders/SetAnElementValueExtensions.cs b/Old/CSF.Screenplay.Selenium_old/Builders/SetAnElementValueExtensions.cs
deleted file mode 100644
index 92b3912c..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Builders/SetAnElementValueExtensions.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// SetAnElementValueExtensions.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.Actions;
-using CSF.Screenplay.Selenium.Models;
-using CSF.Screenplay.Selenium.ScriptResources;
-
-namespace CSF.Screenplay.Selenium.Builders
-{
- ///
- /// Extension methods for a , related to building performables which use the
- /// JavaScript.
- ///
- public static class SetAnElementValueExtensions
- {
- ///
- /// Gets a builder which assists in the creation of the performable. In this method call, the target of the
- /// value-setting operation is decided.
- ///
- /// The set-element-value builder.
- /// Builder.
- /// The target element, which is to have its value set.
- public static SetAnElementValueBuilder WhichSetsTheValueOf(this ExecuteJavaScriptBuilder builder,
- IWebElementAdapter element)
- {
- if(builder == null)
- throw new ArgumentNullException(nameof(builder));
- if(element == null)
- throw new ArgumentNullException(nameof(element));
-
- return new SetAnElementValueBuilder(builder, element);
- }
-
- ///
- /// A builder type which creates a performable which uses the JavaScript.
- ///
- public class SetAnElementValueBuilder
- {
- readonly IWebElementAdapter element;
- readonly ExecuteJavaScriptBuilder builder;
-
- ///
- /// Gets the performable action from the new value to set into the element's 'value' property.
- ///
- /// The new value.
- public IPerformableJavaScript To(object value)
- {
- var webElement = element.GetUnderlyingElement();
- return builder.AsPerformableBuilder.BuildAction(webElement, value);
- }
-
- internal SetAnElementValueBuilder(ExecuteJavaScriptBuilder builder, IWebElementAdapter element)
- {
- if(builder == null)
- throw new ArgumentNullException(nameof(builder));
- if(element == null)
- throw new ArgumentNullException(nameof(element));
-
- this.builder = builder;
- this.element = element;
- }
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Builders/UpdateSelectElementSelectionExtensions.cs b/Old/CSF.Screenplay.Selenium_old/Builders/UpdateSelectElementSelectionExtensions.cs
deleted file mode 100644
index 1628ba13..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Builders/UpdateSelectElementSelectionExtensions.cs
+++ /dev/null
@@ -1,138 +0,0 @@
-//
-// UpdateSelectElementSelectionExtensions.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Selenium.Actions;
-using CSF.Screenplay.Selenium.Models;
-using CSF.Screenplay.Selenium.ScriptResources;
-using static CSF.Screenplay.Selenium.ScriptResources.UpdateSelectElementSelection;
-
-namespace CSF.Screenplay.Selenium.Builders
-{
- ///
- /// Extension methods for a , related to building performables which use the
- /// JavaScript.
- ///
- public static class UpdateSelectElementSelectionExtensions
- {
- ///
- /// Creates a builder for selecting a single option within an HTML <select> element.
- ///
- /// The builder.
- /// A JavaScript execution builder.
- /// Element.
- public static OptionChoiceBuilder WhichSelectsTheOptionFrom(this ExecuteJavaScriptBuilder builder,
- IWebElementAdapter element)
- {
- return new OptionChoiceBuilder(builder, element, true);
- }
-
- ///
- /// Creates a builder for deselecting a single option within an HTML <select> element.
- ///
- /// The builder.
- /// A JavaScript execution builder.
- /// Element.
- public static OptionChoiceBuilder WhichDeselectsTheOptionFrom(this ExecuteJavaScriptBuilder builder,
- IWebElementAdapter element)
- {
- return new OptionChoiceBuilder(builder, element, false);
- }
-
- ///
- /// Creates a performable action for deselecting every option from an HTML <select> element.
- ///
- /// The builder.
- /// A JavaScript execution builder.
- /// Element.
- public static IPerformableJavaScript WhichDeselectsEverythingFrom(this ExecuteJavaScriptBuilder builder,
- IWebElementAdapter element)
- {
- var jsBuilder = builder.AsPerformableBuilder;
- return jsBuilder.BuildAction(element.GetUnderlyingElement(), DeselectAllActionName);
- }
-
- ///
- /// A builder type for choosing a single option element.
- ///
- public class OptionChoiceBuilder
- {
- readonly IWebElementAdapter element;
- readonly bool select;
- readonly ExecuteJavaScriptBuilder builder;
-
- ///
- /// Chooses an option by its zero-based index and returns a performable JavaScript object
- ///
- /// A performable JavaScript.
- /// Index.
- public IPerformableJavaScript ByIndex(int index)
- {
- var actionName = select? SelectByIndexActionName : DeselectByIndexActionName;
- return BuildAction(actionName, index);
- }
-
- ///
- /// Chooses an option by its underlying value and returns a performable JavaScript object
- ///
- /// A performable JavaScript.
- /// Value.
- public IPerformableJavaScript ByValue(string value)
- {
- var actionName = select? SelectByValueActionName : DeselectByValueActionName;
- return BuildAction(actionName, value);
- }
-
- ///
- /// Chooses an option by its displayed text and returns a performable JavaScript object
- ///
- /// A performable JavaScript.
- /// Text.
- public IPerformableJavaScript ByText(string text)
- {
- var actionName = select? SelectByTextActionName : DeselectByTextActionName;
- return BuildAction(actionName, text);
- }
-
- IPerformableJavaScript BuildAction(string actionName, object actionValue)
- {
- var jsBuilder = builder.AsPerformableBuilder;
- return jsBuilder.BuildAction(element.GetUnderlyingElement(), actionName, actionValue);
- }
-
- internal OptionChoiceBuilder(ExecuteJavaScriptBuilder builder, IWebElementAdapter element, bool select)
- {
- if(builder == null)
- throw new ArgumentNullException(nameof(builder));
- if(element == null)
- throw new ArgumentNullException(nameof(element));
-
- this.builder = builder;
- this.element = element;
- this.select = select;
- }
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/CSF.Selenium.Support.UI/CHANGELOG b/Old/CSF.Screenplay.Selenium_old/CSF.Selenium.Support.UI/CHANGELOG
deleted file mode 100644
index 3f5d60b0..00000000
--- a/Old/CSF.Screenplay.Selenium_old/CSF.Selenium.Support.UI/CHANGELOG
+++ /dev/null
@@ -1,8 +0,0 @@
-The file SelectElement.cs is copied directly from the Selenium support
-repository as of tag v3.4.0. Minor changes have been made in order to make
-it easier to subclass.
-
-The original file may be found (as it appeared at the time of
-copying) in its repository at:
-
- https://github.com/SeleniumHQ/selenium/blob/selenium-3.4.0/dotnet/src/support/UI/SelectElement.cs
\ No newline at end of file
diff --git a/Old/CSF.Screenplay.Selenium_old/CSF.Selenium.Support.UI/NOTICE b/Old/CSF.Screenplay.Selenium_old/CSF.Selenium.Support.UI/NOTICE
deleted file mode 100644
index ea6a613d..00000000
--- a/Old/CSF.Screenplay.Selenium_old/CSF.Selenium.Support.UI/NOTICE
+++ /dev/null
@@ -1,5 +0,0 @@
-This notice file applies ONLY to files within the namespace CSF.Selenium.Support.UI
-
-Some portions copyright 2018 CSF Software Limited
-Copyright 2011-2016 Software Freedom Conservancy
-Copyright 2004-2011 Selenium committers
\ No newline at end of file
diff --git a/Old/CSF.Screenplay.Selenium_old/CSF.Selenium.Support.UI/SelectElement.cs b/Old/CSF.Screenplay.Selenium_old/CSF.Selenium.Support.UI/SelectElement.cs
deleted file mode 100644
index 43d1de17..00000000
--- a/Old/CSF.Screenplay.Selenium_old/CSF.Selenium.Support.UI/SelectElement.cs
+++ /dev/null
@@ -1,501 +0,0 @@
-//
-// SelectElement.cs
-//
-// Author:
-// Various Selenium authors
-// Screenplay modifications: Craig Fowler
-//
-// This file began its life as a copy of the following:
-// https://github.com/SeleniumHQ/selenium/blob/selenium-3.4.0/dotnet/src/support/UI/SelectElement.cs
-//
-// The original file is copyright 2011-2016 [various authors].
-// Further modifications are copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Text;
-using OpenQA.Selenium;
-using OpenQA.Selenium.Internal;
-using OpenQA.Selenium.Support.UI;
-
-namespace CSF.Selenium.Support.UI
-{
- ///
- /// Provides a convenience method for manipulating selections of options in an HTML select element.
- ///
- public class SelectElement : IWrapsElement
- {
- #region fields
-
- readonly IWebElement element;
-
- #endregion
-
- #region properties
-
- ///
- /// Gets the wrapped by this object.
- ///
- public IWebElement WrappedElement
- {
- get { return this.element; }
- }
-
- ///
- /// Gets a value indicating whether the parent element supports multiple selections.
- ///
- public bool IsMultiple { get; private set; }
-
- ///
- /// Gets the list of options for the select element.
- ///
- public IList Options
- {
- get
- {
- return this.element.FindElements(By.TagName("option"));
- }
- }
-
- ///
- /// Gets the selected item within the select element.
- ///
- /// If more than one item is selected this will return the first item.
- /// Thrown if no option is selected.
- public IWebElement SelectedOption
- {
- get
- {
- foreach (IWebElement option in this.Options)
- {
- if (option.Selected)
- {
- return option;
- }
- }
-
- throw new NoSuchElementException("No option is selected");
- }
- }
-
- ///
- /// Gets all of the selected options within the select element.
- ///
- public IList AllSelectedOptions
- {
- get
- {
- List returnValue = new List();
- foreach (IWebElement option in this.Options)
- {
- if (option.Selected)
- {
- returnValue.Add(option);
- }
- }
-
- return returnValue;
- }
- }
-
- #endregion
-
- #region methods
-
- ///
- /// Select all options by the text displayed.
- ///
- /// The text of the option to be selected. If an exact match is not found,
- /// this method will perform a substring match.
- /// When given "Bar" this method would select an option like:
- ///
- /// <option value="foo">Bar</option>
- ///
- ///
- /// Thrown if there is no element with the given text present.
- public void SelectByText(string text)
- {
- if (text == null)
- {
- throw new ArgumentNullException("text", "text must not be null");
- }
-
- // try to find the option via XPATH ...
- IList options = this.element.FindElements(By.XPath(".//option[normalize-space(.) = " + EscapeQuotes(text) + "]"));
-
- bool matched = false;
- foreach (IWebElement option in options)
- {
- SetSelected(option, true);
- if (!this.IsMultiple)
- {
- return;
- }
-
- matched = true;
- }
-
- if (options.Count == 0 && text.Contains(" "))
- {
- string substringWithoutSpace = GetLongestSubstringWithoutSpace(text);
- IList candidates;
- if (string.IsNullOrEmpty(substringWithoutSpace))
- {
- // hmm, text is either empty or contains only spaces - get all options ...
- candidates = this.element.FindElements(By.TagName("option"));
- }
- else
- {
- // get candidates via XPATH ...
- candidates = this.element.FindElements(By.XPath(".//option[contains(., " + EscapeQuotes(substringWithoutSpace) + ")]"));
- }
-
- foreach (IWebElement option in candidates)
- {
- if (text == option.Text)
- {
- SetSelected(option, true);
- if (!this.IsMultiple)
- {
- return;
- }
-
- matched = true;
- }
- }
- }
-
- if (!matched)
- {
- throw new NoSuchElementException("Cannot locate element with text: " + text);
- }
- }
-
- ///
- /// Select an option by the value.
- ///
- /// The value of the option to be selected.
- /// When given "foo" this method will select an option like:
- ///
- /// <option value="foo">Bar</option>
- ///
- ///
- /// Thrown when no element with the specified value is found.
- public void SelectByValue(string value)
- {
- StringBuilder builder = new StringBuilder(".//option[@value = ");
- builder.Append(EscapeQuotes(value));
- builder.Append("]");
- IList options = this.element.FindElements(By.XPath(builder.ToString()));
-
- bool matched = false;
- foreach (IWebElement option in options)
- {
- SetSelected(option, true);
- if (!this.IsMultiple)
- {
- return;
- }
-
- matched = true;
- }
-
- if (!matched)
- {
- throw new NoSuchElementException("Cannot locate option with value: " + value);
- }
- }
-
- ///
- /// Select the option by the index, as determined by the "index" attribute of the element.
- ///
- /// The value of the index attribute of the option to be selected.
- /// Thrown when no element exists with the specified index attribute.
- public void SelectByIndex(int index)
- {
- string match = index.ToString(CultureInfo.InvariantCulture);
-
- foreach (IWebElement option in this.Options)
- {
- if (option.GetAttribute("index") == match)
- {
- SetSelected(option, true);
- return;
- }
- }
-
- throw new NoSuchElementException("Cannot locate option with index: " + index);
- }
-
- ///
- /// Clear all selected entries. This is only valid when the SELECT supports multiple selections.
- ///
- /// Thrown when attempting to deselect all options from a SELECT
- /// that does not support multiple selections.
- public void DeselectAll()
- {
- if (!this.IsMultiple)
- {
- throw new InvalidOperationException("You may only deselect all options if multi-select is supported");
- }
-
- foreach (IWebElement option in this.Options)
- {
- SetSelected(option, false);
- }
- }
-
- ///
- /// Deselect the option by the text displayed.
- ///
- /// Thrown when attempting to deselect option from a SELECT
- /// that does not support multiple selections.
- /// Thrown when no element exists with the specified test attribute.
- /// The text of the option to be deselected.
- /// When given "Bar" this method would deselect an option like:
- ///
- /// <option value="foo">Bar</option>
- ///
- ///
- public void DeselectByText(string text)
- {
- if (!this.IsMultiple)
- {
- throw new InvalidOperationException("You may only deselect option if multi-select is supported");
- }
-
- bool matched = false;
- StringBuilder builder = new StringBuilder(".//option[normalize-space(.) = ");
- builder.Append(EscapeQuotes(text));
- builder.Append("]");
- IList options = this.element.FindElements(By.XPath(builder.ToString()));
- foreach (IWebElement option in options)
- {
- SetSelected(option, false);
- matched = true;
- }
-
- if (!matched)
- {
- throw new NoSuchElementException("Cannot locate option with text: " + text);
- }
- }
-
- ///
- /// Deselect the option having value matching the specified text.
- ///
- /// Thrown when attempting to deselect option from a SELECT
- /// that does not support multiple selections.
- /// Thrown when no element exists with the specified value attribute.
- /// The value of the option to deselect.
- /// When given "foo" this method will deselect an option like:
- ///
- /// <option value="foo">Bar</option>
- ///
- ///
- public void DeselectByValue(string value)
- {
- if (!this.IsMultiple)
- {
- throw new InvalidOperationException("You may only deselect option if multi-select is supported");
- }
-
- bool matched = false;
- StringBuilder builder = new StringBuilder(".//option[@value = ");
- builder.Append(EscapeQuotes(value));
- builder.Append("]");
- IList options = this.element.FindElements(By.XPath(builder.ToString()));
- foreach (IWebElement option in options)
- {
- SetSelected(option, false);
- matched = true;
- }
-
- if (!matched)
- {
- throw new NoSuchElementException("Cannot locate option with value: " + value);
- }
- }
-
- ///
- /// Deselect the option by the index, as determined by the "index" attribute of the element.
- ///
- /// Thrown when attempting to deselect option from a SELECT
- /// that does not support multiple selections.
- /// Thrown when no element exists with the specified index attribute.
- /// The value of the index attribute of the option to deselect.
- public void DeselectByIndex(int index)
- {
- if (!this.IsMultiple)
- {
- throw new InvalidOperationException("You may only deselect option if multi-select is supported");
- }
-
- string match = index.ToString(CultureInfo.InvariantCulture);
- foreach (IWebElement option in this.Options)
- {
- if (match == option.GetAttribute("index"))
- {
- SetSelected(option, false);
- return;
- }
- }
-
- throw new NoSuchElementException("Cannot locate option with index: " + index);
- }
-
- ///
- /// Sets the selected state of the given option.
- ///
- /// The option element for which to set selection state.
- /// If set to true then the state will be set to 'selected'; if false then deselected.
- protected virtual void SetSelected(IWebElement option, bool select)
- {
- if(option == null)
- throw new ArgumentNullException(nameof(option));
-
- bool isSelected = option.Selected;
- if ((!isSelected && select) || (isSelected && !select))
- {
- ToggleSelectedState(option);
- }
- }
-
- ///
- /// Toggles the selected/deselected state of the given option element.
- ///
- /// The option element for which to toggle the selection state.
- protected virtual void ToggleSelectedState(IWebElement option)
- {
- if(option == null)
- throw new ArgumentNullException(nameof(option));
-
- option.Click();
- }
-
- #endregion
-
- #region constructor
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The element to be wrapped
- /// Thrown when the object is
- /// Thrown when the element wrapped is not a <select> element.
- public SelectElement(IWebElement element)
- {
- if (element == null)
- {
- throw new ArgumentNullException("element", "element cannot be null");
- }
-
- if (string.IsNullOrEmpty(element.TagName) || string.Compare(element.TagName, "select", StringComparison.OrdinalIgnoreCase) != 0)
- {
- throw new UnexpectedTagNameException("select", element.TagName);
- }
-
- this.element = element;
-
- // let check if it's a multiple
- string attribute = element.GetAttribute("multiple");
- this.IsMultiple = attribute != null && attribute.ToLowerInvariant() != "false";
- }
-
- #endregion
-
- #region static methods
-
- static string EscapeQuotes(string toEscape)
- {
- // Convert strings with both quotes and ticks into: foo'"bar -> concat("foo'", '"', "bar")
- if (toEscape.IndexOf("\"", StringComparison.OrdinalIgnoreCase) > -1 && toEscape.IndexOf("'", StringComparison.OrdinalIgnoreCase) > -1)
- {
- bool quoteIsLast = false;
- if (toEscape.LastIndexOf("\"", StringComparison.OrdinalIgnoreCase) == toEscape.Length - 1)
- {
- quoteIsLast = true;
- }
-
- List substrings = new List(toEscape.Split('\"'));
- if (quoteIsLast && string.IsNullOrEmpty(substrings[substrings.Count - 1]))
- {
- // If the last character is a quote ('"'), we end up with an empty entry
- // at the end of the list, which is unnecessary. We don't want to split
- // ignoring *all* empty entries, since that might mask legitimate empty
- // strings. Instead, just remove the empty ending entry.
- substrings.RemoveAt(substrings.Count - 1);
- }
-
- StringBuilder quoted = new StringBuilder("concat(");
- for (int i = 0; i < substrings.Count; i++)
- {
- quoted.Append("\"").Append(substrings[i]).Append("\"");
- if (i == substrings.Count - 1)
- {
- if (quoteIsLast)
- {
- quoted.Append(", '\"')");
- }
- else
- {
- quoted.Append(")");
- }
- }
- else
- {
- quoted.Append(", '\"', ");
- }
- }
-
- return quoted.ToString();
- }
-
- // Escape string with just a quote into being single quoted: f"oo -> 'f"oo'
- if (toEscape.IndexOf("\"", StringComparison.OrdinalIgnoreCase) > -1)
- {
- return string.Format(CultureInfo.InvariantCulture, "'{0}'", toEscape);
- }
-
- // Otherwise return the quoted string
- return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", toEscape);
- }
-
- static string GetLongestSubstringWithoutSpace(string s)
- {
- string result = string.Empty;
- string[] substrings = s.Split(' ');
- foreach (string substring in substrings)
- {
- if (substring.Length > result.Length)
- {
- result = substring;
- }
- }
-
- return result;
- }
-
- #endregion
-
- }
-}
\ No newline at end of file
diff --git a/Old/CSF.Screenplay.Selenium_old/CSF.Selenium.Support.UI/SelectElementUsingModifierKey.cs b/Old/CSF.Screenplay.Selenium_old/CSF.Selenium.Support.UI/SelectElementUsingModifierKey.cs
deleted file mode 100644
index 244304e4..00000000
--- a/Old/CSF.Screenplay.Selenium_old/CSF.Selenium.Support.UI/SelectElementUsingModifierKey.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// SelectElementUsingModifierKey.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using OpenQA.Selenium;
-using OpenQA.Selenium.Interactions;
-
-namespace CSF.Selenium.Support.UI
-{
- ///
- /// Specialisation of which makes use of a modifier key in order to
- /// toggle the selection state of an option inside the select element when that select element
- /// allows multiple options to be selected.
- ///
- ///
- ///
- /// Recent browsers are now requiring ctrl-click or command-click in order to toggle the selection
- /// of a single option. This enables that behaviour.
- ///
- ///
- /// It works around the issue described at: https://github.com/SeleniumHQ/selenium/issues/4490
- ///
- ///
- public class SelectElementUsingModifierKey : SelectElement
- {
- readonly string modifierKey;
- readonly IWebDriver driver;
-
- ///
- /// Toggles the selected/deselected state of the given option element.
- ///
- /// The option element for which to toggle the selection state.
- protected override void ToggleSelectedState(IWebElement option)
- {
- if(!IsMultiple)
- {
- base.ToggleSelectedState(option);
- return;
- }
-
- new Actions(driver)
- .KeyDown(modifierKey)
- .Click(option)
- .KeyUp(modifierKey)
- .Perform();
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Element.
- /// Modifier key.
- /// Driver.
- public SelectElementUsingModifierKey(IWebElement element, string modifierKey, IWebDriver driver) : base(element)
- {
- if(driver == null)
- throw new ArgumentNullException(nameof(driver));
- if(modifierKey == null)
- throw new ArgumentNullException(nameof(modifierKey));
-
- this.driver = driver;
- this.modifierKey = modifierKey;
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/FlagsDefinitionProvider.cs b/Old/CSF.Screenplay.Selenium_old/FlagsDefinitionProvider.cs
deleted file mode 100644
index 9514757b..00000000
--- a/Old/CSF.Screenplay.Selenium_old/FlagsDefinitionProvider.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using CSF.WebDriverExtras.Flags;
-
-namespace CSF.Screenplay.Selenium
-{
- ///
- /// Implementation of which provides flags definitions from two sources:
- /// The definitions compiled into the CSF.Screenplay.Selenium.BrowserFlags assembly and also any
- /// optionally definitions found in a collection of definitions file paths passed in the constructor.
- ///
- public class FlagsDefinitionProvider : IProvidesFlagsDefinitions
- {
- readonly IReadsFlagsDefinitions definitionReader;
- readonly IReadOnlyCollection extraDefinitionFilePaths;
- readonly Encoding fileEncoding;
-
- ///
- /// Gets the flags definitions.
- ///
- /// The flags definitions.
- public IReadOnlyCollection GetFlagsDefinitions()
- {
- var baseDefinitions = GetBrowserFlagsDefinitions.FromDefinitionsAssembly();
- var fileDefinitions = extraDefinitionFilePaths.SelectMany(x => ReadDefinitionsFromFile(x));
-
- return baseDefinitions.Union(fileDefinitions).ToArray();
- }
-
- IReadOnlyCollection ReadDefinitionsFromFile(string filePath)
- {
- Stream stream = null;
-
- try
- {
- stream = File.OpenRead(filePath);
- return ReadDefinitionsFromFileStream(stream, filePath);
- }
- // In any of these exception cases, where we can't open the file, drop the error to the console and skip the file
- catch(PathTooLongException ex) { return GetBadDefinitionsFileResult(ex, filePath); }
- catch(DirectoryNotFoundException ex) { return GetBadDefinitionsFileResult(ex, filePath); }
- catch(UnauthorizedAccessException ex) { return GetBadDefinitionsFileResult(ex, filePath); }
- catch(FileNotFoundException ex) { return GetBadDefinitionsFileResult(ex, filePath); }
- catch(IOException ex) { return GetBadDefinitionsFileResult(ex, filePath); }
- // And finally clean up the stream
- finally
- {
- if(stream != null)
- stream.Dispose();
- stream = null;
- }
- }
-
- IReadOnlyCollection ReadDefinitionsFromFileStream(Stream stream, string filePath)
- {
- try
- {
- return definitionReader.GetFlagsDefinitions(stream);
- }
- catch(Exception ex)
- {
- Console.Error.WriteLine("WARNING: Skipped browser flags definition file '{0}' because reading the file raised an exception:{1}{2}",
- filePath,
- Environment.NewLine,
- ex);
-
- return new FlagsDefinition[0];
- }
- }
-
- IReadOnlyCollection GetBadDefinitionsFileResult(Exception ex, string filePath)
- {
- Console.Error.WriteLine("WARNING: Skipped browser flags definition file '{0}' because opening the file raised an exception:{1}{2}",
- filePath,
- Environment.NewLine,
- ex);
-
- return new FlagsDefinition[0];
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// An optional collection of file paths, each of which contains one or more JSON flags definitions.
- public FlagsDefinitionProvider(params string[] extraDefinitionFilePaths)
- : this(Encoding.UTF8, extraDefinitionFilePaths) { }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The file encoding for externally-provided definitions files.
- /// An optional collection of file paths, each of which contains one or more JSON flags definitions.
- public FlagsDefinitionProvider(Encoding fileEncoding, params string[] extraDefinitionFilePaths)
- {
- if(fileEncoding == null)
- throw new ArgumentNullException(nameof(fileEncoding));
-
- this.fileEncoding = fileEncoding;
- this.extraDefinitionFilePaths = extraDefinitionFilePaths ?? new string[0];
- this.definitionReader = new DefinitionReader();
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Tasks/ClearTheDate.cs b/Old/CSF.Screenplay.Selenium_old/Tasks/ClearTheDate.cs
deleted file mode 100644
index 93ce153d..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Tasks/ClearTheDate.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-//
-// ClearTheDateField.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Actors;
-using CSF.Screenplay.Performables;
-using CSF.Screenplay.Selenium.Abilities;
-using CSF.Screenplay.Selenium.Builders;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Tasks
-{
- ///
- /// A task which clears the value from an HTML <input type="date"> element.
- ///
- ///
- ///
- /// This is required because web browsers which have the flag
- /// cannot use the 'normal'
- /// mechanism to clear the value of a date field. This task abstracts around browsers that can or can't do
- /// that and uses a JavaScript workaround to clear dates when the browser couldn't otherwise do it.
- ///
- ///
- public class ClearTheDate : Performable
- {
- readonly ITarget target;
-
- ///
- /// Gets the report of the current instance, for the given actor.
- ///
- /// The human-readable report text.
- /// An actor for whom to write the report.
- protected override string GetReport(INamed actor) => $"{actor.Name} clears the date from {target.GetName()}";
-
- ///
- /// Performs this operation, as the given actor.
- ///
- /// The actor performing this task.
- protected override void PerformAs(IPerformer actor)
- {
- var browseTheWeb = actor.GetAbility();
-
- if(browseTheWeb.FlagsDriver.HasFlag(Flags.HtmlElements.InputTypeDate.RequiresInputViaJavaScriptWorkaround))
- actor.Perform(ClearTheTargetUsingAJavaScriptWorkaround(browseTheWeb));
- else
- actor.Perform(Clear.TheContentsOf(target));
- }
-
- IPerformable ClearTheTargetUsingAJavaScriptWorkaround(BrowseTheWeb browseTheWeb)
- {
- var webElement = target.GetWebElementAdapter(browseTheWeb);
- return Execute.JavaScript.WhichSetsTheValueOf(webElement).To(String.Empty);
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Target.
- public ClearTheDate(ITarget target)
- {
- if(target == null)
- throw new ArgumentNullException(nameof(target));
-
- this.target = target;
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Tasks/EnterTheDate.cs b/Old/CSF.Screenplay.Selenium_old/Tasks/EnterTheDate.cs
deleted file mode 100644
index 498d8cf9..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Tasks/EnterTheDate.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-using System;
-using CSF.Screenplay.Actors;
-using CSF.Screenplay.Performables;
-using CSF.Screenplay.Selenium.Abilities;
-using CSF.Screenplay.Selenium.Builders;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Tasks
-{
- ///
- /// A task which enters a date value into an input element (of type "date") in a cross-browser manner.
- ///
- public class EnterTheDate : Performable
- {
- readonly DateTime date;
- readonly ITarget target;
-
- ///
- /// Gets the report of the current instance, for the given actor.
- ///
- /// The human-readable report text.
- /// An actor for whom to write the report.
- protected override string GetReport(INamed actor)
- => $"{actor.Name} enters the date {date.ToString("yyyy-MM-dd")} into {target.GetName()}";
-
- ///
- /// Performs this operation, as the given actor.
- ///
- /// The actor performing this task.
- protected override void PerformAs(IPerformer actor)
- {
- var browseTheWeb = actor.GetAbility();
-
- if(browseTheWeb.FlagsDriver.HasFlag(Flags.HtmlElements.InputTypeDate.RequiresEntryUsingLocaleFormat))
- actor.Perform(EnterTheDateInLocaleFormat());
- else if(browseTheWeb.FlagsDriver.HasFlag(Flags.HtmlElements.InputTypeDate.RequiresInputViaJavaScriptWorkaround))
- actor.Perform(EnterTheDateViaAJavaScriptWorkaround());
- else
- actor.Perform(EnterTheDateInIsoFormat());
- }
-
- IPerformable EnterTheDateInLocaleFormat()
- => new EnterTheDateIntoAnHtml5InputTypeDate(date, target);
-
- IPerformable EnterTheDateInIsoFormat()
- => new EnterTheDateAsAnIsoFormattedString(date, target);
-
- IPerformable EnterTheDateViaAJavaScriptWorkaround()
- => new SetTheDateUsingAJavaScriptWorkaround(date, target);
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Date.
- /// Target.
- public EnterTheDate(DateTime date, ITarget target)
- {
- if(target == null)
- throw new ArgumentNullException(nameof(target));
-
- this.date = date;
- this.target = target;
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Tasks/EnterTheDateAsAnIsoFormattedString.cs b/Old/CSF.Screenplay.Selenium_old/Tasks/EnterTheDateAsAnIsoFormattedString.cs
deleted file mode 100644
index b9efb63b..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Tasks/EnterTheDateAsAnIsoFormattedString.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System;
-using CSF.Screenplay.Actors;
-using CSF.Screenplay.Performables;
-using CSF.Screenplay.Selenium.Builders;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Tasks
-{
- ///
- /// A task which enters a date as a plain ISO-formatted yyyy-MM-dd string into a plain
- /// text control. This may be used as a fallback for web browsers which do not fully support HTML 5 input
- /// type="date" elements.
- ///
- public class EnterTheDateAsAnIsoFormattedString : Performable
- {
- readonly DateTime date;
- readonly ITarget target;
-
- ///
- /// Gets the report of the current instance, for the given actor.
- ///
- /// The human-readable report text.
- /// An actor for whom to write the report.
- protected override string GetReport(INamed actor)
- => $"{actor.Name} enters the date {date.ToString("yyyy-MM-dd")} into {target.GetName()} as an ISO-formatted string";
-
- ///
- /// Performs this operation, as the given actor.
- ///
- /// The actor performing this task.
- protected override void PerformAs(IPerformer actor)
- {
- actor.Perform(Clear.TheContentsOf(target));
- actor.Perform(Enter.TheText(date.ToString("yyyy-MM-dd")).Into(target));
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Date.
- /// Target.
- public EnterTheDateAsAnIsoFormattedString(DateTime date, ITarget target)
- {
- if(target == null)
- throw new ArgumentNullException(nameof(target));
-
- this.date = date;
- this.target = target;
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Tasks/EnterTheDateIntoAnHtml5InputTypeDate.cs b/Old/CSF.Screenplay.Selenium_old/Tasks/EnterTheDateIntoAnHtml5InputTypeDate.cs
deleted file mode 100644
index 743a4004..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Tasks/EnterTheDateIntoAnHtml5InputTypeDate.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-using System;
-using System.Text.RegularExpressions;
-using CSF.Screenplay.Actors;
-using CSF.Screenplay.Performables;
-using CSF.Screenplay.Selenium.Builders;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Tasks
-{
- ///
- /// A task which manages the inputting of a date value into an HTML 5 <input type="date" /> element
- /// as a locale-formatted string.
- ///
- public class EnterTheDateIntoAnHtml5InputTypeDate : Performable
- {
- const string
- Numbers = @"\d+",
- NonNumericCharacters = @"\D";
- static readonly Regex
- NumberMatcher = new Regex(Numbers, RegexOptions.Compiled),
- NonNumericStripper = new Regex(NonNumericCharacters, RegexOptions.Compiled);
-
- readonly DateTime date;
- readonly ITarget target;
-
- ///
- /// Gets the report of the current instance, for the given actor.
- ///
- /// The human-readable report text.
- /// An actor for whom to write the report.
- protected override string GetReport(INamed actor)
- => $"{actor.Name} enters the date {date.ToString("yyyy-MM-dd")} into {target.GetName()} using the current locale's format";
-
- ///
- /// Performs this operation, as the given actor.
- ///
- /// The actor performing this task.
- protected override void PerformAs(IPerformer actor)
- {
- var localeFormattedDate = actor.Perform(GetTheLocaleFormattedDate());
- var keysToPress = GetTheKeysToPress(localeFormattedDate);
- actor.Perform(Enter.TheText(keysToPress).Into(target));
- }
-
- IQuestion GetTheLocaleFormattedDate()
- => new GetTheLocaleFormattedDate(date);
-
- string GetTheKeysToPress(string formattedDate)
- {
- var zeroPaddedFormattedDate = GetZeroPaddedFormattedDate(formattedDate);
- return NonNumericStripper.Replace(zeroPaddedFormattedDate, String.Empty);
- }
-
- string GetZeroPaddedFormattedDate(string formattedDate)
- {
- return NumberMatcher.Replace(formattedDate, match => {
- if(match.Length > 1)
- return match.Value;
-
- return String.Concat("0", match.Value);
- });
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Date.
- /// Target.
- public EnterTheDateIntoAnHtml5InputTypeDate(DateTime date, ITarget target)
- {
- if(target == null)
- throw new ArgumentNullException(nameof(target));
-
- this.date = date;
- this.target = target;
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Tasks/GetTheLocaleFormattedDate.cs b/Old/CSF.Screenplay.Selenium_old/Tasks/GetTheLocaleFormattedDate.cs
deleted file mode 100644
index c4922da6..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Tasks/GetTheLocaleFormattedDate.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using System;
-using CSF.Screenplay.Actors;
-using CSF.Screenplay.Performables;
-using CSF.Screenplay.Selenium.Builders;
-using CSF.Screenplay.Selenium.ScriptResources;
-
-namespace CSF.Screenplay.Selenium.Tasks
-{
- ///
- /// A task which gets the representation of a System.DateTime in a format compatible with the web browser's
- /// current localisation.
- ///
- public class GetTheLocaleFormattedDate : Question
- {
- readonly DateTime date;
-
- ///
- /// Gets the report of the current instance, for the given actor.
- ///
- /// The human-readable report text.
- /// An actor for whom to write the report.
- protected override string GetReport(INamed actor)
- => $"{actor.Name} gets the locale-formatted representation of the date {date.ToString("yyyy-MM-dd")}";
-
- ///
- /// Performs this operation, as the given actor.
- ///
- /// The response or result.
- /// The actor performing this task.
- protected override string PerformAs(IPerformer actor)
- {
- return (string) actor.Perform(Execute.JavaScript.WhichGetsALocaleFormattedVersionOf(date));
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Date.
- public GetTheLocaleFormattedDate(DateTime date)
- {
- this.date = date;
- }
- }
-}
diff --git a/Old/CSF.Screenplay.Selenium_old/Tasks/SetTheDateUsingAJavaScriptWorkaround.cs b/Old/CSF.Screenplay.Selenium_old/Tasks/SetTheDateUsingAJavaScriptWorkaround.cs
deleted file mode 100644
index 6ad92c20..00000000
--- a/Old/CSF.Screenplay.Selenium_old/Tasks/SetTheDateUsingAJavaScriptWorkaround.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-//
-// SetTheDateUsingAJavaScriptWorkaround.cs
-//
-// Author:
-// Craig Fowler
-//
-// Copyright (c) 2018 Craig Fowler
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using CSF.Screenplay.Performables;
-using CSF.Screenplay.Selenium.Abilities;
-using CSF.Screenplay.Selenium.Builders;
-using CSF.Screenplay.Selenium.Models;
-
-namespace CSF.Screenplay.Selenium.Tasks
-{
- ///
- /// Sets the value of an HTML <input type="date"> element, using a JavaScript workaround.
- ///
- public class SetTheDateUsingAJavaScriptWorkaround : Performable
- {
- readonly DateTime date;
- readonly ITarget target;
-
- ///
- /// Gets the report of the current instance, for the given actor.
- ///
- /// The human-readable report text.
- /// An actor for whom to write the report.
- protected override string GetReport(Actors.INamed actor)
- => $"{actor.Name} enters the date {date.ToString("yyyy-MM-dd")} into {target.GetName()} using a JavaScript workaround";
-
- ///
- /// Performs this operation, as the given actor.
- ///
- /// The actor performing this task.
- protected override void PerformAs(Actors.IPerformer actor)
- {
- var browseTheWeb = actor.GetAbility();
- var webElement = target.GetWebElementAdapter(browseTheWeb);
-
- actor.Perform(Execute.JavaScript.WhichSetsTheValueOf(webElement).To(date.ToString("yyyy-MM-dd")));
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Date.
- /// Target.
- public SetTheDateUsingAJavaScriptWorkaround(DateTime date, ITarget target)
- {
- if(target == null)
- throw new ArgumentNullException(nameof(target));
-
- this.date = date;
- this.target = target;
- }
- }
-}
diff --git a/Old/README.md b/Old/README.md
deleted file mode 100644
index f21b3673..00000000
--- a/Old/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Old content
-
-This old content is kept just as reference, for a few features which are not yet migrated to v2.0.0.
-Before v2.0.0 is released, this whole directory should be deleted.
diff --git a/Tests/CSF.Screenplay.Selenium.Tests/Actions/ClickTests.cs b/Tests/CSF.Screenplay.Selenium.Tests/Actions/ClickTests.cs
index 973e32a1..c00fd9d8 100644
--- a/Tests/CSF.Screenplay.Selenium.Tests/Actions/ClickTests.cs
+++ b/Tests/CSF.Screenplay.Selenium.Tests/Actions/ClickTests.cs
@@ -1,4 +1,5 @@
+using CSF.Screenplay.Performables;
using CSF.Screenplay.Selenium.Elements;
using static CSF.Screenplay.PerformanceStarter;
using static CSF.Screenplay.Selenium.PerformableBuilder;
@@ -10,6 +11,7 @@ public class ClickTests
{
static readonly ITarget
clickableButton = new ElementId("clickable", "the clickable button"),
+ nonExistent = new ElementId("nope", "the non-existent element"),
displayText = new ElementId("display", "the displayable text");
static readonly NamedUri testPage = new NamedUri("ClickTests.html", "the test page");
@@ -25,4 +27,31 @@ public async Task ClickingAButtonShouldTriggerAnEvent(IStage stage)
Assert.That(contents, Is.EqualTo("Clicked!"));
}
+
+ [Test, Screenplay]
+ public async Task ClickingAnElementWhichDoesNotExistShouldThrow(IStage stage)
+ {
+ var webster = stage.Spotlight();
+
+ await Given(webster).WasAbleTo(OpenTheUrl(testPage));
+ Assert.That(async () => await When(webster).AttemptsTo(ClickOn(nonExistent)),
+ Throws.InstanceOf().And.InnerException.InstanceOf());
+ }
+
+ [Test, Screenplay]
+ public async Task ClickingAnElementWhichDoesNotExistShouldIncludeTheCorrectTargetInTheException(IStage stage)
+ {
+ var webster = stage.Spotlight();
+
+ await Given(webster).WasAbleTo(OpenTheUrl(testPage));
+ try
+ {
+ await When(webster).AttemptsTo(ClickOn(nonExistent));
+ Assert.Fail("Should have thrown an exception!");
+ }
+ catch(PerformableException e) when (e is { InnerException: TargetNotFoundException tnfEx })
+ {
+ Assert.That(tnfEx.Target, Has.Property(nameof(ITarget.Name)).EqualTo("the non-existent element"));
+ }
+ }
}
\ No newline at end of file
diff --git a/Tests/CSF.Screenplay.Selenium.Tests/Actions/OpenUrlTests.cs b/Tests/CSF.Screenplay.Selenium.Tests/Actions/OpenUrlTests.cs
index b7e514b6..e3d65372 100644
--- a/Tests/CSF.Screenplay.Selenium.Tests/Actions/OpenUrlTests.cs
+++ b/Tests/CSF.Screenplay.Selenium.Tests/Actions/OpenUrlTests.cs
@@ -38,20 +38,20 @@ public async Task OpenTheUrlWithDifferentBasePathShouldYieldDifferentContent(ISt
}
[Test, AutoMoqData]
- public async Task PerformAsAsyncShouldThrowIfTheUrlIsNotAbsolute(Actor actor,
+ public void PerformAsAsyncShouldThrowIfTheUrlIsNotAbsolute(Actor actor,
[MockDriver] BrowseTheWeb ability)
{
actor.IsAbleTo(ability);
var sut = new OpenUrl(new NamedUri("foo/bar/baz.html"));
- Assert.That(() => sut.PerformAsAsync(actor), Throws.InstanceOf());
+ Assert.That(async () => await sut.PerformAsAsync(actor), Throws.InstanceOf());
}
[Test, AutoMoqData]
- public async Task PerformAsAsyncShouldNotThrowIfTheUrlIsAbsolute(Actor actor,
- [MockDriver] BrowseTheWeb ability)
+ public void PerformAsAsyncShouldNotThrowIfTheUrlIsAbsolute(Actor actor,
+ [MockDriver] BrowseTheWeb ability)
{
actor.IsAbleTo(ability);
var sut = new OpenUrl(new NamedUri("https://example.com/foo/bar/baz.html"));
- Assert.That(() => sut.PerformAsAsync(actor), Throws.Nothing);
+ Assert.That(async () => await sut.PerformAsAsync(actor), Throws.Nothing);
}
}
\ No newline at end of file
diff --git a/Tests/CSF.Screenplay.Selenium.Tests/Actions/SetTheElementValueTests.cs b/Tests/CSF.Screenplay.Selenium.Tests/Actions/SetTheElementValueTests.cs
new file mode 100644
index 00000000..e8b076f3
--- /dev/null
+++ b/Tests/CSF.Screenplay.Selenium.Tests/Actions/SetTheElementValueTests.cs
@@ -0,0 +1,47 @@
+using CSF.Screenplay.Performables;
+using CSF.Screenplay.Selenium.Elements;
+using Moq;
+using OpenQA.Selenium;
+using static CSF.Screenplay.Selenium.PerformableBuilder;
+
+namespace CSF.Screenplay.Selenium.Actions;
+
+[TestFixture, Parallelizable]
+public class SetTheElementValueTests
+{
+ [Test, AutoMoqData]
+ public async Task PerformAsAsyncShouldUseTheSimulatedInteractiveScriptIfApplicable([MockDriver] BrowseTheWeb browseTheWeb,
+ object value,
+ Actor actor,
+ ITarget target,
+ SeleniumElement element)
+ {
+ actor.IsAbleTo(browseTheWeb);
+ Mock.Get(target).Setup(x => x.GetElement(browseTheWeb.WebDriver)).Returns(element);
+
+ var sut = SetTheValueOf(target).To(value).AsIfSetInteractively();
+ await sut.PerformAsAsync(actor);
+
+ Mock.Get(browseTheWeb.WebDriver)
+ .As()
+ .Verify(x => x.ExecuteScript(Scripts.SetElementValueSimulatedInteractively.ScriptBody, element.WebElement, value));
+ }
+
+ [Test, AutoMoqData]
+ public async Task PerformAsAsyncShouldUseTheNonInteractiveScriptInteractiveNotRequested([MockDriver] BrowseTheWeb browseTheWeb,
+ object value,
+ Actor actor,
+ ITarget target,
+ SeleniumElement element)
+ {
+ actor.IsAbleTo(browseTheWeb);
+ Mock.Get(target).Setup(x => x.GetElement(browseTheWeb.WebDriver)).Returns(element);
+
+ var sut = ((IGetsPerformable) SetTheValueOf(target).To(value)).GetPerformable();
+ await sut.PerformAsAsync(actor);
+
+ Mock.Get(browseTheWeb.WebDriver)
+ .As()
+ .Verify(x => x.ExecuteScript(Scripts.SetElementValue.ScriptBody, element.WebElement, value));
+ }
+}
\ No newline at end of file
diff --git a/Tests/CSF.Screenplay.Selenium.Tests/MockDriverAttribute.cs b/Tests/CSF.Screenplay.Selenium.Tests/MockDriverAttribute.cs
index dae743ba..20bcb1b9 100644
--- a/Tests/CSF.Screenplay.Selenium.Tests/MockDriverAttribute.cs
+++ b/Tests/CSF.Screenplay.Selenium.Tests/MockDriverAttribute.cs
@@ -3,6 +3,7 @@
using CSF.Extensions.WebDriver;
using CSF.Extensions.WebDriver.Factories;
using Moq;
+using OpenQA.Selenium;
namespace CSF.Screenplay.Selenium;
@@ -16,6 +17,11 @@ public class MockDriverCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
+ fixture.Customize(c =>
+ {
+ return c
+ .FromFactory(() => (IWebDriver) new Mock().As().Object);
+ });
fixture.Customize(c => c.FromFactory((WebDriverAndOptions d) => Mock.Of(m => m.GetDefaultWebDriver(null) == d
&& m.GetWebDriver(It.IsAny(), null) == d)));
fixture.Customize(c => c.FromFactory((IGetsWebDriver d) => new BrowseTheWeb(d)));
diff --git a/Tests/CSF.Screenplay.Selenium.Tests/ScreenplayFactory.cs b/Tests/CSF.Screenplay.Selenium.Tests/ScreenplayFactory.cs
index 5fde4d84..24912094 100644
--- a/Tests/CSF.Screenplay.Selenium.Tests/ScreenplayFactory.cs
+++ b/Tests/CSF.Screenplay.Selenium.Tests/ScreenplayFactory.cs
@@ -12,15 +12,10 @@ public Screenplay GetScreenplay()
var screenplay = Screenplay.Create(services =>
{
services.AddSingleton(GetConfiguration());
- services.AddWebDriverFactory();
services.AddLogging(l => l.AddConsole(c => c.LogToStandardErrorThreshold = LogLevel.Warning));
-
+ services.AddSelenium();
services.AddTransient();
services.AddTransient();
- }, options =>
- {
- options.ValueFormatters.Add(typeof(Reporting.OptionsFormatter));
- options.ValueFormatters.Add(typeof(Reporting.ScreenshotFormatter));
});
return screenplay;
diff --git a/Tests/CSF.Screenplay.Selenium.Tests/Tasks/ClickAndWaitForDocumentReadyTests.cs b/Tests/CSF.Screenplay.Selenium.Tests/Tasks/ClickAndWaitForDocumentReadyTests.cs
index f11f401f..7420f833 100644
--- a/Tests/CSF.Screenplay.Selenium.Tests/Tasks/ClickAndWaitForDocumentReadyTests.cs
+++ b/Tests/CSF.Screenplay.Selenium.Tests/Tasks/ClickAndWaitForDocumentReadyTests.cs
@@ -16,8 +16,6 @@ static readonly ITarget
link = new ElementId("clickable"),
displayText = new ElementId("textContent");
- static readonly string[] ignoredBrowsers = ["chrome", "MicrosoftEdge"];
-
[Test, Screenplay]
public async Task PerformAsAsyncShouldWaitSoItCanGetTheAppropriateContent(IStage stage)
{
@@ -36,7 +34,7 @@ public async Task PerformAsAsyncShouldThrowIfWeDontWaitLongEnough(IStage stage)
var webster = stage.Spotlight();
var ability = webster.GetAbility();
- if(ignoredBrowsers.Contains(ability.DriverOptions.BrowserName))
+ if(!ability.WebDriver.HasQuirk(BrowserQuirks.NeedsToWaitAfterPageLoad))
Assert.Pass("This test cannot meaningfully be run on a Chrome or Edge browser, because they always wait for the page load. Treating this test as an implicit pass.");
await Given(webster).WasAbleTo(OpenTheUrl(startPage));
diff --git a/Tests/CSF.Screenplay.Selenium.Tests/Tasks/EnterTheDateTests.cs b/Tests/CSF.Screenplay.Selenium.Tests/Tasks/EnterTheDateTests.cs
index 08cbb1fb..1be82a05 100644
--- a/Tests/CSF.Screenplay.Selenium.Tests/Tasks/EnterTheDateTests.cs
+++ b/Tests/CSF.Screenplay.Selenium.Tests/Tasks/EnterTheDateTests.cs
@@ -1,6 +1,8 @@
using System;
using System.Globalization;
+using System.Linq;
using CSF.Screenplay.Selenium.Elements;
+using OpenQA.Selenium;
using static CSF.Screenplay.PerformanceStarter;
using static CSF.Screenplay.Selenium.PerformableBuilder;
@@ -47,6 +49,11 @@ public async Task EnteringADateInAnUnusualCultureShouldYieldIncorrectResults(ISt
if(CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern.StartsWith("y", StringComparison.InvariantCultureIgnoreCase))
Assert.Inconclusive("This test can't be meaningfully run when the current culture uses Y/M/D date formatting");
+ var ability = webster.GetAbility();
+
+ if(ability.WebDriver.HasQuirk(BrowserQuirks.CannotSetInputTypeDateWithSendKeys))
+ Assert.Pass("This test cannot meaningfully be run on a browser which requires a JS workaround to set dates. Treating this test as an implicit pass.");
+
await Given(webster).WasAbleTo(OpenTheUrl(testPage));
await When(webster).AttemptsTo(EnterTheDate(new DateTime(2025, 11, 12)).Into(inputArea).ForTheCultureNamed("ja-JP"));
var result = await Then(webster).Should(ReadFromTheElement(displayText).TheText());
diff --git a/Tests/CSF.Screenplay.Tests/CSF.Screenplay.Tests.csproj b/Tests/CSF.Screenplay.Tests/CSF.Screenplay.Tests.csproj
index 09f16731..89c5a653 100644
--- a/Tests/CSF.Screenplay.Tests/CSF.Screenplay.Tests.csproj
+++ b/Tests/CSF.Screenplay.Tests/CSF.Screenplay.Tests.csproj
@@ -18,7 +18,7 @@
-
+
diff --git a/Tests/CSF.Screenplay.Tests/DefaultScreenplayCustomization.cs b/Tests/CSF.Screenplay.Tests/DefaultScreenplayCustomization.cs
index 2e375640..e2e4cff4 100644
--- a/Tests/CSF.Screenplay.Tests/DefaultScreenplayCustomization.cs
+++ b/Tests/CSF.Screenplay.Tests/DefaultScreenplayCustomization.cs
@@ -1,4 +1,5 @@
using AutoFixture;
+using Microsoft.Extensions.DependencyInjection;
namespace CSF.Screenplay;
@@ -6,6 +7,6 @@ public class DefaultScreenplayCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
- fixture.Customize(c => c.FromFactory(() => Screenplay.Create(options: o => o.ReportPath = null)));
+ fixture.Customize(c => c.FromFactory(() => Screenplay.Create(s => s.Configure(o => o.ReportPath = null))));
}
}
\ No newline at end of file
diff --git a/Tests/CSF.Screenplay.Tests/ScreenplayExtensionsTests.cs b/Tests/CSF.Screenplay.Tests/ScreenplayExtensionsTests.cs
index c661674b..80c5a30c 100644
--- a/Tests/CSF.Screenplay.Tests/ScreenplayExtensionsTests.cs
+++ b/Tests/CSF.Screenplay.Tests/ScreenplayExtensionsTests.cs
@@ -65,7 +65,7 @@ public void ExecuteAsPerformanceShouldThrowIfTheTaskTakesTooLong([DefaultScreenp
[Test,AutoMoqData]
public void ExecuteAsPerformanceGenericShouldExecuteThePerformanceHostLogic()
{
- var sut = Screenplay.Create(s => s.AddSingleton(), o => o.ReportPath = null);
+ var sut = Screenplay.Create(s => s.AddSingleton().Configure(o => o.ReportPath = null));
sut.ExecuteAsPerformanceAsync();