#![allow(clippy::pedantic)]
use std::path::{Path, PathBuf};
use std::process::Command;
fn temp_workspace(prefix: &str) -> PathBuf {
let dir = std::env::temp_dir().join(format!(
"{prefix}_{}_{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
));
std::fs::create_dir_all(&dir).unwrap();
dir
}
fn write(dir: &Path, name: &str, contents: &str) {
std::fs::write(dir.join(name), contents).unwrap();
}
const CONFIG: &str = r#"
engines:
harper: true
auto_fix:
- find: "teh"
replace: "the"
description: "Fix common typo"
- find: "colour"
replace: "color"
context: "American"
"#;
fn fix(workspace: &Path, file: &str) -> String {
let output = Command::new(env!("CARGO_BIN_EXE_language-check"))
.current_dir(workspace)
.args(["fix", file])
.output()
.expect("the CLI runs");
assert!(output.status.success(), "{output:?}");
std::fs::read_to_string(workspace.join(file)).expect("the file is still there")
}
#[test]
fn a_rule_without_a_context_applies_anywhere() {
let workspace = temp_workspace("lang_check_autofix_plain");
write(&workspace, ".languagecheck.yaml", CONFIG);
write(&workspace, "doc.md", "A frobnicate and teh word.\n");
let fixed = fix(&workspace, "doc.md");
assert!(
fixed.contains("the word"),
"the rule did not apply: {fixed:?}"
);
assert!(!fixed.contains("teh "), "the typo survived: {fixed:?}");
std::fs::remove_dir_all(&workspace).ok();
}
#[test]
fn a_context_rule_applies_only_where_its_context_appears() {
let workspace = temp_workspace("lang_check_autofix_context");
write(&workspace, ".languagecheck.yaml", CONFIG);
write(
&workspace,
"us.md",
"American English: the colour is red.\n",
);
write(&workspace, "gb.md", "British English: the colour is red.\n");
let us = fix(&workspace, "us.md");
assert!(
us.contains("the color is red"),
"the context matched but the rule did not apply: {us:?}"
);
let gb = fix(&workspace, "gb.md");
assert!(
gb.contains("the colour is red"),
"the rule applied although its context was absent: {gb:?}"
);
std::fs::remove_dir_all(&workspace).ok();
}
#[test]
fn the_run_says_how_many_of_its_own_rules_fired() {
let workspace = temp_workspace("lang_check_autofix_count");
write(&workspace, ".languagecheck.yaml", CONFIG);
write(&workspace, "doc.md", "American English: a colour here.\n");
let output = Command::new(env!("CARGO_BIN_EXE_language-check"))
.current_dir(&workspace)
.args(["fix", "doc.md"])
.output()
.expect("the CLI runs");
let printed = String::from_utf8_lossy(&output.stdout);
assert!(
printed.contains("user-defined auto-fix"),
"the run did not report its own rules: {printed}"
);
std::fs::remove_dir_all(&workspace).ok();
}
#[test]
fn a_file_with_nothing_to_fix_is_left_exactly_as_it_was() {
let workspace = temp_workspace("lang_check_autofix_noop");
write(&workspace, ".languagecheck.yaml", CONFIG);
let original = "British English: a colour here, spelled correctly.\n";
write(&workspace, "doc.md", original);
let fixed = fix(&workspace, "doc.md");
assert_eq!(
fixed, original,
"a file with no applicable rule was rewritten anyway"
);
std::fs::remove_dir_all(&workspace).ok();
}