using GitConverter.Lib.Factories;
using GitConverter.Lib.Models;
using GitConverter.TestsApp.TestSupport;
namespace GitConverter.TestsApp.Converters
{
///
/// Integration-style tests for Shapefile conversion flows.
///
///
/// Purpose
/// - Exercise end-to-end Shapefile conversion using the real ConversionService and ShapefileConverter
/// against small sample archives placed under TestData\Shapefile.
///
/// 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 ShapefileConverter 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 shapefile archives (.7z or .zip) under TestData\Shapefile 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.
/// - Tests intentionally pass the detected source format to Convert so converters that vary behavior by source
/// format can use that information.
///
[Collection("Integration")]
public class ShapefileConverterIntegrationTests : IDisposable
{
private readonly string _root;
public ShapefileConverterIntegrationTests()
{
_root = Path.Combine(Path.GetTempPath(), "GitConverter.ShapefileTests", Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(_root);
}
public void Dispose()
{
try { if (Directory.Exists(_root)) Directory.Delete(_root, true); } catch { }
}
private static string TestDataShapefileFolder => IntegrationTestConstants.TestDataShapefileFolder;
///
/// Execute Shapefile conversion against the first available shapefile archive found under the configured test data folder.
///
///
/// Preconditions:
/// - Small shapefile archives (.7z or .zip) must be present under and copied to test output.
///
/// Test steps:
/// 1. Locate the first *.7z or *.zip archive under the test data folder. If none exists the test is skipped (no failure).
/// 2. Use to resolve a converter for the input archive. A failed detection is treated
/// as a test failure (indicates misconfiguration or regression in detection logic).
/// 3. For each supported targetFormatOption 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 = "ShapefileConverter.Convert direct call against first archive (if present)")]
public void Convert_SingleShapefileArchive_ToAllTargetOptions()
{
if (!Directory.Exists(TestDataShapefileFolder))
return;
var sample = Directory.EnumerateFiles(TestDataShapefileFolder, "*", SearchOption.TopDirectoryOnly)
.FirstOrDefault(f => f.EndsWith(".7z", StringComparison.OrdinalIgnoreCase)
|| f.EndsWith(".zip", 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 archive; 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, "Csv", 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 { }
}
}
}
}
}