Cleaned up test code files.
This commit is contained in:
19
JSMR.Tests/Search/Circle/CircleSearchProviderFixture.cs
Normal file
19
JSMR.Tests/Search/Circle/CircleSearchProviderFixture.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using JSMR.Infrastructure.Data;
|
||||
using JSMR.Tests.Fixtures;
|
||||
|
||||
namespace JSMR.Tests.Search.Circle;
|
||||
|
||||
public sealed class CircleSearchProviderFixture(MariaDbContainerFixture container) : SearchProviderFixture(container)
|
||||
{
|
||||
protected override async Task SeedAsync(AppDbContext context)
|
||||
{
|
||||
context.Circles.AddRange(
|
||||
new() { CircleId = 1, Name = "Good Dreams", MakerId = "RG00001" },
|
||||
new() { CircleId = 2, Name = "Sweet Dreams", Favorite = true, MakerId = "RG00002" },
|
||||
new() { CircleId = 3, Name = "Nightmare Fuel", Blacklisted = true, MakerId = "RG00003" },
|
||||
new() { CircleId = 4, Name = "Garbage Studio", Spam = true, MakerId = "RG00004" }
|
||||
);
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
210
JSMR.Tests/Search/Circle/CircleSearchProviderTests.cs
Normal file
210
JSMR.Tests/Search/Circle/CircleSearchProviderTests.cs
Normal file
@@ -0,0 +1,210 @@
|
||||
using JSMR.Application.Circles.Queries.Search;
|
||||
using JSMR.Application.Common.Search;
|
||||
using JSMR.Infrastructure.Data;
|
||||
using JSMR.Infrastructure.Data.Repositories.Circles;
|
||||
using Shouldly;
|
||||
using SortDirection = JSMR.Application.Common.Search.SortDirection;
|
||||
|
||||
namespace JSMR.Tests.Search.Circle;
|
||||
|
||||
public class CircleSearchProviderTests(CircleSearchProviderFixture fixture) : IClassFixture<CircleSearchProviderFixture>
|
||||
{
|
||||
private async Task<SearchResult<CircleSearchItem>> SearchAsync(SearchOptions<CircleSearchCriteria, CircleSortField> options)
|
||||
{
|
||||
AppDbContext context = fixture.DbContext!;
|
||||
CircleSearchProvider provider = new(context);
|
||||
|
||||
return await provider.SearchAsync(options, TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_None()
|
||||
{
|
||||
var options = new SearchOptions<CircleSearchCriteria, CircleSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(4);
|
||||
result.TotalItems.ShouldBe(4);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_By_Status_Not_Blacklisted()
|
||||
{
|
||||
var options = new SearchOptions<CircleSearchCriteria, CircleSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Status = CircleStatus.NotBlacklisted
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(3);
|
||||
result.TotalItems.ShouldBe(3);
|
||||
result.Items.ShouldNotContain(item => item.Blacklisted);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_By_Status_Favorited()
|
||||
{
|
||||
var options = new SearchOptions<CircleSearchCriteria, CircleSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Status = CircleStatus.Favorited
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
result.Items.ShouldAllBe(item => item.Favorite);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_By_Status_Blacklisted()
|
||||
{
|
||||
var options = new SearchOptions<CircleSearchCriteria, CircleSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Status = CircleStatus.Blacklisted
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
result.Items.ShouldAllBe(item => item.Blacklisted);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_By_Status_Spam()
|
||||
{
|
||||
var options = new SearchOptions<CircleSearchCriteria, CircleSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Status = CircleStatus.Spam
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
result.Items.ShouldAllBe(item => item.Spam);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_By_Name_Circle_Name()
|
||||
{
|
||||
var options = new SearchOptions<CircleSearchCriteria, CircleSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Name = "Dreams"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(2);
|
||||
result.TotalItems.ShouldBe(2);
|
||||
result.Items.ShouldAllBe(item => item.Name.Contains("Dreams", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_By_Name_Circle_Id()
|
||||
{
|
||||
var options = new SearchOptions<CircleSearchCriteria, CircleSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Name = "003"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
result.Items.ShouldContain(item => item.MakerId.Contains("003", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sort_By_Name_Descending()
|
||||
{
|
||||
var options = new SearchOptions<CircleSearchCriteria, CircleSortField>()
|
||||
{
|
||||
SortOptions = [new(CircleSortField.Name, SortDirection.Descending)]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(4);
|
||||
result.TotalItems.ShouldBe(4);
|
||||
result.Items[0].Name.ShouldBe("Sweet Dreams");
|
||||
result.Items[1].Name.ShouldBe("Nightmare Fuel");
|
||||
result.Items[2].Name.ShouldBe("Good Dreams");
|
||||
result.Items[3].Name.ShouldBe("Garbage Studio");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sort_By_Favorite_Ascending()
|
||||
{
|
||||
var options = new SearchOptions<CircleSearchCriteria, CircleSortField>()
|
||||
{
|
||||
SortOptions = [new(CircleSortField.Favorite, SortDirection.Ascending)]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(4);
|
||||
result.TotalItems.ShouldBe(4);
|
||||
result.Items[0].Name.ShouldBe("Sweet Dreams");
|
||||
result.Items[1].Name.ShouldBe("Garbage Studio");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sort_By_Blacklisted_Ascending()
|
||||
{
|
||||
var options = new SearchOptions<CircleSearchCriteria, CircleSortField>()
|
||||
{
|
||||
SortOptions = [new(CircleSortField.Blacklisted, SortDirection.Ascending)]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(4);
|
||||
result.TotalItems.ShouldBe(4);
|
||||
result.Items[0].Name.ShouldBe("Nightmare Fuel");
|
||||
result.Items[1].Name.ShouldBe("Garbage Studio");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sort_By_Spam_Ascending()
|
||||
{
|
||||
var options = new SearchOptions<CircleSearchCriteria, CircleSortField>()
|
||||
{
|
||||
SortOptions = [new(CircleSortField.Spam, SortDirection.Ascending)]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(4);
|
||||
result.TotalItems.ShouldBe(4);
|
||||
result.Items[0].Name.ShouldBe("Garbage Studio");
|
||||
result.Items[1].Name.ShouldBe("Good Dreams");
|
||||
}
|
||||
}
|
||||
18
JSMR.Tests/Search/Creator/CreatorSearchProviderFixture.cs
Normal file
18
JSMR.Tests/Search/Creator/CreatorSearchProviderFixture.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using JSMR.Infrastructure.Data;
|
||||
using JSMR.Tests.Fixtures;
|
||||
|
||||
namespace JSMR.Tests.Search.Creator;
|
||||
|
||||
public sealed class CreatorSearchProviderFixture(MariaDbContainerFixture container) : SearchProviderFixture(container)
|
||||
{
|
||||
protected override async Task SeedAsync(AppDbContext context)
|
||||
{
|
||||
context.Creators.AddRange(
|
||||
new() { CreatorId = 1, Name = "John Smith" },
|
||||
new() { CreatorId = 2, Name = "John Doe", Favorite = true },
|
||||
new() { CreatorId = 3, Name = "Jane Doe", Blacklisted = true }
|
||||
);
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
95
JSMR.Tests/Search/Creator/CreatorSearchProviderTests.cs
Normal file
95
JSMR.Tests/Search/Creator/CreatorSearchProviderTests.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using JSMR.Application.Common.Search;
|
||||
using JSMR.Application.Creators.Queries.Search.Contracts;
|
||||
using JSMR.Infrastructure.Data;
|
||||
using JSMR.Infrastructure.Data.Repositories.Creators;
|
||||
using Shouldly;
|
||||
using SortDirection = JSMR.Application.Common.Search.SortDirection;
|
||||
|
||||
namespace JSMR.Tests.Search.Creator;
|
||||
|
||||
public class CreatorSearchProviderTests(CreatorSearchProviderFixture fixture) : IClassFixture<CreatorSearchProviderFixture>
|
||||
{
|
||||
private async Task<SearchResult<CreatorSearchItem>> SearchAsync(SearchOptions<CreatorSearchCriteria, CreatorSortField> options)
|
||||
{
|
||||
AppDbContext context = fixture.DbContext!;
|
||||
CreatorSearchProvider provider = new(context);
|
||||
|
||||
return await provider.SearchAsync(options, TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_None_Sort_Name_Ascending()
|
||||
{
|
||||
var options = new SearchOptions<CreatorSearchCriteria, CreatorSortField>()
|
||||
{
|
||||
SortOptions = [new(CreatorSortField.Name, SortDirection.Ascending)]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(3);
|
||||
result.TotalItems.ShouldBe(3);
|
||||
result.Items[0].Name.ShouldBe("Jane Doe");
|
||||
result.Items[2].Name.ShouldBe("John Smith");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_None_Sort_Name_Descending()
|
||||
{
|
||||
var options = new SearchOptions<CreatorSearchCriteria, CreatorSortField>()
|
||||
{
|
||||
SortOptions = [new(CreatorSortField.Name, SortDirection.Descending)]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(3);
|
||||
result.TotalItems.ShouldBe(3);
|
||||
result.Items[0].Name.ShouldBe("John Smith");
|
||||
result.Items[2].Name.ShouldBe("Jane Doe");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_None_Sort_Favorite_Descending()
|
||||
{
|
||||
var options = new SearchOptions<CreatorSearchCriteria, CreatorSortField>()
|
||||
{
|
||||
SortOptions = [new(CreatorSortField.Favorite, SortDirection.Ascending)]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items[0].Name.ShouldBe("John Doe");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_None_Sort_Blacklisted_Descending()
|
||||
{
|
||||
var options = new SearchOptions<CreatorSearchCriteria, CreatorSortField>()
|
||||
{
|
||||
SortOptions = [new(CreatorSortField.Blacklisted, SortDirection.Ascending)]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items[0].Name.ShouldBe("Jane Doe");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_By_Name_Creator_Name()
|
||||
{
|
||||
var options = new SearchOptions<CreatorSearchCriteria, CreatorSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Name = "Jane"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
result.Items.ShouldContain(creatorView => creatorView.Name == "Jane Doe");
|
||||
}
|
||||
}
|
||||
29
JSMR.Tests/Search/SearchProviderFixture.cs
Normal file
29
JSMR.Tests/Search/SearchProviderFixture.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using JSMR.Infrastructure.Data;
|
||||
using JSMR.Tests.Fixtures;
|
||||
|
||||
namespace JSMR.Tests.Search;
|
||||
|
||||
public abstract class SearchProviderFixture(MariaDbContainerFixture container) : IAsyncLifetime
|
||||
{
|
||||
public AppDbContext? DbContext { get; private set; }
|
||||
|
||||
public async ValueTask InitializeAsync()
|
||||
{
|
||||
DbContext = await MariaDbClone.CloneFromTemplateAsync(
|
||||
container.RootConnectionString,
|
||||
container.TemplateDbName,
|
||||
seed: SeedAsync);
|
||||
}
|
||||
|
||||
protected abstract Task SeedAsync(AppDbContext context);
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (DbContext is not null)
|
||||
{
|
||||
await DbContext.DisposeAsync();
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
24
JSMR.Tests/Search/Tag/TagSearchProviderFixture.cs
Normal file
24
JSMR.Tests/Search/Tag/TagSearchProviderFixture.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using JSMR.Infrastructure.Data;
|
||||
using JSMR.Tests.Fixtures;
|
||||
|
||||
namespace JSMR.Tests.Search.Tag;
|
||||
|
||||
public sealed class TagSearchProviderFixture(MariaDbContainerFixture container) : SearchProviderFixture(container)
|
||||
{
|
||||
protected override async Task SeedAsync(AppDbContext context)
|
||||
{
|
||||
context.Tags.AddRange(
|
||||
new() { TagId = 1, Name = "OL" },
|
||||
new() { TagId = 2, Name = "ほのぼの", Favorite = true },
|
||||
new() { TagId = 3, Name = "ツンデレ", Blacklisted = true }
|
||||
);
|
||||
|
||||
context.EnglishTags.AddRange(
|
||||
new() { EnglishTagId = 1, TagId = 1, Name = "Office Lady" },
|
||||
new() { EnglishTagId = 2, TagId = 2, Name = "Heartwarming" },
|
||||
new() { EnglishTagId = 3, TagId = 3, Name = "Tsundere" }
|
||||
);
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
87
JSMR.Tests/Search/Tag/TagSearchProviderTests.cs
Normal file
87
JSMR.Tests/Search/Tag/TagSearchProviderTests.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using JSMR.Application.Common.Search;
|
||||
using JSMR.Application.Tags.Queries.Search.Contracts;
|
||||
using JSMR.Infrastructure.Data;
|
||||
using JSMR.Infrastructure.Data.Repositories.Tags;
|
||||
using Shouldly;
|
||||
using SortDirection = JSMR.Application.Common.Search.SortDirection;
|
||||
|
||||
namespace JSMR.Tests.Search.Tag;
|
||||
|
||||
public class TagSearchProviderTests(TagSearchProviderFixture fixture) : IClassFixture<TagSearchProviderFixture>
|
||||
{
|
||||
private async Task<SearchResult<TagSearchItem>> SearchAsync(SearchOptions<TagSearchCriteria, TagSortField> options)
|
||||
{
|
||||
AppDbContext context = fixture.DbContext!;
|
||||
TagSearchProvider provider = new(context);
|
||||
|
||||
return await provider.SearchAsync(options, TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_None_Sort_Name()
|
||||
{
|
||||
var options = new SearchOptions<TagSearchCriteria, TagSortField>()
|
||||
{
|
||||
SortOptions = [new(TagSortField.Name, SortDirection.Ascending)]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(3);
|
||||
result.TotalItems.ShouldBe(3);
|
||||
result.Items[0].Name.ShouldBe("OL");
|
||||
result.Items[2].Name.ShouldBe("ツンデレ");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_None_Sort_EnglishName()
|
||||
{
|
||||
var options = new SearchOptions<TagSearchCriteria, TagSortField>()
|
||||
{
|
||||
SortOptions = [new(TagSortField.EnglishName, SortDirection.Ascending)]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(3);
|
||||
result.TotalItems.ShouldBe(3);
|
||||
result.Items[0].EnglishName.ShouldBe("Heartwarming");
|
||||
result.Items[2].EnglishName.ShouldBe("Tsundere");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_By_Name_Tag_Name()
|
||||
{
|
||||
var options = new SearchOptions<TagSearchCriteria, TagSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Name = "ほの"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
result.Items.ShouldContain(tagView => tagView.Name == "ほのぼの");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_By_Name_English_Tag_Name()
|
||||
{
|
||||
var options = new SearchOptions<TagSearchCriteria, TagSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Name = "Heart"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
result.Items.ShouldContain(tagView => tagView.EnglishName == "Heartwarming");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using JSMR.Domain.Enums;
|
||||
using JSMR.Infrastructure.Data;
|
||||
using JSMR.Tests.Fixtures;
|
||||
|
||||
namespace JSMR.Tests.Search.VoiceWork;
|
||||
|
||||
public sealed class VoiceWorkSearchProviderFixture(MariaDbContainerFixture container) : SearchProviderFixture(container)
|
||||
{
|
||||
protected override async Task SeedAsync(AppDbContext context)
|
||||
{
|
||||
context.Circles.AddRange(
|
||||
new() { CircleId = 1, Name = "Good Dreams", MakerId = "RG00001" },
|
||||
new() { CircleId = 2, Name = "Sweet Dreams", Favorite = true, MakerId = "RG00002" },
|
||||
new() { CircleId = 3, Name = "Nightmare Fuel", Blacklisted = true, MakerId = "RG00003" }
|
||||
);
|
||||
|
||||
context.VoiceWorks.AddRange(
|
||||
new() { VoiceWorkId = 1, CircleId = 1, ProductId = "RJ0000001", ProductName = "Today Sounds", Description = "An average product.", Status = (byte)VoiceWorkStatus.Available, SalesDate = new(2025, 1, 1), Downloads = 500, WishlistCount = 750, StarRating = 35 },
|
||||
new() { VoiceWorkId = 2, CircleId = 2, ProductId = "RJ0000002", ProductName = "Super Comfy ASMR", Description = "An amazing product!", Status = (byte)VoiceWorkStatus.NewRelease, SalesDate = new(2025, 1, 3), Downloads = 5000, WishlistCount = 12000, StarRating = 50, Favorite = true },
|
||||
new() { VoiceWorkId = 3, CircleId = 3, ProductId = "RJ0000003", ProductName = "Low Effort", Description = "A bad product.", Status = (byte)VoiceWorkStatus.Available, SalesDate = new(2025, 1, 2), Downloads = 50, WishlistCount = 100, StarRating = 20 },
|
||||
new() { VoiceWorkId = 4, CircleId = 1, ProductId = "RJ0000004", ProductName = "Tomorrow Sounds", Description = "A average upcoming product.", Status = (byte)VoiceWorkStatus.Upcoming, ExpectedDate = new(2025, 1, 1), WishlistCount = 300 },
|
||||
new() { VoiceWorkId = 5, CircleId = 2, ProductId = "RJ0000005", ProductName = "Super Comfy ASMR+", Description = "All your favorite sounds, plus more!", Status = (byte)VoiceWorkStatus.NewAndUpcoming, ExpectedDate = new(2025, 1, 11), WishlistCount = 10000 }
|
||||
);
|
||||
|
||||
context.Tags.AddRange(
|
||||
new() { TagId = 1, Name = "ASMR" },
|
||||
new() { TagId = 2, Name = "OL" },
|
||||
new() { TagId = 3, Name = "ほのぼの" },
|
||||
new() { TagId = 4, Name = "エルフ/妖精" },
|
||||
new() { TagId = 5, Name = "ツンデレ", Favorite = true },
|
||||
new() { TagId = 6, Name = "オールハッピー" },
|
||||
new() { TagId = 7, Name = "ギャル" },
|
||||
new() { TagId = 8, Name = "メイド" },
|
||||
new() { TagId = 9, Name = "ノンフィクション/体験談", Blacklisted = true }
|
||||
);
|
||||
|
||||
context.EnglishTags.AddRange(
|
||||
new() { EnglishTagId = 1, TagId = 1, Name = "ASMR" },
|
||||
new() { EnglishTagId = 2, TagId = 2, Name = "Office Lady" },
|
||||
new() { EnglishTagId = 3, TagId = 3, Name = "Heartwarming" },
|
||||
new() { EnglishTagId = 4, TagId = 4, Name = "Elf / Fairy" },
|
||||
new() { EnglishTagId = 5, TagId = 5, Name = "Tsundere" },
|
||||
new() { EnglishTagId = 6, TagId = 6, Name = "All Happy" },
|
||||
new() { EnglishTagId = 7, TagId = 7, Name = "Gal" },
|
||||
new() { EnglishTagId = 8, TagId = 8, Name = "Maid" },
|
||||
new() { EnglishTagId = 9, TagId = 9, Name = "Non-Fiction / Narrative" }
|
||||
);
|
||||
|
||||
context.VoiceWorkTags.AddRange(
|
||||
new() { VoiceWorkId = 1, TagId = 1 }, // ASMR
|
||||
new() { VoiceWorkId = 1, TagId = 2 }, // Office Lady
|
||||
|
||||
new() { VoiceWorkId = 2, TagId = 1 }, // ASMR
|
||||
new() { VoiceWorkId = 2, TagId = 3 }, // Heartwarming
|
||||
new() { VoiceWorkId = 2, TagId = 4 }, // Elf / Fairy
|
||||
new() { VoiceWorkId = 2, TagId = 5 }, // Tsundere
|
||||
new() { VoiceWorkId = 2, TagId = 6 }, // All Happy
|
||||
new() { VoiceWorkId = 2, TagId = 7 }, // Gal
|
||||
new() { VoiceWorkId = 2, TagId = 8 }, // Maid
|
||||
|
||||
new() { VoiceWorkId = 3, TagId = 5 }, // Tsundere
|
||||
new() { VoiceWorkId = 3, TagId = 9 } // Non-Fiction / Narrative
|
||||
);
|
||||
|
||||
context.Creators.AddRange(
|
||||
new() { CreatorId = 1, Name = "陽向葵ゅか", Favorite = true },
|
||||
new() { CreatorId = 2, Name = "秋野かえで" },
|
||||
new() { CreatorId = 3, Name = "柚木つばめ" },
|
||||
new() { CreatorId = 4, Name = "逢坂成美" },
|
||||
new() { CreatorId = 5, Name = "山田じぇみ子", Blacklisted = true }
|
||||
);
|
||||
|
||||
context.VoiceWorkCreators.AddRange(
|
||||
new() { VoiceWorkId = 1, CreatorId = 2 }, // 秋野かえで
|
||||
|
||||
new() { VoiceWorkId = 2, CreatorId = 1 }, // 陽向葵ゅか
|
||||
|
||||
new() { VoiceWorkId = 3, CreatorId = 5 }, // 山田じぇみ子
|
||||
new() { VoiceWorkId = 3, CreatorId = 1 }, // 陽向葵ゅか
|
||||
|
||||
new() { VoiceWorkId = 4, CreatorId = 3 }, // 柚木つばめ
|
||||
|
||||
new() { VoiceWorkId = 5, CreatorId = 1 }, // 陽向葵ゅか
|
||||
new() { VoiceWorkId = 5, CreatorId = 4 } // 逢坂成美
|
||||
);
|
||||
|
||||
// <Product Id> <Maker Id> <Circle Name> <Product Name> <Product Description> <Tags> <Creators>
|
||||
context.VoiceWorkSearches.AddRange(
|
||||
new() { VoiceWorkId = 1, SearchText = "RJ0000001 RG00001 Good Dreams Today Sounds An average product. ASMR Office Lady" },
|
||||
new() { VoiceWorkId = 2, SearchText = "RJ0000002 RG00002 Sweet Dreams Super Comfy ASMR An amazing product! ASMR Heartwarming Elf / Fairy Tsundere All Happy Gal Maid" },
|
||||
new() { VoiceWorkId = 3, SearchText = "RJ0000003 RG00003 Nightmare Fuel Low Effort A bad product." },
|
||||
new() { VoiceWorkId = 4, SearchText = "RJ0000004 RG00001 Good Dreams Tomorrow Sounds A average upcoming product." },
|
||||
new() { VoiceWorkId = 5, SearchText = "RJ0000005 RG00002 Sweet Dreams Super Comfy ASMR+ All your favorite sounds, plus more!" }
|
||||
);
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
628
JSMR.Tests/Search/VoiceWork/VoiceWorkSearchProviderTests.cs
Normal file
628
JSMR.Tests/Search/VoiceWork/VoiceWorkSearchProviderTests.cs
Normal file
@@ -0,0 +1,628 @@
|
||||
using JSMR.Application.Common.Search;
|
||||
using JSMR.Application.VoiceWorks.Queries.Search;
|
||||
using JSMR.Infrastructure.Data;
|
||||
using JSMR.Infrastructure.Data.Repositories.VoiceWorks;
|
||||
using Shouldly;
|
||||
using SortDirection = JSMR.Application.Common.Search.SortDirection;
|
||||
|
||||
namespace JSMR.Tests.Search.VoiceWork;
|
||||
|
||||
public class VoiceWorkSearchProviderTests(VoiceWorkSearchProviderFixture fixture) : IClassFixture<VoiceWorkSearchProviderFixture>
|
||||
{
|
||||
private async Task<SearchResult<VoiceWorkSearchResult>> SearchAsync(SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField> options)
|
||||
{
|
||||
AppDbContext context = fixture.DbContext!;
|
||||
MySqlVoiceWorkFullTextSearch fullTextSearch = new();
|
||||
VoiceWorkSearchProvider provider = new(context, fullTextSearch);
|
||||
|
||||
return await provider.SearchAsync(options, TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Default()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
SaleStatus = SaleStatus.Available,
|
||||
CircleStatus = CircleStatus.NotBlacklisted
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(2);
|
||||
result.TotalItems.ShouldBe(2);
|
||||
result.Items.ShouldAllBe(item => item.SalesDate != null);
|
||||
result.Items.ShouldNotContain(item => item.ExpectedDate != null);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Upcoming_Favorite()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
SaleStatus = SaleStatus.Upcoming,
|
||||
CircleStatus = CircleStatus.Favorited
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
result.Items.ShouldAllBe(item => item.ExpectedDate != null);
|
||||
result.Items.ShouldNotContain(item => item.SalesDate != null);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Availble_Blacklisted()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
SaleStatus = SaleStatus.Available,
|
||||
CircleStatus = CircleStatus.Blacklisted
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
result.Items.ShouldAllBe(item => item.SalesDate != null);
|
||||
result.Items.ShouldNotContain(item => item.ExpectedDate != null);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Keywords_Basic()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Keywords = "ASMR"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(3);
|
||||
result.TotalItems.ShouldBe(3);
|
||||
result.Items.ShouldAllBe(item => item.Tags.Any(tag => tag.Name == "ASMR") || item.ProductName.Contains("ASMR") || (item.Description ?? string.Empty).Contains("ASMR"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Keywords_Not_Good()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Keywords = "ASMR -Good"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(2);
|
||||
result.TotalItems.ShouldBe(2);
|
||||
result.Items.ShouldAllBe(item => item.Tags.Any(tag => tag.Name == "ASMR") || item.ProductName.Contains("ASMR") || (item.Description ?? string.Empty).Contains("ASMR"));
|
||||
result.Items.ShouldAllBe(item => !item.Tags.Any(tag => tag.Name == "Good") || !item.ProductName.Contains("Good") || !(item.Description ?? string.Empty).Contains("Good"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Keywords_Dreams_And_Amazing_Or_Favorite()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Keywords = "Dreams + (Amazing|Favorite)"
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(2);
|
||||
result.TotalItems.ShouldBe(2);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000002", "RJ0000005"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Keywords_Phrase_Search()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Keywords = "\"All Your Favorite\""
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
result.Items.ShouldAllBe(item => (item.Description ?? string.Empty).Contains("All Your Favorite", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Tags_Favorite_Exclude_Blacklisted()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
TagStatus = TagStatus.FavoriteExcludeBlacklist
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000002"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Tags_Favorite_Include_Blacklisted()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
TagStatus = TagStatus.FavoriteIncludeBlacklist
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(2);
|
||||
result.TotalItems.ShouldBe(2);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000002", "RJ0000003"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Tags_Not_Blacklisted()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
TagStatus = TagStatus.NotBlacklisted
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(4);
|
||||
result.TotalItems.ShouldBe(4);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000001", "RJ0000002", "RJ0000004", "RJ0000005"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Tags_Blacklisted()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
TagStatus = TagStatus.Blacklisted
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000003"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_TagIds_Or()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
TagIds = [1,2],
|
||||
IncludeAllTags = false
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(2);
|
||||
result.TotalItems.ShouldBe(2);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000001", "RJ0000002"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_TagIds_And()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
TagIds = [1, 2],
|
||||
IncludeAllTags = true
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000001"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Creators_Favorite_Exclude_Blacklisted()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
CreatorStatus = CreatorStatus.FavoriteExcludeBlacklist
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(2);
|
||||
result.TotalItems.ShouldBe(2);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000002", "RJ0000005"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Creators_Favorite_Include_Blacklisted()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
CreatorStatus = CreatorStatus.FavoriteIncludeBlacklist
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(3);
|
||||
result.TotalItems.ShouldBe(3);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000002", "RJ0000003", "RJ0000005"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Creators_Not_Blacklisted()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
CreatorStatus = CreatorStatus.NotBlacklisted
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(4);
|
||||
result.TotalItems.ShouldBe(4);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000001", "RJ0000002", "RJ0000004", "RJ0000005"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Creators_Blacklisted()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
CreatorStatus = CreatorStatus.Blacklisted
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000003"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_CreatorIds_Or()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
CreatorIds = [1, 4],
|
||||
IncludeAllCreators = false
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(3);
|
||||
result.TotalItems.ShouldBe(3);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000002", "RJ0000003", "RJ0000005"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_CreatorIds_And()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
CreatorIds = [1, 4],
|
||||
IncludeAllCreators = true
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items.Length.ShouldBe(1);
|
||||
result.TotalItems.ShouldBe(1);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000005"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sort_By_Release_Date_Ascending()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
SortOptions =
|
||||
[
|
||||
new(VoiceWorkSortField.ReleaseDate, SortDirection.Ascending)
|
||||
]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000001", "RJ0000004", "RJ0000003", "RJ0000002", "RJ0000005"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sort_By_Release_Date_Descending()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
SortOptions =
|
||||
[
|
||||
new(VoiceWorkSortField.ReleaseDate, SortDirection.Descending)
|
||||
]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000005", "RJ0000002", "RJ0000003", "RJ0000001", "RJ0000004"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sort_By_Downloads_Ascending()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
SortOptions =
|
||||
[
|
||||
new(VoiceWorkSortField.Downloads, SortDirection.Ascending)
|
||||
]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000004", "RJ0000005", "RJ0000003", "RJ0000001", "RJ0000002"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sort_By_Downloads_Descending()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
SortOptions =
|
||||
[
|
||||
new(VoiceWorkSortField.Downloads, SortDirection.Descending)
|
||||
]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000002", "RJ0000001", "RJ0000003", "RJ0000004", "RJ0000005"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sort_By_WishlistCount_Ascending()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
SortOptions =
|
||||
[
|
||||
new(VoiceWorkSortField.WishlistCount, SortDirection.Ascending)
|
||||
]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000003", "RJ0000004", "RJ0000001", "RJ0000005", "RJ0000002"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sort_By_WishlistCount_Descending()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
SortOptions =
|
||||
[
|
||||
new(VoiceWorkSortField.WishlistCount, SortDirection.Descending)
|
||||
]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000002", "RJ0000005", "RJ0000001", "RJ0000004", "RJ0000003"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sort_By_StarRating_Ascending()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
SortOptions =
|
||||
[
|
||||
new(VoiceWorkSortField.StarRating, SortDirection.Ascending)
|
||||
]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000004", "RJ0000005", "RJ0000003", "RJ0000001", "RJ0000002"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Sort_By_StarRating_Descending()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
SortOptions =
|
||||
[
|
||||
new(VoiceWorkSortField.StarRating, SortDirection.Descending)
|
||||
]
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000002", "RJ0000001", "RJ0000003", "RJ0000004", "RJ0000005"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Release_Date_Range()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
ReleaseDateStart = new DateOnly(2025, 1, 1),
|
||||
ReleaseDateEnd = new DateOnly(2025, 1, 2)
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000001", "RJ0000003"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Downloads_Range()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
MinDownloads = 100,
|
||||
MaxDownloads = 10000
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000001", "RJ0000002"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Filter_Favorite()
|
||||
{
|
||||
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
ShowFavoriteVoiceWorks = true
|
||||
}
|
||||
};
|
||||
|
||||
var result = await SearchAsync(options);
|
||||
|
||||
result.Items
|
||||
.OrderBy(item => item.ProductId)
|
||||
.Select(item => item.ProductId)
|
||||
.ShouldBe(["RJ0000002"]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user