use std::path::{self, Path, PathBuf};
use ec4rs::{
language_tags::LanguageTag,
property::{Charset, FinalNewline, IndentSize, IndentStyle, SpellingLanguage, TrimTrailingWs},
};
use itertools::Itertools;
use ecformat::{
status,
status_types::{ConsideredFile, ConsideredFiles, EditorConfigFiles},
};
mod integration_test_utils;
use integration_test_utils::test_utils;
#[test]
fn test_status_ecformat() {
let repo = test_utils::get_repo();
let mut args = integration_test_utils::get_command_args(&repo);
args.ignore_args.hidden = true;
let status_info = status(&args).expect("Status command has no error");
assert_editorconfigs(
&status_info.editorconfig_files,
&["", "LICENSES", "tests/resources", ".vscode"],
&repo,
);
let readme = get_considered_file(&status_info.considered_files, &repo.join("README.md"));
let main = get_considered_file(
&status_info.considered_files,
&repo.join("src").join("main.rs"),
);
let this_file = get_considered_file(
&status_info.considered_files,
&repo.join("tests").join("status.rs"),
);
let examples = vec![readme, main, this_file];
for file in examples {
assert_charset(file);
assert_end_of_line(file);
assert_indent_style(file, IndentStyle::Spaces);
assert_tab_width(file);
assert_insert_final_newline(file, true);
assert_spelling_language(file);
assert_trim_trailing_whitespace(file, true);
}
assert_indent_size(readme, 1);
assert_indent_size(main, 4);
assert_indent_size(this_file, 4);
let license_dir = repo.join("LICENSES");
let example_licenses = vec![
get_considered_file(
&status_info.considered_files,
&license_dir.join("BlueOak-1.0.0.txt"),
),
get_considered_file(
&status_info.considered_files,
&license_dir.join("CC0-1.0.txt"),
),
];
for license in example_licenses {
assert_all_not_set(license);
}
let tests_resources_dir = repo.join("tests").join("resources");
let trim_trailing_whitespace_example = get_considered_file(
&status_info.considered_files,
&tests_resources_dir
.join("trim_trailing_whitespace")
.join("trimmed.md"),
);
let indent_style_example = get_considered_file(
&status_info.considered_files,
&tests_resources_dir
.join("indent_style")
.join("mix_allowed-tab-3-4-7-9.md"),
);
let indent_size_example = get_considered_file(
&status_info.considered_files,
&tests_resources_dir
.join("indent_size")
.join("correct_tabs-tab-4-4.md"),
);
let insert_final_newline_example = get_considered_file(
&status_info.considered_files,
&tests_resources_dir
.join("insert_final_newline")
.join("empty-needs_no_final_newline.md"),
);
assert_trim_trailing_whitespace(trim_trailing_whitespace_example, false);
assert_indent_style(indent_style_example, IndentStyle::Tabs);
assert_indent_style(indent_size_example, IndentStyle::Tabs);
assert_insert_final_newline(insert_final_newline_example, false);
assert_trim_trailing_whitespace(insert_final_newline_example, false);
assert!(
status_info.considered_files.files().len() > 128,
"Considered files are ways too few"
);
}
#[test]
fn test_status_ecformat_licenses() {
let license_dir = test_utils::get_repo().join("LICENSES");
let mut args = integration_test_utils::get_command_args(&license_dir);
args.ignore_args.hidden = true;
let status_info = status(&args).expect("Status command has no error");
assert_editorconfigs(&status_info.editorconfig_files, &[""], &license_dir);
for file in status_info.considered_files.files() {
assert_all_not_set(file);
}
assert!(
status_info.considered_files.files().len() > 2,
"Considered files are too few"
);
}
#[test]
fn test_status_ecformat_tests_resources() {
let tests_resources_dir_relative = test_utils::get_repo_relative()
.join("tests")
.join("resources");
let tests_resources_dir = path::absolute(&tests_resources_dir_relative)
.expect("Absolute path to tests/resources needs to be available");
let mut args = integration_test_utils::get_command_args(&tests_resources_dir_relative);
args.ignore_args.hidden = true;
let status_info = status(&args).expect("Status command has no error");
assert_editorconfigs(&status_info.editorconfig_files, &[""], &tests_resources_dir);
let mut md_considered = false;
let trim_trailing_whitespace_dir = tests_resources_dir.join("trim_trailing_whitespace");
let mut trim_trailing_whitespace_considered = false;
let indent_style_dir = tests_resources_dir.join("indent_style");
let mut indent_style_considered = false;
let indent_size_dir = tests_resources_dir.join("indent_size");
let mut indent_size_considered = false;
let insert_final_newline_dir = tests_resources_dir.join("insert_final_newline");
let mut insert_final_newline_considered = false;
for file in status_info.considered_files.files() {
if file.path().extension().is_some_and(|e| e == "md") {
md_considered = true;
match file.path().parent().unwrap() {
dir if dir == trim_trailing_whitespace_dir => {
trim_trailing_whitespace_considered = true;
assert_trim_trailing_whitespace(file, false);
}
dir if dir == indent_style_dir => {
indent_style_considered = true;
assert_indent_style(file, IndentStyle::Tabs);
}
dir if dir == indent_size_dir => {
indent_size_considered = true;
assert_indent_style(file, IndentStyle::Tabs);
}
dir if dir == insert_final_newline_dir => {
insert_final_newline_considered = true;
assert_insert_final_newline(file, false);
assert_trim_trailing_whitespace(file, false);
}
_ => (),
}
}
}
assert!(md_considered, "No md file considered");
assert!(
trim_trailing_whitespace_considered,
"No md file in trim_trailing_whitespace directory considered"
);
assert!(
indent_style_considered,
"No md file in indent_style directory considered"
);
assert!(
indent_size_considered,
"No md file in indent_size directory considered"
);
assert!(
insert_final_newline_considered,
"No md file in insert_final_newline directory considered"
);
assert!(
status_info.considered_files.files().len() > 32,
"Considered files are ways too few"
);
}
fn assert_editorconfigs(
editorconfig_files: &EditorConfigFiles,
expected: &[&str],
target_dir: &Path,
) {
let expected_editorconfis = expected
.iter()
.map(|dir| target_dir.join(dir).join(".editorconfig"))
.sorted()
.collect_vec();
let found_editoroconfigs = editorconfig_files
.paths()
.iter()
.cloned()
.sorted()
.collect_vec();
assert_eq!(
expected_editorconfis, found_editoroconfigs,
"Found EditorConfig files are not as expected"
);
}
fn get_considered_file<'a>(
considered_files: &'a ConsideredFiles,
file: &PathBuf,
) -> &'a ConsideredFile {
considered_files
.files()
.iter()
.find(|f| f.path() == file)
.unwrap_or_else(|| panic!("{} needs to be a considered file", file.display()))
}
fn assert_charset(file: &ConsideredFile) {
match file.charset {
Some(charset) => assert_eq!(
charset,
Charset::Utf8, "charset of {} is {charset} and not {} as expected",
file.path().display(),
Charset::Utf8
),
None => panic!("no charset for {} found", file.path().display()),
}
}
fn assert_end_of_line(file: &ConsideredFile) {
if let Some(end_of_line) = file.end_of_line {
panic!(
"end_of_line of {} is {end_of_line} and is not unset as expected",
file.path().display(),
)
}
}
fn assert_indent_style(file: &ConsideredFile, expected: IndentStyle) {
match file.indent_style {
Some(indent_style) => assert_eq!(
indent_style,
expected,
"indent_style of {} is {indent_style} and not {expected} as expected",
file.path().display(),
),
None => panic!("no indent_style for {} found", file.path().display()),
}
}
fn assert_indent_size(file: &ConsideredFile, expected: usize) {
match file.indent_size {
Some(indent_size) => assert_eq!(
indent_size,
IndentSize::Value(expected),
"indent_size of {} is {indent_size} and not {} as expected",
file.path().display(),
IndentSize::Value(expected),
),
None => panic!("no indent_size for {} found", file.path().display()),
}
}
fn assert_tab_width(file: &ConsideredFile) {
if let Some(tab_width) = file.tab_width {
panic!(
"tab_width of {} is {tab_width} and is not unset as expected",
file.path().display(),
)
}
}
fn assert_insert_final_newline(file: &ConsideredFile, expected: bool) {
match file.insert_final_newline {
Some(FinalNewline::Value(insert_final_newline)) => assert_eq!(
insert_final_newline,
expected,
"insert_final_newline of {} is set to {insert_final_newline}",
file.path().display(),
),
None => panic!(
"no insert_final_newline for {} found",
file.path().display()
),
}
}
fn assert_spelling_language(file: &ConsideredFile) {
match file.spelling_language.as_ref() {
Some(SpellingLanguage::Value(language_tag)) => {
let expected_tag = LanguageTag::parse("en-US").expect("en-US is a valid language tag");
assert_eq!(
language_tag,
&expected_tag,
"spelling_language of {} is {language_tag} and not {expected_tag} as expected",
file.path().display(),
)
}
None => panic!("no spelling_language for {} found", file.path().display()),
}
}
fn assert_trim_trailing_whitespace(file: &ConsideredFile, expected: bool) {
match file.trim_trailing_whitespace {
Some(TrimTrailingWs::Value(trim_trailing_whitespace)) => assert_eq!(
trim_trailing_whitespace,
expected,
"trim_trailing_whitespace of {} is set to {trim_trailing_whitespace}",
file.path().display(),
),
None => panic!(
"no trim_trailing_whitespace for {} found",
file.path().display()
),
}
}
fn assert_all_not_set(file: &ConsideredFile) {
assert!(
file.charset.is_none(),
"charset of {} is set",
file.path().display()
);
assert!(
file.end_of_line.is_none(),
"end_of_line of {} is set",
file.path().display()
);
assert!(
file.indent_style.is_none(),
"indent_style of {} is set",
file.path().display()
);
assert!(
file.tab_width.is_none(),
"tab_width of {} is set",
file.path().display()
);
assert!(
file.insert_final_newline.is_none(),
"insert_final_newline of {} is set",
file.path().display()
);
assert!(
file.spelling_language.is_none(),
"spelling_language of {} is set",
file.path().display()
);
assert!(
file.trim_trailing_whitespace.is_none(),
"trim_trailing_whitespace of {} is set",
file.path().display()
);
}