Getting ready to seed more data
This commit is contained in:
@@ -10,9 +10,9 @@ using SVSim.UnitTests.Infrastructure;
|
||||
namespace SVSim.UnitTests.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Coverage for <c>/deck/*</c> — the deck-editor CRUD surface. Plain-JSON path; the
|
||||
/// camelCase'd C# property names are what tests see (see the note on Phase 6 / encrypted
|
||||
/// pipeline for the msgpack contract).
|
||||
/// Coverage for <c>/deck/*</c> — the deck-editor CRUD surface. Tests assert against the
|
||||
/// <c>[Key("...")]</c>-driven wire keys (mirrored to <c>[JsonPropertyName]</c>); these are
|
||||
/// the names the decompiled client actually parses, NOT <c>SnakeCaseLower(C# property)</c>.
|
||||
/// </summary>
|
||||
public class DeckControllerTests
|
||||
{
|
||||
@@ -53,7 +53,7 @@ public class DeckControllerTests
|
||||
Assert.That(decks.GetArrayLength(), Is.EqualTo(2),
|
||||
"Only Rotation-format decks should be returned for a Rotation request.");
|
||||
var names = Enumerable.Range(0, decks.GetArrayLength())
|
||||
.Select(i => decks[i].GetProperty("name").GetString())
|
||||
.Select(i => decks[i].GetProperty("deck_name").GetString())
|
||||
.ToList();
|
||||
Assert.That(names, Is.EquivalentTo(new[] { "Slot 1", "Slot 2" }));
|
||||
}
|
||||
@@ -74,7 +74,7 @@ public class DeckControllerTests
|
||||
using var doc = JsonDocument.Parse(body);
|
||||
var decks = doc.RootElement.GetProperty("user_deck_list");
|
||||
Assert.That(decks.GetArrayLength(), Is.EqualTo(1));
|
||||
Assert.That(decks[0].GetProperty("name").GetString(), Is.EqualTo("Unlimited Deck"));
|
||||
Assert.That(decks[0].GetProperty("deck_name").GetString(), Is.EqualTo("Unlimited Deck"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -232,7 +232,7 @@ public class DeckControllerTests
|
||||
Assert.That(decks.GetArrayLength(), Is.EqualTo(2),
|
||||
"/deck/update should hand back the full refreshed list, saving the client a follow-up.");
|
||||
var names = Enumerable.Range(0, decks.GetArrayLength())
|
||||
.Select(i => decks[i].GetProperty("name").GetString())
|
||||
.Select(i => decks[i].GetProperty("deck_name").GetString())
|
||||
.ToList();
|
||||
Assert.That(names, Is.EquivalentTo(new[] { "Existing", "Second" }));
|
||||
}
|
||||
@@ -252,7 +252,7 @@ public class DeckControllerTests
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
using var doc = JsonDocument.Parse(body);
|
||||
Assert.That(doc.RootElement.GetProperty("user_deck").GetProperty("name").GetString(),
|
||||
Assert.That(doc.RootElement.GetProperty("user_deck").GetProperty("deck_name").GetString(),
|
||||
Is.EqualTo("New Name"));
|
||||
|
||||
using var scope = factory.Services.CreateScope();
|
||||
|
||||
@@ -17,24 +17,23 @@ public class LoadControllerTests
|
||||
"""{"viewer_id":"0","steam_id":0,"steam_session_ticket":"","carrier":"steam","card_master_hash":""}""";
|
||||
|
||||
/// <summary>
|
||||
/// JSON keys (camelCased C# property names) for fields the client reads unconditionally.
|
||||
/// These come from the plain-JSON path; the wire-format snake_case keys
|
||||
/// (<c>user_rank</c>, <c>rotation_card_set_id_list</c>, ...) only apply when the
|
||||
/// encrypted msgpack pipeline is in play — see <c>EncryptedPipelineTests</c> (Phase 6).
|
||||
/// Missing any of these is a wire-shape regression in either path.
|
||||
/// Wire keys (from <c>[Key("...")]</c> / mirrored <c>[JsonPropertyName]</c>) for fields the
|
||||
/// client reads unconditionally in <c>LoadDetail.ConvertJsonData</c>. These are the names
|
||||
/// the decompiled client actually looks up — NOT <c>SnakeCaseLower(C# property name)</c>.
|
||||
/// Missing any of these crashes the client with <c>KeyNotFoundException</c> on /load/index.
|
||||
/// </summary>
|
||||
private static readonly string[] RequiredIndexKeys =
|
||||
{
|
||||
"user_tutorial", "user_info", "user_currency", "user_items",
|
||||
"user_rotation_decks", "user_unlimited_decks", "user_my_rotation_decks",
|
||||
"user_cards", "user_classes", "sleeves", "user_emblems",
|
||||
"user_degrees", "leader_skins", "my_page_backgrounds",
|
||||
"user_rank_info", "user_ranked_matches", "daily_login_bonus", "arena_config",
|
||||
"red_ether_overrides", "maintenance_cards", "arena_infos", "rank_info",
|
||||
"class_exp", "loading_tip_card_exclusions", "default_settings",
|
||||
"unlimited_ban_list", "rotation_sets",
|
||||
"reprinted_cards", "spot_cards", "feature_maintenances",
|
||||
"special_crystal_infos", "open_battlefield_ids", "loot_box_regulations",
|
||||
"user_tutorial", "user_info", "user_crystal_count", "user_item_list",
|
||||
"user_deck_rotation", "user_deck_unlimited", "user_deck_my_rotation",
|
||||
"user_card_list", "user_class_list", "user_sleeve_list", "user_emblem_list",
|
||||
"user_degree_list", "user_leader_skin_list", "user_mypage_list",
|
||||
"user_rank", "user_rank_match_list", "daily_login_bonus", "challenge_config",
|
||||
"red_ether_overwrite_list", "maintenance_card_list", "rank_info",
|
||||
"class_exp", "loading_exclusion_card_list", "default_setting",
|
||||
"unlimited_restricted_base_card_id_list", "rotation_card_set_id_list",
|
||||
"reprinted_base_card_ids", "spot_cards", "feature_maintenance_list",
|
||||
"special_crystal_info", "open_battle_field_id_list", "loot_box_regulation",
|
||||
"gathering_info", "user_config", "deck_format", "card_set_id_for_resource_dl_view"
|
||||
};
|
||||
|
||||
@@ -100,7 +99,7 @@ public class LoadControllerTests
|
||||
|
||||
var root = await PostIndexAndReadBody(factory, viewerId);
|
||||
|
||||
Assert.That(root.GetProperty("user_rank_info").ValueKind, Is.EqualTo(JsonValueKind.Array));
|
||||
Assert.That(root.GetProperty("user_rank").ValueKind, Is.EqualTo(JsonValueKind.Array));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -114,7 +113,7 @@ public class LoadControllerTests
|
||||
|
||||
var root = await PostIndexAndReadBody(factory, viewerId);
|
||||
|
||||
Assert.That(root.GetProperty("user_rank_info").GetArrayLength(), Is.EqualTo(5));
|
||||
Assert.That(root.GetProperty("user_rank").GetArrayLength(), Is.EqualTo(5));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -127,10 +126,26 @@ public class LoadControllerTests
|
||||
|
||||
var root = await PostIndexAndReadBody(factory, viewerId);
|
||||
|
||||
Assert.That(root.GetProperty("rotation_sets").GetArrayLength(),
|
||||
Assert.That(root.GetProperty("rotation_card_set_id_list").GetArrayLength(),
|
||||
Is.GreaterThanOrEqualTo(2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Index_omits_arena_info_when_empty()
|
||||
{
|
||||
// ArenaData(JsonData) ctor reads data[0] inside the Keys.Contains("arena_info")
|
||||
// branch (LoadDetail.cs:261 → ArenaData.cs:48) — an empty array crashes the client
|
||||
// with ArgumentOutOfRangeException. Field must be absent when there's no arena.
|
||||
using var factory = new SVSimTestFactory();
|
||||
long viewerId = await factory.SeedViewerAsync();
|
||||
|
||||
var root = await PostIndexAndReadBody(factory, viewerId);
|
||||
|
||||
Assert.That(root.TryGetProperty("arena_info", out _), Is.False,
|
||||
"arena_info must be omitted when empty; the client crashes on []. " +
|
||||
"If you re-add it, populate at least one entry with a valid format_info.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Index_when_viewer_has_no_decks_returns_empty_format_lists()
|
||||
{
|
||||
@@ -141,15 +156,15 @@ public class LoadControllerTests
|
||||
|
||||
var root = await PostIndexAndReadBody(factory, viewerId);
|
||||
|
||||
foreach (var key in new[] { "user_rotation_decks", "user_unlimited_decks", "user_my_rotation_decks" })
|
||||
foreach (var key in new[] { "user_deck_rotation", "user_deck_unlimited", "user_deck_my_rotation" })
|
||||
{
|
||||
var container = root.GetProperty(key);
|
||||
Assert.That(container.ValueKind, Is.EqualTo(JsonValueKind.Object),
|
||||
$"{key} should be the UserFormatDeckInfo object wrapper, not a raw array.");
|
||||
var inner = container.GetProperty("user_decks");
|
||||
var inner = container.GetProperty("user_deck_list");
|
||||
Assert.That(inner.ValueKind, Is.EqualTo(JsonValueKind.Array));
|
||||
Assert.That(inner.GetArrayLength(), Is.EqualTo(0),
|
||||
$"{key}.userDecks must be an empty array for a deckless viewer, not null.");
|
||||
$"{key}.user_deck_list must be an empty array for a deckless viewer, not null.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,9 +58,9 @@ public class PracticeControllerTests
|
||||
var rotation = doc.RootElement.GetProperty("user_deck_rotation");
|
||||
var unlimited = doc.RootElement.GetProperty("user_deck_unlimited");
|
||||
Assert.That(rotation.GetArrayLength(), Is.EqualTo(1));
|
||||
Assert.That(rotation[0].GetProperty("name").GetString(), Is.EqualTo("Rotation Deck"));
|
||||
Assert.That(rotation[0].GetProperty("deck_name").GetString(), Is.EqualTo("Rotation Deck"));
|
||||
Assert.That(unlimited.GetArrayLength(), Is.EqualTo(1));
|
||||
Assert.That(unlimited[0].GetProperty("name").GetString(), Is.EqualTo("Unlimited Deck"));
|
||||
Assert.That(unlimited[0].GetProperty("deck_name").GetString(), Is.EqualTo("Unlimited Deck"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
Reference in New Issue
Block a user