All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.serenitybdd.screenplay.Actor Maven / Gradle / Ivy

There is a newer version: 1.1.26-rc.1
Show newest version
package net.serenitybdd.screenplay;

import com.google.common.base.Optional;
import net.serenitybdd.core.PendingStepException;
import net.serenitybdd.core.Serenity;
import net.serenitybdd.core.SkipNested;
import net.serenitybdd.core.eventbus.Broadcaster;
import net.serenitybdd.screenplay.events.*;
import net.serenitybdd.screenplay.exceptions.IgnoreStepException;
import net.serenitybdd.screenplay.formatting.FormattedTitle;
import net.thucydides.core.annotations.Pending;
import net.thucydides.core.steps.StepEventBus;

import java.lang.reflect.Method;
import java.util.Map;

import static com.google.common.collect.Maps.newHashMap;

public class Actor implements PerformsTasks, SkipNested {

    private final String name;

    private final PerformedTaskTally taskTally = new PerformedTaskTally();
    private EventBusInterface eventBusInterface = new EventBusInterface();
    private ConsequenceListener consequenceListener = new ConsequenceListener(eventBusInterface);

    private Map notepad = newHashMap();
    private Map abilities = newHashMap();

    public Actor(String name) {
        this.name = name;
    }

    public String toString() {
        return name;
    }

    public static Actor named(String name) {
        return new Actor(name);
    }

    public String getName() {
        return name;
    }

    public  Actor can(T doSomething) {
        doSomething.asActor(this);
        abilities.put(doSomething.getClass(), doSomething);
        return this;
    }

    @SuppressWarnings("unchecked")
    public  T abilityTo(Class doSomething) {
        return (T) abilities.get(doSomething);
    }

    public final void has(Performable... todos) {
        attemptsTo(todos);
    }

    /**
     * A tense-neutral synonyme for has() for use with given() clauses
     */
    public final void wasAbleTo(Performable... todos) {
        attemptsTo(todos);
    }

    public final void attemptsTo(Performable... tasks) {
        beginPerformance();
        for (Performable task : tasks) {
            perform(task);
        }
        endPerformance();
    }

    public  ANSWER asksFor(Question question) {
        return question.answeredBy(this);
    }

    private  void perform(T todo) {
        if (isPending(todo)) {
            StepEventBus.getEventBus().stepPending();
        }
        try {
            notifyPerformanceOf(todo);
            taskTally.newTask();
            todo.performAs(this);

            if (anOutOfStepErrorOccurred()) {
                eventBusInterface.mergePreviousStep();
            }
        } catch (Throwable exception) {
            if (!pendingOrIgnore(exception)) {
                eventBusInterface.reportStepFailureFor(todo, exception);
            }
            if (Serenity.shouldThrowErrorsImmediately() || isAnAssumptionFailure(exception)) {
                throw exception;
            }
        } finally {
            eventBusInterface.updateOverallResult();
        }
    }

    private  void notifyPerformanceOf(T todo) {
        Broadcaster.getEventBus().post(new ActorPerforms(todo));
    }

    private  boolean isPending(T todo) {
            Method performAs = getPerformAsForClass(todo.getClass().getSuperclass()).
                               or(getPerformAsForClass(todo.getClass()).orNull());

            return (performAs != null) && (performAs.getAnnotation(Pending.class) != null);
    }

    private Optional getPerformAsForClass(Class taskClass) {
        try {
            return Optional.of(taskClass.getMethod("performAs", Actor.class));
        } catch (NoSuchMethodException e) {
            return Optional.absent();
        }
    }

    private  void logSkippedTask() {
        StepEventBus.getEventBus().testSkipped();
    }

    private boolean pendingOrIgnore(Throwable exception) {
        return exception instanceof IgnoreStepException ||
                exception instanceof PendingStepException;
    }

    private boolean isAnAssumptionFailure(Throwable e) {
        return e.getClass().getSimpleName().contains("Assumption");
    }

    public final void can(Consequence... consequences) {
        should(consequences);
    }



    public final void should(Consequence... consequences) {

        ErrorTally errorTally = new ErrorTally(eventBusInterface);

        startConsequenceCheck();

        for (Consequence consequence : consequences) {
            check(consequence, errorTally);
        }

        endConsequenceCheck();

        errorTally.reportAnyErrors();

    }

    private boolean anOutOfStepErrorOccurred() {
        return eventBusInterface.aStepHasFailed()
                && eventBusInterface.getStepCount() > taskTally.getPerformedTaskCount();
    }

    private  void check(Consequence consequence, ErrorTally errorTally) {
        try {
            eventBusInterface.reportNewStepWithTitle(FormattedTitle.ofConsequence(consequence));
            if (eventBusInterface.shouldIgnoreConsequences()) {
                StepEventBus.getEventBus().stepIgnored();
            } else {
                consequence.evaluateFor(this);
            }
            eventBusInterface.reportStepFinished();
        } catch (IgnoreStepException e) {
            eventBusInterface.reportStepIgnored();
        } catch (Throwable e) {
            errorTally.recordError(consequence, e);
        }
    }

    public  void remember(String key, Question question) {
        ANSWER answer = this.asksFor(question);
        notepad.put(key, answer);
    }

    public void remember(String key, Object value) {
        notepad.put(key, value);
    }

    @SuppressWarnings("unchecked")
    public  T recall(String key) {
        return (T) notepad.get(key);
    }

    public  T sawAsThe(String key) {
        return recall(key);
    }

    public  T gaveAsThe(String key) {
        return recall(key);
    }

    private void beginPerformance() {
        Broadcaster.getEventBus().post(new ActorBeginsPerformanceEvent(name));
    }

    private void endPerformance() {
        Broadcaster.getEventBus().post(new ActorEndsPerformanceEvent(name));
    }


    private void startConsequenceCheck() {
        consequenceListener.beginConsequenceCheck();
        Broadcaster.getEventBus().post(new ActorBeginsConsequenceCheckEvent(name));
    }

    private void endConsequenceCheck() {
        consequenceListener.endConsequenceCheck();
        Broadcaster.getEventBus().post(new ActorEndsConsequenceCheckEvent(name));
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy