import_viewer: round-trip ViewerAchievement + counter
This commit is contained in:
@@ -637,6 +637,125 @@ public class AdminControllerTests
|
||||
Is.EqualTo(10));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ImportViewer_Achievements_RoundTripsWithCounter()
|
||||
{
|
||||
using var factory = new SVSimTestFactory();
|
||||
using (var seedScope = factory.Services.CreateScope())
|
||||
{
|
||||
var db = seedScope.ServiceProvider.GetRequiredService<SVSimDbContext>();
|
||||
db.AchievementCatalog.Add(new AchievementCatalogEntry
|
||||
{
|
||||
AchievementType = 501, Level = 3, EventType = "cards_owned_total", EventArg = null
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
var client = factory.CreateClient();
|
||||
ulong steamId = 70000000000000007UL;
|
||||
|
||||
var resp = await client.PostAsJsonAsync("/admin/import_viewer", new ImportViewerRequest
|
||||
{
|
||||
SteamId = steamId,
|
||||
Achievements = new List<ImportAchievement>
|
||||
{
|
||||
new() { AchievementType = 501, Level = 3, NowAchievedLevel = 3, ResultAnnounceSawLevel = 2, TotalCount = 42 }
|
||||
}
|
||||
});
|
||||
resp.EnsureSuccessStatusCode();
|
||||
var body = await resp.Content.ReadFromJsonAsync<ImportViewerResponse>(JsonOptions);
|
||||
Assert.That(body!.SkippedAchievementCount, Is.EqualTo(0));
|
||||
Assert.That(body.SkippedAchievementCounterCount, Is.EqualTo(0));
|
||||
|
||||
using var scope = factory.Services.CreateScope();
|
||||
var db2 = scope.ServiceProvider.GetRequiredService<SVSimDbContext>();
|
||||
var viewerId = await db2.Viewers
|
||||
.Where(v => v.SocialAccountConnections
|
||||
.Any(s => s.AccountType == SocialAccountType.Steam && s.AccountId == steamId))
|
||||
.Select(v => v.Id).SingleAsync();
|
||||
var ach = await db2.ViewerAchievements
|
||||
.SingleAsync(a => a.ViewerId == viewerId && a.AchievementType == 501);
|
||||
Assert.That(ach.Level, Is.EqualTo(3));
|
||||
Assert.That(ach.NowAchievedLevel, Is.EqualTo(3));
|
||||
Assert.That(ach.ResultAnnounceSawLevel, Is.EqualTo(2));
|
||||
Assert.That(db2.ViewerEventCounters
|
||||
.Count(c => c.ViewerId == viewerId && c.EventKey == "cards_owned_total" && c.Count == 42), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ImportViewer_Achievements_UnknownTypeSkipped()
|
||||
{
|
||||
using var factory = new SVSimTestFactory();
|
||||
var client = factory.CreateClient();
|
||||
ulong steamId = 70000000000000008UL;
|
||||
|
||||
var resp = await client.PostAsJsonAsync("/admin/import_viewer", new ImportViewerRequest
|
||||
{
|
||||
SteamId = steamId,
|
||||
Achievements = new List<ImportAchievement>
|
||||
{
|
||||
new() { AchievementType = 999999, Level = 1, NowAchievedLevel = 1, ResultAnnounceSawLevel = 0, TotalCount = 1 }
|
||||
}
|
||||
});
|
||||
resp.EnsureSuccessStatusCode();
|
||||
var body = await resp.Content.ReadFromJsonAsync<ImportViewerResponse>(JsonOptions);
|
||||
Assert.That(body!.SkippedAchievementCount, Is.EqualTo(1));
|
||||
|
||||
using var scope = factory.Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<SVSimDbContext>();
|
||||
Assert.That(db.ViewerAchievements.Any(), Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ImportViewer_Achievements_TwoAchievementsSharingEventType_SingleCounterUpsert()
|
||||
{
|
||||
// Two achievements with different (AchievementType, Level) but the same EventType — same
|
||||
// (EventKey, AllTime) cache key. Without the pre-materialized achievementCounterCache the
|
||||
// second DB read won't see the first achievement's pending Add → duplicate insert /
|
||||
// unique-constraint failure. With the fix both achievements upsert the SAME counter,
|
||||
// resulting in exactly one ViewerEventCounter row.
|
||||
using var factory = new SVSimTestFactory();
|
||||
using (var seedScope = factory.Services.CreateScope())
|
||||
{
|
||||
var seedDb = seedScope.ServiceProvider.GetRequiredService<SVSimDbContext>();
|
||||
seedDb.AchievementCatalog.AddRange(
|
||||
new AchievementCatalogEntry { AchievementType = 601, Level = 1, EventType = "battle_win_total", EventArg = null },
|
||||
new AchievementCatalogEntry { AchievementType = 602, Level = 1, EventType = "battle_win_total", EventArg = null });
|
||||
await seedDb.SaveChangesAsync();
|
||||
}
|
||||
var client = factory.CreateClient();
|
||||
ulong steamId = 70000000000000009UL;
|
||||
|
||||
var resp = await client.PostAsJsonAsync("/admin/import_viewer", new ImportViewerRequest
|
||||
{
|
||||
SteamId = steamId,
|
||||
Achievements = new List<ImportAchievement>
|
||||
{
|
||||
new() { AchievementType = 601, Level = 1, NowAchievedLevel = 1, ResultAnnounceSawLevel = 0, TotalCount = 20 },
|
||||
new() { AchievementType = 602, Level = 1, NowAchievedLevel = 1, ResultAnnounceSawLevel = 0, TotalCount = 20 },
|
||||
}
|
||||
});
|
||||
resp.EnsureSuccessStatusCode();
|
||||
var body = await resp.Content.ReadFromJsonAsync<ImportViewerResponse>(JsonOptions);
|
||||
Assert.That(body!.SkippedAchievementCount, Is.EqualTo(0));
|
||||
Assert.That(body.SkippedAchievementCounterCount, Is.EqualTo(0));
|
||||
|
||||
using var verifyScope = factory.Services.CreateScope();
|
||||
var verifyDb = verifyScope.ServiceProvider.GetRequiredService<SVSimDbContext>();
|
||||
var viewerId = await verifyDb.Viewers
|
||||
.Where(v => v.SocialAccountConnections
|
||||
.Any(s => s.AccountType == SocialAccountType.Steam && s.AccountId == steamId))
|
||||
.Select(v => v.Id).SingleAsync();
|
||||
|
||||
// Must be exactly ONE counter row for (EventKey="battle_win_total"), not two.
|
||||
Assert.That(
|
||||
verifyDb.ViewerEventCounters.Count(c => c.ViewerId == viewerId && c.EventKey == "battle_win_total"),
|
||||
Is.EqualTo(1));
|
||||
Assert.That(
|
||||
verifyDb.ViewerEventCounters
|
||||
.Single(c => c.ViewerId == viewerId && c.EventKey == "battle_win_total").Count,
|
||||
Is.EqualTo(20));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ImportViewer_Missions_ExplicitSlotRoundTrips()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user