rust_actions/
hooks.rs

1use crate::parser::Step;
2use crate::runner::StepResult;
3use crate::world::World;
4use std::future::Future;
5use std::pin::Pin;
6
7pub type BeforeAllFn = fn() -> Pin<Box<dyn Future<Output = ()> + Send>>;
8pub type AfterAllFn = fn() -> Pin<Box<dyn Future<Output = ()> + Send>>;
9pub type BeforeScenarioFn<W> = for<'a> fn(&'a mut W) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
10pub type AfterScenarioFn<W> = for<'a> fn(&'a mut W) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
11pub type BeforeStepFn<W> = for<'a> fn(&'a mut W, &'a Step) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
12pub type AfterStepFn<W> =
13    for<'a> fn(&'a mut W, &'a Step, &'a StepResult) -> Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
14
15pub enum HookDef<W: World> {
16    BeforeAll(BeforeAllFn),
17    AfterAll(AfterAllFn),
18    BeforeScenario(BeforeScenarioFn<W>),
19    AfterScenario(AfterScenarioFn<W>),
20    BeforeStep(BeforeStepFn<W>),
21    AfterStep(AfterStepFn<W>),
22}
23
24impl<W: World> HookDef<W> {
25    pub fn before_all(f: BeforeAllFn) -> Self {
26        HookDef::BeforeAll(f)
27    }
28
29    pub fn after_all(f: AfterAllFn) -> Self {
30        HookDef::AfterAll(f)
31    }
32
33    pub fn before_scenario(f: BeforeScenarioFn<W>) -> Self {
34        HookDef::BeforeScenario(f)
35    }
36
37    pub fn after_scenario(f: AfterScenarioFn<W>) -> Self {
38        HookDef::AfterScenario(f)
39    }
40
41    pub fn before_step(f: BeforeStepFn<W>) -> Self {
42        HookDef::BeforeStep(f)
43    }
44
45    pub fn after_step(f: AfterStepFn<W>) -> Self {
46        HookDef::AfterStep(f)
47    }
48}
49
50pub struct HookRegistry<W: World> {
51    before_all: Vec<BeforeAllFn>,
52    after_all: Vec<AfterAllFn>,
53    before_scenario: Vec<BeforeScenarioFn<W>>,
54    after_scenario: Vec<AfterScenarioFn<W>>,
55    before_step: Vec<BeforeStepFn<W>>,
56    after_step: Vec<AfterStepFn<W>>,
57}
58
59impl<W: World> HookRegistry<W> {
60    pub fn new() -> Self {
61        Self {
62            before_all: Vec::new(),
63            after_all: Vec::new(),
64            before_scenario: Vec::new(),
65            after_scenario: Vec::new(),
66            before_step: Vec::new(),
67            after_step: Vec::new(),
68        }
69    }
70
71    pub fn register(&mut self, hook: HookDef<W>) {
72        match hook {
73            HookDef::BeforeAll(f) => self.before_all.push(f),
74            HookDef::AfterAll(f) => self.after_all.push(f),
75            HookDef::BeforeScenario(f) => self.before_scenario.push(f),
76            HookDef::AfterScenario(f) => self.after_scenario.push(f),
77            HookDef::BeforeStep(f) => self.before_step.push(f),
78            HookDef::AfterStep(f) => self.after_step.push(f),
79        }
80    }
81
82    pub async fn run_before_all(&self) {
83        for hook in &self.before_all {
84            hook().await;
85        }
86    }
87
88    pub async fn run_after_all(&self) {
89        for hook in &self.after_all {
90            hook().await;
91        }
92    }
93
94    pub async fn run_before_scenario(&self, world: &mut W) {
95        for hook in &self.before_scenario {
96            hook(world).await;
97        }
98    }
99
100    pub async fn run_after_scenario(&self, world: &mut W) {
101        for hook in &self.after_scenario {
102            hook(world).await;
103        }
104    }
105
106    pub async fn run_before_step(&self, world: &mut W, step: &Step) {
107        for hook in &self.before_step {
108            hook(world, step).await;
109        }
110    }
111
112    pub async fn run_after_step(&self, world: &mut W, step: &Step, result: &StepResult) {
113        for hook in &self.after_step {
114            hook(world, step, result).await;
115        }
116    }
117}
118
119impl<W: World> Default for HookRegistry<W> {
120    fn default() -> Self {
121        Self::new()
122    }
123}