Added English localization integration tests.
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
using JSMR.Infrastructure.Data;
|
||||
using DotNet.Testcontainers.Builders;
|
||||
using DotNet.Testcontainers.Containers;
|
||||
using JSMR.Infrastructure.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySqlConnector;
|
||||
using Testcontainers.MariaDb;
|
||||
using Testcontainers.Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace JSMR.Tests.Fixtures;
|
||||
|
||||
@@ -64,4 +69,113 @@ public class MariaDbFixture : IAsyncLifetime
|
||||
await context.Database.EnsureDeletedAsync();
|
||||
await context.Database.EnsureCreatedAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[CollectionDefinition("db")]
|
||||
public sealed class MariaDbCollection : ICollectionFixture<MariaDbContainerFixture> { }
|
||||
|
||||
//[UsedImplicitly]
|
||||
public sealed class MariaDbContainerFixture2(IMessageSink messageSink)
|
||||
: ContainerFixture<MariaDbBuilder, MariaDbContainer>(messageSink)
|
||||
{
|
||||
const int MajorVersion = 10;
|
||||
const int MinorVersion = 11;
|
||||
const int Build = 6;
|
||||
|
||||
public string RootConnectionString => $"Server={Container.IpAddress};Port=3306;User=root;Password=rootpw;SslMode=none;";
|
||||
|
||||
protected override MariaDbBuilder Configure(MariaDbBuilder builder)
|
||||
{
|
||||
return builder.WithImage($"mariadb:{MajorVersion}.{MinorVersion}.{Build}")
|
||||
.WithEnvironment("MARIADB_ROOT_PASSWORD", "rootpw")
|
||||
.WithPortBinding(3307, 3306)
|
||||
//.WithPortBinding(3306, assignRandomHostPort: true)
|
||||
.WithWaitStrategy(Wait.ForUnixContainer().UntilInternalTcpPortIsAvailable(3306));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public sealed class MariaDbContainerFixture : IAsyncLifetime
|
||||
{
|
||||
const int MajorVersion = 10;
|
||||
const int MinorVersion = 11;
|
||||
const int Build = 6;
|
||||
|
||||
private IContainer _container = default!;
|
||||
public string RootConnectionString { get; private set; } = default!;
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
//_container = new ContainerBuilder()
|
||||
// .WithImage("mariadb:11")
|
||||
// .WithEnvironment("MARIADB_ROOT_PASSWORD", "rootpw")
|
||||
// .WithPortBinding(3307, 3306)
|
||||
// .WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(3306))
|
||||
// .Build();
|
||||
|
||||
_container = new ContainerBuilder()
|
||||
.WithImage($"mariadb:{MajorVersion}.{MinorVersion}.{Build}")
|
||||
.WithEnvironment("MARIADB_ROOT_PASSWORD", "rootpw")
|
||||
.WithPortBinding(3307, 3306)
|
||||
//.WithPortBinding(3306, assignRandomHostPort: true)
|
||||
.WithWaitStrategy(Wait.ForUnixContainer().UntilInternalTcpPortIsAvailable(3306))
|
||||
.Build();
|
||||
|
||||
await _container.StartAsync();
|
||||
|
||||
// No database specified: we’ll create per-test DBs
|
||||
//RootConnectionString = "Server=127.0.0.1;Port=3307;User=root;Password=rootpw;SslMode=none;";
|
||||
|
||||
//RootConnectionString = _container.GetConnectionString();
|
||||
var port = _container.GetMappedPublicPort(3306);
|
||||
RootConnectionString = $"Server=127.0.0.1;Port={port};User=root;Password=rootpw;SslMode=none;";
|
||||
}
|
||||
|
||||
public async Task DisposeAsync() => await _container.DisposeAsync();
|
||||
}
|
||||
|
||||
public static class MariaTestDb
|
||||
{
|
||||
public static async Task<AppDbContext> CreateIsolatedAsync(string rootConnectionString, Func<AppDbContext, Task>? seed = null)
|
||||
{
|
||||
string databaseName = $"t_{DateTime.UtcNow:yyyyMMddHHmmss}_{Guid.NewGuid():N}";
|
||||
|
||||
await CreateDatabaseAsync(rootConnectionString, databaseName);
|
||||
|
||||
MySqlConnectionStringBuilder connectionStringBuilder = new(rootConnectionString)
|
||||
{
|
||||
Database = databaseName
|
||||
};
|
||||
|
||||
AppDbContext dbContext = CreateDbContext(connectionStringBuilder.ConnectionString);
|
||||
await dbContext.Database.EnsureCreatedAsync();
|
||||
|
||||
if (seed != null)
|
||||
await seed(dbContext);
|
||||
|
||||
return dbContext;
|
||||
}
|
||||
|
||||
private static async Task CreateDatabaseAsync(string rootConnectionString, string databaseName)
|
||||
{
|
||||
await using MySqlConnection connection = new(rootConnectionString);
|
||||
|
||||
await connection.OpenAsync();
|
||||
|
||||
await using MySqlCommand command = connection.CreateCommand();
|
||||
command.CommandText = $"CREATE DATABASE `{databaseName}` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;";
|
||||
|
||||
await command.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
private static AppDbContext CreateDbContext(string connectionString)
|
||||
{
|
||||
DbContextOptions<AppDbContext> options = new DbContextOptionsBuilder<AppDbContext>()
|
||||
.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString),
|
||||
o => o.EnableRetryOnFailure())
|
||||
.EnableSensitiveDataLogging()
|
||||
.Options;
|
||||
|
||||
return new AppDbContext(options);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
using JSMR.Infrastructure.Data;
|
||||
using JSMR.Tests.Ingestion;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySqlConnector;
|
||||
using Testcontainers.MariaDb;
|
||||
|
||||
namespace JSMR.Tests.Fixtures;
|
||||
|
||||
@@ -29,4 +32,44 @@ public class TagSearchProviderFixture : MariaDbFixture
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class TagSearchProviderFixture2(MariaDbContainerFixture container) : IAsyncLifetime
|
||||
{
|
||||
public AppDbContext? DbContext { get; private set; }
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
DbContext = await MariaTestDb.CreateIsolatedAsync(
|
||||
container.RootConnectionString,
|
||||
seed: SeedAsync);
|
||||
}
|
||||
|
||||
private static async Task SeedAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.Tags.AnyAsync())
|
||||
return;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public async Task DisposeAsync()
|
||||
{
|
||||
if (DbContext is not null)
|
||||
{
|
||||
await DbContext.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
using JSMR.Application.Common;
|
||||
using JSMR.Application.Integrations.DLSite.Models;
|
||||
using JSMR.Application.Scanning.Contracts;
|
||||
using JSMR.Infrastructure.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace JSMR.Tests.Fixtures;
|
||||
|
||||
public class VoiceWorkUpsertFixture : MariaDbFixture
|
||||
{
|
||||
protected override async Task OnInitializedAsync(AppDbContext context)
|
||||
{
|
||||
await SeedAsync(context);
|
||||
}
|
||||
|
||||
private static async Task SeedAsync(AppDbContext context)
|
||||
{
|
||||
if (await context.VoiceWorks.AnyAsync())
|
||||
return;
|
||||
|
||||
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
|
||||
//new() { VoiceWorkId = 3, TagId = 1 },
|
||||
//new() { VoiceWorkId = 3, TagId = 1 },
|
||||
//new() { VoiceWorkId = 3, TagId = 1 },
|
||||
//new() { VoiceWorkId = 3, TagId = 1 },
|
||||
//new() { VoiceWorkId = 3, TagId = 1 },
|
||||
|
||||
//new() { VoiceWorkId = 4, TagId = 1 },
|
||||
//new() { VoiceWorkId = 4, TagId = 1 },
|
||||
//new() { VoiceWorkId = 4, TagId = 1 },
|
||||
//new() { VoiceWorkId = 4, TagId = 1 },
|
||||
//new() { VoiceWorkId = 4, TagId = 1 },
|
||||
//new() { VoiceWorkId = 4, TagId = 1 },
|
||||
//new() { VoiceWorkId = 4, TagId = 1 },
|
||||
|
||||
//new() { VoiceWorkId = 5, TagId = 5 } // Tsundere
|
||||
//new() { VoiceWorkId = 5, TagId = 1 },
|
||||
//new() { VoiceWorkId = 5, TagId = 1 },
|
||||
//new() { VoiceWorkId = 5, TagId = 1 },
|
||||
//new() { VoiceWorkId = 5, TagId = 1 },
|
||||
//new() { VoiceWorkId = 5, TagId = 1 },
|
||||
//new() { VoiceWorkId = 5, TagId = 1 }
|
||||
);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public VoiceWorkIngest[] GetFirstRoundIngests()
|
||||
{
|
||||
VoiceWorkIngest[] ingests =
|
||||
[
|
||||
new()
|
||||
{
|
||||
MakerId = "RG00001",
|
||||
MakerName = "Good Dreams",
|
||||
ProductId = "RJ0000001",
|
||||
Title = "Today Sounds",
|
||||
Description = "An average product.",
|
||||
Tags = ["ASMR", "Office Lady"],
|
||||
AgeRating = AgeRating.R15,
|
||||
SalesDate = new DateOnly(2025, 1, 1),
|
||||
ExpectedDate = null,
|
||||
WishlistCount = 750,
|
||||
Downloads = 500,
|
||||
HasTrial = true,
|
||||
HasDLPlay = true
|
||||
},
|
||||
new()
|
||||
{
|
||||
MakerId = "RG00002",
|
||||
MakerName = "Sweet Dreams",
|
||||
ProductId = "RJ0000002",
|
||||
Title = "Super Comfy ASMR",
|
||||
Description = "An amazing product!",
|
||||
AgeRating = AgeRating.AllAges,
|
||||
Tags = ["ASMR", "Heartwarming", "Elf / Fairy", "Tsundere", "All Happy", "Gal", "Maid"],
|
||||
SalesDate = new DateOnly(2025, 3, 1),
|
||||
ExpectedDate = null,
|
||||
WishlistCount = 12000,
|
||||
Downloads = 5000,
|
||||
HasTrial = true,
|
||||
HasDLPlay = true
|
||||
},
|
||||
new()
|
||||
{
|
||||
MakerId = "RG00003",
|
||||
MakerName = "Nightmare Fuel",
|
||||
ProductId = "RJ0000003",
|
||||
Title = "Low Effort",
|
||||
Description = "A bad product.",
|
||||
Tags = ["Tsundere", "Non-Fiction / Narrative"],
|
||||
AgeRating = AgeRating.R18,
|
||||
SalesDate = new DateOnly(2025, 1, 1),
|
||||
ExpectedDate = null,
|
||||
WishlistCount = 100,
|
||||
Downloads = 50,
|
||||
HasTrial = true,
|
||||
HasDLPlay = false
|
||||
}
|
||||
];
|
||||
|
||||
return ingests;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user