using GitConverter.Lib.Factories;
using GitConverter.Lib.Models;
using GitConverter.TestsApp.TestSupport;
namespace GitConverter.TestsApp.Converters
{
///
/// Integration-style tests for GML conversion flows.
///
///
/// Purpose
/// - Exercise end-to-end GML conversion using the real ConversionService and GmlConverter
/// against small sample files/archives placed under TestData\Gml.
///
/// 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 GmlConverter 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 GML samples (or archives containing GML) under TestData\Gml 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 GmlConversionIntegrationTests : IDisposable
{
private readonly string _root;
public GmlConversionIntegrationTests()
{
_root = Path.Combine(Path.GetTempPath(), "GitConverter.GmlTests", Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(_root);
}
public void Dispose()
{
try { if (Directory.Exists(_root)) Directory.Delete(_root, true); } catch { }
}
private static string TestDataGmlFolder => IntegrationTestConstants.TestDataGmlFolder;
///
/// Execute GML conversion against the first available GML sample found under the configured test data folder.
///
///
/// Preconditions:
/// - Small GML samples or archives must be present under and copied to test output.
///
/// Test steps:
/// 1. Locate the first *.gml, *.zip or *.7z 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, detected source format, 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 = "GmlConverter.Convert direct call against first GML (if present)")]
public void Convert_SingleGml_ToAllTargetOptions()
{
if (!Directory.Exists(TestDataGmlFolder))
return;
var sample = Directory.EnumerateFiles(TestDataGmlFolder, "*", SearchOption.TopDirectoryOnly)
.FirstOrDefault(f => f.EndsWith(".gml", StringComparison.OrdinalIgnoreCase)
|| f.EndsWith(".zip", StringComparison.OrdinalIgnoreCase)
|| f.EndsWith(".7z", StringComparison.OrdinalIgnoreCase));
if (sample == null)
return;
var factory = new ConverterFactory();
foreach (var targetFormatOption in IntegrationTestConstants.TargetOptions)
{
var outDir = Path.Combine(_root, $"{Path.GetFileNameWithoutExtension(sample)}_{targetFormatOption}_out");
var tempDir = Path.Combine(_root, $"{Path.GetFileNameWithoutExtension(sample)}_{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(sample, out var converter, out var detectedSourceFormat, out var detectReason) || converter == null)
{
throw new Xunit.Sdk.XunitException($"Failed to detect converter for '{sample}': {detectReason ?? ""}");
}
// Execute conversion. Pass detectedSourceFormat so converters with source-specific behavior can use it.
ConversionResult result = converter.Convert(sample, 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 '{sample}'.");
}
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 ({sample}).");
throw new Xunit.Sdk.XunitException($"Conversion to '{targetFormatOption}' failed: {result.Message ?? ""} ({sample}).");
}
}
finally
{
try { if (Directory.Exists(outDir)) Directory.Delete(outDir, true); } catch { }
try { if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); } catch { }
}
}
}
}
}