diff --git a/CHANGELOG.md b/CHANGELOG.md index ca5f884..c18679b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ ## Unreleased +* Add `before_all` commands to the Toolproof config + ## v0.4.1 (October 2, 2024) * Improve resilience launching a Chrome instance diff --git a/test_interactive.sh b/test_interactive.sh new file mode 100755 index 0000000..44d3c00 --- /dev/null +++ b/test_interactive.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +cargo build + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd $SCRIPT_DIR + +TOOLPROOF=$(realpath "$SCRIPT_DIR/target/debug/toolproof") + +cargo run --release -- --placeholders toolproof_path="$TOOLPROOF" -c 1 -i --all diff --git a/toolproof/src/main.rs b/toolproof/src/main.rs index 5be0d1e..660e526 100644 --- a/toolproof/src/main.rs +++ b/toolproof/src/main.rs @@ -1,6 +1,8 @@ use std::collections::BTreeMap; use std::fmt::Display; +use std::process::Stdio; use std::sync::Arc; +use std::time::Duration; use std::{collections::HashMap, time::Instant}; use console::{style, Term}; @@ -11,6 +13,7 @@ use schematic::color::owo::OwoColorize; use segments::ToolproofSegments; use similar_string::compare_similarity; use tokio::fs::read_to_string; +use tokio::process::Command; use tokio::sync::OnceCell; use wax::Glob; @@ -167,6 +170,42 @@ fn closest_strings<'o>(target: &String, options: &'o Vec) -> Vec<(&'o St async fn main_inner() -> Result<(), ()> { let ctx = configure(); + for before in &ctx.params.before_all { + let before_cmd = &before.command; + let mut command = Command::new("sh"); + command + .arg("-c") + .current_dir(&ctx.working_directory) + .arg(before_cmd); + + command.stdout(Stdio::piped()); + command.stderr(Stdio::piped()); + + println!( + "{}{}", + "Running before_all command: ".blue().bold(), + before_cmd.cyan().bold(), + ); + + let running = command + .spawn() + .map_err(|_| eprintln!("Failed to run command: {before_cmd}"))?; + + let Ok(_) = + (match tokio::time::timeout(Duration::from_secs(300), running.wait_with_output()).await + { + Ok(out) => out, + Err(_) => { + eprintln!("Failed to run command due to timeout: {before_cmd}"); + return Err(()); + } + }) + else { + eprintln!("Failed to run command: {before_cmd}"); + return Err(()); + }; + } + let start = Instant::now(); let glob = Glob::new("**/*.toolproof.yml").expect("Valid glob"); diff --git a/toolproof/src/options.rs b/toolproof/src/options.rs index 90e8550..bfec3b7 100644 --- a/toolproof/src/options.rs +++ b/toolproof/src/options.rs @@ -130,6 +130,12 @@ pub enum ToolproofBrowserImpl { Pagebrowse, } +#[derive(Config, Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +#[config(rename_all = "snake_case")] +pub struct ToolproofBeforeAll { + pub command: String, +} + #[derive(Config, Debug, Clone)] #[config(rename_all = "snake_case")] pub struct ToolproofParams { @@ -171,6 +177,9 @@ pub struct ToolproofParams { /// Placeholder keys, and the values they should be replaced with pub placeholders: HashMap, + + /// Commands to run in the working directory before starting to run Toolproof tests + pub before_all: Vec, } // The configuration object used internally diff --git a/toolproof/test_suite/hooks/before_all.toolproof.yml b/toolproof/test_suite/hooks/before_all.toolproof.yml new file mode 100644 index 0000000..23d0452 --- /dev/null +++ b/toolproof/test_suite/hooks/before_all.toolproof.yml @@ -0,0 +1,31 @@ +name: Toolproof runs before_all hooks + +steps: + - step: I have a "misc_file" file with the content "lorem ipsum" + - step: I have a "toolproof.yml" file with the content {yaml} + yaml: |- + before_all: + - command: 'echo " donor" >> misc_file' + - step: I have a "my_test.toolproof.yml" file with the content {yaml} + yaml: |- + name: Inner modified test + + steps: + - step: I run "cat %toolproof_test_directory%/misc_file" + - stdout should contain "lorem ipsum donor" + - I run "%toolproof_path% --porcelain" + - snapshot: stdout + snapshot_content: |- + ╎Running before_all command: echo " donor" >> misc_file + ╎ + ╎Running tests + ╎ + ╎✓ Inner modified test + ╎ + ╎Finished running tests + ╎ + ╎Passing tests: 1 + ╎Failing tests: 0 + ╎Skipped tests: 0 + ╎ + ╎All tests passed