using GitConverter.Lib.Factories;
using GitConverter.Lib.Models;
using GitConverter.TestsApp.TestSupport;
namespace GitConverter.TestsApp.Converters
{
///
/// Integration-style tests for CSV conversion flows.
///
///
/// Purpose
/// - Exercise end-to-end CSV conversion using the real ConversionService and CsvConverter
/// against small sample files/archives placed under TestData\Csv.
///
/// Behavior & expectations
/// - Tests are defensive: they skip when no TestData is present so CI remains non-fatal.
/// - For each sample the tests create isolated output and temp folders under a unique temp root.
/// - When ConversionService or CsvConverter returns Success the test asserts that at least one file
/// was created inside the output folder. When the result is Failure the test asserts a non-empty
/// diagnostic message is present.
///
/// Test data
/// - Place representative, small CSV samples (or archives containing CSV) under TestData\Csv in the test project
/// and mark them with CopyToOutputDirectory=PreserveNewest so they are available at runtime via AppContext.BaseDirectory.
///
/// Notes
/// - Integration tests avoid asserting exact filenames; they verify that outputs exist. When asserting suffixes
/// prefer FileExtensionHelpers.FromOption(...) + ToDotExtension() to compute expectations.
///
[Collection("Integration")]
public class CsvConverterIntegrationTests : IDisposable
{
private readonly string _root;
public CsvConverterIntegrationTests()
{
_root = Path.Combine(Path.GetTempPath(), "GitConverter.CsvTests", Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(_root);
}
public void Dispose()
{
try { if (Directory.Exists(_root)) Directory.Delete(_root, true); } catch { }
}
private static string TestDataCsvFolder => IntegrationTestConstants.TestDataCsvFolder;
///
/// Execute CSV conversion against the first available CSV sample found under the configured test data folder.
///
///
/// Preconditions:
/// - Small CSV samples or archives must be present under and copied to test output.
///
/// Test steps:
/// 1. Locate the first *.csv file under the test data folder. If none exists the test is skipped (no failure).
/// 2. Use to resolve a converter for the input file. A failed detection is treated
/// as a test failure (indicates misconfiguration or regression in detection logic).
/// 3. For each supported target option from :
/// a. Create isolated output and temp directories under the per-test temp root.
/// b. Invoke the converter's Convert method with the input, target, output and temp paths.
/// c. On success (ConversionResult.IsSuccess == true) assert that one or more files were written to the output directory.
/// d. On failure assert that the returned ConversionResult.Message is non-empty and fail the test with that message.
///
/// Cleanup:
/// - Output and temp folders created for a target are deleted in a finally block to avoid leaving artifacts.
///
/// Logging & diagnostics:
/// - Converters emit diagnostics via the configured logging adapter; this test surface captures filesystem outputs
/// and conversion results to determine pass/fail.
///
/// Determinism:
/// - Tests deliberately do not assert on exact output filenames to remain resilient to implementation changes.
/// - Sample artifacts should be small to keep tests fast and reliable in CI.
///
[Fact(DisplayName = "CsvConverter.Convert direct call against first CSV (if present)")]
public void Convert_SingleCsv_ToAllTargetOptions()
{
if (!Directory.Exists(TestDataCsvFolder))
return;
var csvFile = Directory.EnumerateFiles(TestDataCsvFolder, "*.csv", SearchOption.TopDirectoryOnly).FirstOrDefault();
if (csvFile == null)
return;
var factory = new ConverterFactory();
foreach (var targetFormatOption in IntegrationTestConstants.TargetOptions)
{
var outDir = Path.Combine(_root, $"{Path.GetFileNameWithoutExtension(csvFile)}_{targetFormatOption}_out");
var tempDir = Path.Combine(_root, $"{Path.GetFileNameWithoutExtension(csvFile)}_{targetFormatOption}_tmp");
Directory.CreateDirectory(outDir);
Directory.CreateDirectory(tempDir);
try
{
// Resolve a converter for the input; treat detection failure as a test failure.
if (!factory.TryCreateForInput(csvFile, out var converter, out var detectedSourceFormat, out var detectReason) || converter == null)
{
throw new Xunit.Sdk.XunitException($"Failed to detect converter for '{csvFile}': {detectReason ?? ""}");
}
// Execute conversion
ConversionResult result = converter.Convert(csvFile, detectedSourceFormat, targetFormatOption, outDir, tempDir);
Assert.NotNull(result);
if (result.IsSuccess)
{
var files = Directory.EnumerateFiles(outDir, "*", SearchOption.AllDirectories).ToList();
Assert.True(files.Count > 0, $"No output files for target format option '{targetFormatOption}' when converting '{csvFile}'.");
}
else
{
// On failure ensure a diagnostic message is present and fail clearly.
Assert.False(string.IsNullOrWhiteSpace(result.Message), $"Conversion to '{targetFormatOption}' failed with empty message ({csvFile}).");
throw new Xunit.Sdk.XunitException($"Conversion to '{targetFormatOption}' failed: {result.Message ?? ""} ({csvFile}).");
}
}
finally
{
try { if (Directory.Exists(outDir)) Directory.Delete(outDir, true); } catch { }
try { if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); } catch { }
}
}
}
}
}