# GitConverter.Lib.Models Canonical model types and small helpers used across the conversion library. This document explains the intent, key types, usage patterns, testing guidance and troubleshooting notes for model types such as `ConversionResult`, `ConversionStatus`, `FileExtension` and `FileExtensionHelpers`. Targets - Library: .NET Standard 2.1 (compatible with .NET 9 hosts used by the ConsoleApp and tests). Purpose Keep domain value types and deterministic helpers centralized so converters and orchestration code can rely on consistent semantics for extension mapping, result reporting and lightweight option passing. Models are kept small, immutable where appropriate and easy to reason about in unit and integration tests. Key types - `ConversionResult` - Immutable carrier returned by converters to represent success or failure. - Created via helpers: `ConversionResult.Success(string message)` and `ConversionResult.Failure(string message)`. - Contains: `Status` (`ConversionStatus`), `Message` (human-readable), and `TimestampUtc` (diagnostic). - Equality semantics intentionally ignore `TimestampUtc` so logical comparisons in tests remain stable. - `ConversionStatus` - Enum representing the outcome: `Success` or `Failure`. - `FileExtension` (enum) and `FileExtensionHelpers` - Central, canonical enum of supported output file types (for example `GeoJson`, `Shapefile`, `Csv`). - `FileExtensionHelpers.FromOption(string option)` maps a canonical option string to a `FileExtension?`. - `FileExtensionHelpers.ToDotExtension(FileExtension ext)` returns the dot-prefixed extension (for example `.geojson`). - These helpers are the authoritative source for tests and runtime code that construct output filenames. Design notes - Immutability and small surface - `ConversionResult` is designed to be immutable after creation. This reduces surprises when results are passed between components and simplifies reasoning in tests. - Equality and diagnostics - `TimestampUtc` is included for diagnostic display but excluded from equality checks and hash computation by design. - Logical equality focuses on `Status` and `Message` so tests that compare results across processes or runs are stable. - Hash codes - Hash code implementations may use unchecked arithmetic (intentional) to produce a compact integer; this is idiomatic for .NET Standard compatibility and not relied upon for persistence or cross-process comparison. Usage patterns - Returning results from converters ```csharp if (error) return ConversionResult.Failure("Missing companion files (.shx/.dbf)"); return ConversionResult.Success($"Converted to {targetOption}; output: {outputPath}"); ``` - Building canonical filenames ```csharp var maybeExt = FileExtensionHelpers.FromOption(gisTargetFormatOption); var dotExt = FileExtensionHelpers.ToDotExtension(maybeExt ?? FileExtension.Shapefile); var fileName = $"output_{DateTime.UtcNow:yyyyMMdd_HHmmss}{dotExt}"; ``` Testing guidance - Assert on logical result semantics - Prefer `Assert.Equal(ConversionStatus.Success, result.Status)` and substring checks on `result.Message`. - Avoid asserting on `TimestampUtc` or exact message formatting unless the test specifically targets that behavior. - Use `FileExtensionHelpers` in tests - When verifying produced filenames or extensions compute expected suffixes via `FileExtensionHelpers.ToDotExtension(...)` rather than hard-coding string values. This keeps tests aligned with production mappings. - Creating expected `ConversionResult` - Use the factory helpers `Success`/`Failure` to build expected results for mocks and fakes so tests mirror production representation. Example assertions ```csharp var res = converter.Convert(...); Assert.Equal(ConversionStatus.Success, res.Status); Assert.Contains("Converted to GeoJson", res.Message, StringComparison.OrdinalIgnoreCase); var ext = FileExtensionHelpers.FromOption("GeoJson"); var dot = FileExtensionHelpers.ToDotExtension(ext.Value); Assert.True(Directory.GetFiles(outputFolder, "*" + dot, SearchOption.AllDirectories).Any()); ``` Extending the model surface - When adding a new `FileExtension` value: 1. Add the enum value to `FileExtension`. 2. Update `FileExtensionHelpers.FromOption` and `ToDotExtension` to include mappings and dot extension. 3. Add unit tests covering mapping and any downstream behaviors that depend on the extension. Notes on MapInfo / MIF recognition - `FileExtensionHelpers.FromOption` recognizes several aliases for MapInfo interchange formats. Supported inputs include (case-insensitive): - `"mapinfointerchange"`, `"mapinfo"`, `"mif"`, `"mid"` which all map to `FileExtension.MapInfoInterchange`. - This ensures tests and CLI users specifying `mif`, `mid` or `mapinfo` are routed consistently. Troubleshooting - Unexpected `ConversionResult` inequality - Confirm `Message` strings match exactly (ordinal equality); if messages include timestamps or variable data prefer substring checks. - Missing expected output files in integration tests - Use `FileExtensionHelpers.ToDotExtension(...)` to compute the extension expected by the converter under test and search the output tree for matches rather than assuming exact filename patterns. - Changes to extension mappings - If you change or rename a canonical file extension mapping update corresponding tests and README notes so consumers remain consistent. Contact and maintenance - When making changes to model semantics (equality, added fields, or extension mappings) update unit tests and this README to document the rationale. - Keep the model surface small — prefer adding specific option objects or converters rather than inflating `ConversionResult` with extra fields unless necessary.