- Updated `IMediaSourceCatalog` to support user-added media sources, allowing dynamic editing and management of sources. - Removed the `UrlListSource` class as its functionality is now integrated into the new catalog structure. - Enhanced `CollectOptions` to default `RequireProxy` to true, ensuring stricter handling of proxy requirements. - Improved error handling in `ParseError` to include a `Subject` field for better context on failures. - Adjusted dependency injection to reflect changes in media source management, removing old source registrations. - Introduced background proxy checks to ensure a more robust proxy pool management during collection processes. These changes streamline the media collection process and improve the overall user experience by providing clearer error reporting and more flexible source management.
125 lines
3.6 KiB
C#
125 lines
3.6 KiB
C#
using AvParser.Core.Collecting.Sources;
|
|
using AvParser.Infrastructure.Collecting;
|
|
using AvParser.Infrastructure.Storage;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
|
|
namespace AvParser.Infrastructure.Tests.Collecting;
|
|
|
|
public sealed class JsonUserSourceStoreTests : IDisposable
|
|
{
|
|
private readonly string _directory = Path.Combine(
|
|
Path.GetTempPath(),
|
|
"AvParserTests",
|
|
Guid.NewGuid().ToString("N")
|
|
);
|
|
|
|
private JsonUserSourceStore Create() => new(new AppPaths(_directory), NullLogger<JsonUserSourceStore>.Instance);
|
|
|
|
private static PatternSourceConfig Config(string id, string name = "Test", bool allowDirect = false)
|
|
{
|
|
PatternSourceConfig.TryCreate(
|
|
name,
|
|
"https://imgtest.example/test1/",
|
|
6,
|
|
8,
|
|
IdAlphabet.Alphanumeric,
|
|
null,
|
|
".jpg",
|
|
allowDirect,
|
|
out var config,
|
|
id
|
|
);
|
|
return config!;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Directory.Exists(_directory))
|
|
{
|
|
Directory.Delete(_directory, recursive: true);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void An_absent_file_reads_as_an_empty_list()
|
|
{
|
|
using var store = Create();
|
|
|
|
store.List().ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Added_sources_survive_a_reload()
|
|
{
|
|
using (var store = Create())
|
|
{
|
|
await store.AddAsync(Config("s1", "Kept"), TestContext.Current.CancellationToken);
|
|
}
|
|
|
|
// A brand-new instance reads from disk rather than from the in-memory cache.
|
|
using var reopened = Create();
|
|
|
|
var config = reopened.List().ShouldHaveSingleItem();
|
|
config.Id.ShouldBe("s1");
|
|
config.Name.ShouldBe("Kept");
|
|
config.BaseUrl.AbsoluteUri.ShouldBe("https://imgtest.example/test1/");
|
|
config.Extension.ShouldBe(".jpg");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Updating_replaces_the_matching_config()
|
|
{
|
|
using var store = Create();
|
|
await store.AddAsync(Config("s1", "Before"), TestContext.Current.CancellationToken);
|
|
|
|
var updated = Config("s1", "After");
|
|
(await store.UpdateAsync(updated, TestContext.Current.CancellationToken)).ShouldBeTrue();
|
|
|
|
store.List().ShouldHaveSingleItem().Name.ShouldBe("After");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Updating_an_unknown_id_changes_nothing()
|
|
{
|
|
using var store = Create();
|
|
|
|
(await store.UpdateAsync(Config("ghost"), TestContext.Current.CancellationToken)).ShouldBeFalse();
|
|
store.List().ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Removing_takes_the_config_out()
|
|
{
|
|
using var store = Create();
|
|
await store.AddAsync(Config("s1"), TestContext.Current.CancellationToken);
|
|
|
|
(await store.RemoveAsync("s1", TestContext.Current.CancellationToken)).ShouldBeTrue();
|
|
store.List().ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Mutations_raise_the_changed_event()
|
|
{
|
|
using var store = Create();
|
|
var changed = 0;
|
|
store.Changed += (_, _) => changed++;
|
|
|
|
await store.AddAsync(Config("s1"), TestContext.Current.CancellationToken);
|
|
await store.RemoveAsync("s1", TestContext.Current.CancellationToken);
|
|
|
|
changed.ShouldBe(2);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task A_corrupt_file_reads_as_an_empty_list()
|
|
{
|
|
Directory.CreateDirectory(_directory);
|
|
IAppPaths paths = new AppPaths(_directory);
|
|
await File.WriteAllTextAsync(paths.UserSourcesFile, "{ not json ]", TestContext.Current.CancellationToken);
|
|
|
|
using var store = Create();
|
|
|
|
store.List().ShouldBeEmpty();
|
|
}
|
|
}
|