/// <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)); }
public ContextualCompositeStepBuilder(ICompositeStepBuilder runner, Func <object> contextProvider, bool takeOwnership) { _target = runner.Integrate().WithStepContext(contextProvider, takeOwnership); }
public ContextualCompositeStepBuilder(ICompositeStepBuilder runner, Func <IDependencyResolver, object> contextResolver) { _target = runner.Integrate().WithStepContext(contextResolver); }
/// <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); }
/// <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)); }
/// <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<SpeditionContext>().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); }
private static ExtendedCompositeStepBuilder <TContext> AsExtended <TContext>(this ICompositeStepBuilder <TContext> runner) { return(runner.Integrate().Enrich(ExtendedCompositeStepBuilder <TContext> .Create)); }
/// <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); }