using System.Text; using GitConverter.Lib.Converters; using GitConverter.Lib.Factories; using GitConverter.Lib.Models; namespace GitConverter.TestsApp.Factories { /// /// Unit tests for ConverterFactoryInputExtensions (single-file JSON / extension detection). /// - Uses a lightweight FakeFactory that implements IConverterFactory.TryCreate to capture requested keys. /// - Tests create temporary files with small headers to drive the header-sniffing code paths. /// public class ConverterFactoryInputExtensionsTests : IDisposable { private readonly string _tmpFolder; public ConverterFactoryInputExtensionsTests() { _tmpFolder = Path.Combine(Path.GetTempPath(), "GitConverter.Tests", Guid.NewGuid().ToString("N")); Directory.CreateDirectory(_tmpFolder); } public void Dispose() { try { if (Directory.Exists(_tmpFolder)) Directory.Delete(_tmpFolder, true); } catch { } } private string CreateTempFile(string extension, string content) { var path = Path.Combine(_tmpFolder, Guid.NewGuid().ToString("N") + extension); File.WriteAllText(path, content ?? string.Empty, Encoding.UTF8); return path; } private class FakeFactory : IConverterFactory { public string LastRequestedKey { get; private set; } public IConverter CreatedConverter { get; private set; } public IConverter Create(string formatOption) => throw new KeyNotFoundException(); public bool TryCreate(string formatOption, out IConverter converter) { LastRequestedKey = formatOption; converter = new DummyConverter(formatOption); CreatedConverter = converter; return true; } public System.Collections.Generic.IReadOnlyCollection GetSupportedOptions() => new string[0]; } private class DummyConverter : IConverter { public string Option { get; } public DummyConverter(string option) { Option = option; } public ConversionResult Convert(string gisInputFilePath, string gisTargetFormatOption, string outputFolderPath, string tempFolderPath) { return ConversionResult.Success("ok"); } } [Fact(DisplayName = "Explicit .geojson extension maps to GeoJson converter")] public void GeoJson_Extension_Mapped() { var f = new FakeFactory(); var file = CreateTempFile(".geojson", "{ \"type\": \"FeatureCollection\", \"features\": [] }"); var ok = f.TryCreateForInput(file, out var conv, out var reason); Assert.True(ok); Assert.NotNull(conv); Assert.Equal("GeoJson", f.LastRequestedKey, ignoreCase: true); Assert.Contains("Mapped extension", reason, StringComparison.OrdinalIgnoreCase); } [Fact(DisplayName = "Explicit .esrijson extension maps to EsriJson converter")] public void EsriJson_Extension_Mapped() { var f = new FakeFactory(); var file = CreateTempFile(".esrijson", "{ \"spatialReference\": { \"wkid\": 4326 } }"); var ok = f.TryCreateForInput(file, out var conv, out var reason); Assert.True(ok); Assert.NotNull(conv); Assert.Equal("EsriJson", f.LastRequestedKey, ignoreCase: true); Assert.Contains("Mapped extension", reason, StringComparison.OrdinalIgnoreCase); } [Fact(DisplayName = "Generic .json with FeatureCollection detected as GeoJson")] public void Json_FeatureCollection_Detected_As_GeoJson() { var f = new FakeFactory(); var file = CreateTempFile(".json", "{ \"type\": \"FeatureCollection\", \"features\": [] }"); var ok = f.TryCreateForInput(file, out var conv, out var reason); Assert.True(ok); Assert.NotNull(conv); Assert.Equal("GeoJson", f.LastRequestedKey, ignoreCase: true); Assert.Contains("Detected JSON format", reason, StringComparison.OrdinalIgnoreCase); } [Fact(DisplayName = "Generic .json with spatialReference detected as EsriJson")] public void Json_With_SpatialReference_Detected_As_EsriJson() { var f = new FakeFactory(); var file = CreateTempFile(".json", "{ \"spatialReference\": { \"wkid\": 3857 }, \"features\": [] }"); var ok = f.TryCreateForInput(file, out var conv, out var reason); Assert.True(ok); Assert.NotNull(conv); Assert.Equal("EsriJson", f.LastRequestedKey, ignoreCase: true); Assert.Contains("Detected JSON format", reason, StringComparison.OrdinalIgnoreCase); } [Fact(DisplayName = "NDJSON (.json with multiple JSON lines) detected as GeoJsonSeq")] public void Json_Ndjson_Detected_As_GeoJsonSeq() { var f = new FakeFactory(); var content = "{\"type\":\"Feature\",\"properties\":{}}\n{\"type\":\"Feature\",\"properties\":{}}\n"; var file = CreateTempFile(".json", content); var ok = f.TryCreateForInput(file, out var conv, out var reason); Assert.True(ok); Assert.NotNull(conv); Assert.Equal("GeoJsonSeq", f.LastRequestedKey, ignoreCase: true); // The detector reason can come from the JsonFormatDetector or from header sniffing. // Assert on the stable detected key instead of a specific phrase like "NDJSON". Assert.Contains("GeoJsonSeq", reason, StringComparison.OrdinalIgnoreCase); } [Fact(DisplayName = "TopoJSON fingerprint detected from .json header")] public void Json_TopoJson_Detected_As_TopoJson() { var f = new FakeFactory(); var file = CreateTempFile(".json", "{ \"type\": \"Topology\", \"topology\": {} }"); var ok = f.TryCreateForInput(file, out var conv, out var reason); Assert.True(ok); Assert.NotNull(conv); Assert.Equal("TopoJson", f.LastRequestedKey, ignoreCase: true); Assert.Contains("Detected JSON format", reason, StringComparison.OrdinalIgnoreCase); } } }