diff --git a/CSF.Screenplay.Reporting.Html/CSF.Screenplay.Reporting.Html.csproj b/CSF.Screenplay.Reporting.Html/CSF.Screenplay.Reporting.Html.csproj index 5094e5e5..51db60ab 100644 --- a/CSF.Screenplay.Reporting.Html/CSF.Screenplay.Reporting.Html.csproj +++ b/CSF.Screenplay.Reporting.Html/CSF.Screenplay.Reporting.Html.csproj @@ -90,6 +90,11 @@ + + + + + @@ -100,6 +105,10 @@ {18010B4E-22A7-4462-B057-7199B3386D48} CSF.Screenplay.Reporting + + {46E6DEAA-E6D5-4EE6-A552-17376BEA80DC} + CSF.Screenplay + diff --git a/CSF.Screenplay.Reporting.Html/Models/FeatureModel.cs b/CSF.Screenplay.Reporting.Html/Models/FeatureModel.cs new file mode 100644 index 00000000..0d74e309 --- /dev/null +++ b/CSF.Screenplay.Reporting.Html/Models/FeatureModel.cs @@ -0,0 +1,102 @@ +// +// FeatureModel.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using System.Linq; + +namespace CSF.Screenplay.Reporting.Models +{ + /// + /// Model for HTML report features (wraps a instance). + /// + public class FeatureModel + { + readonly Feature feature; + readonly IObjectFormattingService formattingService; + + /// + /// Gets the identity of this feature. + /// + public string Id => feature.Id; + + /// + /// Gets the human-readable friendly-name of this feature. + /// + public string FriendlyName => feature.FriendlyName; + + /// + /// Gets a collection of the scenarios in the current feature. + /// + public IReadOnlyCollection Scenarios + => feature.Scenarios.Select(x => new ScenarioModel(x, formattingService)).ToArray(); + + /// + /// Gets or sets a value indicating whether this contains any scenarios which are themselves failures. + /// + /// true if this feature contains any failures; otherwise, false. + public bool HasFailures => feature.Scenarios.Any(x => x.IsFailure); + + /// + /// Gets or sets a value indicating whether every within this is a success. + /// + /// true if the feature contains only successful scenarios; otherwise, false. + public bool IsSuccess => feature.Scenarios.All(x => x.IsSuccess); + + /// + /// Gets the HTML class attribute value indicating the outcome of a given feature. + /// + /// The feature outcome class. + public string GetOutcomeClass() + { + if(feature == null) return String.Empty; + var outcome = GetOutcomeClass(feature.IsSuccess, feature.HasFailures); + return $"feature {outcome}"; + } + + string GetOutcomeClass(bool success, bool failure) + { + if(success) return ReportConstants.SuccessClass; + if(failure) return ReportConstants.FailureClass; + return ReportConstants.InconclusiveClass; + } + + /// + /// Initializes a new instance of the class. + /// + /// Feature. + /// Formatting service. + public FeatureModel(Feature feature, IObjectFormattingService formattingService) + { + if(formattingService == null) + throw new ArgumentNullException(nameof(formattingService)); + if(feature == null) + throw new ArgumentNullException(nameof(feature)); + + this.feature = feature; + this.formattingService = formattingService; + } + } +} diff --git a/CSF.Screenplay.Reporting.Html/Models/ReportConstants.cs b/CSF.Screenplay.Reporting.Html/Models/ReportConstants.cs new file mode 100644 index 00000000..f0d3aaa4 --- /dev/null +++ b/CSF.Screenplay.Reporting.Html/Models/ReportConstants.cs @@ -0,0 +1,45 @@ +// +// ReportConstants.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +namespace CSF.Screenplay.Reporting.Models +{ + /// + /// A number of constants used by HTML reports. + /// + public static class ReportConstants + { + internal const string + SuccessClass = "success", + FailureClass = "failure", + InconclusiveClass = "inconclusive", + AbilityClass = "ability", + PerformanceClass = "performance", + AbilityMacro = "ability", + PerformanceWithResultMacro = "performance_success_result", + PerformanceWithExceptionMacro = "performance_failure_exception", + PerformanceMacro = "performance"; + } +} diff --git a/CSF.Screenplay.Reporting.Html/Models/ReportDocument.cs b/CSF.Screenplay.Reporting.Html/Models/ReportDocument.cs index f1358f16..b6111034 100644 --- a/CSF.Screenplay.Reporting.Html/Models/ReportDocument.cs +++ b/CSF.Screenplay.Reporting.Html/Models/ReportDocument.cs @@ -10,26 +10,15 @@ namespace CSF.Screenplay.Reporting.Models /// public class ReportDocument { - const string - SuccessClass = "success", - FailureClass = "failure", - InconclusiveClass = "inconclusive", - AbilityClass = "ability", - PerformanceClass = "performance", - AbilityMacro = "ability", - PerformanceWithResultMacro = "performance_success_result", - PerformanceWithExceptionMacro = "performance_failure_exception", - PerformanceMacro = "performance"; - readonly IObjectFormattingService formattingService; readonly IZptDocument document; - readonly Report report; + readonly ReportModel report; /// /// Gets the report to be rendered. /// /// The report. - public Report Report => report; + public ReportModel Report => report; /// /// Gets a reference to the ZPT template being used to render the report. @@ -59,122 +48,6 @@ public IMetalMacroContainer GetMacros() return output; } - /// - /// Formats a given object using a formatting service. - /// - /// Object. - public string Format(object obj) => formattingService.Format(obj); - - /// - /// Gets a value which indicates whether the formatting service has an explicit formatter for the given object or not. - /// - /// true, if the formatting service has an explicit format for the object, false otherwise. - /// Object. - public bool HasFormat(object obj) => formattingService.HasExplicitSupport(obj); - - /// - /// Gets the HTML class attribute value indicating the outcome of a given scenario. - /// - /// The scenario outcome class. - /// A test sscenario. - public string GetOutcomeClass(Scenario scenario) - { - if(scenario == null) return String.Empty; - var outcome = GetOutcomeClass(scenario.IsSuccess, scenario.IsFailure); - return $"scenario {outcome}"; - } - - /// - /// Gets the HTML class attribute value indicating the outcome of a given feature. - /// - /// The feature outcome class. - /// A test feature. - public string GetOutcomeClass(Feature feature) - { - if(feature == null) return String.Empty; - var outcome = GetOutcomeClass(feature.IsSuccess, feature.HasFailures); - return $"feature {outcome}"; - } - - /// - /// Gets the HTML class attribute value indicating the outcome of a given reportable step within a scenario. - /// - /// The reportable's outcome class. - /// A reportable step, part of a scenario. - public string GetOutcomeClass(Reportable reportable) - { - - switch(reportable.Outcome) - { - case PerformanceOutcome.Success: - case PerformanceOutcome.SuccessWithResult: - return GetOutcomeClass(true, false); - - default: - return GetOutcomeClass(false, true); - } - } - - string GetOutcomeClass(bool success, bool failure) - { - if(success) return SuccessClass; - if(failure) return FailureClass; - return InconclusiveClass; - } - - /// - /// Gets an HTML class attribute value which describes a reportable step within a scenario. - /// - /// The reportable class. - /// A reportable step, part of a scenario. - public string GetReportableClass(Reportable reportable) - { - if(reportable == null) return String.Empty; - - if(reportable is GainAbility) - return AbilityClass; - - if(reportable is Performance) - return PerformanceClass; - - return String.Empty; - } - - /// - /// Gets the name of the METAL macro to use for rendering the specified reportable. - /// - /// The macro name. - /// A reportable step, part of a scenario. - public string GetMacroName(Reportable reportable) - { - if(reportable == null) return null; - - if(reportable is GainAbility) - return GetMacroName((GainAbility) reportable); - - if(reportable is Performance) - return GetMacroName((Performance) reportable); - - return null; - } - - string GetMacroName(GainAbility reportable) => AbilityMacro; - - string GetMacroName(Performance reportable) - { - switch(reportable.Outcome) - { - case PerformanceOutcome.SuccessWithResult: - return PerformanceWithResultMacro; - - case PerformanceOutcome.FailureWithException: - return PerformanceWithExceptionMacro; - - default: - return PerformanceMacro; - } - } - /// /// Initializes a new instance of the class. /// @@ -192,7 +65,7 @@ public ReportDocument(Report report, if(report == null) throw new ArgumentNullException(nameof(report)); - this.report = report; + this.report = new ReportModel(report, formattingService); this.formattingService = formattingService; this.document = document; } diff --git a/CSF.Screenplay.Reporting.Html/Models/ReportModel.cs b/CSF.Screenplay.Reporting.Html/Models/ReportModel.cs new file mode 100644 index 00000000..e86eef77 --- /dev/null +++ b/CSF.Screenplay.Reporting.Html/Models/ReportModel.cs @@ -0,0 +1,124 @@ +// +// ReportModel.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using System.Linq; + +namespace CSF.Screenplay.Reporting.Models +{ + /// + /// Model for HTML reports (wraps a instance). + /// + public class ReportModel + { + readonly Report report; + readonly IObjectFormattingService formattingService; + + /// + /// Gets a collection of the scenarios in this report. + /// + /// The scenarios. + public virtual IReadOnlyList Features + => report.Features.Select(x => new FeatureModel(x, formattingService)).ToArray(); + + /// + /// Gets the count of features (total) in this report. + /// + /// The feature count. + public virtual int TotalFeatureCount => report.Features.Count; + + /// + /// Gets the count of successful features in this report. + /// + /// The successful feature count. + public virtual int SuccessfulFeatureCount => report.Features.Count(x => x.IsSuccess); + + /// + /// Gets the count of failing features in this report. + /// + /// The failing feature count. + public virtual int FailingFeatureCount => report.Features.Count(x => x.HasFailures); + + /// + /// Gets the scenarios in the current report instance. + /// + /// The scenarios. + public virtual IReadOnlyList Scenarios + => report.Features.SelectMany(x => x.Scenarios).Select(x => new ScenarioModel(x, formattingService)).ToArray(); + + /// + /// Gets the count of scenarios (total) in this report. + /// + /// The scenario count. + public virtual int TotalScenarioCount => report.Scenarios.Count; + + /// + /// Gets the count of successful scenarios in this report. + /// + /// The successful scenario count. + public virtual int SuccessfulScenarioCount => report.Scenarios.Count(x => x.IsSuccess); + + /// + /// Gets the count of failing scenarios in this report. + /// + /// The failing scenario count. + public virtual int FailingScenarioCount => report.Scenarios.Count(x => x.IsFailure); + + /// + /// Gets the timestamp for the creation of this report. + /// + /// The timestamp. + public virtual DateTime Timestamp => report.Timestamp; + + /// + /// Gets the formatted time. + /// + /// The formatted time. + public string FormattedTime => Timestamp.ToString("T"); + + /// + /// Gets the formatted date. + /// + /// The formatted date. + public string FormattedDate => Timestamp.ToString("D"); + + /// + /// Initializes a new instance of the class. + /// + /// Report. + /// Formatting service. + public ReportModel(Report report, IObjectFormattingService formattingService) + { + if(formattingService == null) + throw new ArgumentNullException(nameof(formattingService)); + if(report == null) + throw new ArgumentNullException(nameof(report)); + + this.report = report; + this.formattingService = formattingService; + } + } +} diff --git a/CSF.Screenplay.Reporting.Html/Models/ReportableModel.cs b/CSF.Screenplay.Reporting.Html/Models/ReportableModel.cs new file mode 100644 index 00000000..575d56c9 --- /dev/null +++ b/CSF.Screenplay.Reporting.Html/Models/ReportableModel.cs @@ -0,0 +1,271 @@ +// +// ReportableModel.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using System.Linq; +using CSF.Screenplay.Abilities; +using CSF.Screenplay.Actors; +using CSF.Screenplay.Performables; + +namespace CSF.Screenplay.Reporting.Models +{ + /// + /// Model for HTML reportables (wraps a instance). + /// + public class ReportableModel + { + readonly Reportable reportable; + readonly IObjectFormattingService formattingService; + + #region common to all reportables + + /// + /// Gets the actor. + /// + /// The actor. + public virtual INamed Actor => reportable.Actor; + + /// + /// Gets the type of the performance. + /// + /// The type of the performance. + public virtual PerformanceType PerformanceType => reportable.PerformanceType; + + /// + /// Gets the outcome of the reported-upon action. + /// + /// The outcome. + public virtual PerformanceOutcome Outcome => reportable.Outcome; + + #endregion + + #region abilities + + /// + /// Gets the ability. + /// + /// The ability. + public virtual IAbility Ability => GainAbility?.Ability; + + /// + /// Gets reportable as a instance. + /// + /// The gain ability. + protected GainAbility GainAbility => reportable as GainAbility; + + #endregion + + #region performances + + /// + /// Gets the contained reportables. + /// + /// The reportables. + public virtual IReadOnlyList Reportables + => Performance?.Reportables.Select(x => new ReportableModel(x, formattingService)).ToArray(); + + /// + /// Gets a value indicating whether this performance has any child reportables or not. + /// + /// true if this performance has child reportables; otherwise, false. + public virtual bool HasReportables => (Performance?.HasReportables).GetValueOrDefault(); + + /// + /// Gets a value indicating whether this performance has a result. + /// + /// true if this performance has a result; otherwise, false. + public virtual bool HasResult => (Performance?.HasResult).GetValueOrDefault(); + + /// + /// Gets a value indicating whether this performance has an exception. + /// + /// true if this performance has an exception; otherwise, false. + public virtual bool HasException => (Performance?.HasException).GetValueOrDefault(); + + /// + /// Gets a value indicating whether this performance has additional content (child reportables, a result or an + /// exception). + /// + /// true if this performance has additional content; otherwise, false. + public virtual bool HasAdditionalContent => (Performance?.HasAdditionalContent).GetValueOrDefault(); + + /// + /// Gets the performable associated with the current instance. + /// + /// The performable. + public virtual IPerformable Performable => Performance.Performable; + + /// + /// Gets the result received from the performable. + /// + /// The result. + public virtual object Result => Performance.Result; + + /// + /// Gets an exception raised by the performable. + /// + /// The exception. + public virtual Exception Exception => Performance.Exception; + + /// + /// Gets the reportable as a instance. + /// + /// The performance. + protected Performance Performance => reportable as Performance; + + #endregion + + #region additional functionality + + /// + /// Gets the HTML class attribute value indicating the outcome of a given reportable step within a scenario. + /// + /// The reportable's outcome class. + public string GetOutcomeClass() + { + switch(reportable.Outcome) + { + case PerformanceOutcome.Success: + case PerformanceOutcome.SuccessWithResult: + return GetOutcomeClass(true, false); + + default: + return GetOutcomeClass(false, true); + } + } + + /// + /// Gets an HTML class attribute value which describes a reportable step within a scenario. + /// + /// The reportable class. + public string GetReportableClass() + { + if(reportable is GainAbility) + return ReportConstants.AbilityClass; + + if(reportable is Performance) + return ReportConstants.PerformanceClass; + + return String.Empty; + } + + /// + /// Gets the string report for an ability. + /// + /// The ability report. + public string GetAbilityReport() + { + if(Ability == null) return String.Empty; + return Ability.GetReport(Actor); + } + + /// + /// Gets the string report for a performance. + /// + /// The performance report. + public string GetPerformanceReport() + { + if(Performable == null) return String.Empty; + return Performable.GetReport(Actor); + } + + /// + /// Gets the name of the METAL macro to use for rendering the specified reportable. + /// + /// The macro name. + public string GetMacroName() + { + if(reportable == null) return null; + + if(reportable is GainAbility) + return GetMacroName((GainAbility) reportable); + + if(reportable is Performance) + return GetMacroName((Performance) reportable); + + return null; + } + + /// + /// Formats a given object using a formatting service. + /// + public string GetFormattedResult() => formattingService.Format(Result); + + /// + /// Formats a given object using a formatting service. + /// + public string GetFormattedException() => formattingService.Format(Exception); + + /// + /// Gets a value indicating whether or not an exception can be formatted. + /// + /// true, if exception can be formatted, false otherwise. + public bool CanFormatException() + => Exception != null && formattingService.HasExplicitSupport(Exception); + + string GetMacroName(GainAbility ability) => ReportConstants.AbilityMacro; + + string GetMacroName(Performance performance) + { + switch(performance.Outcome) + { + case PerformanceOutcome.SuccessWithResult: + return ReportConstants.PerformanceWithResultMacro; + + case PerformanceOutcome.FailureWithException: + return ReportConstants.PerformanceWithExceptionMacro; + + default: + return ReportConstants.PerformanceMacro; + } + } + + string GetOutcomeClass(bool success, bool failure) + { + if(success) return ReportConstants.SuccessClass; + if(failure) return ReportConstants.FailureClass; + return ReportConstants.InconclusiveClass; + } + + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// Reportable. + /// Formatting service. + public ReportableModel(Reportable reportable, IObjectFormattingService formattingService) + { + if(formattingService == null) + throw new ArgumentNullException(nameof(formattingService)); + if(reportable == null) + throw new ArgumentNullException(nameof(reportable)); + + this.reportable = reportable; + this.formattingService = formattingService; + } + } +} diff --git a/CSF.Screenplay.Reporting.Html/Models/ScenarioModel.cs b/CSF.Screenplay.Reporting.Html/Models/ScenarioModel.cs new file mode 100644 index 00000000..67855ce4 --- /dev/null +++ b/CSF.Screenplay.Reporting.Html/Models/ScenarioModel.cs @@ -0,0 +1,131 @@ +// +// ScenarioModel.cs +// +// Author: +// Craig Fowler +// +// Copyright (c) 2018 Craig Fowler +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using System.Linq; + +namespace CSF.Screenplay.Reporting.Models +{ + /// + /// Model for HTML report scenarios (wraps a instance). + /// + public class ScenarioModel + { + readonly Scenario scenario; + readonly IObjectFormattingService formattingService; + + /// + /// Gets the unique identifier name of the scenario. + /// + /// The identifier. + public virtual string Id => scenario.Id; + + /// + /// Gets the name of the scenario. + /// + /// The scenario name. + public virtual string FriendlyName => scenario.FriendlyName; + + /// + /// Gets the name of the feature. + /// + /// The feature name. + public virtual string FeatureName => scenario.FeatureName; + + /// + /// Gets the identifier for the feature. + /// + /// The feature identifier. + public virtual string FeatureId => scenario.FeatureId; + + /// + /// Gets the contained reportables. + /// + /// The reportables. + public virtual IReadOnlyList Reportables + => scenario.Reportables.Select(x => new ReportableModel(x, formattingService)).ToArray(); + + /// + /// Gets or sets the outcome for the test scenario. + /// + /// The outcome. + public virtual bool? Outcome => scenario.Outcome; + + /// + /// Gets or sets a value indicating whether this + /// is inconclusive (neither success nor failure). + /// + /// true if this scenario is inconclusive; otherwise, false. + public virtual bool IsInconclusive => scenario.IsInconclusive; + + /// + /// Gets or sets a value indicating whether this + /// is a failure. + /// + /// true if this scenario is a failure; otherwise, false. + public virtual bool IsFailure => scenario.IsFailure; + + /// + /// Gets a value indicating whether this is a success. + /// + /// true if is success; otherwise, false. + public virtual bool IsSuccess => scenario.IsSuccess; + + /// + /// Gets the HTML class attribute value indicating the outcome of a given scenario. + /// + /// The scenario outcome class. + public string GetOutcomeClass() + { + if(scenario == null) return String.Empty; + var outcome = GetOutcomeClass(scenario.IsSuccess, scenario.IsFailure); + return $"scenario {outcome}"; + } + + string GetOutcomeClass(bool success, bool failure) + { + if(success) return ReportConstants.SuccessClass; + if(failure) return ReportConstants.FailureClass; + return ReportConstants.InconclusiveClass; + } + + /// + /// Initializes a new instance of the class. + /// + /// Scenario. + /// Formatting service. + public ScenarioModel(Scenario scenario, IObjectFormattingService formattingService) + { + if(formattingService == null) + throw new ArgumentNullException(nameof(formattingService)); + if(scenario == null) + throw new ArgumentNullException(nameof(scenario)); + + this.scenario = scenario; + this.formattingService = formattingService; + } + } +} diff --git a/CSF.Screenplay.Reporting.Html/Views/DocumentTemplate.pt b/CSF.Screenplay.Reporting.Html/Views/DocumentTemplate.pt index e4a9a249..9f0b4676 100644 --- a/CSF.Screenplay.Reporting.Html/Views/DocumentTemplate.pt +++ b/CSF.Screenplay.Reporting.Html/Views/DocumentTemplate.pt @@ -55,7 +55,7 @@
+ myMacros template/macros">
  • @@ -85,8 +85,8 @@
  • @@ -113,10 +113,7 @@

    Given Joe is able to browse the web

    @@ -129,10 +126,7 @@

    When Joe attempts to do a thing

    1. - @@ -175,7 +169,7 @@ metal:fill-slot="extended_content">

      Result - The performance result + The performance result

    @@ -194,12 +188,12 @@
    -

    + canFormatException reportable/CanFormatException"> +

    Failed - The formatted exception + The formatted exception

    -

    +

    Failed with an exception

    Exception
       at My.Funky.Stack.Trace.Line1 > Something
    @@ -219,7 +213,7 @@
         
  • + tal:attributes="class feature/GetOutcomeClass">
    @@ -234,7 +228,7 @@
    • + tal:attributes="class scenario/GetOutcomeClass">
      @@ -248,9 +242,9 @@
        + rootReportable string:true">
      1. -
        @@ -310,8 +304,8 @@
-