Added English localization integration tests.
This commit is contained in:
189
JSMR.Tests/Ingestion/EnglishLocalizationTests.cs
Normal file
189
JSMR.Tests/Ingestion/EnglishLocalizationTests.cs
Normal file
@@ -0,0 +1,189 @@
|
||||
using JSMR.Application.Scanning.Contracts;
|
||||
using JSMR.Application.Scanning.Ports;
|
||||
using JSMR.Domain.Entities;
|
||||
using JSMR.Infrastructure.Common.Languages;
|
||||
using JSMR.Infrastructure.Data;
|
||||
using JSMR.Infrastructure.Ingestion;
|
||||
using JSMR.Tests.Fixtures;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Shouldly;
|
||||
|
||||
namespace JSMR.Tests.Ingestion;
|
||||
|
||||
public class EnglishLocalizationTests(MariaDbContainerFixture container) : IClassFixture<MariaDbContainerFixture>
|
||||
{
|
||||
private readonly LanguageIdentifier languageIdentifier = new();
|
||||
|
||||
[Fact]
|
||||
public async Task Insert_Then_Update()
|
||||
{
|
||||
await using AppDbContext dbContext = await MariaTestDb.CreateIsolatedAsync(
|
||||
container.RootConnectionString,
|
||||
seed: VoiceWorkIngestionSeedData.SeedAsync);
|
||||
|
||||
// Part 1 -- Insert
|
||||
VoiceWorkIngest ingest = new()
|
||||
{
|
||||
MakerId = "RG00001",
|
||||
MakerName = "Good Dreams",
|
||||
ProductId = "RJ0000001",
|
||||
Title = "Today Sounds (EN)",
|
||||
Description = "An average product. (EN)"
|
||||
};
|
||||
|
||||
EnglishVoiceWorkUpdater updater = new(dbContext, languageIdentifier);
|
||||
VoiceWorkUpsertResult[] results = await updater.UpsertAsync([ingest], CancellationToken.None);
|
||||
|
||||
VoiceWork voiceWork = await dbContext.VoiceWorks.SingleAsync(v => v.ProductId == "RJ0000001");
|
||||
EnglishVoiceWork? englishVoiceWork = await dbContext.EnglishVoiceWorks.SingleOrDefaultAsync(e => e.VoiceWorkId == voiceWork.VoiceWorkId);
|
||||
|
||||
englishVoiceWork.ShouldNotBeNull();
|
||||
englishVoiceWork.ProductName.ShouldBe("Today Sounds (EN)");
|
||||
englishVoiceWork.Description.ShouldBe("An average product. (EN)");
|
||||
englishVoiceWork.IsValid?.ShouldBeTrue();
|
||||
|
||||
results.Length.ShouldBe(1);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Inserted).ShouldBe(1);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Updated).ShouldBe(0);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Skipped).ShouldBe(0);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Unchanged).ShouldBe(0);
|
||||
results.Sum(r => r.Issues.Count).ShouldBe(0);
|
||||
|
||||
// Part 2 -- Update
|
||||
VoiceWorkIngest ingestUpdate = ingest with
|
||||
{
|
||||
Title = "Today Sounds (EN v2)",
|
||||
Description = "Updated English description."
|
||||
};
|
||||
|
||||
VoiceWorkUpsertResult[] updatedResults = await updater.UpsertAsync([ingestUpdate], CancellationToken.None);
|
||||
|
||||
EnglishVoiceWork? updatedEnglishVoiceWork = await dbContext.EnglishVoiceWorks.SingleOrDefaultAsync(e => e.VoiceWorkId == voiceWork.VoiceWorkId);
|
||||
updatedEnglishVoiceWork.ShouldNotBeNull();
|
||||
updatedEnglishVoiceWork.ProductName.ShouldBe("Today Sounds (EN v2)");
|
||||
updatedEnglishVoiceWork.Description.ShouldBe("Updated English description.");
|
||||
updatedEnglishVoiceWork.IsValid?.ShouldBeTrue();
|
||||
|
||||
updatedResults.Length.ShouldBe(1);
|
||||
updatedResults.Count(r => r.Status == VoiceWorkUpsertStatus.Inserted).ShouldBe(0);
|
||||
updatedResults.Count(r => r.Status == VoiceWorkUpsertStatus.Updated).ShouldBe(1);
|
||||
updatedResults.Count(r => r.Status == VoiceWorkUpsertStatus.Skipped).ShouldBe(0);
|
||||
updatedResults.Count(r => r.Status == VoiceWorkUpsertStatus.Unchanged).ShouldBe(0);
|
||||
updatedResults.Sum(r => r.Issues.Count).ShouldBe(0);
|
||||
|
||||
// Part 3 -- Update Again (No Change)
|
||||
VoiceWorkUpsertResult[] updatedAgainResults = await updater.UpsertAsync([ingestUpdate], CancellationToken.None);
|
||||
|
||||
EnglishVoiceWork? updatedAgainEnglishVoiceWork = await dbContext.EnglishVoiceWorks.SingleOrDefaultAsync(e => e.VoiceWorkId == voiceWork.VoiceWorkId);
|
||||
updatedAgainEnglishVoiceWork.ShouldNotBeNull();
|
||||
updatedAgainEnglishVoiceWork.ProductName.ShouldBe("Today Sounds (EN v2)");
|
||||
updatedAgainEnglishVoiceWork.Description.ShouldBe("Updated English description.");
|
||||
updatedAgainEnglishVoiceWork.IsValid?.ShouldBeTrue();
|
||||
|
||||
updatedAgainResults.Length.ShouldBe(1);
|
||||
updatedAgainResults.Count(r => r.Status == VoiceWorkUpsertStatus.Inserted).ShouldBe(0);
|
||||
updatedAgainResults.Count(r => r.Status == VoiceWorkUpsertStatus.Updated).ShouldBe(0);
|
||||
updatedAgainResults.Count(r => r.Status == VoiceWorkUpsertStatus.Skipped).ShouldBe(0);
|
||||
updatedAgainResults.Count(r => r.Status == VoiceWorkUpsertStatus.Unchanged).ShouldBe(1);
|
||||
updatedAgainResults.Sum(r => r.Issues.Count).ShouldBe(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Fail_Attempted_Insert_With_Missing_Circle()
|
||||
{
|
||||
await using AppDbContext dbContext = await MariaTestDb.CreateIsolatedAsync(
|
||||
container.RootConnectionString,
|
||||
seed: VoiceWorkIngestionSeedData.SeedAsync);
|
||||
|
||||
VoiceWorkIngest ingest = new()
|
||||
{
|
||||
MakerId = "RG99999",
|
||||
MakerName = "Missing Maker",
|
||||
ProductId = "RJ9999999",
|
||||
Title = "EN Title",
|
||||
Description = "EN Desc"
|
||||
};
|
||||
|
||||
EnglishVoiceWorkUpdater updater = new(dbContext, languageIdentifier);
|
||||
VoiceWorkUpsertResult[] results = await updater.UpsertAsync([ingest], CancellationToken.None);
|
||||
|
||||
int englishVoiceWorkCount = await dbContext.EnglishVoiceWorks.CountAsync(CancellationToken.None);
|
||||
englishVoiceWorkCount.ShouldBe(0);
|
||||
|
||||
results.Length.ShouldBe(1);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Inserted).ShouldBe(0);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Updated).ShouldBe(0);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Skipped).ShouldBe(1);
|
||||
results.Sum(r => r.Issues.Count).ShouldBe(1);
|
||||
|
||||
VoiceWorkUpsertIssue issue = results[0].Issues.ElementAt(0);
|
||||
issue.Severity.ShouldBe(VoiceWorkUpsertIssueSeverity.Error);
|
||||
issue.Message.ShouldBe($"Unable to find circle for maker id: {ingest.MakerId}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Fail_Attempted_Insert_With_Missing_Product()
|
||||
{
|
||||
await using AppDbContext dbContext = await MariaTestDb.CreateIsolatedAsync(
|
||||
container.RootConnectionString,
|
||||
seed: VoiceWorkIngestionSeedData.SeedAsync);
|
||||
|
||||
VoiceWorkIngest ingest = new()
|
||||
{
|
||||
MakerId = "RG00001",
|
||||
MakerName = "Good Dreams",
|
||||
ProductId = "RJ9999999",
|
||||
Title = "EN Title",
|
||||
Description = "EN Desc"
|
||||
};
|
||||
|
||||
EnglishVoiceWorkUpdater updater = new(dbContext, languageIdentifier);
|
||||
VoiceWorkUpsertResult[] results = await updater.UpsertAsync([ingest], CancellationToken.None);
|
||||
|
||||
int englishVoiceWorkCount = await dbContext.EnglishVoiceWorks.CountAsync(CancellationToken.None);
|
||||
englishVoiceWorkCount.ShouldBe(0);
|
||||
|
||||
results.Length.ShouldBe(1);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Inserted).ShouldBe(0);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Updated).ShouldBe(0);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Skipped).ShouldBe(1);
|
||||
results.Sum(r => r.Issues.Count).ShouldBe(1);
|
||||
|
||||
VoiceWorkUpsertIssue issue = results[0].Issues.ElementAt(0);
|
||||
issue.Severity.ShouldBe(VoiceWorkUpsertIssueSeverity.Error);
|
||||
issue.Message.ShouldBe($"Unable to find voice work for product id: {ingest.ProductId}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Fail_Attempted_Insert_When_Not_English()
|
||||
{
|
||||
await using AppDbContext dbContext = await MariaTestDb.CreateIsolatedAsync(
|
||||
container.RootConnectionString,
|
||||
seed: VoiceWorkIngestionSeedData.SeedAsync);
|
||||
|
||||
VoiceWorkIngest ingest = new()
|
||||
{
|
||||
MakerId = "RG00001",
|
||||
MakerName = "Good Dreams",
|
||||
ProductId = "RJ0000001",
|
||||
Title = "すごく快適なASMR",
|
||||
Description = "最高の製品です!"
|
||||
};
|
||||
|
||||
EnglishVoiceWorkUpdater updater = new(dbContext, languageIdentifier);
|
||||
VoiceWorkUpsertResult[] results = await updater.UpsertAsync([ingest], CancellationToken.None);
|
||||
|
||||
int englishVoiceWorkCount = await dbContext.EnglishVoiceWorks.CountAsync(CancellationToken.None);
|
||||
englishVoiceWorkCount.ShouldBe(0);
|
||||
|
||||
results.Length.ShouldBe(1);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Inserted).ShouldBe(0);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Updated).ShouldBe(0);
|
||||
results.Count(r => r.Status == VoiceWorkUpsertStatus.Skipped).ShouldBe(1);
|
||||
results.Sum(r => r.Issues.Count).ShouldBe(1);
|
||||
|
||||
VoiceWorkUpsertIssue issue = results[0].Issues.ElementAt(0);
|
||||
issue.Severity.ShouldBe(VoiceWorkUpsertIssueSeverity.Information);
|
||||
issue.Message.ShouldBe("Product title and/or description is not in English");
|
||||
}
|
||||
}
|
||||
49
JSMR.Tests/Ingestion/VoiceWorkIngestionTests.cs
Normal file
49
JSMR.Tests/Ingestion/VoiceWorkIngestionTests.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using JSMR.Application.Scanning.Contracts;
|
||||
using JSMR.Infrastructure.Common.Time;
|
||||
using JSMR.Infrastructure.Data;
|
||||
using JSMR.Infrastructure.Ingestion;
|
||||
using NSubstitute;
|
||||
using Shouldly;
|
||||
|
||||
namespace JSMR.Tests.Ingestion;
|
||||
|
||||
//public class VoiceWorkIngestionTests(VoiceWorkIngestionFixture fixture)
|
||||
//{
|
||||
// [Fact]
|
||||
// public async Task Simple_Upsert()
|
||||
// {
|
||||
// await using AppDbContext context = fixture.CreateDbContext();
|
||||
|
||||
// VoiceWorkIngest[] ingests =
|
||||
// [
|
||||
// // TODO
|
||||
// //new()
|
||||
// //{
|
||||
// // MakerId = "RG00001",
|
||||
// // MakerName = "Good Dreams",
|
||||
// // ProductId = "A Newly Announced Work",
|
||||
// // Title = "",
|
||||
// // Description = ""
|
||||
// //},
|
||||
// //new()
|
||||
// //{
|
||||
// // MakerId = "RG00002",
|
||||
// // MakerName = "Sweet Dreams",
|
||||
// // ProductId = "",
|
||||
// // Title = "",
|
||||
// // Description = ""
|
||||
// //}
|
||||
// ];
|
||||
|
||||
// IClock clock = Substitute.For<IClock>();
|
||||
// clock.UtcNow.Returns(new DateTimeOffset(2025, 1, 3, 0, 0, 0, 0, TimeSpan.FromSeconds(0)));
|
||||
|
||||
// TokyoTimeProvider timeProvider = new(clock);
|
||||
|
||||
// VoiceWorkUpdater updater = new(context, timeProvider);
|
||||
// await updater.UpsertAsync(ingests, CancellationToken.None);
|
||||
|
||||
// // TODO
|
||||
// //context.VoiceWorks.Count().ShouldBe(2);
|
||||
// }
|
||||
//}
|
||||
122
JSMR.Tests/Ingestion/VoiceWorkUpsertFixture.cs
Normal file
122
JSMR.Tests/Ingestion/VoiceWorkUpsertFixture.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using JSMR.Application.Common;
|
||||
using JSMR.Infrastructure.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace JSMR.Tests.Ingestion;
|
||||
|
||||
public static class VoiceWorkIngestionSeedData
|
||||
{
|
||||
public 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user