Implementing actions - Galad/tranquire GitHub Wiki

Introduction

Interfaces

There are 2 interfaces that represent an action: IAction<T> and IAction<TAbility, T>. You should choose to implement IAction<T> when your action does not have any direct dependency. Typically, you can choose to implement this interface when the action only call other actions. On the other hand, you should choose to implement IAction<TAbility, T> when your action requires a direct dependency, for instance a Selenium WebDriver instance.

Methods to implement

The IAction interfaces require to implement 2 methods, ExecuteGiven and ExecuteWhen, and the property Name. The name is a string value that allow to identify what an action does, and is used in the logs. The methods ExecuteGiven and ExecuteWhen allow you do define different way to perform the action, depending on whether the first action was called with the Given or the When method.

Each methods provides a IActor instance, that you can use to execute other actions.

In order to simplify implementing actions, Tranquire provides abstract classes that you can inherit (see below).

Return value

Actions can return a value, which type is defined in the generic type of the interface. Most of the time, you won't need to return a value, so you can use the type Unit to indicates that the action does not return a value. Unit is a type that has a single possible value (Unit.Default). It is similar to creating a method with void.

Implementing IAction<T>

This interface is used for actions that do not require a dependency. It is recommended to use one of the following abstract class:

  • ActionUnit
  • Action

Both base class requires to implement only ExecuteWhen. If ExecuteGiven is not overridden and the action is executed in the Given context, the method ExecuteWhen will be used instead.

ActionUnit

The abstract class ActionUnit can be used to implement an action that does not return a value. Here is an example:

public class AddItem : ActionUnit
{
    private readonly Item item;

    public AddItemWithId(Item item)
    {
        this.item = item;
    }

    public override string Name => "Generate an access token";

    protected override void ExecuteWhen(IActor actor)
    {
        actor.Execute(Click.On(ItemTextArea));
        actor.Execute(Enter.TheValue(this.item.Name));
        actor.Execute(Click.On(AddButton));
    }
}

Action<T>

The abstract class Action<T> (do not confound with the System.Action<T> delegate) can be used to implement an action that returns a value. Here is an example of an action that creates an item and returns the ID that is generated by the SUT. Such an action can be used to combine it with another action that needs the ID to work:

public class AddItemWithId : Action<string>
{
    private readonly Item item;

    public AddItemWithId(Item item)
    {
        this.item = item;
    }

    public override string Name => "Generate an access token";

    protected override string ExecuteWhen(IActor actor)
    {
        actor.Execute(Add.Item(this.item));
        return actor.AsksFor(Get.ItemIdOf(this.item.Name));
    }
}

Implementing IAction<TAbility, T>

This interface is used for actions that require a dependency. It is recommended to use one of the following abstract class:

  • ActionUnit
  • Action<TAbility, TResult>

ActionUnit<T>

The abstract class Action<TAbility, TResult> can be used to implement an action that require an ability, and does not return a result. Here is an example:

public sealed class Clear : ActionUnit<WebBrowser>
{
    public ITarget Target { get; }

    public override string Name => "Click on " + Target.Name;

    public Clear(ITarget target)
    {
        Guard.ForNull(target, nameof(target));
        Target = target;
    }

    protected override void ExecuteWhen(IActor actor, WebBrowser ability)
    {
        var element = Target.ResolveFor(ability);
        element.SendKeys(Keys.LeftShift + Keys.Home);
        element.SendKeys(Keys.Backspace);
    }
}

Action<TAbility, TResult>

The abstract class Action<TAbility, TResult> can be used to implement an action that require an ability, and returns a result.

⚠️ **GitHub.com Fallback** ⚠️