ecformat 0.2.0

command line tool to keep files correct in respect of your EditorConfig
Documentation
// SPDX-FileCopyrightText: Contributors to ecformat project <https://codeberg.org/BaumiCoder/ecformat>
//
// SPDX-License-Identifier: BlueOak-1.0.0

//! Tests for the indentation related property of EditorConfig,
//! i.e., `indent_style`, `indent_size` and `tab_width`
//! Files for the Integration Tests here, and some unit tests
//! are in `tests/resources/indent_style` and `tests/resources/indent_size`.

use std::{fs, io};

use ec4rs::{PropertyKey, property};
use itertools::Itertools;
use tempfile::{NamedTempFile, TempDir};

use ecformat::errors::{CheckErrorType, EditorConfigError};

mod integration_test_utils;

use integration_test_utils::test_utils;

/// Runs the `check` command to the test files for the `indent_style` property
#[test]
fn test_check_indentation_on_indent_style_files() {
    test_check_indentation::<property::IndentStyle>();
}

/// Runs the `check` command to the test files for the `indent_size` property
#[test]
fn test_check_indentation_on_indent_size_files() {
    test_check_indentation::<property::IndentSize>();
}

/// Runs the `check` command to the test files for the property type
fn test_check_indentation<P: PropertyKey>() {
    let temp_dir = copy_test_files::<P>().expect("Copy tests file into temp dir necessary");
    let error_list = integration_test_utils::run_check_command(temp_dir.path());
    // All files with errors found?
    let error_files = integration_test_utils::check_error_list_as_file_names(&error_list);
    let expected_error_files =
        integration_test_utils::get_filtered_test_file_names::<P, _>(|test_entry| {
            let (_, _, _, lines_with_wrong_indentation) =
                test_utils::indentation::get_infos_from_file_name(test_entry);
            !lines_with_wrong_indentation.is_empty()
        });
    assert_eq!(
        error_files, expected_error_files,
        "Detected files with wrong indentations are not as expected"
    );

    // Type and fields of error correct?
    for error in &error_list {
        match error {
            EditorConfigError::FileError(file_error) => match file_error.error_type() {
                CheckErrorType::IndentationError {
                    lines_with_wrong_indentation,
                } => {
                    let (_, _, _, actual_lines_with_wrong_indentation) =
                        test_utils::indentation::get_infos_from_file_name(file_error.path());
                    assert_eq!(
                        &actual_lines_with_wrong_indentation,
                        lines_with_wrong_indentation,
                        "Not the lines with wrong indentations found as expected for {}",
                        file_error.path().display()
                    );
                }
                _ => panic!(
                    "The check error is not about indentation: {}",
                    file_error.path().display()
                ),
            },
            e => panic!("The error is no file error: {e}"),
        }
    }
}

/// Runs the `fix` command to the test files for the `indent_style` property
#[test]
fn test_fix_indentation_on_indent_style_files() {
    test_fix_indentation::<property::IndentStyle>();
}

/// Runs the `fix` command to the test files for the `indent_size` property
#[test]
fn test_fix_indentation_on_indent_size_files() {
    test_fix_indentation::<property::IndentSize>();
}

/// Runs the `fix` command to the test files for the property type
fn test_fix_indentation<P: PropertyKey>() {
    let temp_dir = copy_test_files::<P>().expect("Copy tests file into temp dir necessary");
    integration_test_utils::run_fix_command(temp_dir.path());
}

/// Copy the given test file and a suitable `.editorconfig` file into a temporary directory.
fn copy_test_files<P: PropertyKey>() -> io::Result<TempDir> {
    let test_file_helper = test_utils::TestFileHelper::new::<P>();
    let editorconfig_file =
        NamedTempFile::with_suffix_in(".editorconfig", test_file_helper.get_test_dir())?;
    let editorconfig = String::from("root = true\n")
        + &test_file_helper
            .get_test_file_paths()
            .map(|test_file| {
                let (indent_style, indent_size, tab_width, _) =
                    test_utils::indentation::get_infos_from_file_name(&test_file);
                let file_name = test_file.file_name().unwrap().to_str().unwrap();
                format!(
                    "[{file_name}]
                indent_style={indent_style}
                indent_size={indent_size}
                tab_width={tab_width}"
                )
            })
            .join("\n");

    fs::write(editorconfig_file.path(), editorconfig)?;
    integration_test_utils::copy_test_files(
        test_file_helper,
        editorconfig_file
            .path()
            .file_stem()
            .unwrap()
            .to_str()
            .unwrap()
            .to_string(),
    )
}