Files
jsmr/JSMR.Tests/Integration/VoiceWorkSearchProviderTests.cs
2025-10-20 23:32:38 -04:00

717 lines
23 KiB
C#

using JSMR.Application.Common.Search;
using JSMR.Application.VoiceWorks.Queries.Search;
using JSMR.Infrastructure.Data;
using JSMR.Infrastructure.Data.Repositories.VoiceWorks;
using JSMR.Tests.Fixtures;
using Shouldly;
namespace JSMR.Tests.Integration;
public class VoiceWorkSearchProviderTests(VoiceWorkSearchProviderFixture fixture) : IClassFixture<VoiceWorkSearchProviderFixture>
{
private static VoiceWorkSearchProvider InitializeVoiceWorkSearchProvider(AppDbContext context)
{
MySqlVoiceWorkFullTextSearch fullTextSearch = new();
VoiceWorkSearchProvider provider = new(context, fullTextSearch);
return provider;
}
[Fact]
public async Task Filter_Default()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
SaleStatus = SaleStatus.Available,
CircleStatus = CircleStatus.NotBlacklisted
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
SaleStatus = SaleStatus.Upcoming,
CircleStatus = CircleStatus.Favorited
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
SaleStatus = SaleStatus.Available,
CircleStatus = CircleStatus.Blacklisted
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
Keywords = "ASMR"
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
Keywords = "ASMR -Good"
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
Keywords = "Dreams + (Amazing|Favorite)"
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
Keywords = "\"All Your Favorite\""
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
TagStatus = TagStatus.FavoriteExcludeBlacklist
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
TagStatus = TagStatus.FavoriteIncludeBlacklist
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
TagStatus = TagStatus.NotBlacklisted
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
TagStatus = TagStatus.Blacklisted
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
TagIds = [1,2],
IncludeAllTags = false
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
TagIds = [1, 2],
IncludeAllTags = true
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
CreatorStatus = CreatorStatus.FavoriteExcludeBlacklist
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
CreatorStatus = CreatorStatus.FavoriteIncludeBlacklist
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
CreatorStatus = CreatorStatus.NotBlacklisted
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
CreatorStatus = CreatorStatus.Blacklisted
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
CreatorIds = [1, 4],
IncludeAllCreators = false
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
CreatorIds = [1, 4],
IncludeAllCreators = true
}
};
var result = await provider.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()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
SortOptions =
[
new(VoiceWorkSortField.ReleaseDate, Application.Common.Search.SortDirection.Ascending)
]
};
var result = await provider.SearchAsync(options);
result.Items
.Select(item => item.ProductId)
.ShouldBe(["RJ0000001", "RJ0000004", "RJ0000003", "RJ0000002", "RJ0000005"]);
}
[Fact]
public async Task Sort_By_Release_Date_Descending()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
SortOptions =
[
new(VoiceWorkSortField.ReleaseDate, Application.Common.Search.SortDirection.Descending)
]
};
var result = await provider.SearchAsync(options);
result.Items
.Select(item => item.ProductId)
.ShouldBe(["RJ0000005", "RJ0000002", "RJ0000003", "RJ0000001", "RJ0000004"]);
}
[Fact]
public async Task Sort_By_Downloads_Ascending()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
SortOptions =
[
new(VoiceWorkSortField.Downloads, Application.Common.Search.SortDirection.Ascending)
]
};
var result = await provider.SearchAsync(options);
result.Items
.Select(item => item.ProductId)
.ShouldBe(["RJ0000004", "RJ0000005", "RJ0000003", "RJ0000001", "RJ0000002"]);
}
[Fact]
public async Task Sort_By_Downloads_Descending()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
SortOptions =
[
new(VoiceWorkSortField.Downloads, Application.Common.Search.SortDirection.Descending)
]
};
var result = await provider.SearchAsync(options);
result.Items
.Select(item => item.ProductId)
.ShouldBe(["RJ0000002", "RJ0000001", "RJ0000003", "RJ0000004", "RJ0000005"]);
}
[Fact]
public async Task Sort_By_WishlistCount_Ascending()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
SortOptions =
[
new(VoiceWorkSortField.WishlistCount, Application.Common.Search.SortDirection.Ascending)
]
};
var result = await provider.SearchAsync(options);
result.Items
.Select(item => item.ProductId)
.ShouldBe(["RJ0000003", "RJ0000004", "RJ0000001", "RJ0000005", "RJ0000002"]);
}
[Fact]
public async Task Sort_By_WishlistCount_Descending()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
SortOptions =
[
new(VoiceWorkSortField.WishlistCount, Application.Common.Search.SortDirection.Descending)
]
};
var result = await provider.SearchAsync(options);
result.Items
.Select(item => item.ProductId)
.ShouldBe(["RJ0000002", "RJ0000005", "RJ0000001", "RJ0000004", "RJ0000003"]);
}
[Fact]
public async Task Sort_By_StarRating_Ascending()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
SortOptions =
[
new(VoiceWorkSortField.StarRating, Application.Common.Search.SortDirection.Ascending)
]
};
var result = await provider.SearchAsync(options);
result.Items
.Select(item => item.ProductId)
.ShouldBe(["RJ0000004", "RJ0000005", "RJ0000003", "RJ0000001", "RJ0000002"]);
}
[Fact]
public async Task Sort_By_StarRating_Descending()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
SortOptions =
[
new(VoiceWorkSortField.StarRating, Application.Common.Search.SortDirection.Descending)
]
};
var result = await provider.SearchAsync(options);
result.Items
.Select(item => item.ProductId)
.ShouldBe(["RJ0000002", "RJ0000001", "RJ0000003", "RJ0000004", "RJ0000005"]);
}
[Fact]
public async Task Filter_Release_Date_Range()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
ReleaseDateStart = new DateOnly(2025, 1, 1),
ReleaseDateEnd = new DateOnly(2025, 1, 2)
}
};
var result = await provider.SearchAsync(options);
result.Items
.OrderBy(item => item.ProductId)
.Select(item => item.ProductId)
.ShouldBe(["RJ0000001", "RJ0000003"]);
}
[Fact]
public async Task Filter_Downloads_Range()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
MinDownloads = 100,
MaxDownloads = 10000
}
};
var result = await provider.SearchAsync(options);
result.Items
.OrderBy(item => item.ProductId)
.Select(item => item.ProductId)
.ShouldBe(["RJ0000001", "RJ0000002"]);
}
[Fact]
public async Task Filter_Favorite()
{
await using AppDbContext context = fixture.CreateDbContext();
VoiceWorkSearchProvider provider = InitializeVoiceWorkSearchProvider(context);
var options = new SearchOptions<VoiceWorkSearchCriteria, VoiceWorkSortField>()
{
Criteria = new()
{
ShowFavoriteVoiceWorks = true
}
};
var result = await provider.SearchAsync(options);
result.Items
.OrderBy(item => item.ProductId)
.Select(item => item.ProductId)
.ShouldBe(["RJ0000002"]);
}
}