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");
}
}
}
}