///|
/// Execute a single scenario from a compiled Pickle.
pub fn execute_scenario(
registry : @core.StepRegistry,
feature_name~ : String,
scenario_name~ : String,
pickle_id~ : String,
tags~ : Array[String],
steps~ : Array[@cucumber_messages.PickleStep],
) -> ScenarioResult {
let step_results : Array[StepResult] = []
let mut failed = false
for step in steps {
let keyword = match step.type_ {
Some(@cucumber_messages.PickleStepType::Context) => "Given "
Some(@cucumber_messages.PickleStepType::Action) => "When "
Some(@cucumber_messages.PickleStepType::Outcome) => "Then "
_ => "* "
}
if failed {
step_results.push({
text: step.text,
keyword,
status: StepStatus::Skipped,
duration_ms: 0L,
diagnostic: None,
})
continue
}
let (status, diagnostic) : (StepStatus, Error?) = match
registry.find_match(step.text, keyword~) {
Undefined(step_text~, keyword=kw, snippet~, suggestions~) =>
(
StepStatus::Undefined,
Some(
@core.undefined_step_error(
step=step_text,
keyword=kw,
snippet~,
suggestions~,
),
),
)
Matched(step_def, args) =>
try {
(step_def.handler.0)(args)
(StepStatus::Passed, None)
} catch {
@core.MoonspecError::PendingStep(step~, keyword=kw, message~) =>
(
StepStatus::Pending,
Some(@core.pending_step_error(step~, keyword=kw, message~)),
)
e =>
(
StepStatus::Failed(e.to_string()),
Some(
@core.step_failed_error(
step=step.text,
keyword~,
message=e.to_string(),
),
),
)
}
}
match status {
StepStatus::Failed(_) | StepStatus::Undefined | StepStatus::Pending =>
failed = true
_ => ()
}
step_results.push({
text: step.text,
keyword,
status,
duration_ms: 0L,
diagnostic,
})
}
let statuses = step_results.map(fn(r) { r.status })
{
feature_name,
scenario_name,
pickle_id,
tags,
steps: step_results,
status: ScenarioStatus::from_steps(statuses),
duration_ms: 0L,
}
}
///|
/// Execute a single scenario with lifecycle hooks.
/// Calls before/after_scenario and before/after_step on the world.
pub fn[W : @core.Hooks] execute_scenario_with_hooks(
world : W,
registry : @core.StepRegistry,
feature_name~ : String,
scenario_name~ : String,
pickle_id~ : String,
tags~ : Array[String],
steps~ : Array[@cucumber_messages.PickleStep],
) -> ScenarioResult {
let info : @core.ScenarioInfo = { feature_name, scenario_name, tags }
// before_scenario hook
let hook_err = try {
@core.Hooks::before_scenario(world, info)
None
} catch {
e => Some(e.to_string())
}
if hook_err is Some(msg) {
// All steps skipped when before_scenario fails
let step_results = steps.map(fn(step) {
let keyword = match step.type_ {
Some(@cucumber_messages.PickleStepType::Context) => "Given "
Some(@cucumber_messages.PickleStepType::Action) => "When "
Some(@cucumber_messages.PickleStepType::Outcome) => "Then "
_ => "* "
}
{
text: step.text,
keyword,
status: StepStatus::Skipped,
duration_ms: 0L,
diagnostic: None,
}
})
let _ = @core.Hooks::after_scenario(world, info, Some(msg)) catch {
_ => ()
}
return {
feature_name,
scenario_name,
pickle_id,
tags,
steps: step_results,
status: ScenarioStatus::Failed,
duration_ms: 0L,
}
}
// Execute steps with before/after_step hooks
let step_results : Array[StepResult] = []
let mut failed = false
let mut scenario_error : String? = None
for step in steps {
let keyword = match step.type_ {
Some(@cucumber_messages.PickleStepType::Context) => "Given "
Some(@cucumber_messages.PickleStepType::Action) => "When "
Some(@cucumber_messages.PickleStepType::Outcome) => "Then "
_ => "* "
}
if failed {
step_results.push({
text: step.text,
keyword,
status: StepStatus::Skipped,
duration_ms: 0L,
diagnostic: None,
})
continue
}
let step_info : @core.StepInfo = { keyword, text: step.text }
// before_step hook
let before_err = try {
@core.Hooks::before_step(world, step_info)
None
} catch {
e => Some(e.to_string())
}
let (status, diagnostic) : (StepStatus, Error?) = if before_err is Some(msg) {
(
StepStatus::Failed(msg),
Some(@core.step_failed_error(step=step.text, keyword~, message=msg)),
)
} else {
match registry.find_match(step.text, keyword~) {
Undefined(step_text~, keyword=kw, snippet~, suggestions~) =>
(
StepStatus::Undefined,
Some(
@core.undefined_step_error(
step=step_text,
keyword=kw,
snippet~,
suggestions~,
),
),
)
Matched(step_def, args) =>
try {
(step_def.handler.0)(args)
(StepStatus::Passed, None)
} catch {
@core.MoonspecError::PendingStep(step~, keyword=kw, message~) =>
(
StepStatus::Pending,
Some(@core.pending_step_error(step~, keyword=kw, message~)),
)
e =>
(
StepStatus::Failed(e.to_string()),
Some(
@core.step_failed_error(
step=step.text,
keyword~,
message=e.to_string(),
),
),
)
}
}
}
// after_step hook
let step_result_msg : String? = match status {
StepStatus::Failed(msg) => Some(msg)
_ => None
}
let _ = @core.Hooks::after_step(world, step_info, step_result_msg) catch {
_ => ()
}
match status {
StepStatus::Failed(msg) => {
failed = true
scenario_error = Some(msg)
}
StepStatus::Undefined | StepStatus::Pending => {
failed = true
scenario_error = None
}
_ => ()
}
step_results.push({
text: step.text,
keyword,
status,
duration_ms: 0L,
diagnostic,
})
}
// after_scenario hook
let _ = @core.Hooks::after_scenario(world, info, scenario_error) catch {
_ => ()
}
let statuses = step_results.map(fn(r) { r.status })
{
feature_name,
scenario_name,
pickle_id,
tags,
steps: step_results,
status: ScenarioStatus::from_steps(statuses),
duration_ms: 0L,
}
}