/// <summary>
        /// Adds steps specified by <paramref name="steps"/> parameter to the composite step.<br/>
        /// The step name is determined from lambda parameter name reflecting action type keyword, corresponding action name and passed list of parameters to called method.<br/>
        /// If scenario is defined with context, the context instance is provided with lambda parameter.<br/>
        /// Example usage:
        /// <code>
        /// AddSteps(
        ///         _ => Given_numbers(5, 8),
        ///         _ => When_I_add_them(),
        ///         _ => I_should_receive_number(13))
        /// </code>
        /// Expected step signature: <code>void Given_numbers(params int[] numbers) { /* ... */ }</code>
        /// </summary>
        /// <param name="builder">Builder.</param>
        /// <param name="steps">Steps to add, like: <c>AddSteps(_ => Given_numbers(5, 8), _ => When_I_add_them(), _ => I_should_receive_number(13))</c></param>
        public static ICompositeStepBuilder <TContext> AddSteps <TContext>(this ICompositeStepBuilder <TContext> builder, params Expression <Action <TContext> >[] steps)
        {
            var coreBuilder = builder.Integrate();
            var compiler    = new ExtendedStepCompiler <TContext>(coreBuilder.Configuration);

            coreBuilder.AddSteps(steps.Select(compiler.ToStep));
            return(builder);
        }
 /// <summary>
 /// Specifies that composite step will be executed in dedicated context <typeparamref name="TContext"/> type.<br/>
 /// The <paramref name="onConfigure"/> function can be used to configure the context after instantiation.<br/>
 /// The context instance will be created by calling default constructor just before composite step execution.<br/>
 /// All context instances implementing <see cref="IDisposable"/> interface will be disposed after composite step execution.
 /// </summary>
 /// <param name="runner"><see cref="ICompositeStepBuilder"/> instance.</param>
 /// <param name="onConfigure">Custom context configuration executed after context creation. Can be null.</param>
 /// <typeparam name="TContext">Context type.</typeparam>
 /// <returns>Contextual runner.</returns>
 public static ICompositeStepBuilder <TContext> WithContext <TContext>(this ICompositeStepBuilder runner, Action <TContext> onConfigure)
 {
     return(new ContextualCompositeStepBuilder <TContext>(runner, resolver =>
     {
         var context = resolver.Resolve <TContext>();
         onConfigure?.Invoke(context);
         return context;
     }));
 }
 /// <summary>
 /// Specifies that composite step will be executed in dedicated context <typeparamref name="TContext"/> type, created by <paramref name="contextFactory"/> function.<br/>
 /// The <paramref name="onConfigure"/> function can be used to configure the context after instantiation.<br/>
 /// The context instance will be created by calling default constructor just before composite step execution.<br/>
 /// All context instances implementing <see cref="IDisposable"/> interface will be disposed after composite step execution.
 /// </summary>
 /// <param name="runner"><see cref="ICompositeStepBuilder"/> instance.</param>
 /// <param name="contextFactory">Context factory function.</param>
 /// <param name="onConfigure">Custom context configuration executed after context creation. Can be null.</param>
 /// <typeparam name="TContext">Context type.</typeparam>
 /// <returns>Contextual runner.</returns>
 public static ICompositeStepBuilder <TContext> WithContext <TContext>(this ICompositeStepBuilder runner, Func <IDependencyResolver, TContext> contextFactory, Action <TContext> onConfigure = null)
 {
     return(new ContextualCompositeStepBuilder <TContext>(runner, resolver =>
     {
         var context = contextFactory.Invoke(resolver);
         onConfigure?.Invoke(context);
         return context;
     }));
 }
        /// <summary>
        /// Method allowing to retrieve the <see cref="IIntegrableCompositeStepBuilder"/> instance allowing to add steps to composite step or scenario that is currently being defined.
        /// This method is dedicated for projects extending LightBDD with user friendly API for defining steps - it should not be used directly by regular LightBDD users.
        /// </summary>
        /// <typeparam name="TContext">Step context type.</typeparam>
        /// <param name="builder">Builder.</param>
        /// <returns>Instance of <see cref="IIntegrableCompositeStepBuilder"/>.</returns>
        /// <exception cref="NotSupportedException">Thrown if <paramref name="builder"/> does not implement <see cref="IIntegrableCompositeStepBuilder"/>.</exception>
        public static IIntegrableCompositeStepBuilder Integrate <TContext>(this ICompositeStepBuilder <TContext> builder)
        {
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }

            if (!(builder is IIntegrableCompositeStepBuilder))
            {
                throw new NotSupportedException($"The type '{builder.GetType().Name}' has to implement '{nameof(IIntegrableCompositeStepBuilder)}' interface to support integration.");
            }

            return((IIntegrableCompositeStepBuilder)builder);
        }
 public void SetUp()
 {
     _builder = new TestableCompositeStepBuilder();
 }
 /// <summary>
 /// Specifies that composite step will be executed in dedicated context <typeparamref name="TContext"/> type.<br/>
 /// The context instance will be created by calling default constructor just before composite step execution.<br/>
 /// All context instances implementing <see cref="IDisposable"/> interface will be disposed after composite step execution.
 /// </summary>
 /// <param name="runner"><see cref="ICompositeStepBuilder"/> instance.</param>
 /// <typeparam name="TContext">Context type.</typeparam>
 /// <returns>Contextual runner.</returns>
 public static ICompositeStepBuilder <TContext> WithContext <TContext>(this ICompositeStepBuilder runner)
 {
     return(new ContextualCompositeStepBuilder <TContext>(runner, resolver => resolver.Resolve(typeof(TContext))));
 }
 /// <summary>
 /// Specifies that composite step will be executed in dedicated <paramref name="context"/> of <typeparamref name="TContext"/> type.<br/>
 /// The <paramref name="takeOwnership"/> specifies if created context should be disposed (when implements <see cref="IDisposable"/> interface) by runner. By default is it set to <c>false</c>.
 /// </summary>
 /// <typeparam name="TContext">Context type.</typeparam>
 /// <param name="runner"><see cref="ICompositeStepBuilder"/> instance.</param>
 /// <param name="context">Context instance.</param>
 /// <param name="takeOwnership">Specifies if scenario runner should take ownership of the context instance. If set to true and context instance implements <see cref="IDisposable"/>, it will be disposed after composite step finish.</param>
 /// <returns>Contextual runner.</returns>
 public static ICompositeStepBuilder <TContext> WithContext <TContext>(this ICompositeStepBuilder runner, TContext context, bool takeOwnership = false)
 {
     return(new ContextualCompositeStepBuilder <TContext>(runner, () => context, takeOwnership));
 }
 /// <summary>
 /// Specifies that composite step will be executed in dedicated context of <typeparamref name="TContext"/> type, created by <paramref name="contextFactory"/> function.<br/>
 /// The <paramref name="takeOwnership"/> specifies if created context should be disposed (when implements <see cref="IDisposable"/> interface) by runner. By default is it set to <c>true</c>.
 /// </summary>
 /// <typeparam name="TContext">Context type.</typeparam>
 /// <param name="runner"><see cref="ICompositeStepBuilder"/> instance.</param>
 /// <param name="contextFactory">Context factory function.</param>
 /// <param name="takeOwnership">Specifies if scenario runner should take ownership of the context instance. If set to true and context instance implements <see cref="IDisposable"/>, it will be disposed after scenario finish.</param>
 /// <returns>Contextual runner.</returns>
 public static ICompositeStepBuilder <TContext> WithContext <TContext>(this ICompositeStepBuilder runner, Func <TContext> contextFactory, bool takeOwnership = true)
 {
     return(new ContextualCompositeStepBuilder <TContext>(runner, () => contextFactory(), takeOwnership));
 }
