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}