fix(pack): tutorial pack_open ThenIncludes OwnedItemEntry.Item
Without .ThenInclude(i => i.Item), the OwnedItemEntry.Item nav defaults to a new ItemEntry() with Id=0 (project_ef_nav_include_pitfall), so the FirstOrDefault(i => i.Item.Id == ticketItemId) lookup never matched. The ticket was never decremented and reward_list omitted the post-state entry — on the next /tutorial/pack_info the pack stayed visible and the client re-clicked into plain /pack/open, which 501s on type_detail=5. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -397,6 +397,52 @@ internal sealed class SVSimTestFactory : WebApplicationFactory<Program>
|
||||
return (viewer.Currency.Crystals, viewer.Currency.Rupees, viewer.Currency.RedEther);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seeds an OwnedItemEntry for the viewer. Inserts the ItemEntry master row if missing
|
||||
/// (Type defaults to 2 = card-pack ticket since both tutorial gift items 80001 and 90001
|
||||
/// are tickets). Tests use this to set up the ticket inventory that /tutorial/pack_open
|
||||
/// is supposed to consume.
|
||||
/// </summary>
|
||||
public async Task SeedOwnedItemAsync(long viewerId, int itemId, int count, string itemName = "TestItem", int itemType = 2)
|
||||
{
|
||||
using var scope = Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<SVSimDbContext>();
|
||||
var item = await db.Items.FindAsync(itemId);
|
||||
if (item is null)
|
||||
{
|
||||
item = new ItemEntry { Id = itemId, Name = itemName, Type = itemType };
|
||||
db.Items.Add(item);
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
var viewer = await db.Viewers
|
||||
.Include(v => v.Items).ThenInclude(i => i.Item)
|
||||
.FirstAsync(v => v.Id == viewerId);
|
||||
var existing = viewer.Items.FirstOrDefault(i => i.Item.Id == itemId);
|
||||
if (existing is null)
|
||||
{
|
||||
viewer.Items.Add(new OwnedItemEntry { Item = item, Count = count, Viewer = viewer });
|
||||
}
|
||||
else
|
||||
{
|
||||
existing.Count = count;
|
||||
}
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads the viewer's current owned count for <paramref name="itemId"/>. Returns 0 if no
|
||||
/// row exists. Tests use this to assert ticket consumption after /tutorial/pack_open.
|
||||
/// </summary>
|
||||
public async Task<int> GetOwnedItemCountAsync(long viewerId, int itemId)
|
||||
{
|
||||
using var scope = Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<SVSimDbContext>();
|
||||
var viewer = await db.Viewers
|
||||
.Include(v => v.Items).ThenInclude(i => i.Item)
|
||||
.FirstAsync(v => v.Id == viewerId);
|
||||
return viewer.Items.FirstOrDefault(i => i.Item.Id == itemId)?.Count ?? 0;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
Reference in New Issue
Block a user