Beispiel #9
0
 public ContextualCompositeStepBuilder(ICompositeStepBuilder runner, Func <object> contextProvider, bool takeOwnership)
 {
     _target = runner.Integrate().WithStepContext(contextProvider, takeOwnership);
 }
Beispiel #10
0
 public ContextualCompositeStepBuilder(ICompositeStepBuilder runner, Func <IDependencyResolver, object> contextResolver)
 {
     _target = runner.Integrate().WithStepContext(contextResolver);
 }
Beispiel #11
0
 /// <summary>
 /// Adds asynchronous step with name specified by <paramref name="name"/> parameter and action specified by <paramref name="step"/> parameter to the composite step.
 /// </summary>
 /// <typeparam name="TContext">Scenario context, if specified.</typeparam>
 /// <param name="builder">Builder.</param>
 /// <param name="name">Step name to be rendered.</param>
 /// <param name="step">Step action</param>
 /// <returns>Builder.</returns>
 public static ICompositeStepBuilder <TContext> AddAsyncStep <TContext>(this ICompositeStepBuilder <TContext> builder, string name, Func <TContext, Task> step)
 {
     builder.Integrate().AddSteps(new[] { CompactStepCompiler.ToAsynchronousStep(name, step) });
     return(builder);
 }
Beispiel #12
0
 /// <summary>
 /// Returns runner that will be executing scenarios in dedicated context of <typeparamref name="TContext"/> type.<br/>
 /// The context instance will be created by calling default constructor just before scenario execution.
 ///
 /// All context instances implementing <see cref="IDisposable"/> interface will be disposed after scenario.
 /// </summary>
 /// <param name="runner"><see cref="ICompositeStepBuilder"/> instance.</param>
 /// <typeparam name="TContext">Context type.</typeparam>
 /// <returns>Contextual runner.</returns>
 public static ICompositeStepBuilder <TContext> WithContext <TContext>(this ICompositeStepBuilder runner) where TContext : new()
 {
     return(new ContextualCompositeStepBuilder <TContext>(runner, () => new TContext(), true));
 }
