diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c61226..f601e8a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,21 +1,45 @@ name: CI + on: push: - branches: [main] + branches: ["**"] pull_request: branches: [main] + env: CARGO_TERM_COLOR: always + jobs: test: + name: Test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable + + - name: Install Rust stable + uses: dtolnay/rust-toolchain@stable + with: + components: clippy, rustfmt + + - name: Cache cargo + uses: actions/cache@v4 with: - components: rustfmt, clippy - - uses: Swatinem/rust-cache@v2 - - run: cargo fmt --check - - run: cargo clippy -- -D warnings - - run: cargo test - - run: cargo build --release + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Check formatting + run: cargo fmt --all -- --check + + - name: Clippy + run: cargo clippy --all-targets --all-features -- -D warnings + + - name: Test + run: cargo test --all + + - name: Build release + run: cargo build --release diff --git a/src/cli.rs b/src/cli.rs index 04f8003..dfc56bb 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,7 +1,11 @@ use clap::{Parser, Subcommand}; #[derive(Parser)] -#[command(name = "screendiff", about = "Screenshot pixel diff engine — detect visual regressions", version)] +#[command( + name = "screendiff", + about = "Screenshot pixel diff engine — detect visual regressions", + version +)] pub struct Cli { #[command(subcommand)] pub command: Commands, diff --git a/src/main.rs b/src/main.rs index fcec503..dc0b360 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,20 @@ mod cli; mod output; -use screendiff::{diff, report}; use anyhow::Result; use clap::Parser; use cli::{Cli, Commands}; +use screendiff::{diff, report}; fn main() -> Result<()> { let cli = Cli::parse(); match cli.command { - Commands::Compare { before, after, threshold, json } => { + Commands::Compare { + before, + after, + threshold, + json, + } => { let result = diff::compare(&before, &after, threshold)?; let report = report::build(&before, &after, &result); if json { diff --git a/src/report.rs b/src/report.rs index 0fb2ae6..c75a60b 100644 --- a/src/report.rs +++ b/src/report.rs @@ -1,5 +1,5 @@ -use serde::{Deserialize, Serialize}; use crate::diff::DiffResult; +use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] pub struct DiffReport { diff --git a/tests/integration_test.rs b/tests/integration_test.rs index e2fc3b0..1f523bb 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -51,12 +51,8 @@ fn test_compare_help() { fn test_identical_images_zero_diff() { let a = solid_png(255, 0, 0); let b = solid_png(255, 0, 0); - let result = diff::compare( - a.path().to_str().unwrap(), - b.path().to_str().unwrap(), - 0.01, - ) - .unwrap(); + let result = + diff::compare(a.path().to_str().unwrap(), b.path().to_str().unwrap(), 0.01).unwrap(); assert_eq!(result.diff_pixels, 0); assert_eq!(result.diff_percent, 0.0); } @@ -65,12 +61,8 @@ fn test_identical_images_zero_diff() { fn test_completely_different_images_full_diff() { let a = solid_png(255, 0, 0); let b = solid_png(0, 0, 255); - let result = diff::compare( - a.path().to_str().unwrap(), - b.path().to_str().unwrap(), - 0.01, - ) - .unwrap(); + let result = + diff::compare(a.path().to_str().unwrap(), b.path().to_str().unwrap(), 0.01).unwrap(); assert_eq!(result.diff_pixels, 10_000); assert_eq!(result.diff_percent, 1.0); } @@ -79,12 +71,8 @@ fn test_completely_different_images_full_diff() { fn test_one_pixel_diff_counted() { let a = solid_png(255, 0, 0); let b = mostly_red_png(); - let result = diff::compare( - a.path().to_str().unwrap(), - b.path().to_str().unwrap(), - 0.01, - ) - .unwrap(); + let result = + diff::compare(a.path().to_str().unwrap(), b.path().to_str().unwrap(), 0.01).unwrap(); assert_eq!(result.diff_pixels, 1); } @@ -110,12 +98,8 @@ fn test_dimension_mismatch_returns_error() { fn test_zero_diff_verdict_is_pass() { let a = solid_png(0, 255, 0); let b = solid_png(0, 255, 0); - let result = diff::compare( - a.path().to_str().unwrap(), - b.path().to_str().unwrap(), - 0.01, - ) - .unwrap(); + let result = + diff::compare(a.path().to_str().unwrap(), b.path().to_str().unwrap(), 0.01).unwrap(); let rep = report::build("a.png", "b.png", &result); assert!(matches!(rep.verdict, Verdict::Pass)); } @@ -124,12 +108,8 @@ fn test_zero_diff_verdict_is_pass() { fn test_over_threshold_verdict_is_fail() { let a = solid_png(255, 0, 0); let b = solid_png(0, 0, 255); - let result = diff::compare( - a.path().to_str().unwrap(), - b.path().to_str().unwrap(), - 0.01, - ) - .unwrap(); + let result = + diff::compare(a.path().to_str().unwrap(), b.path().to_str().unwrap(), 0.01).unwrap(); let rep = report::build("a.png", "b.png", &result); assert!(matches!(rep.verdict, Verdict::Fail)); } @@ -139,12 +119,8 @@ fn test_single_pixel_diff_within_threshold_passes() { // 1 changed pixel in 10000 = 0.0001 — well under 1% threshold let a = solid_png(255, 0, 0); let b = mostly_red_png(); - let result = diff::compare( - a.path().to_str().unwrap(), - b.path().to_str().unwrap(), - 0.01, - ) - .unwrap(); + let result = + diff::compare(a.path().to_str().unwrap(), b.path().to_str().unwrap(), 0.01).unwrap(); let rep = report::build("a.png", "b.png", &result); assert!(matches!(rep.verdict, Verdict::Pass)); }