use super::support::*;
use crate::analysis::findings::Severity;
use crate::languages::runner::*;
fn credo_json() -> &'static str {
r##"{"issues":[
{"category":"design","check":"Credo.Check.Design.TagTODO","column":null,"column_end":null,"filename":"lib/demo.ex","line_no":2,"message":"Found a TODO tag in a comment: # TODO: fix this","priority":1,"scope":"Demo","trigger":"# TODO: fix this"},
{"category":"readability","check":"Credo.Check.Readability.ModuleDoc","column":11,"column_end":15,"filename":"lib/demo.ex","line_no":1,"message":"Modules should have a @moduledoc tag.","priority":1,"scope":"Demo","trigger":"Demo"}]}"##
}
#[test]
fn credo_parser_reads_the_verified_fixture() {
let spec = credo_like_spec();
let findings = parse_output(&spec, credo_json(), "root").expect("credo json parses");
assert_eq!(findings.len(), 2);
assert_eq!(findings[0].file_path, "lib/demo.ex");
assert_eq!(findings[0].kind, "Credo.Check.Design.TagTODO");
assert_eq!(findings[0].line, 2);
assert_eq!(findings[0].severity, Severity::Warning);
assert_eq!(
findings[0].message,
"Found a TODO tag in a comment: # TODO: fix this"
);
assert_eq!(findings[1].file_path, "lib/demo.ex");
assert_eq!(findings[1].kind, "Credo.Check.Readability.ModuleDoc");
assert_eq!(findings[1].line, 1);
assert_eq!(findings[1].severity, Severity::Info);
assert_eq!(findings[1].message, "Modules should have a @moduledoc tag.");
}
#[test]
fn credo_parser_null_column_is_none_not_some_zero() {
let spec = credo_like_spec();
let findings = parse_output(&spec, credo_json(), "root").unwrap();
assert_eq!(findings[0].column, None);
assert_eq!(findings[1].column, Some(11));
}
#[test]
fn credo_parser_empty_output_and_empty_issues_are_clean() {
let spec = credo_like_spec();
assert!(parse_output(&spec, "", "root").unwrap().is_empty());
assert!(parse_output(&spec, " \n\t ", "root").unwrap().is_empty());
assert!(
parse_output(&spec, r#"{"issues":[]}"#, "root")
.unwrap()
.is_empty()
);
}
#[test]
fn credo_parser_errors_on_unparseable_input() {
let spec = credo_like_spec();
let err = parse_output(&spec, "** (Mix) nope", "root").expect_err("garbage is not a clean run");
assert!(err.0.contains("credo"), "message was {:?}", err.0);
}
#[test]
fn credo_parser_errors_when_issues_is_missing_or_not_an_array() {
let spec = credo_like_spec();
let err = parse_output(&spec, r#"{"error":"boom"}"#, "root").unwrap_err();
assert!(err.0.contains("issues"), "message was {:?}", err.0);
let err = parse_output(&spec, r#"{"issues":{}}"#, "root").unwrap_err();
assert!(err.0.contains("object"), "message was {:?}", err.0);
}
#[test]
fn credo_category_mapping_covers_every_branch() {
let spec = credo_like_spec();
for (category, expected) in [
("warning", Severity::Error),
("refactor", Severity::Warning),
("design", Severity::Warning),
("readability", Severity::Info),
("consistency", Severity::Info),
("bogus", Severity::Warning),
] {
let input = format!(
r#"{{"issues":[{{"category":"{category}","check":"C","column":1,"filename":"a.ex","line_no":1,"message":"m"}}]}}"#
);
let findings = parse_output(&spec, &input, "root").unwrap();
assert_eq!(findings[0].severity, expected, "category {category}");
}
}
#[test]
fn credo_parser_missing_filename_falls_back_to_root_name() {
let spec = credo_like_spec();
let input =
r#"{"issues":[{"category":"warning","check":"C","column":1,"line_no":1,"message":"m"}]}"#;
let findings = parse_output(&spec, input, "fallback.ex").unwrap();
assert_eq!(findings[0].file_path, "fallback.ex");
}
#[test]
fn credo_parser_reads_findings_in_every_file() {
let spec = credo_like_spec();
let input = r#"{"issues":[
{"category":"warning","check":"C1","column":1,"filename":"lib/a.ex","line_no":1,"message":"m1"},
{"category":"design","check":"C2","column":2,"filename":"lib/b.ex","line_no":2,"message":"m2"}
]}"#;
let findings = parse_output(&spec, input, "root").unwrap();
assert_eq!(findings.len(), 2);
assert_eq!(findings[0].file_path, "lib/a.ex");
assert_eq!(findings[1].file_path, "lib/b.ex");
assert_eq!(findings[1].line, 2);
}