diff --git a/.appveyor.yml b/.appveyor.yml
index fa45fc94..6f18d6fa 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -21,14 +21,18 @@ install:
cd CSF.Screenplay.JsonToHtmlReport.Template\src
npm ci
cd ..\..
+ # This was taken from https://stackoverflow.com/questions/60304251/unable-to-open-x-display-when-trying-to-run-google-chrome-on-centos-rhel-7-5
+ # It's the minimum dependencies for running Chrome in a headless environment on Linux
+ - sh: |
+ sudo apt-get update
+ sudo apt install -y xorg xvfb gtk2-engines-pixbuf dbus-x11 xfonts-base xfonts-100dpi xfonts-75dpi xfonts-cyrillic xfonts-scalable
before_build:
- dotnet --version
- dotnet restore --verbosity m
- dotnet clean
- - cmd: >
- IF NOT DEFINED APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH (SET BranchName=%APPVEYOR_REPO_BRANCH%)
- ELSE (SET BranchName=%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%)
+ - cmd: Tools\appveyor-setup-sonarscanner.bat
+ - cmd: Tools\appveyor-setup-selenium.bat
- cmd: >
dotnet-sonarscanner begin
/k:"csf-dev_CSF.Screenplay"
@@ -36,9 +40,14 @@ before_build:
/o:craigfowler-github
/d:sonar.host.url=https://sonarcloud.io
/d:sonar.token=%SONARCLOUD_SECRET_KEY%
- /d:sonar.branch.name=%BranchName%
+ /d:%BranchParam%=%BranchName%
+ %PRParam%
/d:sonar.javascript.lcov.reportPaths=%APPVEYOR_BUILD_FOLDER%\CSF.Screenplay.JsonToHtmlReport.Template\src\TestResults\lcov.info
/s:%APPVEYOR_BUILD_FOLDER%\.sonarqube-analysisproperties.xml
+ # Activate Xvfb and export a display so that Chrome can run in Linux
+ - sh: |
+ Xvfb -ac :99 -screen 0 1280x1024x16 &
+ export DISPLAY=:99
build_script:
- dotnet build --no-incremental
diff --git a/.gitignore b/.gitignore
index c3b716f9..51db7c89 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,5 +4,8 @@ obj/
TestResults/
Tests/**/*.feature.cs
node_modules/
+*.orig
/CSF.Screenplay.JsonToHtmlReport/template/
/CSF.Screenplay.JsonToHtmlReport.Template/src/output/
+**/ScreenplayReport*
+**/TestResult.xml
diff --git a/.sonarqube-analysisproperties.xml b/.sonarqube-analysisproperties.xml
index f923c073..61a28780 100644
--- a/.sonarqube-analysisproperties.xml
+++ b/.sonarqube-analysisproperties.xml
@@ -2,9 +2,12 @@
- Tests/**/*,**/*Exception.cs,*_old/**/*,**/*.spec.js,**/*.config.js
- Tests/**/*,*_old/**/*,**/*.spec.js
+ Tests\**\*,**\*Exception.cs,**\*.spec.js,**\*.config.js
+ docs\**\*,*_old\**\*
+ Tests\**\*,**\*.spec.jsTests\**\TestResults.xmlTestResults\*.opencover.xmlfalse
+ Tests\**\*,**\*.spec.js
+ true
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 00000000..074847c3
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,15 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "dotnet",
+ "projectPath": "${workspaceFolder}/Tests/CSF.Screenplay.Selenium.TestWebapp/CSF.Screenplay.Selenium.TestWebapp.csproj",
+ "name": "Selenium testing web app",
+ "request": "launch",
+
+ }
+ ]
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Abstractions/Abilities/GetAssetFilePaths.cs b/CSF.Screenplay.Abstractions/Abilities/GetAssetFilePaths.cs
new file mode 100644
index 00000000..4ab345a6
--- /dev/null
+++ b/CSF.Screenplay.Abstractions/Abilities/GetAssetFilePaths.cs
@@ -0,0 +1,39 @@
+using CSF.Screenplay.Reporting;
+
+namespace CSF.Screenplay.Abilities
+{
+ ///
+ /// Screenplay ability which gets the file system path for asset files generated by actors participating in the current performance.
+ ///
+ public class GetAssetFilePaths
+ {
+ readonly IGetsAssetFilePath pathProvider;
+
+ ///
+ /// Gets the file system path for the specified asset file.
+ ///
+ ///
+ ///
+ /// The returned file system path is an absolute path to which the asset file should be written. The path is determined by the
+ /// logic of the service . This means that the final filename will not be identical to the
+ /// but will include that base name within it.
+ ///
+ ///
+ /// If this method returns then the asset file should not be written to the file system.
+ ///
+ ///
+ /// A short descriptive file name fragment for the asset file, including the file extension.
+ /// The asset file path.
+ ///
+ public string GetAssetFilePath(string baseName) => pathProvider.GetAssetFilePath(baseName);
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The path provider used to get asset file paths.
+ public GetAssetFilePaths(IGetsAssetFilePath pathProvider)
+ {
+ this.pathProvider = pathProvider ?? throw new System.ArgumentNullException(nameof(pathProvider));
+ }
+ }
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Abstractions/Actor.cs b/CSF.Screenplay.Abstractions/Actor.cs
index 4cec7968..e1c27a8a 100644
--- a/CSF.Screenplay.Abstractions/Actor.cs
+++ b/CSF.Screenplay.Abstractions/Actor.cs
@@ -58,6 +58,9 @@ public partial class Actor : IHasName, IHasPerformanceIdentity
Guid IHasPerformanceIdentity.PerformanceIdentity => PerformanceIdentity;
+ ///
+ public override string ToString() => $"[Actor '{Name}' in Performance {PerformanceIdentity}]";
+
/// Initialises a new instance of
///
///
diff --git a/CSF.Screenplay.Abstractions/Actor.performer.cs b/CSF.Screenplay.Abstractions/Actor.performer.cs
index 8b95e54a..1726e2ee 100644
--- a/CSF.Screenplay.Abstractions/Actor.performer.cs
+++ b/CSF.Screenplay.Abstractions/Actor.performer.cs
@@ -79,7 +79,8 @@ protected virtual ValueTask PerformAsync(IPerformableWithResult perform
PerformableException GetPerformableException(object performable, Exception ex)
{
- return new PerformableException($"{Name} encountered an unexpected exception whilst performing a performable of type {performable.GetType().FullName}", ex)
+
+ return new PerformableException($"{Name} encountered an unexpected exception whilst executing the performable logic of {performable.GetType().FullName}", ex)
{
Performable = performable,
};
diff --git a/CSF.Screenplay.Abstractions/ActorExtensions.abilities.cs b/CSF.Screenplay.Abstractions/ActorExtensions.abilities.cs
index 8c2ac7e3..315e6262 100644
--- a/CSF.Screenplay.Abstractions/ActorExtensions.abilities.cs
+++ b/CSF.Screenplay.Abstractions/ActorExtensions.abilities.cs
@@ -80,6 +80,42 @@ public static object GetAbility(this ICanPerform actor, Type abilityType)
?? throw new InvalidOperationException($"{((IHasName) actor).Name} must have an ability of type {abilityType.FullName}");
}
+ /// Tries to get the first ability which the actor has of the specified type
+ /// The actor from whom to get the ability
+ /// If this method returns then this exposes the strongly-typed ability; if not then this value is undefined
+ /// The type of ability desired
+ /// if the actor has an ability of the specified type; if not.
+ /// If the is
+ /// If the actor does not implement
+ public static bool TryGetAbility(this ICanPerform actor, out T ability)
+ {
+ ability = default;
+ if (!TryGetAbility(actor, typeof(T), out var untypedAbility)) return false;
+ ability = (T) untypedAbility;
+ return true;
+ }
+
+ /// Gets the first ability which the actor has of the specified type
+ /// The actor from whom to get the ability
+ /// The type of ability desired
+ /// If this method returns then this exposes the strongly-typed ability; if not then this value is undefined
+ /// if the actor has an ability of the specified type; if not.
+ /// If any parameter is
+ public static bool TryGetAbility(this ICanPerform actor, Type abilityType, out object ability)
+ {
+ if(actor is null) throw new ArgumentNullException(nameof(actor));
+ if(abilityType is null) throw new ArgumentNullException(nameof(abilityType));
+
+ if(!actor.HasAbility(abilityType))
+ {
+ ability = default;
+ return false;
+ }
+
+ ability = actor.GetAbility(abilityType);
+ return true;
+ }
+
/// Adds an ability to the specified actor
/// The actor from whom to get the ability
/// The ability to add to the actor
diff --git a/CSF.Screenplay.Abstractions/Performances/IRelaysPerformanceEvents.cs b/CSF.Screenplay.Abstractions/Performances/IRelaysPerformanceEvents.cs
index cd92421a..82e9a4e7 100644
--- a/CSF.Screenplay.Abstractions/Performances/IRelaysPerformanceEvents.cs
+++ b/CSF.Screenplay.Abstractions/Performances/IRelaysPerformanceEvents.cs
@@ -53,6 +53,9 @@ public interface IRelaysPerformanceEvents
///
///
/// Use this method when ending a performance, as a convenience to unsubscribe from all of its actors at once.
+ /// Note that this method might not result in unsubscribing any actors. If the subscribed actors are also managed
+ /// by an implementation of then the disposal of the cast will automatically unsubscribe these actors
+ /// on its own. This method is provided & used as a backup technique, in case the actors are not managed by a cast.
///
///
/// The identity of a performance.
@@ -103,17 +106,15 @@ public interface IRelaysPerformanceEvents
///
/// Invokes an event indicating that a has begun.
///
- /// The performance identity
- /// The performance's hierarchical name
- void InvokePerformanceBegun(Guid performanceIdentity, IList namingHierarchy);
+ /// The performance
+ void InvokePerformanceBegun(IPerformance performance);
///
/// Invokes an event indicating that a has finished.
///
- /// The performance identity
- /// The performance's hierarchical name
+ /// The performance
/// A value indicating whether or not the performance was a success
- void InvokePerformanceFinished(Guid performanceIdentity, IList namingHierarchy, bool? success);
+ void InvokePerformanceFinished(IPerformance performance, bool? success);
#endregion
diff --git a/CSF.Screenplay.Abstractions/Performances/PerformanceCompleteEventArgs.cs b/CSF.Screenplay.Abstractions/Performances/PerformanceCompleteEventArgs.cs
index e3b1d6db..40eacacd 100644
--- a/CSF.Screenplay.Abstractions/Performances/PerformanceCompleteEventArgs.cs
+++ b/CSF.Screenplay.Abstractions/Performances/PerformanceCompleteEventArgs.cs
@@ -34,13 +34,10 @@ public class PerformanceFinishedEventArgs : PerformanceEventArgs
public bool? Success { get; }
/// Initialises a new instance of
- /// The performance identity
- /// The scenario hierarchy
+ /// The performance.
/// A value indicating whether or not the scenario completed with a succeess result
/// If the scenario hierarchy is
- public PerformanceFinishedEventArgs(Guid performanceIdentity,
- IReadOnlyList namingHierarchy,
- bool? success) : base(performanceIdentity, namingHierarchy)
+ public PerformanceFinishedEventArgs(IPerformance performance, bool? success) : base(performance)
{
Success = success;
}
diff --git a/CSF.Screenplay.Abstractions/Performances/PerformanceEventArgs.cs b/CSF.Screenplay.Abstractions/Performances/PerformanceEventArgs.cs
index 6806b4a9..efe6e465 100644
--- a/CSF.Screenplay.Abstractions/Performances/PerformanceEventArgs.cs
+++ b/CSF.Screenplay.Abstractions/Performances/PerformanceEventArgs.cs
@@ -10,6 +10,11 @@ namespace CSF.Screenplay.Performances
///
public class PerformanceEventArgs : PerformanceScopeEventArgs
{
+ ///
+ /// Gets the to which this event relates.
+ ///
+ public IPerformance Performance { get; }
+
/// Gets an ordered list of identifiers which indicate the 's name within an organisational hierarchy.
///
///
@@ -18,15 +23,14 @@ public class PerformanceEventArgs : PerformanceScopeEventArgs
///
///
///
- public IReadOnlyList NamingHierarchy { get; }
+ public IReadOnlyList NamingHierarchy => Performance.NamingHierarchy;
/// Initialises a new instance of
- /// The performance identity
- /// The screenplay naming hierarchy
+ /// The performance
/// If the scenario hierarchy is
- public PerformanceEventArgs(Guid performanceIdentity, IReadOnlyList namingHierarchy) : base(performanceIdentity)
+ public PerformanceEventArgs(IPerformance performance) : base(performance.PerformanceIdentity)
{
- NamingHierarchy = namingHierarchy ?? throw new ArgumentNullException(nameof(namingHierarchy));
+ Performance = performance;
}
}
}
\ No newline at end of file
diff --git a/CSF.Screenplay.Abstractions/Reporting/IGetsAssetFilePath.cs b/CSF.Screenplay.Abstractions/Reporting/IGetsAssetFilePath.cs
new file mode 100644
index 00000000..c783354a
--- /dev/null
+++ b/CSF.Screenplay.Abstractions/Reporting/IGetsAssetFilePath.cs
@@ -0,0 +1,29 @@
+namespace CSF.Screenplay.Reporting
+{
+ ///
+ /// A service which gets a filesystem path to which Screenplay asset files should be written, if they are to be written at all.
+ ///
+ public interface IGetsAssetFilePath
+ {
+ ///
+ /// Gets the filesystem path to which an asset file should be written.
+ ///
+ ///
+ ///
+ /// If reporting is disabled, for the same reasons as would return ,
+ /// then this method will also return .
+ /// In that case, reporting is disabled and no asset files should be written to the file system.
+ ///
+ ///
+ /// If reporting is enabled, then this method should return an absolute file system path to which an asset file should be written,
+ /// where the asset has the specified 'base name'. That base name should be a short filename fragment which describes the asset.
+ /// This file name will be embellished with other information by this method, such as to ensure that the file name is unique within
+ /// the current Screenplay run.
+ ///
+ ///
+ /// A short & descriptive filename fragment, which includes the file extension but no path information
+ /// An absolute file system path at which the asset file should be saved, or a reference indicating that
+ /// the asset file should not be saved.
+ string GetAssetFilePath(string baseName);
+ }
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Abstractions/Reporting/IGetsReportPath.cs b/CSF.Screenplay.Abstractions/Reporting/IGetsReportPath.cs
new file mode 100644
index 00000000..6ee81c59
--- /dev/null
+++ b/CSF.Screenplay.Abstractions/Reporting/IGetsReportPath.cs
@@ -0,0 +1,26 @@
+namespace CSF.Screenplay.Reporting
+{
+ ///
+ /// A service which gets the path to which the Screenplay report should be written.
+ ///
+ public interface IGetsReportPath
+ {
+ ///
+ /// Gets the path to which the report should be written.
+ ///
+ ///
+ ///
+ /// If the returned path is then Screenplay's reporting functionality should be disabled and no report should be written.
+ /// Otherwise, implementations of this interface should return an absolute file system path to which the report should be written.
+ /// This path must be writable by the executing process.
+ ///
+ ///
+ /// Reporting could be disabled if either the Screenplay Options report path is or a whitespace-only string, or if the path
+ /// indicated by those options is not writable.
+ ///
+ ///
+ /// The report path.
+ string GetReportPath();
+ }
+}
+
diff --git a/CSF.Screenplay.Docs/docfx.json b/CSF.Screenplay.Docs/docfx.json
index d4bc2031..144d8cd7 100644
--- a/CSF.Screenplay.Docs/docfx.json
+++ b/CSF.Screenplay.Docs/docfx.json
@@ -9,8 +9,9 @@
"docs/**",
"**/bin/**",
"**/obj/**",
- "Tests_old/**",
- "Tests/**"
+ "Tests/**",
+ "*_old/**",
+ "CSF.Screenplay.JsonToHtmlReport.Template/**"
]
}
],
diff --git a/CSF.Screenplay.JsonToHtmlReport.Template/src/js/ReportLoader.js b/CSF.Screenplay.JsonToHtmlReport.Template/src/js/ReportLoader.js
index 893c6f2a..8b33e496 100644
--- a/CSF.Screenplay.JsonToHtmlReport.Template/src/js/ReportLoader.js
+++ b/CSF.Screenplay.JsonToHtmlReport.Template/src/js/ReportLoader.js
@@ -19,8 +19,7 @@ export class ReportLoader {
const jsonData = JSON.parse(scriptElement.textContent);
return jsonData;
} catch (error) {
- console.error(error);
- throw new Error('Failed to parse JSON content');
+ throw new Error('Failed to parse JSON content whilst loading a Screenplay report', { cause: error });
}
}
}
diff --git a/CSF.Screenplay.JsonToHtmlReport.Template/src/package-lock.json b/CSF.Screenplay.JsonToHtmlReport.Template/src/package-lock.json
index 42daa487..2b8db19d 100644
--- a/CSF.Screenplay.JsonToHtmlReport.Template/src/package-lock.json
+++ b/CSF.Screenplay.JsonToHtmlReport.Template/src/package-lock.json
@@ -39,15 +39,15 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.26.2",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
- "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.27.1",
"js-tokens": "^4.0.0",
- "picocolors": "^1.0.0"
+ "picocolors": "^1.1.1"
},
"engines": {
"node": ">=6.9.0"
@@ -386,9 +386,9 @@
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
- "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -396,9 +396,9 @@
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
- "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -431,27 +431,27 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.26.0",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz",
- "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==",
+ "version": "7.28.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
+ "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/template": "^7.25.9",
- "@babel/types": "^7.26.0"
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.4"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.26.2",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz",
- "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
+ "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.26.0"
+ "@babel/types": "^7.28.5"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -1778,28 +1778,25 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.26.0",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
- "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
+ "version": "7.28.4",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
+ "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "regenerator-runtime": "^0.14.0"
- },
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/template": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
- "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.25.9",
- "@babel/parser": "^7.25.9",
- "@babel/types": "^7.25.9"
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1825,14 +1822,14 @@
}
},
"node_modules/@babel/types": {
- "version": "7.26.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
- "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
+ "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
},
"engines": {
"node": ">=6.9.0"
@@ -3061,9 +3058,9 @@
"license": "ISC"
},
"node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3134,6 +3131,20 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -3441,9 +3452,9 @@
}
},
"node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3953,6 +3964,21 @@
"tslib": "^2.0.3"
}
},
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/electron-to-chromium": {
"version": "1.5.50",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.50.tgz",
@@ -4027,6 +4053,26 @@
"is-arrayish": "^0.2.1"
}
},
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/es-module-lexer": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
@@ -4034,6 +4080,35 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -4296,14 +4371,16 @@
}
},
"node_modules/form-data": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
- "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"dev": true,
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
@@ -4362,6 +4439,31 @@
"node": "6.* || 8.* || >= 10.*"
}
},
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/get-package-type": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
@@ -4372,6 +4474,20 @@
"node": ">=8.0.0"
}
},
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/get-stream": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@@ -4424,6 +4540,19 @@
"node": ">=4"
}
},
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -4441,6 +4570,35 @@
"node": ">=8"
}
},
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
@@ -5592,9 +5750,9 @@
"license": "MIT"
},
"node_modules/js-yaml": {
- "version": "3.14.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
- "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5838,6 +5996,16 @@
"tmpl": "1.0.5"
}
},
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/mdn-data": {
"version": "2.0.30",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
@@ -5941,9 +6109,9 @@
"license": "MIT"
},
"node_modules/nanoid": {
- "version": "3.3.7",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"dev": true,
"funding": [
{
@@ -6211,9 +6379,9 @@
"license": "MIT"
},
"node_modules/picocolors": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz",
- "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
@@ -6948,13 +7116,6 @@
"node": ">=4"
}
},
- "node_modules/regenerator-runtime": {
- "version": "0.14.1",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
- "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/regenerator-transform": {
"version": "0.15.2",
"resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz",
diff --git a/CSF.Screenplay.JsonToHtmlReport/CSF.Screenplay.JsonToHtmlReport.csproj b/CSF.Screenplay.JsonToHtmlReport/CSF.Screenplay.JsonToHtmlReport.csproj
index 198c1413..b5b533fb 100644
--- a/CSF.Screenplay.JsonToHtmlReport/CSF.Screenplay.JsonToHtmlReport.csproj
+++ b/CSF.Screenplay.JsonToHtmlReport/CSF.Screenplay.JsonToHtmlReport.csproj
@@ -7,6 +7,9 @@
NU1903,NU1902CSF.Screenplay.JsonToHtmlReport$(MSBuildProjectDirectory)\bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml
+
+ false
diff --git a/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/AutoMoqDataAttribute.cs b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/AutoMoqDataAttribute.cs
new file mode 100644
index 00000000..63115422
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/AutoMoqDataAttribute.cs
@@ -0,0 +1,14 @@
+using System;
+using Ploeh.AutoFixture;
+using Ploeh.AutoFixture.AutoMoq;
+using Ploeh.AutoFixture.NUnit3;
+
+namespace CSF.Screenplay.Selenium.Tests
+{
+ public class AutoMoqDataAttribute : AutoDataAttribute
+ {
+ public AutoMoqDataAttribute() : base(new Fixture().Customize(new AutoMoqCustomization()))
+ {
+ }
+ }
+}
diff --git a/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/CSF.Screenplay.Selenium.BrowserFlags.Tests.csproj b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/CSF.Screenplay.Selenium.BrowserFlags.Tests.csproj
new file mode 100644
index 00000000..f1d2c1b4
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/CSF.Screenplay.Selenium.BrowserFlags.Tests.csproj
@@ -0,0 +1,83 @@
+
+
+
+ Debug
+ AnyCPU
+ {87454F03-FBB3-4506-9055-551297445891}
+ Library
+ CSF.Screenplay.Selenium.Tests
+ CSF.Screenplay.Selenium.BrowserFlags.Tests
+ v4.5
+ 1.0.0
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;
+ prompt
+ 4
+
+
+ true
+ bin\Release
+ prompt
+ 4
+
+
+
+
+ ..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll
+
+
+ ..\packages\AutoFixture.3.50.3\lib\net40\Ploeh.AutoFixture.dll
+
+
+ ..\packages\AutoFixture.AutoMoq.3.50.3\lib\net40\Ploeh.AutoFixture.AutoMoq.dll
+
+
+ ..\packages\AutoFixture.NUnit3.3.50.3\lib\net40\Ploeh.AutoFixture.NUnit3.dll
+
+
+ ..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll
+
+
+ ..\packages\Moq.4.7.25\lib\net45\Moq.dll
+
+
+ ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
+
+
+ ..\packages\Selenium.WebDriver.3.4.0\lib\net40\WebDriver.dll
+
+
+
+ ..\packages\CSF.Configuration.1.1.2\lib\net45\CSF.Configuration.dll
+
+
+ ..\packages\CSF.WebDriverExtras.1.0.3\lib\net45\CSF.WebDriverExtras.dll
+
+
+
+
+
+
+
+
+
+ FooBrowser.flags.json
+
+
+
+
+
+
+
+
+ {0665F99E-DB05-4208-BCF1-137EF914CBF5}
+ CSF.Screenplay.Selenium.BrowserFlags
+
+
+
+
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/FooBrowser.flags.json b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/FooBrowser.flags.json
new file mode 100644
index 00000000..d6c1fd8c
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/FooBrowser.flags.json
@@ -0,0 +1,8 @@
+[
+ {
+ "browserName": "FooBrowser",
+ "flags": [
+ "SampleFlag1",
+ ],
+ },
+]
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/GetBrowserFlagsDefinitionsTests.cs b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/GetBrowserFlagsDefinitionsTests.cs
new file mode 100644
index 00000000..cd2fb6ca
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/GetBrowserFlagsDefinitionsTests.cs
@@ -0,0 +1,89 @@
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using CSF.WebDriverExtras.Flags;
+using Moq;
+using NUnit.Framework;
+
+namespace CSF.Screenplay.Selenium.Tests
+{
+ [TestFixture,Parallelizable(ParallelScope.All)]
+ public class GetBrowserFlagsDefinitionsTests
+ {
+ [Test,AutoMoqData]
+ public void GetDefinitions_from_test_assembly_returns_one_definition(IReadsFlagsDefinitions definitionReader,
+ FlagsDefinition def)
+ {
+ // Arrange
+ var testAssembly = Assembly.GetExecutingAssembly();
+ Mock.Get(definitionReader)
+ .Setup(x => x.GetFlagsDefinitions(It.IsAny()))
+ .Returns(new [] { def });
+ var sut = new GetBrowserFlagsDefinitions(definitionReader);
+
+ // Act
+ var result = sut.GetDefinitions(testAssembly);
+
+ // Assert
+ Assert.That(result, Has.Length.EqualTo(1));
+ }
+
+ [Test,AutoMoqData]
+ public void GetDefinitions_from_test_assembly_uses_definition_reader(IReadsFlagsDefinitions definitionReader,
+ FlagsDefinition def)
+ {
+ // Arrange
+ var testAssembly = Assembly.GetExecutingAssembly();
+ Mock.Get(definitionReader)
+ .Setup(x => x.GetFlagsDefinitions(It.IsAny()))
+ .Returns(new [] { def });
+ var sut = new GetBrowserFlagsDefinitions(definitionReader);
+
+ // Act
+ var result = sut.GetDefinitions(testAssembly);
+
+ // Assert
+ Mock.Get(definitionReader)
+ .Verify(x => x.GetFlagsDefinitions(It.IsAny()), Times.Once);
+ }
+
+ [Test,Category("Integration")]
+ public void GetDefinitions_integration_test_only_finds_one_definition()
+ {
+ // Arrange
+ var testAssembly = Assembly.GetExecutingAssembly();
+ var sut = new GetBrowserFlagsDefinitions();
+
+ // Act
+ var result = sut.GetDefinitions(testAssembly);
+
+ // Assert
+ Assert.That(result, Has.Length.EqualTo(1));
+ }
+
+ [Test,Category("Integration")]
+ public void GetDefinitions_integration_test_finds_definition_for_FooBrowser()
+ {
+ // Arrange
+ var testAssembly = Assembly.GetExecutingAssembly();
+ var sut = new GetBrowserFlagsDefinitions();
+
+ // Act
+ var result = sut.GetDefinitions(testAssembly).Single();
+
+ // Assert
+ Assert.That(result.BrowserNames.First(), Is.EqualTo("FooBrowser"));
+ }
+
+ [Test,Category("Integration")]
+ public void FromDefinitionsAssembly_integration_test_returns_more_than_two_flags_definitions()
+ {
+ // Act
+ var result = GetBrowserFlagsDefinitions.FromDefinitionsAssembly();
+
+ // Assert
+ Assert.That(result, Is.Not.Null);
+ Assert.That(result, Has.Length.GreaterThan(2));
+ }
+ }
+}
diff --git a/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/InvalidFlagsDefinition.json b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/InvalidFlagsDefinition.json
new file mode 100644
index 00000000..c4b1955f
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/InvalidFlagsDefinition.json
@@ -0,0 +1,8 @@
+[
+ {
+ "browserName": "BarBrowser",
+ "flags": [
+ "SampleFlag1",
+ ],
+ },
+]
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/app.config b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/app.config
new file mode 100644
index 00000000..437c6629
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/app.config
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/packages.config b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/packages.config
new file mode 100644
index 00000000..3ab15217
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags.Tests_old/packages.config
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium.BrowserFlags_old/CSF.Screenplay.Selenium.BrowserFlags.csproj b/CSF.Screenplay.Selenium.BrowserFlags_old/CSF.Screenplay.Selenium.BrowserFlags.csproj
new file mode 100644
index 00000000..4a22cc42
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/CSF.Screenplay.Selenium.BrowserFlags.csproj
@@ -0,0 +1,80 @@
+
+
+
+ Debug
+ AnyCPU
+ {0665F99E-DB05-4208-BCF1-137EF914CBF5}
+ Library
+ CSF.Screenplay.Selenium
+ CSF.Screenplay.Selenium.BrowserFlags
+ v4.5
+ 1.0.0
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;
+ prompt
+ 4
+ bin\Debug\CSF.Screenplay.Selenium.BrowserFlags.xml
+ false
+
+
+ true
+ bin\Release
+ prompt
+ 4
+ bin\Release\CSF.Screenplay.Selenium.BrowserFlags.xml
+ false
+
+
+
+
+ ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
+
+
+ ..\packages\Selenium.WebDriver.3.4.0\lib\net40\WebDriver.dll
+
+
+
+ ..\packages\CSF.Configuration.1.1.2\lib\net45\CSF.Configuration.dll
+
+
+ ..\packages\CSF.WebDriverExtras.1.0.3\lib\net45\CSF.WebDriverExtras.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ AppleSafari.flags.json
+
+
+ GoogleChrome.flags.json
+
+
+ InternetExplorer.flags.json
+
+
+ MicrosoftEdge.flags.json
+
+
+ MozillaFirefox.flags.json
+
+
+
+
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium.BrowserFlags_old/CSF.Screenplay.Selenium.BrowserFlags.nuspec b/CSF.Screenplay.Selenium.BrowserFlags_old/CSF.Screenplay.Selenium.BrowserFlags.nuspec
new file mode 100644
index 00000000..7e2b9106
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/CSF.Screenplay.Selenium.BrowserFlags.nuspec
@@ -0,0 +1,21 @@
+
+
+
+ CSF.Screenplay.Selenium.BrowserFlags
+ 1.0.0
+ CSF.Screenplay.Selenium.BrowserFlags
+ CSF Software Ltd
+ MIT
+ https://github.com/csf-dev/CSF.Screenplay.Selenium
+ false
+ An assembly containing 'browser flags definitions' for CSF.Screenplay.Selenium. This indicates the quirks and behaviours of various popular web browsers which are compatible with Selenium WebDriver.
+ Copyright 2018
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/AppleSafari.flags.json b/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/AppleSafari.flags.json
new file mode 100644
index 00000000..286888f1
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/AppleSafari.flags.json
@@ -0,0 +1,15 @@
+[
+ {
+ "browserName": "Safari",
+ "flags": [
+ ],
+ },
+ {
+ "browserName": "Safari",
+ "minVersion": "11",
+ "flags": [
+ "HtmlElements.Select.RequiresUpdatesViaJavaScriptWorkaround",
+ ],
+ },
+]
+
diff --git a/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/GoogleChrome.flags.json b/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/GoogleChrome.flags.json
new file mode 100644
index 00000000..b62dc273
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/GoogleChrome.flags.json
@@ -0,0 +1,8 @@
+[
+ {
+ "browserName": "Chrome",
+ "flags": [
+ "HtmlElements.InputTypeDate.RequiresEntryUsingLocaleFormat",
+ ],
+ },
+]
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/InternetExplorer.flags.json b/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/InternetExplorer.flags.json
new file mode 100644
index 00000000..f92a921c
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/InternetExplorer.flags.json
@@ -0,0 +1,7 @@
+[
+ {
+ "browserName": [ "InternetExplorer", "Internet Explorer" ],
+ "flags": [
+ ],
+ },
+]
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/MicrosoftEdge.flags.json b/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/MicrosoftEdge.flags.json
new file mode 100644
index 00000000..d9fd8749
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/MicrosoftEdge.flags.json
@@ -0,0 +1,10 @@
+[
+ {
+ "browserName": "MicrosoftEdge",
+ "flags": [
+ "Browser.CannotClearDomainCookies",
+ "HtmlElements.SelectMultiple.RequiresCtrlClickToToggleOptionSelection",
+ "HtmlElements.InputTypeDate.RequiresInputViaJavaScriptWorkaround",
+ ],
+ },
+]
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/MozillaFirefox.flags.json b/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/MozillaFirefox.flags.json
new file mode 100644
index 00000000..c8e38046
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/Definitions/MozillaFirefox.flags.json
@@ -0,0 +1,8 @@
+[
+ {
+ "browserName": "Firefox",
+ "flags": [
+ "HtmlElements.InputTypeDate.RequiresInputViaJavaScriptWorkaround"
+ ],
+ },
+]
diff --git a/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.Browser.cs b/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.Browser.cs
new file mode 100644
index 00000000..b1cef97f
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.Browser.cs
@@ -0,0 +1,23 @@
+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/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.HtmlElements.cs b/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.HtmlElements.cs
new file mode 100644
index 00000000..3be266d8
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.HtmlElements.cs
@@ -0,0 +1,55 @@
+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/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.cs b/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.cs
new file mode 100644
index 00000000..2a0f2e1c
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/Flags.cs
@@ -0,0 +1,10 @@
+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/CSF.Screenplay.Selenium.BrowserFlags_old/GetBrowserFlagsDefinitions.cs b/CSF.Screenplay.Selenium.BrowserFlags_old/GetBrowserFlagsDefinitions.cs
new file mode 100644
index 00000000..d0a30191
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/GetBrowserFlagsDefinitions.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using CSF.WebDriverExtras.Flags;
+
+namespace CSF.Screenplay.Selenium
+{
+ ///
+ /// Helper type which gets browser flags definitions stored inside an assembly as embedded resources,
+ /// using the resource suffix .flags.json.
+ ///
+ public sealed class GetBrowserFlagsDefinitions
+ {
+ #region constants
+
+ const string FlagsResourceSuffix = ".flags.json";
+
+ #endregion
+
+ #region fields
+
+ readonly IReadsFlagsDefinitions definitionReader;
+ readonly object syncRoot;
+ IReadOnlyCollection cachedDefinitions;
+
+ #endregion
+
+ #region properties
+
+ Assembly ThisAssembly => Assembly.GetExecutingAssembly();
+
+ #endregion
+
+ #region public methods
+
+ ///
+ /// Gets the browser flags definitions contained within the CSF.Screenplay.Selenium.BrowserFlags assembly.
+ ///
+ /// The browser flags definitions.
+ public IReadOnlyCollection GetDefinitions() => GetDefinitions(ThisAssembly);
+
+ ///
+ /// Gets the browser flags definitions contained within the given assembly.
+ ///
+ /// The browser flags definitions.
+ /// An assembly to search for flags definitions.
+ public IReadOnlyCollection GetDefinitions(Assembly assembly)
+ {
+ if(assembly == null)
+ throw new ArgumentNullException(nameof(assembly));
+
+ if(assembly != ThisAssembly)
+ {
+ return GetDefinitionsFromAssembly(assembly);
+ }
+
+ lock(syncRoot)
+ {
+ if(cachedDefinitions != null)
+ return cachedDefinitions;
+
+ cachedDefinitions = GetDefinitionsFromAssembly(assembly);
+ return cachedDefinitions;
+ }
+ }
+
+ #endregion
+
+ #region methods
+
+ IReadOnlyCollection GetDefinitionsFromAssembly(Assembly assembly)
+ {
+ var resourceNames = GetDefinitionsResourceNames(assembly);
+ return resourceNames
+ .SelectMany(x => GetDefinitions(x, assembly))
+ .ToArray();
+ }
+
+ IEnumerable GetDefinitionsResourceNames(Assembly assembly)
+ => assembly
+ .GetManifestResourceNames()
+ .Where(x => x.EndsWith(FlagsResourceSuffix, StringComparison.InvariantCulture));
+
+ IReadOnlyCollection GetDefinitions(string resourceName, Assembly assembly)
+ {
+ using(var stream = assembly.GetManifestResourceStream(resourceName))
+ return definitionReader.GetFlagsDefinitions(stream);
+ }
+
+ #endregion
+
+ #region constructor
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public GetBrowserFlagsDefinitions() : this(null) {}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Definition reader.
+ public GetBrowserFlagsDefinitions(IReadsFlagsDefinitions definitionReader)
+ {
+ syncRoot = new object();
+ this.definitionReader = definitionReader ?? new DefinitionReader();
+ }
+
+ #endregion
+
+ #region static methods
+
+ ///
+ /// Helper method which gets the flags definitions from the CSF.Screenplay.Selenium.BrowserFlags assembly.
+ ///
+ /// The dlags definitions.
+ public static IReadOnlyCollection FromDefinitionsAssembly()
+ => new GetBrowserFlagsDefinitions().GetDefinitions();
+
+ #endregion
+ }
+}
diff --git a/CSF.Screenplay.Selenium.BrowserFlags_old/Properties/AssemblyInfo.cs b/CSF.Screenplay.Selenium.BrowserFlags_old/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..d14392e2
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/Properties/AssemblyInfo.cs
@@ -0,0 +1,26 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("CSF.Screenplay.Selenium.BrowserFlags")]
+[assembly: AssemblyDescription("A repository of pre-defined Browser Flags for CSF.Screenplay.Selenium")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("CSF Software Limited")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Craig Fowler")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.0.0")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
diff --git a/CSF.Screenplay.Selenium.BrowserFlags_old/ScreenplayLocator.cs b/CSF.Screenplay.Selenium.BrowserFlags_old/ScreenplayLocator.cs
new file mode 100644
index 00000000..713eab14
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/ScreenplayLocator.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Concurrent;
+using System.Reflection;
+using NUnit.Framework.Interfaces;
+
+namespace CSF.Screenplay
+{
+ ///
+ /// A small static service locator of sorts, dedicated to getting an appropriate instance of for
+ /// a specified test object.
+ ///
+ ///
+ ///
+ /// This type uses reflection to find the which decorates the assembly in which the
+ /// specified object (a test, a test method or the assembly itself) resides.
+ /// It additionally caches the results in-memory to avoid repetitive reflection, only to retrieve the same results.
+ ///
+ ///
+ public static class ScreenplayLocator
+ {
+ static readonly ConcurrentDictionary screenplayCache = new ConcurrentDictionary();
+
+ ///
+ /// Gets a instance from the specified .
+ ///
+ ///
+ ///
+ /// This method makes use of the which decorates the assembly to get a
+ /// Screenplay object instance for that assembly.
+ /// If the specified assembly is not decorated with the Screenplay assembly attribute then this method will raise
+ /// an exception.
+ ///
+ ///
+ /// The test assembly for which to get a Screenplay object.
+ /// The Screenplay object for the specified assembly.
+ /// If is .
+ /// If the is not decorated with .
+ public static Screenplay GetScreenplay(Assembly assembly)
+ {
+ if (assembly is null) throw new ArgumentNullException(nameof(assembly));
+ return screenplayCache.GetOrAdd(assembly, GetScreenplayFromAssembly);
+ }
+
+ ///
+ /// Gets a instance from the specified test method.
+ ///
+ ///
+ ///
+ /// This method makes use of the which decorates the assembly in which the
+ /// specified method was declared, to get a Screenplay object instance applicable to the test method.
+ /// If the method's assembly is not decorated with the Screenplay assembly attribute then this method will raise
+ /// an exception.
+ ///
+ ///
+ /// The test method for which to get a Screenplay object.
+ /// The Screenplay object for the specified test method.
+ /// If is .
+ /// If the 's assembly is or
+ /// is not decorated with .
+ public static Screenplay GetScreenplay(IMethodInfo method)
+ {
+ if (method is null) throw new ArgumentNullException(nameof(method));
+
+ var assembly = method.MethodInfo?.DeclaringType?.Assembly;
+ if (assembly is null)
+ throw new ArgumentException($"The test method must have an associated {nameof(Assembly)}.", nameof(method));
+ return GetScreenplay(assembly);
+ }
+
+ ///
+ /// Gets a instance from the specified test.
+ ///
+ ///
+ ///
+ /// This method makes use of the which decorates the assembly in which the
+ /// specified test's method was declared, to get a Screenplay object instance applicable to the test method.
+ /// If the test's method's assembly is not decorated with the Screenplay assembly attribute then this method will raise
+ /// an exception.
+ ///
+ ///
+ /// The test for which to get a Screenplay object.
+ /// The Screenplay object for the specified test.
+ /// If is .
+ /// If the 's method's assembly is or
+ /// is not decorated with .
+ public static Screenplay GetScreenplay(ITest test)
+ {
+ if(test is null) throw new ArgumentNullException(nameof(test));
+ return GetScreenplay(test.Method);
+ }
+
+ static Screenplay GetScreenplayFromAssembly(Assembly assembly)
+ {
+ var assemblyAttrib = assembly.GetCustomAttribute()
+ ?? throw new ArgumentException($"The assembly {assembly.FullName} must be decorated with {nameof(ScreenplayAssemblyAttribute)}.", nameof(assembly));
+ return assemblyAttrib.GetScreenplay();
+ }
+ }
+}
diff --git a/CSF.Screenplay.Selenium.BrowserFlags_old/packages.config b/CSF.Screenplay.Selenium.BrowserFlags_old/packages.config
new file mode 100644
index 00000000..51dabf90
--- /dev/null
+++ b/CSF.Screenplay.Selenium.BrowserFlags_old/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/CSF.Screenplay.Selenium.JavaScriptWorkarounds.csproj b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/CSF.Screenplay.Selenium.JavaScriptWorkarounds.csproj
new file mode 100644
index 00000000..fb372e78
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/CSF.Screenplay.Selenium.JavaScriptWorkarounds.csproj
@@ -0,0 +1,76 @@
+
+
+
+ Debug
+ AnyCPU
+ {CC20F88D-C4B9-4FDB-B5B1-7349547430FA}
+ Library
+ CSF.Screenplay.Selenium
+ CSF.Screenplay.Selenium.JavaScriptWorkarounds
+ v4.5
+ 1.0.0
+
+
+ true
+ full
+ false
+ bin\Debug
+ DEBUG;
+ prompt
+ 4
+ bin\Debug\CSF.Screenplay.Selenium.JavaScriptWorkarounds.xml
+ false
+ true
+
+
+ true
+ bin\Release
+ prompt
+ 4
+ bin\Release\CSF.Screenplay.Selenium.JavaScriptWorkarounds.xml
+ false
+
+
+
+
+ ..\packages\Selenium.WebDriver.3.4.0\lib\net40\WebDriver.dll
+
+
+
+ ..\packages\CSF.Reflection.1.0.3\lib\net45\CSF.Reflection.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/Properties/AssemblyInfo.cs b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..13b84a46
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/Properties/AssemblyInfo.cs
@@ -0,0 +1,26 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("CSF.Screenplay.Selenium.JavaScriptWorkarounds")]
+[assembly: AssemblyDescription("Workarounds, using JavaScript, for browser-specific issues relating to Selenium actions")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("CSF Software Limited")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Craig Fowler")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.0.0")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
diff --git a/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/ArgumentsArrayValidator.cs b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/ArgumentsArrayValidator.cs
new file mode 100644
index 00000000..06e95245
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/ArgumentsArrayValidator.cs
@@ -0,0 +1,57 @@
+//
+// 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/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/ArgumentsArrayValidator.js b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/ArgumentsArrayValidator.js
new file mode 100644
index 00000000..6b653445
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/ArgumentsArrayValidator.js
@@ -0,0 +1,87 @@
+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/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetALocalisedDate.cs b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetALocalisedDate.cs
new file mode 100644
index 00000000..8cb0206f
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetALocalisedDate.cs
@@ -0,0 +1,64 @@
+//
+// 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/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetALocalisedDate.js b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetALocalisedDate.js
new file mode 100644
index 00000000..9456b68c
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetALocalisedDate.js
@@ -0,0 +1,17 @@
+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/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetDocumentReadyState.cs b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetDocumentReadyState.cs
new file mode 100644
index 00000000..bff50835
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetDocumentReadyState.cs
@@ -0,0 +1,42 @@
+//
+// 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/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetDocumentReadyState.js b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetDocumentReadyState.js
new file mode 100644
index 00000000..b8953856
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/GetDocumentReadyState.js
@@ -0,0 +1,4 @@
+function executeScript(argsArray) {
+ 'use strict';
+ return document.readyState;
+}
\ No newline at end of file
diff --git a/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementAttribute.cs b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementAttribute.cs
new file mode 100644
index 00000000..93126cf8
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementAttribute.cs
@@ -0,0 +1,48 @@
+//
+// 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/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementAttribute.js b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementAttribute.js
new file mode 100644
index 00000000..79c5f7e9
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementAttribute.js
@@ -0,0 +1,24 @@
+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/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementValue.cs b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementValue.cs
new file mode 100644
index 00000000..3b9279da
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementValue.cs
@@ -0,0 +1,64 @@
+//
+// 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/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementValue.js b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementValue.js
new file mode 100644
index 00000000..d93f5b4f
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/SetAnElementValue.js
@@ -0,0 +1,36 @@
+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/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/UpdateSelectElementSelection.cs b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/UpdateSelectElementSelection.cs
new file mode 100644
index 00000000..ef9a59a6
--- /dev/null
+++ b/CSF.Screenplay.Selenium.JavaScriptWorkarounds_old/ScriptResources/UpdateSelectElementSelection.cs
@@ -0,0 +1,83 @@
+//
+// 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