diff --git a/SVSim.UnitTests/Controllers/AdminControllerTests.cs b/SVSim.UnitTests/Controllers/AdminControllerTests.cs index 87f6b84..37796b8 100644 --- a/SVSim.UnitTests/Controllers/AdminControllerTests.cs +++ b/SVSim.UnitTests/Controllers/AdminControllerTests.cs @@ -342,4 +342,62 @@ public class AdminControllerTests Assert.That(stored.Decks, Is.Empty, "Default-deck cloning was removed; a fresh viewer with no imported decks has none."); } + + [Test] + public async Task ImportViewer_binds_new_fields_from_literal_client_json() + { + using var factory = new SVSimTestFactory(); + const ulong steamId = 76_561_198_111_222_340UL; + long viewerId = await factory.SeedViewerAsync(steamId: steamId); + await factory.SeedOwnedItemAsync(viewerId, itemId: 70001, count: 0); // register item master + + int classId, leaderSkinId; long sleeveId; + using (var scope = factory.Services.CreateScope()) + { + var db = scope.ServiceProvider.GetRequiredService(); + classId = (await db.Classes.FirstAsync()).Id; + sleeveId = (await db.Sleeves.FirstAsync()).Id; + leaderSkinId = (await db.LeaderSkins.FirstAsync()).Id; + } + + string json = $$""" + { + "steam_id": {{steamId}}, + "owned_cards": [ { "card_id": 10001001, "count": 2, "is_protected": true } ], + "items": [ { "item_id": 70001, "count": 4 } ], + "decks": [ { + "deck_format": 1, + "deck_no": 2, + "deck_name": "Wire Deck", + "class_id": {{classId}}, + "sleeve_id": {{sleeveId}}, + "leader_skin_id": {{leaderSkinId}}, + "is_random_leader_skin": 0, + "card_id_array": [10001001, 10001002] + } ] + } + """; + + using var client = factory.CreateClient(); + using var content = new StringContent(json, System.Text.Encoding.UTF8, "application/json"); + var response = await client.PostAsync("/admin/import_viewer", content); + + Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK), + await response.Content.ReadAsStringAsync()); + + using var scope2 = factory.Services.CreateScope(); + var db2 = scope2.ServiceProvider.GetRequiredService(); + var stored = await db2.Viewers + .Include(v => v.Cards).ThenInclude(c => c.Card) + .Include(v => v.Items).ThenInclude(i => i.Item) + .Include(v => v.Decks) + .FirstAsync(v => v.Id == viewerId); + + Assert.That(stored.Cards.Any(c => c.Card.Id == 10001001L && c.Count == 2 && c.IsProtected), Is.True, + "owned_cards snake_case keys must bind (card_id/count/is_protected)."); + Assert.That(stored.Items.Any(i => i.Item.Id == 70001 && i.Count == 4), Is.True, + "items snake_case keys must bind (item_id/count)."); + Assert.That(stored.Decks.Any(d => d.Name == "Wire Deck" && d.Format == Format.Rotation), Is.True, + "decks snake_case keys must bind (deck_format/deck_no/class_id/card_id_array/...)."); + } }