rust-actions 0.2.1

BDD testing framework with GitHub Actions YAML syntax
Documentation
use crate::parser::Step;
use crate::runner::StepResult;
use crate::world::World;
use std::future::Future;
use std::pin::Pin;

pub type BeforeAllFn = fn() -> Pin<Box<dyn Future<Output = ()> + Send>>;
pub type AfterAllFn = fn() -> Pin<Box<dyn Future<Output = ()> + Send>>;
pub type BeforeScenarioFn<W> = for<'a> fn(&'a mut W) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
pub type AfterScenarioFn<W> = for<'a> fn(&'a mut W) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
pub type BeforeStepFn<W> = for<'a> fn(&'a mut W, &'a Step) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
pub type AfterStepFn<W> =
    for<'a> fn(&'a mut W, &'a Step, &'a StepResult) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>;

pub enum HookDef<W: World> {
    BeforeAll(BeforeAllFn),
    AfterAll(AfterAllFn),
    BeforeScenario(BeforeScenarioFn<W>),
    AfterScenario(AfterScenarioFn<W>),
    BeforeStep(BeforeStepFn<W>),
    AfterStep(AfterStepFn<W>),
}

impl<W: World> HookDef<W> {
    pub fn before_all(f: BeforeAllFn) -> Self {
        HookDef::BeforeAll(f)
    }

    pub fn after_all(f: AfterAllFn) -> Self {
        HookDef::AfterAll(f)
    }

    pub fn before_scenario(f: BeforeScenarioFn<W>) -> Self {
        HookDef::BeforeScenario(f)
    }

    pub fn after_scenario(f: AfterScenarioFn<W>) -> Self {
        HookDef::AfterScenario(f)
    }

    pub fn before_step(f: BeforeStepFn<W>) -> Self {
        HookDef::BeforeStep(f)
    }

    pub fn after_step(f: AfterStepFn<W>) -> Self {
        HookDef::AfterStep(f)
    }
}

pub struct HookRegistry<W: World> {
    before_all: Vec<BeforeAllFn>,
    after_all: Vec<AfterAllFn>,
    before_scenario: Vec<BeforeScenarioFn<W>>,
    after_scenario: Vec<AfterScenarioFn<W>>,
    before_step: Vec<BeforeStepFn<W>>,
    after_step: Vec<AfterStepFn<W>>,
}

impl<W: World> HookRegistry<W> {
    pub fn new() -> Self {
        Self {
            before_all: Vec::new(),
            after_all: Vec::new(),
            before_scenario: Vec::new(),
            after_scenario: Vec::new(),
            before_step: Vec::new(),
            after_step: Vec::new(),
        }
    }

    pub fn register(&mut self, hook: HookDef<W>) {
        match hook {
            HookDef::BeforeAll(f) => self.before_all.push(f),
            HookDef::AfterAll(f) => self.after_all.push(f),
            HookDef::BeforeScenario(f) => self.before_scenario.push(f),
            HookDef::AfterScenario(f) => self.after_scenario.push(f),
            HookDef::BeforeStep(f) => self.before_step.push(f),
            HookDef::AfterStep(f) => self.after_step.push(f),
        }
    }

    pub async fn run_before_all(&self) {
        for hook in &self.before_all {
            hook().await;
        }
    }

    pub async fn run_after_all(&self) {
        for hook in &self.after_all {
            hook().await;
        }
    }

    pub async fn run_before_scenario(&self, world: &mut W) {
        for hook in &self.before_scenario {
            hook(world).await;
        }
    }

    pub async fn run_after_scenario(&self, world: &mut W) {
        for hook in &self.after_scenario {
            hook(world).await;
        }
    }

    pub async fn run_before_step(&self, world: &mut W, step: &Step) {
        for hook in &self.before_step {
            hook(world, step).await;
        }
    }

    pub async fn run_after_step(&self, world: &mut W, step: &Step, result: &StepResult) {
        for hook in &self.after_step {
            hook(world, step, result).await;
        }
    }
}

impl<W: World> Default for HookRegistry<W> {
    fn default() -> Self {
        Self::new()
    }
}