-
Notifications
You must be signed in to change notification settings - Fork 20
feat: implement CSVDiscoverer and catalog registry models #271
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development
Are you sure you want to change the base?
Changes from 1 commit
c9fa4be
45f8374
35d5c82
6445bc3
938263b
bc8706f
5853ab1
a272d46
58b2780
6d5d16e
61a6156
03ef494
ead2ac6
5ba833a
8a41bed
6e1f2cd
1290c6f
bfda8d3
5eb7fe8
7f58082
b50f52c
317e23c
abf8c8f
2ca99cb
e896fdf
265ac94
3b55070
e4d22fc
4d3363b
7af0378
a78f88e
5d78c8c
5a5992f
d1f34c8
6884e87
ba9f625
af1942f
8b00efd
a725109
fdce2c6
9980a68
58d57e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| using System.Collections.Generic; | ||
|
|
||
| namespace GenHub.Core.Models.Content; | ||
|
|
||
| /// <summary> | ||
| /// Configuration for CSV Catalog discovery. | ||
| /// Binds to "CsvValidationCatalogs" and "CsvCatalogIndexPath" in configuration. | ||
| /// </summary> | ||
| public class CsvCatalogConfiguration | ||
| { | ||
| /// <summary> | ||
| /// Gets or sets the list of fallback validation catalogs defined in configuration. | ||
| /// Used when index.json cannot be reached. | ||
| /// </summary> | ||
| public List<CsvValidationCatalog> CsvValidationCatalogs { get; set; } = []; | ||
|
mnoserat marked this conversation as resolved.
Outdated
|
||
|
|
||
| /// <summary> | ||
| /// Gets or sets the path to the index.json file relative to the docs directory. | ||
| /// </summary> | ||
|
mnoserat marked this conversation as resolved.
Outdated
|
||
| public string IndexFilePath { get; set; } = "docs/GameInstallationFilesRegistry/index.json"; | ||
|
mnoserat marked this conversation as resolved.
Outdated
mnoserat marked this conversation as resolved.
Outdated
|
||
| } | ||
|
|
||
| /// <summary> | ||
| /// Represents a CSV catalog defined in appsettings.json. | ||
| /// Matches the structure of CsvCatalogRegistryEntry but optimized for config binding. | ||
| /// </summary> | ||
| public class CsvValidationCatalog | ||
|
Check warning on line 27 in GenHub/GenHub.Core/Models/Content/CsvCatalogConfiguration.cs
|
||
| { | ||
| /// <summary> | ||
| /// Gets or sets the URL to the CSV file. | ||
| /// </summary> | ||
| public string Url { get; set; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the game type. | ||
| /// </summary> | ||
| public string GameType { get; set; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the version string. | ||
| /// </summary> | ||
| public string Version { get; set; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the supported languages. | ||
| /// </summary> | ||
| public List<string> SupportedLanguages { get; set; } = []; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the file count. | ||
| /// </summary> | ||
| public int FileCount { get; set; } | ||
| } | ||
|
mnoserat marked this conversation as resolved.
Outdated
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
|
|
||
| namespace GenHub.Core.Models.Content; | ||
|
|
||
| /// <summary> | ||
| /// Index of available CSV catalog registries. | ||
| /// Represents the structure of the docs/GameInstallationFilesRegistry/index.json file. | ||
| /// </summary> | ||
| public class CsvCatalogRegistryIndex | ||
| { | ||
| /// <summary> | ||
| /// Gets or sets the schema version. | ||
| /// </summary> | ||
| public int Version { get; set; } = 1; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets when the index was last updated. | ||
| /// </summary> | ||
| public DateTime LastUpdatedAt { get; set; } = DateTime.UtcNow; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the list of available catalog entries. | ||
| /// </summary> | ||
| public List<CsvCatalogRegistryEntry> Entries { get; set; } = []; | ||
|
mnoserat marked this conversation as resolved.
|
||
| } | ||
|
|
||
| /// <summary> | ||
| /// Represents a single CSV catalog entry in the registry. | ||
| /// </summary> | ||
| public class CsvCatalogRegistryEntry | ||
|
Check warning on line 31 in GenHub/GenHub.Core/Models/Content/CsvCatalogRegistryIndex.cs
|
||
| { | ||
| /// <summary> | ||
| /// Gets or sets the URL to the CSV file. | ||
| /// </summary> | ||
| public string Url { get; set; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the game type (e.g., "Generals", "ZeroHour"). | ||
| /// </summary> | ||
| public string GameType { get; set; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the game version (e.g., "1.08", "1.04"). | ||
| /// </summary> | ||
| public string Version { get; set; } = string.Empty; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the list of supported languages in this CSV. | ||
| /// </summary> | ||
| public List<string> SupportedLanguages { get; set; } = []; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets the optional file count in the CSV. | ||
| /// </summary> | ||
| public int? FileCount { get; set; } | ||
| } | ||
|
mnoserat marked this conversation as resolved.
Outdated
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Threading.Tasks; | ||
| using FluentAssertions; | ||
| using GenHub.Core.Interfaces.Common; | ||
| using GenHub.Core.Models.Content; | ||
| using GenHub.Core.Models.Enums; | ||
| using GenHub.Core.Models.Results.Content; | ||
| using GenHub.Features.Content.Services.ContentDiscoverers; | ||
| using Microsoft.Extensions.Logging; | ||
| using Moq; | ||
| using Xunit; | ||
|
|
||
| namespace GenHub.Tests.Core.Features.Content; | ||
|
|
||
| // the whole file is made by AI | ||
|
mnoserat marked this conversation as resolved.
Outdated
greptile-apps[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| /// <summary> | ||
| /// Unit tests for <see cref="CSVDiscoverer"/>. | ||
| /// </summary> | ||
| public class CSVDiscovererTests | ||
| { | ||
| /// <summary> | ||
| /// Verifies that <see cref="CSVDiscoverer.DiscoverAsync"/> returns a valid result when querying for Generals. | ||
| /// </summary> | ||
| /// <returns>A task representing the asynchronous test operation.</returns> | ||
| [Fact] | ||
| public async Task DiscoverAsync_WithGeneralsQuery_ReturnsValidResult() | ||
| { | ||
| // Arrange | ||
| var config = new CsvCatalogConfiguration | ||
| { | ||
| IndexFilePath = "non-existent-index.json", | ||
| CsvValidationCatalogs = new List<CsvValidationCatalog> | ||
| { | ||
| new CsvValidationCatalog | ||
| { | ||
| Url = "https://example.com/generals.csv", | ||
| GameType = "Generals", | ||
| Version = "1.08", | ||
| SupportedLanguages = new List<string> { "en" }, | ||
|
mnoserat marked this conversation as resolved.
Outdated
|
||
| FileCount = 100, | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| var mockConfig = new Mock<IConfigurationProviderService>(); | ||
| mockConfig.Setup(o => o.GetCsvCatalogConfiguration()).Returns(config); | ||
|
|
||
| var discoverer = new CSVDiscoverer( | ||
| Mock.Of<ILogger<CSVDiscoverer>>(), | ||
| mockConfig.Object); | ||
|
|
||
| var query = new ContentSearchQuery { TargetGame = GameType.Generals }; | ||
|
|
||
| // Act | ||
| var result = await discoverer.DiscoverAsync(query); | ||
|
|
||
| // Assert | ||
| result.Success.Should().BeTrue(); | ||
| result.Data.Should().NotBeNull(); | ||
| result.Data!.Items.Should().NotBeEmpty(); | ||
| result.Data.Items.First().ResolverMetadata.Should().ContainKey("csvUrl"); | ||
| result.Data.Items.First().ResolverMetadata["csvUrl"].Should().Be("https://example.com/generals.csv"); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Verifies that <see cref="CSVDiscoverer.DiscoverAsync"/> returns an empty result when the content type is not GameInstallation. | ||
| /// </summary> | ||
| /// <returns>A task representing the asynchronous test operation.</returns> | ||
| [Fact] | ||
| public async Task DiscoverAsync_WithNonGameInstallationContentType_ReturnsEmptyResult() | ||
| { | ||
| // Arrange | ||
| var mockConfig = new Mock<IConfigurationProviderService>(); | ||
| mockConfig.Setup(o => o.GetCsvCatalogConfiguration()).Returns(new CsvCatalogConfiguration()); | ||
|
|
||
| var discoverer = new CSVDiscoverer( | ||
| Mock.Of<ILogger<CSVDiscoverer>>(), | ||
| mockConfig.Object); | ||
|
|
||
| var query = new ContentSearchQuery { ContentType = GenHub.Core.Models.Enums.ContentType.Map }; | ||
|
|
||
| // Act | ||
| var result = await discoverer.DiscoverAsync(query); | ||
|
|
||
| // Assert | ||
| result.Success.Should().BeTrue(); | ||
| result.Data.Should().NotBeNull(); | ||
| result.Data!.Items.Should().BeEmpty(); | ||
| } | ||
|
|
||
|
mnoserat marked this conversation as resolved.
|
||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.