feat(packs): accept all currently-supported currencies on /pack/open
Extends /pack/open beyond the v1 CRYSTAL_MULTI=2 / DAILY=3 / RUPY_MULTI=7
trio to cover every type_detail whose payment primitive already exists:
1 CRYSTAL -> ICurrencySpendService crystal debit
6 RUPY -> ICurrencySpendService rupee debit
4 TICKET / 5 TICKET_MULTI -> debit child.ItemId from OwnedItemEntry
(ticketsNeeded = cost * packNumber), 400 on
missing/short balance; reward_list gets a
RewardType=4 post-state Item entry to mirror
project_wire_reward_list_post_state
Skin-overload type_details (8/9/13) and free-pack overlays (10/11/12)
stay 501 — they need selection / banner plumbing the current code
doesn't have.
Tutorial alias unchanged: it still consumes the gating ticket post-draw
and stamps tutorial_step=100. The two ticket flows diverge by intent
(tutorial = free server-grant; normal = paid by ticket inventory).
Removed Open_rejects_ticket_type_detail (asserted the old 501 path);
covered by Open_rejects_insufficient_tickets. Updated
NonTutorial_pack_open_does_not_emit_tutorial_step to assert the new
200-on-ticket-success behavior — same invariant under test.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -141,26 +141,44 @@ public class PackControllerTests
|
||||
[Test]
|
||||
public async Task NonTutorial_pack_open_does_not_emit_tutorial_step()
|
||||
{
|
||||
// Verify that regular /pack/open still works AND does not include tutorial_step in the response.
|
||||
// Use the tutorial pack (99047/990047) which has type_detail=5 — the non-tutorial path
|
||||
// still hits the currency_path_not_implemented guard and returns 501.
|
||||
// Verify that regular /pack/open works on a ticket-funded pack AND does not include
|
||||
// tutorial_step in the response. Pack 99047 uses type_detail=5 (TICKET_MULTI), which
|
||||
// the non-tutorial path now accepts: a normal viewer with a ticket buys a normal pack
|
||||
// — only the /tutorial/pack_open alias attaches tutorial_step.
|
||||
using var factory = new SVSimTestFactory();
|
||||
await factory.SeedGlobalsAsync();
|
||||
long viewerId = await factory.SeedViewerAsync(tutorialState: 100);
|
||||
|
||||
// Pack 99047 has BasePackId=90001 (Throwback). The minimal card seed only creates set
|
||||
// 10001, so seed set 90001 explicitly + install a draw table pointing at its cards.
|
||||
using (var scope = factory.Services.CreateScope())
|
||||
{
|
||||
var db = scope.ServiceProvider.GetRequiredService<SVSimDbContext>();
|
||||
db.CardSets.Add(new ShadowverseCardSetEntry
|
||||
{
|
||||
Id = 90001, Name = "TutorialStarterSet", IsInRotation = true, IsBasic = false,
|
||||
Cards =
|
||||
[
|
||||
new ShadowverseCardEntry { Id = 90001001L, Name = "StarterCard1", Rarity = Rarity.Bronze },
|
||||
new ShadowverseCardEntry { Id = 90001002L, Name = "StarterCard2", Rarity = Rarity.Gold },
|
||||
new ShadowverseCardEntry { Id = 90001003L, Name = "StarterCard3", Rarity = Rarity.Legendary },
|
||||
],
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
await factory.SeedPackDrawTableAsync(99047, 90001001L, 90001002L, 90001003L);
|
||||
await factory.SeedOwnedItemAsync(viewerId, itemId: 90001, count: 1, itemName: "Starter Legendary Ticket");
|
||||
|
||||
using var client = factory.CreateAuthenticatedClient(viewerId);
|
||||
|
||||
var requestJson = """{"parent_gacha_id":99047,"gacha_id":990047,"gacha_type":1,"pack_number":1,"exclude_card_ids":[],"viewer_id":"0","steam_id":0,"steam_session_ticket":""}""";
|
||||
var response = await client.PostAsync("/pack/open",
|
||||
new StringContent(requestJson, Encoding.UTF8, "application/json"));
|
||||
|
||||
// Non-tutorial pack/open + type_detail=5 STILL returns 501 — that's the established behavior.
|
||||
Assert.That((int)response.StatusCode, Is.EqualTo(501),
|
||||
"Non-tutorial /pack/open with type_detail=5 should still hit the currency_path_not_implemented guard.");
|
||||
|
||||
// Even on a 501, no tutorial_step field should appear in the response body.
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK), body);
|
||||
Assert.That(body.Contains("\"tutorial_step\""), Is.False,
|
||||
"Regular /pack/open must never emit tutorial_step.");
|
||||
"Regular /pack/open must never emit tutorial_step — only /tutorial/pack_open does.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
Reference in New Issue
Block a user