Beispiel #13
0
 /// <summary>
 /// Adds steps specified by <paramref name="steps"/> parameter.<br/>
 /// The steps would be executed in specified order.<br/>
 /// If given step throws, other are not executed.<br/>
 /// Step name is determined from lambda parameter name reflecting action type keyword, corresponding action name and passed list of parameters to called method.<br/>
 /// If scenario is executed with context, the context instance is provided with lambda parameter.
 /// Please note that rules for placing parameter values in step name are as follows, where first matching rule would be used:
 /// <list type="bullet">
 /// <item><description>it will replace first occurrence of variable name written in capital letters (<c>void Price_is_AMOUNT_dollars(int amount)</c> => <c>Price is "27" dollars</c>)</description></item>
 /// <item><description>it will placed after first occurrence of variable name (<c>void Product_is_in_stock(string product)</c> => <c>Product "desk" is in stock</c>)</description></item>
 /// <item><description>it will placed at the end of step name (<c>void Product_is_in_stock(string productId)</c> => <c>Product is in stock [productId: "ABC123"]</c>)</description></item>
 /// </list>
 /// <para>
 /// Example usage for scenarios with no context:
 /// <code>
 /// builder.AddSteps(
 ///     _ => Given_product_is_available_in_product_storage("wooden desk"),
 ///     _ => When_customer_buys_product("wooden desk"),
 ///     _ => Then_invoice_should_contain_product_with_price_of_AMOUNT_pounds("wooden desk", 62));
 /// </code>
 /// Expected step signature:
 /// <code>
 /// void Given_product_is_available_in_product_storage(string product) { /* ... */ }
 /// </code>
 /// </para>
 /// <para>
 /// Example usage for scenarios with context:
 /// <code>
 /// builder.WithContext&lt;SpeditionContext&gt;().AddSteps(
 ///     _ => _.Given_there_is_an_active_customer_with_id("ABC-123"),
 ///     _ => _.Given_the_customer_has_product_in_basket("wooden shelf"),
 ///     _ => _.When_the_customer_payment_finalizes(),
 ///     _ => _.Then_product_should_be_dispatched_to_the_customer("wooden shelf"));
 /// </code>
 /// Expected step signature:
 /// <code>
 /// class SpeditionContext
 /// {
 ///     void Given_product_is_available_in_product_storage(string product) { /* ... */ }
 /// }
 /// </code>
 /// </para>
 /// </summary>
 /// <param name="builder">Composite step builder.</param>
 /// <param name="steps">Steps to add.</param>
 /// <returns><paramref name="builder"/> instance.</returns>
 public static ICompositeStepBuilder <TContext> AddSteps <TContext>(this ICompositeStepBuilder <TContext> builder, params Expression <Action <TContext> >[] steps)
 {
     AsExtended(builder).AddSteps(steps);
     return(builder);
 }
Beispiel #14
0
 private static ExtendedCompositeStepBuilder <TContext> AsExtended <TContext>(this ICompositeStepBuilder <TContext> runner)
 {
     return(runner.Integrate().Enrich(ExtendedCompositeStepBuilder <TContext> .Create));
 }
Beispiel #15
0
 /// <summary>
 /// Adds steps specified by <paramref name="steps"/> parameter.<br/>
 /// The steps would be executed in specified order.<br/>
 /// If given step throws, other are not executed.<br/>
 /// The step name is determined from corresponding action name.<br/>
 /// Example usage:
 /// <code>
 /// builder.AddAsyncSteps(
 ///     Given_the_user_is_about_to_login,
 ///     Given_the_user_entered_valid_login,
 ///     Given_the_user_entered_valid_password,
 ///     When_the_user_clicks_login_button,
 ///     Then_the_login_operation_should_be_successful,
 ///     Then_a_welcome_message_containing_user_name_should_be_returned);
 /// </code>
 /// Expected step signature:
 /// <code>
 /// async Task Given_the_user_is_about_to_login() { /* ... */ }
 /// </code>
 /// </summary>
 /// <param name="builder">Composite step builder.</param>
 /// <param name="steps">Steps to add.</param>
 /// <returns><paramref name="builder"/> instance.</returns>
 public static ICompositeStepBuilder <NoContext> AddAsyncSteps(this ICompositeStepBuilder <NoContext> builder, params Func <Task>[] steps)
 {
     builder.Integrate().AddSteps(steps.Select(BasicStepCompiler.ToAsynchronousStep));
     return(builder);
 }