Skip to content
Merged
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/Reporting/JsonScreenplayReporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ void OnRecordAsset(object sender, PerformableAssetEventArgs e)
=> GetPerformanceBuilder(e).RecordAssetForCurrentPerformable(e.FilePath, e.FileSummary);

void OnPerformableFailed(object sender, PerformableFailureEventArgs e)
=> GetPerformanceBuilder(e).RecordFailureForCurrentPerformable(e.Exception);
=> GetPerformanceBuilder(e).RecordFailureForCurrentPerformable(e.Exception, e.Performable, e.Actor);

void OnPerformableResult(object sender, PerformableResultEventArgs e)
=> GetPerformanceBuilder(e).RecordResultForCurrentPerformable(e.Result);
Expand Down
23 changes: 18 additions & 5 deletions CSF.Screenplay/Reporting/PerformanceReportBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public void SpotlightTurnedOff()
/// <param name="actor">The actor executing the performable</param>
/// <param name="performancePhase">The performance phase in which the performable occurs</param>
/// <seealso cref="EndPerformable(object, Actor)"/>
/// <seealso cref="RecordFailureForCurrentPerformable(Exception)"/>
/// <seealso cref="RecordFailureForCurrentPerformable(Exception,object,Actor)"/>
public void BeginPerformable(object performable, Actor actor, string performancePhase)
{
var performableReport = new PerformableReport
Expand Down Expand Up @@ -239,7 +239,7 @@ public void RecordResultForCurrentPerformable(object result)
public void EndPerformable(object performable, Actor actor)
{
CurrentPerformable.Report = performable is ICanReport reporter
? reporter.GetReportFragment(actor, formatter).FormattedFragment
? TryGetReport(reporter, actor, formatter)
: string.Format(ReportStrings.FallbackReportFormat, actor.Name, performable.GetType().FullName);
CurrentPerformable.Ended = reportTimer.GetCurrentTime();
performableStack.Pop();
Expand All @@ -257,12 +257,25 @@ public void EndPerformable(object performable, Actor actor)
/// </para>
/// </remarks>
/// <param name="exception">The exception which lead to the failure</param>
public void RecordFailureForCurrentPerformable(Exception exception)
/// <param name="performable">The performable which is ending</param>
/// <param name="actor">The actor which was executing the performable</param>
public void RecordFailureForCurrentPerformable(Exception exception, object performable, Actor actor)
{
CurrentPerformable.Exception = exception.ToString();
CurrentPerformable.ExceptionIsFromConsumedPerformable = exception is PerformableException;
CurrentPerformable.Ended = reportTimer.GetCurrentTime();
performableStack.Pop();
EndPerformable(performable, actor);
}

static string TryGetReport(ICanReport reporter, Actor actor, IFormatsReportFragment formatter)
{
try
{
return reporter.GetReportFragment(actor, formatter).FormattedFragment;
}
catch
{
return ReportStrings.ReportErrorMessage;
}
}

#endregion
Expand Down
3 changes: 3 additions & 0 deletions CSF.Screenplay/Resources/ReportStrings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,8 @@ internal static class ReportStrings

/// <summary>Gets a fallback report format string for an actor performing a performable which does not implement <see cref="ICanReport"/>.</summary>
internal static string FallbackReportFormat => resourceManager.GetString("FallbackReportFormat");

/// <summary>Gets a report text which is recorded when a performable raises an exception from <see cref="ICanReport.GetReportFragment(Actor, IFormatsReportFragment)"/>.</summary>
internal static string ReportErrorMessage => resourceManager.GetString("ReportErrorMessage");
}
}
3 changes: 2 additions & 1 deletion CSF.Screenplay/Resources/ReportStrings.restext
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ ActorCreatedFormat = {0} joined the performance
ActorGainedAbilityFormat = {0} is able to {1}
ActorSpotlitFormat = {0} was put into the spotlight
SpotlightTurnedOff = The spotlight was turned off
FallbackReportFormat = {0} performed {1}
FallbackReportFormat = {0} performed {1}
ReportErrorMessage = An unexpected error occurred getting the report text for this performable
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,41 @@ public void RecordFailureForCurrentPerformableShouldAddTheExceptionStringToTheRe
string performancePhase)
{
sut.BeginPerformable(performable, actor, performancePhase);
sut.RecordFailureForCurrentPerformable(new Exception("An error occurred"));
sut.RecordFailureForCurrentPerformable(new Exception("An error occurred"), performable, actor);
var report = sut.GetReport(outcome);
Assert.That(report.Reportables,
Has.One.Matches<PerformableReport>(x => x.Exception.Contains("An error occurred") && x.ExceptionIsFromConsumedPerformable == false));
}

[Test, AutoMoqData]
public void RecordFailureForCurrentPerformableShouldSetTheReportString(PerformanceReportBuilder sut,
[NamedActor("Joe")] Actor actor,
bool? outcome,
string performable,
string performancePhase)
{
sut.BeginPerformable(performable, actor, performancePhase);
sut.RecordFailureForCurrentPerformable(new Exception("An error occurred"), performable, actor);
var report = sut.GetReport(outcome);
Assert.That(report.Reportables,
Has.One.Matches<PerformableReport>(x => x.Report != null));
}

[Test, AutoMoqData]
public void RecordFailureForCurrentPerformableShouldUseAFallbackReportIfGettingTheReportThrows(PerformanceReportBuilder sut,
[NamedActor("Joe")] Actor actor,
bool? outcome,
ICanReport performable,
string performancePhase)
{
Mock.Get(performable).Setup(x => x.GetReportFragment(actor, It.IsAny<IFormatsReportFragment>())).Throws<InvalidOperationException>();
sut.BeginPerformable(performable, actor, performancePhase);
sut.RecordFailureForCurrentPerformable(new Exception("An error occurred"), performable, actor);
var report = sut.GetReport(outcome);
Assert.That(report.Reportables,
Has.One.Matches<PerformableReport>(x => x.Report == "An unexpected error occurred getting the report text for this performable"));
}

[Test, AutoMoqData]
public void RecordFailureForCurrentPerformableShouldSetExceptionIsFromConsumedPerformableToTrueIfTheExceptionIsPerformableException(PerformanceReportBuilder sut,
[NamedActor("Joe")] Actor actor,
Expand All @@ -209,7 +238,7 @@ public void RecordFailureForCurrentPerformableShouldSetExceptionIsFromConsumedPe
string performancePhase)
{
sut.BeginPerformable(performable, actor, performancePhase);
sut.RecordFailureForCurrentPerformable(new PerformableException("An error occurred"));
sut.RecordFailureForCurrentPerformable(new PerformableException("An error occurred"), performable, actor);
var report = sut.GetReport(outcome);
Assert.That(report.Reportables,
Has.One.Matches<PerformableReport>(x => x.Exception.Contains("An error occurred") && x.ExceptionIsFromConsumedPerformable == true));
Expand Down
Loading