#![allow(deprecated)]
#![allow(clippy::unwrap_used)] #![allow(clippy::expect_used)]
use assert_cmd::Command;
use predicates::prelude::*;
use std::fs;
use tempfile::TempDir;
#[allow(deprecated)]
fn rash_cmd() -> Command {
assert_cmd::cargo_bin_cmd!("bashrs")
}
fn create_test_script(dir: &TempDir, name: &str, content: &str) -> String {
let path = dir.path().join(name);
fs::write(&path, content).expect("Failed to write test script");
path.to_string_lossy().to_string()
}
#[test]
fn test_format_001_command_exists() {
rash_cmd()
.arg("format")
.arg("--help")
.assert()
.success()
.stdout(predicate::str::contains("Format bash scripts"));
}
#[test]
fn test_format_002_basic_formatting() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let script = create_test_script(
&temp_dir,
"unformatted.sh",
r#"#!/bin/bash
# Inconsistent indentation
if [ -n "$VAR" ]; then
echo "test"
echo "inconsistent"
fi
function greet() {
echo "hello"
}
"#,
);
rash_cmd()
.arg("format")
.arg(&script)
.assert()
.success()
.stdout(predicate::str::contains("formatted"));
let formatted = fs::read_to_string(&script).expect("Failed to read formatted file");
assert!(formatted.contains(" echo test")); assert!(formatted.contains(" echo inconsistent"));
assert!(formatted.contains(" echo hello")); }
#[test]
fn test_format_003_check_mode_unformatted() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let script = create_test_script(
&temp_dir,
"unformatted.sh",
r#"#!/bin/bash
if [ -n "$VAR" ]; then
echo "bad indent"
fi
"#,
);
rash_cmd()
.arg("format")
.arg("--check")
.arg(&script)
.assert()
.failure()
.stderr(predicate::str::contains("not properly formatted"));
}
#[test]
fn test_format_004_check_mode_formatted() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let script = create_test_script(
&temp_dir,
"formatted.sh",
r#"#!/bin/bash
if [[ -n "$VAR" ]]; then
echo "good indent"
fi
"#,
);
rash_cmd()
.arg("format")
.arg("--check")
.arg(&script)
.assert()
.success()
.stdout(predicate::str::contains("properly formatted"));
}
#[test]
fn test_format_005_quote_variables() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let script = create_test_script(
&temp_dir,
"unquoted.sh",
r#"#!/bin/bash
VAR=value
echo $VAR
"#,
);
rash_cmd().arg("format").arg(&script).assert().success();
let formatted = fs::read_to_string(&script).expect("Failed to read formatted file");
assert!(formatted.contains("\"$VAR\"") || formatted.contains("${VAR}"));
}
#[test]
fn test_format_006_normalize_functions() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let script = create_test_script(
&temp_dir,
"functions.sh",
r#"#!/bin/bash
function foo {
echo "no parens"
}
bar() {
echo "inconsistent indent"
}
"#,
);
rash_cmd().arg("format").arg(&script).assert().success();
let formatted = fs::read_to_string(&script).expect("Failed to read formatted file");
assert!(formatted.contains("foo()") || formatted.contains("function foo()"));
assert!(formatted.contains(" echo")); }
#[test]
fn test_format_007_if_statements() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let script = create_test_script(
&temp_dir,
"if.sh",
r#"#!/bin/bash
if [ "$VAR" = "test" ]
then
echo "split then"
fi
if [ "$VAR" = "test" ]; then
echo "inline then"
fi
"#,
);
rash_cmd().arg("format").arg(&script).assert().success();
let formatted = fs::read_to_string(&script).expect("Failed to read formatted file");
assert!(formatted.contains("]; then"));
}
#[test]
fn test_format_008_preserve_comments() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let script = create_test_script(
&temp_dir,
"comments.sh",
r#"#!/bin/bash
# Header comment
VAR="value" # Inline comment
# Function comment
foo() {
# Inside function
echo "test"
}
"#,
);
rash_cmd().arg("format").arg(&script).assert().success();
let formatted = fs::read_to_string(&script).expect("Failed to read formatted file");
assert!(formatted.contains("#!/bin/bash"));
assert!(formatted.contains("# Header comment"));
assert!(formatted.contains("# Inline comment"));
assert!(formatted.contains("# Function comment"));
assert!(formatted.contains("# Inside function"));
}
#[test]
fn test_format_009_tabs_config() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let config_path = temp_dir.path().join(".bashrs-fmt.toml");
fs::write(
&config_path,
r#"
indent_width = 2
use_tabs = true
"#,
)
.expect("Failed to write config");
let script = create_test_script(
&temp_dir,
"script.sh",
r#"#!/bin/bash
if [ -n "$VAR" ]; then
echo "test"
fi
"#,
);
rash_cmd().arg("format").arg(&script).assert().success();
let formatted = fs::read_to_string(&script).expect("Failed to read formatted file");
assert!(formatted.contains("\techo"));
}
#[test]
fn test_format_010_ignore_directive() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let script = create_test_script(
&temp_dir,
"ignore.sh",
r#"#!/bin/bash
# bashrs-fmt-ignore
if [ -n "$VAR" ]; then
echo "intentionally bad formatting"
fi
# Normal formatting
if [ -n "$VAR2" ]; then
echo "should be formatted"
fi
"#,
);
rash_cmd().arg("format").arg(&script).assert().success();
let formatted = fs::read_to_string(&script).expect("Failed to read formatted file");
let lines: Vec<&str> = formatted.lines().collect();
let ignore_section = lines
.iter()
.skip_while(|line| !line.contains("bashrs-fmt-ignore"))
.take(4)
.cloned()
.collect::<Vec<_>>()
.join("\n");
assert!(ignore_section.contains("echo \"intentionally bad formatting\""));
assert!(formatted.contains(" echo \"should be formatted\""));
}
#[test]
fn test_format_011_case_statements() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let script = create_test_script(
&temp_dir,
"case.sh",
r#"#!/bin/bash
case $VAR in
start)
echo "starting"
;;
stop)
echo "stopping"
;;
*)
echo "unknown"
;;
esac
"#,
);
rash_cmd().arg("format").arg(&script).assert().success();
let formatted = fs::read_to_string(&script).expect("Failed to read formatted file");
assert!(formatted.contains(" start)") || formatted.contains("start)"));
assert!(formatted.contains(" echo") || formatted.contains(" echo"));
}
#[test]
fn test_format_012_multiple_files() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let script1 = create_test_script(
&temp_dir,
"script1.sh",
r#"#!/bin/bash
echo "test1"
"#,
);
let script2 = create_test_script(
&temp_dir,
"script2.sh",
r#"#!/bin/bash
echo "test2"
"#,
);
rash_cmd()
.arg("format")
.arg(&script1)
.arg(&script2)
.assert()
.success()
.stdout(predicate::str::contains("script1.sh"))
.stdout(predicate::str::contains("script2.sh"));
}
#[test]
fn test_format_013_output_option() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let input_script = create_test_script(
&temp_dir,
"input.sh",
r#"#!/bin/bash
echo "test"
"#,
);
let output_path = temp_dir.path().join("output.sh");
rash_cmd()
.arg("format")
.arg(&input_script)
.arg("--output")
.arg(&output_path)
.assert()
.success();
assert!(output_path.exists());
let original = fs::read_to_string(&input_script).expect("Failed to read original");
assert!(original.contains("echo \"test\""));
}
#[test]
fn test_format_014_dry_run() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let script = create_test_script(
&temp_dir,
"script.sh",
r#"#!/bin/bash
if [ -n "$VAR" ]; then
echo "test"
fi
"#,
);
let original = fs::read_to_string(&script).expect("Failed to read original");
rash_cmd()
.arg("format")
.arg("--dry-run")
.arg(&script)
.assert()
.success()
.stdout(predicate::str::contains("Would format:"));
let after = fs::read_to_string(&script).expect("Failed to read after dry-run");
assert_eq!(original, after);
}
#[test]
fn test_format_015_indent_width() {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let config_path = temp_dir.path().join(".bashrs-fmt.toml");
fs::write(
&config_path,
r#"
indent_width = 4
use_tabs = false
"#,
)
.expect("Failed to write config");
let script = create_test_script(
&temp_dir,
"script.sh",
r#"#!/bin/bash
if [ -n "$VAR" ]; then
echo "test"
fi
"#,
);
rash_cmd().arg("format").arg(&script).assert().success();
let formatted = fs::read_to_string(&script).expect("Failed to read formatted file");
assert!(formatted.contains(" echo test"));
}