Skip to content

Commit

Permalink
#225 Implemented ProgressNotifierConfiguration
Browse files Browse the repository at this point in the history
  • Loading branch information
Suremaker committed Feb 27, 2021
1 parent 8447eea commit a1d67b8
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

namespace LightBDD.Core.Notification.Implementation
{
//TODO: remove in LightBDD 4.x
class NotificationAdapter : IProgressNotifier
{
private readonly IFeatureProgressNotifier _featureProgressNotifier;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public static FeatureProgressNotifierConfiguration FeatureProgressNotifierConfig
{
return configuration.Get<FeatureProgressNotifierConfiguration>();
}

/// <summary>
/// Retrieves <see cref="ScenarioProgressNotifierConfiguration"/> from <paramref name="configuration"/> for further customizations.
/// </summary>
Expand All @@ -73,6 +74,16 @@ public static ScenarioProgressNotifierConfiguration ScenarioProgressNotifierConf
return configuration.Get<ScenarioProgressNotifierConfiguration>();
}

/// <summary>
/// Retrieves <see cref="ProgressNotifierConfiguration"/> from <paramref name="configuration"/> for further customizations.
/// </summary>
/// <param name="configuration">Configuration object.</param>
/// <returns>Configuration object.</returns>
public static ProgressNotifierConfiguration ProgressNotifierConfiguration(this LightBddConfiguration configuration)
{
return configuration.Get<ProgressNotifierConfiguration>();
}

/// <summary>
/// Adds <see cref="ReportFileWriter"/> instance configured to format report with <typeparamref name="TFormatter"/> and write it to <paramref name="outputPath"/>.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System;
using System.Linq;
using LightBDD.Core.Configuration;
using LightBDD.Core.Notification;
using LightBDD.Framework.Notification;
using LightBDD.Framework.Notification.Implementation;

namespace LightBDD.Framework.Configuration
{
/// <summary>
/// Configuration class allowing to customize scenario progress notification behavior.
/// </summary>
public class ProgressNotifierConfiguration : FeatureConfiguration
{
/// <summary>
/// Returns progress notifier.<br/>
/// By default it is configured to not report any notifications.
/// </summary>
public IProgressNotifier Notifier { get; private set; } = NoProgressNotifier.Default;

/// <summary>
/// Appends <paramref name="notifiers"/> to existing <see cref="Notifier"/> making all of them used during notification.
/// </summary>
/// <param name="notifiers">Notifiers to append</param>
/// <returns>Self</returns>
/// <exception cref="ArgumentNullException">Throws when <paramref name="notifiers"/> collection or any of it's item is null.</exception>
public ProgressNotifierConfiguration Append(params IProgressNotifier[] notifiers)
{
ThrowIfSealed();
if (notifiers == null)
throw new ArgumentNullException(nameof(notifiers));
Notifier = DelegatingProgressNotifier.Compose(Enumerable.Repeat(Notifier, 1).Concat(notifiers));
return this;
}

/// <summary>
/// Clears <see cref="Notifier"/> to use instance that does not report any notifications.
/// </summary>
/// <returns>Self.</returns>
public ProgressNotifierConfiguration Clear()
{
ThrowIfSealed();
Notifier = NoProgressNotifier.Default;
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ public class ScenarioProgressNotifierConfiguration : FeatureConfiguration
/// </summary>
public Func<object, IScenarioProgressNotifier> NotifierProvider => _composer.Clone().Compose;

internal bool HasAny => _composer.HasAny;

/// <summary>
/// Replaces the <see cref="NotifierProvider"/> with <paramref name="notifierProvider"/> value.
/// </summary>
Expand Down
14 changes: 14 additions & 0 deletions src/LightBDD.Framework/Extensibility/DefaultIntegrationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
using LightBDD.Core.Results;
using System;
using LightBDD.Framework.Configuration;
using LightBDD.Framework.Notification;
using LightBDD.Framework.Notification.Implementation;

namespace LightBDD.Framework.Extensibility
{
Expand Down Expand Up @@ -60,5 +62,17 @@ public DefaultIntegrationContext(LightBddConfiguration configuration, CoreMetada
ExecutionExtensions = configuration.ExecutionExtensionsConfiguration();
DependencyContainer = configuration.DependencyContainerConfiguration().DependencyContainer;
}

/// <inheritdoc />
protected override IProgressNotifier GetProgressNotifier()
{
var notifier = Configuration.ProgressNotifierConfiguration().Notifier;

if (Configuration.ScenarioProgressNotifierConfiguration().HasAny ||
FeatureProgressNotifier != NoProgressNotifier.Default)
notifier = DelegatingProgressNotifier.Compose(notifier, new NotificationAdapter(FeatureProgressNotifier, ScenarioProgressNotifierProvider));

return notifier;
}
}
}
32 changes: 31 additions & 1 deletion src/LightBDD.Framework/Notification/DefaultProgressNotifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using LightBDD.Core.Formatting;
using LightBDD.Core.Metadata;
using LightBDD.Core.Notification;
using LightBDD.Core.Notification.Events;
using LightBDD.Core.Results;
using LightBDD.Core.Results.Parameters.Tabular;
using LightBDD.Framework.Reporting.Formatters;
Expand All @@ -13,7 +14,7 @@ namespace LightBDD.Framework.Notification
/// <summary>
/// The default implementation of <see cref="IScenarioProgressNotifier"/> and <see cref="IFeatureProgressNotifier"/> which renders the notification text and delegates to provided notification actions configured in constructor.
/// </summary>
public class DefaultProgressNotifier : IScenarioProgressNotifier, IFeatureProgressNotifier
public class DefaultProgressNotifier : IScenarioProgressNotifier, IFeatureProgressNotifier, IProgressNotifier
{
private readonly Action<string> _onNotify;

Expand Down Expand Up @@ -110,6 +111,35 @@ public void NotifyFeatureFinished(IFeatureResult feature)
_onNotify($"FEATURE FINISHED: {feature.Info.Name}");
}

/// <inheritdoc />
public void Notify(ProgressEvent e)
{
switch (e)
{
case FeatureFinished featureFinished:
NotifyFeatureFinished(featureFinished.Result);
break;
case FeatureStarting featureStarting:
NotifyFeatureStart(featureStarting.Feature);
break;
case ScenarioFinished scenarioFinished:
NotifyScenarioFinished(scenarioFinished.Result);
break;
case ScenarioStarting scenarioStarting:
NotifyScenarioStart(scenarioStarting.Scenario);
break;
case StepCommented stepCommented:
NotifyStepComment(stepCommented.Step, stepCommented.Comment);
break;
case StepFinished stepFinished:
NotifyStepFinished(stepFinished.Result);
break;
case StepStarting stepStarting:
NotifyStepStart(stepStarting.Step);
break;
}
}

private static string FormatDescription(string description)
{
return string.IsNullOrWhiteSpace(description)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Collections.Generic;
using System.Linq;
using LightBDD.Core.Notification;
using LightBDD.Core.Notification.Events;

namespace LightBDD.Framework.Notification.Implementation
{
class DelegatingProgressNotifier : IProgressNotifier
{
private readonly IList<IProgressNotifier> _notifiers;
private DelegatingProgressNotifier(IList<IProgressNotifier> notifiers)
{
_notifiers = notifiers;
}

public void Notify(ProgressEvent e)
{
foreach (var notifier in _notifiers)
notifier.Notify(e);
}

public static IProgressNotifier Compose(params IProgressNotifier[] notifiers) => Compose(notifiers.AsEnumerable());

public static IProgressNotifier Compose(IEnumerable<IProgressNotifier> notifiers)
{
var result = Flatten(notifiers, new List<IProgressNotifier>());
if (result.Count > 1)
return new DelegatingProgressNotifier(result);

return result.FirstOrDefault() ?? NoProgressNotifier.Default;
}

private static List<IProgressNotifier> Flatten(IEnumerable<IProgressNotifier> notifiers, List<IProgressNotifier> results)
{
foreach (var notifier in notifiers ?? Enumerable.Empty<IProgressNotifier>())
{
if (notifier == null || notifier is NoProgressNotifier)
continue;
if (notifier is DelegatingProgressNotifier dp)
Flatten(dp._notifiers, results);
else
results.Add(notifier);
}

return results;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Threading;
using LightBDD.Core.ExecutionContext;
using LightBDD.Core.Notification;
using LightBDD.Core.Notification.Events;

namespace LightBDD.Framework.Notification.Implementation
{
//TODO: remove in LightBDD 4.x
class NotificationAdapter : IProgressNotifier
{
private readonly IFeatureProgressNotifier _featureProgressNotifier;
private readonly Func<object, IScenarioProgressNotifier> _scenarioProgressNotifierProvider;
private readonly AsyncLocal<IScenarioProgressNotifier> _scenarioNotifier = new AsyncLocal<IScenarioProgressNotifier>();

public NotificationAdapter(IFeatureProgressNotifier featureProgressNotifier, Func<object, IScenarioProgressNotifier> scenarioProgressNotifierProvider)
{
_featureProgressNotifier = featureProgressNotifier;
_scenarioProgressNotifierProvider = scenarioProgressNotifierProvider;
}

public void Notify(ProgressEvent e)
{
switch (e)
{
case FeatureStarting fs:
_featureProgressNotifier.NotifyFeatureStart(fs.Feature);
break;
case FeatureFinished ff:
_featureProgressNotifier.NotifyFeatureFinished(ff.Result);
break;
case ScenarioStarting ss:
HandleScenarioStarted(ss);
break;
case ScenarioFinished sf:
HandleScenarioFinished(sf);
break;
case StepStarting sts:
_scenarioNotifier.Value.NotifyStepStart(sts.Step);
break;
case StepFinished stf:
_scenarioNotifier.Value.NotifyStepFinished(stf.Result);
break;
case StepCommented sc:
_scenarioNotifier.Value.NotifyStepComment(sc.Step, sc.Comment);
break;
}
}

private void HandleScenarioStarted(ScenarioStarting scenarioStarting)
{
_scenarioNotifier.Value = _scenarioProgressNotifierProvider.Invoke(ScenarioExecutionContext.CurrentScenarioFixture);
_scenarioNotifier.Value.NotifyScenarioStart(scenarioStarting.Scenario);
}

private void HandleScenarioFinished(ScenarioFinished scenarioFinished)
{
_scenarioNotifier.Value.NotifyScenarioFinished(scenarioFinished.Result);
_scenarioNotifier.Value = null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
using System.Linq;
using LightBDD.Core.Metadata;
using LightBDD.Core.Notification;
using LightBDD.Core.Notification.Events;
using LightBDD.Core.Results;

namespace LightBDD.Framework.Notification.Implementation
{
internal class ParallelProgressNotifier : IScenarioProgressNotifier, IFeatureProgressNotifier
internal class ParallelProgressNotifier : IScenarioProgressNotifier, IFeatureProgressNotifier, IProgressNotifier
{
private readonly ProgressManager _manager;
private int? _currentScenarioNumber;
Expand Down Expand Up @@ -67,5 +68,33 @@ public void NotifyStepComment(IStepInfo step, string comment)
{
_notifier.NotifyStepComment(step, comment);
}

public void Notify(ProgressEvent e)
{
switch (e)
{
case FeatureFinished featureFinished:
NotifyFeatureFinished(featureFinished.Result);
break;
case FeatureStarting featureStarting:
NotifyFeatureStart(featureStarting.Feature);
break;
case ScenarioFinished scenarioFinished:
NotifyScenarioFinished(scenarioFinished.Result);
break;
case ScenarioStarting scenarioStarting:
NotifyScenarioStart(scenarioStarting.Scenario);
break;
case StepCommented stepCommented:
NotifyStepComment(stepCommented.Step, stepCommented.Comment);
break;
case StepFinished stepFinished:
NotifyStepFinished(stepFinished.Result);
break;
case StepStarting stepStarting:
NotifyStepStart(stepStarting.Step);
break;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ internal class ScenarioProgressNotifierComposer
{
private readonly List<IScenarioProgressNotifierProvider> _providers;

public bool HasAny => _providers.Count > 0;

public ScenarioProgressNotifierComposer() : this(new List<IScenarioProgressNotifierProvider>())
{
}

private ScenarioProgressNotifierComposer(List<IScenarioProgressNotifierProvider> providers)
{
_providers = providers;
Expand Down
7 changes: 6 additions & 1 deletion src/LightBDD.Framework/Notification/NoProgressNotifier.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
using LightBDD.Core.Metadata;
using LightBDD.Core.Notification;
using LightBDD.Core.Notification.Events;
using LightBDD.Core.Results;

namespace LightBDD.Framework.Notification
{
/// <summary>
/// Progress notifier implementation that does nothing when called.
/// </summary>
public class NoProgressNotifier : IFeatureProgressNotifier, IScenarioProgressNotifier
public class NoProgressNotifier : IFeatureProgressNotifier, IScenarioProgressNotifier, IProgressNotifier
{
private NoProgressNotifier() { }
/// <summary>
Expand Down Expand Up @@ -42,5 +43,9 @@ public class NoProgressNotifier : IFeatureProgressNotifier, IScenarioProgressNot
/// Does nothing.
/// </summary>
public void NotifyStepComment(IStepInfo step, string comment) { }
/// <summary>
/// Does nothing.
/// </summary>
public void Notify(ProgressEvent e) { }
}
}
Loading

0 comments on commit a1d67b8

Please sign in to comment.