Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CSF.Screenplay.Abstractions/Abilities/UseAStopwatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace CSF.Screenplay.Abilities
/// <remarks>
/// <para>
/// Use this ability with the actions which exposed by
/// <see cref="CSF.Screenplay.Performables.StopwatchBuilder"/>.
/// <see cref="CSF.Screenplay.PerforamableBuilder"/>.
/// This ability wraps a <see cref="System.Diagnostics.Stopwatch"/> instance, allowing the actor
/// to control &amp; read it from the related actions.
/// </para>
Expand Down
42 changes: 42 additions & 0 deletions CSF.Screenplay.Abstractions/PerformableBuilder.Assets.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.IO;
using CSF.Screenplay.Performables;

namespace CSF.Screenplay
{
/// <summary>
/// Static helper class used to create/build instances of the performables which are bundled with Screenplay.
/// </summary>
/// <remarks>
/// <para>Tip: Consume the members of this class via:</para>
/// <code>using static CSF.Screenplay.PerforamableBuilder;</code>
/// <para>
/// This will allow you use the method names in this class in a more human-readable fashion.
/// </para>
/// </remarks>
public static partial class PerforamableBuilder
{
/// <summary>
/// Gets a builder for an Action which copies a file at the specified source path into the assets for the current performance.
/// </summary>
/// <param name="path">The path to the source file which should be copied</param>
/// <returns>A builder to specify the name of the asset.</returns>
public static CopyFileAsAnAssetFilenameBuilder CopyTheFile(string path)
=> new CopyFileAsAnAssetFilenameBuilder(path);

/// <summary>
/// Gets a builder for an Action which saves a stream of data into the assets for the current performance.
/// </summary>
/// <param name="stream">The stream which should be saved as an asset.</param>
/// <returns>A builder to specify the name of the asset.</returns>
public static SaveStreamAsAnAssetFilenameBuilder SaveTheStream(Stream stream)
=> new SaveStreamAsAnAssetFilenameBuilder(stream);

/// <summary>
/// Gets a builder for an Action which saves some text into an asset file for the current performance.
/// </summary>
/// <param name="text">The text which should be saved as an asset.</param>
/// <returns>A builder to specify the name of the asset.</returns>
public static SaveTheTextAsAnAssetFilenameBuilder SaveTheText(string text)
=> new SaveTheTextAsAnAssetFilenameBuilder(text);
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
using CSF.Screenplay.Abilities;
using CSF.Screenplay.Performables;

namespace CSF.Screenplay.Performables
namespace CSF.Screenplay
{
/// <summary>
/// A builder for actions relating to the <see cref="UseAStopwatch"/> ability.
/// </summary>
/// <remarks>
/// <para>
/// When using this class it is recommended to include <c>using static CSF.Screenplay.Performables.StopwatchBuilder;</c>
/// in the source file which uses it. This will allow you use the method names in this class in a more human-readable
/// fashion.
/// </para>
/// <para>
/// The actions and the question exposed by this builder allow an actor to accurately
/// track and measure time elapsed during a Performance.
/// </para>
/// </remarks>
public static class StopwatchBuilder
public static partial class PerforamableBuilder
{
/// <summary>
/// Gets a performable which starts the stopwatch.
/// </summary>
/// <remarks>
/// <para>
/// Use of this performable requires the actor has the <see cref="UseAStopwatch"/> ability.
/// Use of this performable requires the actor has the <see cref="UseAStopwatch"/> ability,
/// for accurately measuring time, during the course of a performance.
/// </para>
/// </remarks>
public static StartTheStopwatch StartTheStopwatch() => new StartTheStopwatch();
Expand All @@ -33,7 +21,8 @@ public static class StopwatchBuilder
/// </summary>
/// <remarks>
/// <para>
/// Use of this performable requires the actor has the <see cref="UseAStopwatch"/> ability.
/// Use of this performable requires the actor has the <see cref="UseAStopwatch"/> ability,
/// for accurately measuring time, during the course of a performance.
/// </para>
/// </remarks>
public static StopTheStopwatch StopTheStopwatch() => new StopTheStopwatch();
Expand All @@ -43,7 +32,8 @@ public static class StopwatchBuilder
/// </summary>
/// <remarks>
/// <para>
/// Use of this performable requires the actor has the <see cref="UseAStopwatch"/> ability.
/// Use of this performable requires the actor has the <see cref="UseAStopwatch"/> ability,
/// for accurately measuring time, during the course of a performance.
/// </para>
/// </remarks>
public static ResetTheStopwatch ResetTheStopwatch() => new ResetTheStopwatch();
Expand All @@ -53,9 +43,10 @@ public static class StopwatchBuilder
/// </summary>
/// <remarks>
/// <para>
/// Use of this performable requires the actor has the <see cref="UseAStopwatch"/> ability.
/// Use of this performable requires the actor has the <see cref="UseAStopwatch"/> ability,
/// for accurately measuring time, during the course of a performance.
/// </para>
/// </remarks>
public static ReadTheStopwatch ReadTheStopwatch() => new ReadTheStopwatch();
}
}
}
49 changes: 49 additions & 0 deletions CSF.Screenplay.Abstractions/Performables/CopyFileAsAnAsset.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using CSF.Screenplay.Abilities;

namespace CSF.Screenplay.Performables
{
/// <summary>
/// A performable Action which copies an existing file as an asset file.
/// </summary>
public class CopyFileAsAnAsset : IPerformable, ICanReport
{
readonly string sourceFilePath, assetName, assetSummary;

/// <inheritdoc/>
public ReportFragment GetReportFragment(Actor actor, IFormatsReportFragment formatter)
=> formatter.Format("{Actor} copies {SourcePath} as an asset file named {Name}", actor, sourceFilePath, assetName);

/// <inheritdoc/>
public ValueTask PerformAsAsync(ICanPerform actor, CancellationToken cancellationToken = default)
{
var ability = actor.GetAbility<GetAssetFilePaths>();
var path = ability.GetAssetFilePath(assetName);

if(!File.Exists(sourceFilePath)) throw new FileNotFoundException($"The source file '{sourceFilePath}' must exist", sourceFilePath);
File.Copy(sourceFilePath, path);
actor.RecordAsset(this, path, assetSummary);

return default;
}

/// <summary>
/// Initializes a new instance of <see cref="CopyFileAsAnAsset"/>.
/// </summary>
/// <param name="sourceFilePath">The file system path to the file which should be copied into the assets.</param>
/// <param name="assetName">The name of the asset file.</param>
/// <param name="assetSummary">An optional human-readable summary of the asset</param>
public CopyFileAsAnAsset(string sourceFilePath, string assetName, string assetSummary = null)
{
if (string.IsNullOrWhiteSpace(assetName))
throw new ArgumentException($"'{nameof(assetName)}' cannot be null or whitespace.", nameof(assetName));

this.sourceFilePath = sourceFilePath ?? throw new ArgumentNullException(nameof(sourceFilePath));
this.assetName = assetName;
this.assetSummary = assetSummary;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
namespace CSF.Screenplay.Performables
{
/// <summary>
/// A builder for customising the <see cref="CopyFileAsAnAsset"/> action, specifying the asset filename.
/// </summary>
public class CopyFileAsAnAssetFilenameBuilder
{
readonly string sourcePath;

/// <summary>
/// Gets a builder which may be used as a performable, or which may further customise the Action,
/// having specified the filename for the asset.
/// </summary>
/// <param name="filename">The filename of the asset to create, including its extension, but without any path/dirctory information.</param>
/// <returns>A builder.</returns>
public CopyFileAsAnAssetBuilder AsAnAssetWithTheFilename(string filename)
=> new CopyFileAsAnAssetBuilder(sourcePath, filename);

/// <summary>
/// Initializes a new instance of the <see cref="CopyFileAsAnAssetFilenameBuilder"/> class.
/// </summary>
/// <param name="sourcePath">The path to the source file which should be copied.</param>
public CopyFileAsAnAssetFilenameBuilder(string sourcePath)
{
this.sourcePath = sourcePath ?? throw new System.ArgumentNullException(nameof(sourcePath));
}
}

/// <summary>
/// A builder for customising the <see cref="CopyFileAsAnAsset"/> action.
/// </summary>
public class CopyFileAsAnAssetBuilder : IGetsPerformable
{
readonly string sourcePath, filename;

/// <summary>
/// Gets a performable action, specifying a short human-readable summary of the asset.
/// </summary>
/// <param name="summary">A brief human-readable summary of the asset, which will not be used as a filename.</param>
/// <returns>A performable action</returns>
public CopyFileAsAnAsset WithTheSummary(string summary)
=> new CopyFileAsAnAsset(sourcePath, filename, summary);

IPerformable IGetsPerformable.GetPerformable()
=> new CopyFileAsAnAsset(sourcePath, filename);

/// <summary>
/// Initializes a new instance of the <see cref="CopyFileAsAnAssetBuilder"/> class.
/// </summary>
/// <param name="sourcePath">The path to the source file which should be copied.</param>
/// <param name="filename">The filename of the asset to create, including its extension, but without any path/dirctory information.</param>
public CopyFileAsAnAssetBuilder(string sourcePath, string filename)
{
this.sourcePath = sourcePath ?? throw new System.ArgumentNullException(nameof(sourcePath));
this.filename = filename ?? throw new System.ArgumentNullException(nameof(filename));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace CSF.Screenplay.Performables
/// <remarks>
/// <para>
/// This performable requires the actor has the ability <see cref="UseAStopwatch"/>.
/// Use this performable via the builder method <see cref="StopwatchBuilder.ReadTheStopwatch"/>.
/// Use this performable via the builder method <see cref="PerforamableBuilder.ReadTheStopwatch"/>.
/// </para>
/// </remarks>
public class ReadTheStopwatch : IPerformableWithResult<TimeSpan>, ICanReport
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace CSF.Screenplay.Performables
/// <remarks>
/// <para>
/// This performable requires the actor has the ability <see cref="UseAStopwatch"/>.
/// Use this performable via the builder method <see cref="StopwatchBuilder.ResetTheStopwatch"/>.
/// Use this performable via the builder method <see cref="PerforamableBuilder.ResetTheStopwatch"/>.
/// </para>
/// </remarks>
public class ResetTheStopwatch : IPerformable, ICanReport
Expand Down
50 changes: 50 additions & 0 deletions CSF.Screenplay.Abstractions/Performables/SaveAStreamAsAnAsset.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using CSF.Screenplay.Abilities;

namespace CSF.Screenplay.Performables
{
/// <summary>
/// A performable Action which saves a stream to an asset file.
/// </summary>
public class SaveAStreamAsAnAsset : IPerformable, ICanReport
{
readonly Stream stream;
readonly string assetName, assetSummary;

/// <inheritdoc/>
public ReportFragment GetReportFragment(Actor actor, IFormatsReportFragment formatter)
=> formatter.Format("{Actor} saves a stream as an asset file named {Name}", actor, assetName);

/// <inheritdoc/>
public async ValueTask PerformAsAsync(ICanPerform actor, CancellationToken cancellationToken = default)
{
var ability = actor.GetAbility<GetAssetFilePaths>();
var path = ability.GetAssetFilePath(assetName);

using (var fileStream = File.Create(path))
{
await stream.CopyToAsync(fileStream, 81920, cancellationToken);
}
actor.RecordAsset(this, path, assetSummary);
}

/// <summary>
/// Initializes a new instance of <see cref="SaveAStreamAsAnAsset"/>.
/// </summary>
/// <param name="stream">The stream to save.</param>
/// <param name="assetName">The name of the asset file.</param>
/// <param name="assetSummary">An optional human-readable summary of the asset</param>
public SaveAStreamAsAnAsset(Stream stream, string assetName, string assetSummary = null)
{
if (string.IsNullOrWhiteSpace(assetName))
throw new ArgumentException($"'{nameof(assetName)}' cannot be null or whitespace.", nameof(assetName));

this.stream = stream ?? throw new ArgumentNullException(nameof(stream));
this.assetName = assetName;
this.assetSummary = assetSummary;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System.IO;

namespace CSF.Screenplay.Performables
{
/// <summary>
/// A builder for customising the <see cref="SaveAStreamAsAnAsset"/> action, specifying the asset filename.
/// </summary>
public class SaveStreamAsAnAssetFilenameBuilder
{
readonly Stream stream;

/// <summary>
/// Gets a builder which may be used as a performable, or which may further customise the Action,
/// having specified the filename for the asset.
/// </summary>
/// <param name="filename">The filename of the asset to create, including its extension, but without any path/dirctory information.</param>
/// <returns>A builder.</returns>
public SaveStreamAsAnAssetBuilder AsAnAssetWithTheFilename(string filename)
=> new SaveStreamAsAnAssetBuilder(stream, filename);

/// <summary>
/// Initializes a new instance of the <see cref="SaveStreamAsAnAssetFilenameBuilder"/> class.
/// </summary>
/// <param name="stream">The stream which is to be saved.</param>
public SaveStreamAsAnAssetFilenameBuilder(Stream stream)
{
this.stream = stream ?? throw new System.ArgumentNullException(nameof(stream));
}
}

/// <summary>
/// A builder for customising the <see cref="SaveAStreamAsAnAsset"/> action.
/// </summary>
public class SaveStreamAsAnAssetBuilder : IGetsPerformable
{
readonly Stream stream;
readonly string filename;

/// <summary>
/// Gets a performable action, specifying a short human-readable summary of the asset.
/// </summary>
/// <param name="summary">A brief human-readable summary of the asset, which will not be used as a filename.</param>
/// <returns>A performable action</returns>
public SaveAStreamAsAnAsset WithTheSummary(string summary)
=> new SaveAStreamAsAnAsset(stream, filename, summary);

IPerformable IGetsPerformable.GetPerformable()
=> new SaveAStreamAsAnAsset(stream, filename);

/// <summary>
/// Initializes a new instance of the <see cref="CopyFileAsAnAssetBuilder"/> class.
/// </summary>
/// <param name="stream">The stream which is to be saved.</param>
/// <param name="filename">The filename of the asset to create, including its extension, but without any path/dirctory information.</param>
public SaveStreamAsAnAssetBuilder(Stream stream, string filename)
{
this.stream = stream ?? throw new System.ArgumentNullException(nameof(stream));
this.filename = filename ?? throw new System.ArgumentNullException(nameof(filename));
}
}
}
Loading
Loading