#![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) -> std::path::PathBuf {
let file_path = dir.path().join(name);
fs::write(&file_path, content).expect("Failed to write test file");
file_path
}
#[test]
fn test_audit_001_command_exists() {
rash_cmd()
.arg("audit")
.arg("--help")
.assert()
.success()
.stdout(predicate::str::contains("Run comprehensive quality audit"));
}
#[test]
fn test_audit_002_perfect_script_passes() {
let temp_dir = TempDir::new().unwrap();
let script = create_test_script(
&temp_dir,
"perfect.sh",
r#"#!/bin/bash
# Perfect script with all quality features
set -euo pipefail
# Function with proper documentation
# Args: name - The name to greet
greet() {
local name="$1"
echo "Hello, ${name}"
}
# TEST: greet function basic
test_greet_basic() {
result=$(greet "World")
[[ "$result" == "Hello, World" ]] || return 1
}
# Main execution
main() {
greet "Rash"
}
main "$@"
"#,
);
rash_cmd()
.arg("audit")
.arg(&script)
.assert()
.success()
.stdout(predicate::str::contains("Overall:").and(predicate::str::contains("PASS")))
.stdout(predicate::str::contains("Lint"))
.stdout(predicate::str::contains("Test"))
.stdout(predicate::str::contains("Score"));
}
#[test]
fn test_audit_003_poor_script_shows_issues() {
let temp_dir = TempDir::new().unwrap();
let script = create_test_script(
&temp_dir,
"poor.sh",
r#"#!/bin/bash
FILES=$(ls *.txt)
for f in $FILES; do
echo $f
done
"#,
);
rash_cmd()
.arg("audit")
.arg(&script)
.assert()
.success() .stdout(predicate::str::contains("Lint"))
.stdout(predicate::str::contains("warnings").or(predicate::str::contains("errors")))
.stdout(predicate::str::contains("Score"));
}
#[test]
fn test_audit_004_json_output() {
let temp_dir = TempDir::new().unwrap();
let script = create_test_script(
&temp_dir,
"test.sh",
r#"#!/bin/bash
echo "test"
"#,
);
rash_cmd()
.arg("audit")
.arg(&script)
.arg("--format")
.arg("json")
.assert()
.success()
.stdout(predicate::str::contains("{"))
.stdout(predicate::str::contains("lint"))
.stdout(predicate::str::contains("test"))
.stdout(predicate::str::contains("score"));
}
#[test]
fn test_audit_005_strict_mode_fails_on_warnings() {
let temp_dir = TempDir::new().unwrap();
let script = create_test_script(
&temp_dir,
"warnings.sh",
r#"#!/bin/bash
FILES=$(ls *.txt) # SC2012 warning
echo $FILES # Unquoted variable
"#,
);
rash_cmd()
.arg("audit")
.arg(&script)
.arg("--strict")
.assert()
.failure()
.stderr(predicate::str::contains("warnings").or(predicate::str::contains("errors")));
}
#[test]
fn test_audit_006_shows_all_checks() {
let temp_dir = TempDir::new().unwrap();
let script = create_test_script(
&temp_dir,
"basic.sh",
r#"#!/bin/bash
set -e
greet() {
echo "Hello, $1"
}
test_greet() {
result=$(greet "Test")
[[ "$result" == "Hello, Test" ]] || return 1
}
"#,
);
rash_cmd()
.arg("audit")
.arg(&script)
.assert()
.success()
.stdout(predicate::str::contains("Parse"))
.stdout(predicate::str::contains("Lint"))
.stdout(predicate::str::contains("Test"))
.stdout(predicate::str::contains("Score"));
}
#[test]
fn test_audit_007_detailed_output() {
let temp_dir = TempDir::new().unwrap();
let script = create_test_script(
&temp_dir,
"detailed.sh",
r#"#!/bin/bash
set -euo pipefail
main() {
echo "test"
}
main "$@"
"#,
);
rash_cmd()
.arg("audit")
.arg(&script)
.arg("--detailed")
.assert()
.success()
.stdout(predicate::str::contains("Complexity"))
.stdout(predicate::str::contains("Safety"))
.stdout(predicate::str::contains("Maintainability"));
}
#[test]
fn test_audit_008_nonexistent_file_error() {
rash_cmd()
.arg("audit")
.arg("nonexistent.sh")
.assert()
.failure()
.stderr(predicate::str::contains("Error").or(predicate::str::contains("No such file")));
}
#[test]
#[ignore = "Feature not yet implemented - needs GREEN phase implementation"]
fn test_audit_009_min_grade_enforcement() {
let temp_dir = TempDir::new().unwrap();
let script = create_test_script(
&temp_dir,
"low_quality.sh",
r#"#!/bin/bash
# Very basic, low quality script
FILES=$(ls)
rm $FILES
"#,
);
rash_cmd()
.arg("audit")
.arg(&script)
.arg("--min-grade")
.arg("A")
.assert()
.failure()
.stderr(predicate::str::contains("grade").or(predicate::str::contains("below minimum")));
}
#[test]
fn test_audit_010_summary_counts() {
let temp_dir = TempDir::new().unwrap();
let script = create_test_script(
&temp_dir,
"mixed.sh",
r#"#!/bin/bash
set -e
test_pass() {
[[ "1" == "1" ]] || return 1
}
test_fail() {
[[ "1" == "2" ]] || return 1
}
greet() {
echo "Hello"
}
"#,
);
let output = rash_cmd().arg("audit").arg(&script).assert().failure();
output.stdout(predicate::str::contains("passed").or(predicate::str::contains("failed")));
}