mod common;
use ai_slop::Profile;
use common::{has_rule, run};
#[test]
fn em_dash_surface_variants_are_caught() {
for text in [
"A dash — here.",
"A dash — here.",
"A dash — here.",
"A dash — here.",
"A spaced -- double here.",
"word--word here.",
] {
let report = run(text, Profile::Readme);
assert!(has_rule(&report, "SLOP-M001"), "missed: {text}");
}
}
#[test]
fn semicolon_variants_are_caught() {
for text in [
"One; two.",
"One; two.",
"Fullwidth; two.",
"Greek question mark\u{037E} two.",
] {
let report = run(text, Profile::Readme);
assert!(has_rule(&report, "SLOP-M002"), "missed: {text}");
}
}
#[test]
fn zero_width_insertion_does_not_evade_the_lexicon() {
for text in [
"We de\u{200B}lve into it.",
"We de\u{200C}lve into it.",
"We del\u{2060}ve into it.",
] {
let report = run(text, Profile::Readme);
assert!(has_rule(&report, "SLOP-A001"), "missed: {text:?}");
assert!(has_rule(&report, "SLOP-M004"), "M004 missed: {text:?}");
}
}
#[test]
fn crlf_and_soft_break_variants_are_caught() {
let crlf = "First line.\r\nWe delve here — with a dash.\r\n";
let report = run(crlf, Profile::Readme);
assert!(has_rule(&report, "SLOP-A001"));
assert!(has_rule(&report, "SLOP-M001"));
let split = "This is a game\nchanger for sure.\n";
let report = run(split, Profile::Readme);
assert!(has_rule(&report, "SLOP-A001"), "soft-break split missed");
}
#[test]
fn markdown_escape_resolution_reaches_patterns() {
let text = "Escaped \\*star\\* and one; two.\n";
let report = run(text, Profile::Readme);
assert!(has_rule(&report, "SLOP-M002"));
}
#[test]
fn opening_however_fires_only_at_block_start() {
let opening = "However, this fires.\n";
let report = run(opening, Profile::Readme);
assert!(has_rule(&report, "SLOP-M003"));
let sentence_start = "It works. However, it fires here too.\n";
let report = run(sentence_start, Profile::Readme);
assert!(has_rule(&report, "SLOP-M003"));
let mid = "It works well however you spin it.\n";
let report = run(mid, Profile::Readme);
assert!(
!has_rule(&report, "SLOP-M003"),
"mid-sentence however fired"
);
}
#[test]
fn typographic_quotes_fire_only_inside_code() {
let in_code = "Run `let s = “x”;` to see it.\n";
let report = run(in_code, Profile::Readme);
assert!(has_rule(&report, "SLOP-P005"));
let in_prose = "He said “hello” politely.\n";
let report = run(in_prose, Profile::Readme);
assert!(!has_rule(&report, "SLOP-P005"), "prose quotes fired P005");
}
#[test]
fn quotation_downgrade_turns_style_violations_into_candidates() {
let text = "> compiler said: expected `;`, found — this\n";
let report = run(text, Profile::Readme);
let m001 = report
.findings
.iter()
.find(|f| f.rule_id == "SLOP-M001")
.expect("dash detected in quote");
assert_eq!(m001.state, "candidate");
assert_eq!(m001.provenance, "claimed-quotation");
}