using GitConverter.Lib.Factories; using GitConverter.Lib.Converters; using GitConverter.Lib.Models; namespace GitConverter.TestsApp.Factories { /// /// Unit tests for the public APIs (, , ). /// /// /// /// Purpose /// - Validate the factory's behavior for common caller patterns: tolerant lookup, suggestion when mistyped, /// non-throwing TryCreate for CLI flows, and deterministic supported options presentation. /// /// /// Test strategy /// - Prefer the constructor overload that accepts explicit registrations when tests need deterministic /// control over available converters. For tests exercising the built-in registry use the default constructor. /// - Focus assertions on observable contract behavior rather than implementation details: success/failure return /// values, thrown exception types and presence of expected display keys in . /// /// /// Additional tests included /// - Unknown option via TryCreate returns false without throwing. /// - Custom registrations are honored and used to create converters. /// - Create throws for null/whitespace inputs and includes suggestions for near-miss keys. /// - Supported options are returned as an ordered, read-only collection. /// /// public class ConverterFactoryTests { /// /// Happy path: registered option resolves to an IConverter via TryCreate using the built-in registry. /// [Fact] public void TryCreate_KnownOption_ReturnsConverter() { var factory = new ConverterFactory(); var ok = factory.TryCreate("EsriJson", out var converter); Assert.True(ok); Assert.NotNull(converter); Assert.IsAssignableFrom(converter); } /// /// TryCreate returns false for unknown options rather than throwing. /// [Fact] public void TryCreate_UnknownOption_ReturnsFalse() { var factory = new ConverterFactory(); var ok = factory.TryCreate("definitely-not-a-format", out var converter); Assert.False(ok); Assert.Null(converter); } /// /// Input normalization: hyphens and case differences are tolerated. /// [Fact] public void TryCreate_NormalizesInput_HyphenAndCase_ReturnsConverter() { var factory = new ConverterFactory(); // input with hyphen and different case should still resolve var ok = factory.TryCreate("esri-json", out var converter); Assert.True(ok); Assert.NotNull(converter); } /// /// Create throws with a friendly suggestion when input is close to a supported option. /// [Fact] public void Create_UnknownOption_ThrowsWithSuggestionWhenClose() { var factory = new ConverterFactory(); var ex = Assert.Throws(() => factory.Create("esrijsn")); // typo // Should include a helpful suggestion for close matches Assert.Contains("Did you mean", ex.Message, StringComparison.OrdinalIgnoreCase); Assert.Contains("EsriJson", ex.Message, StringComparison.OrdinalIgnoreCase); } /// /// Create validates its input and throws ArgumentException for null or whitespace. /// [Fact] public void Create_NullOrWhitespace_ThrowsArgumentException() { var factory = new ConverterFactory(); Assert.Throws(() => factory.Create(null)); Assert.Throws(() => factory.Create(" ")); } /// /// GetSupportedOptions returns a non-empty list containing expected display keys. /// [Fact] public void GetSupportedOptions_ReturnsNonEmptyList_ContainsExpectedKeys() { var factory = new ConverterFactory(); var supported = factory.GetSupportedOptions().ToList(); Assert.NotEmpty(supported); Assert.Contains("EsriJson", supported); Assert.Contains("GeoJson", supported); } /// /// Custom registrations are honored by the factory and the provided factory delegates are invoked. /// [Fact] public void TryCreate_UsesCustomRegistrations() { var registrations = new Dictionary>(StringComparer.OrdinalIgnoreCase) { { "MyFormat", () => new DummyConverter("MyFormat") } }; var factory = new ConverterFactory(registrations, null); var ok = factory.TryCreate("MyFormat", out var conv); Assert.True(ok); Assert.NotNull(conv); Assert.IsAssignableFrom(conv); } /// /// Create returns a converter instance for known options (throws only for unknowns). /// [Fact] public void Create_KnownOption_ReturnsConverter() { var registrations = new Dictionary>(StringComparer.OrdinalIgnoreCase) { { "X", () => new DummyConverter("X") } }; var factory = new ConverterFactory(registrations, null); var conv = factory.Create("X"); Assert.NotNull(conv); Assert.IsAssignableFrom(conv); } /// /// Dummy converter used by tests to avoid heavy dependencies. /// private class DummyConverter : IConverter { public string Option { get; } public DummyConverter(string option) { Option = option; } public ConversionResult Convert(string gisInputFilePath, string gisSourceFormatOption, string gisTargetFormatOption, string outputFolderPath, string tempFolderPath) { return ConversionResult.Success("ok"); } } } }