feat(tutorial): add /tutorial/gift_receive — grant + receipt + idempotent re-claim
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -47,4 +47,87 @@ public class GiftControllerTests
|
||||
Assert.That(root.GetProperty("present_history_list").GetArrayLength(), Is.EqualTo(0));
|
||||
Assert.That(root.GetProperty("limit_over_present_list").GetArrayLength(), Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GiftReceive_grants_currency_and_items_then_history_is_populated()
|
||||
{
|
||||
using var factory = new SVSimTestFactory();
|
||||
await factory.SeedGlobalsAsync();
|
||||
long viewerId = await factory.SeedViewerAsync(tutorialState: 31);
|
||||
using var client = factory.CreateAuthenticatedClient(viewerId);
|
||||
|
||||
var pre = await factory.GetViewerCurrencyAsync(viewerId);
|
||||
|
||||
var requestJson = $$"""
|
||||
{"present_id_array":["71478626","71478627","71478628","71478629","71478630"],"state":1,{{BaseAuthBlock}}}
|
||||
""";
|
||||
var response = await client.PostAsync("/tutorial/gift_receive",
|
||||
new StringContent(requestJson, Encoding.UTF8, "application/json"));
|
||||
|
||||
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
|
||||
using var doc = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
|
||||
var root = doc.RootElement;
|
||||
|
||||
// Five received ids echoed.
|
||||
var ids = root.GetProperty("received_ids").EnumerateArray()
|
||||
.Select(e => e.GetString()).ToHashSet();
|
||||
Assert.That(ids, Is.EquivalentTo(new[] { "71478626", "71478627", "71478628", "71478629", "71478630" }));
|
||||
|
||||
// present_list emptied, history populated.
|
||||
Assert.That(root.GetProperty("present_list").GetArrayLength(), Is.EqualTo(0));
|
||||
Assert.That(root.GetProperty("present_history_list").GetArrayLength(), Is.EqualTo(5));
|
||||
|
||||
// Currency credited: +400 crystals, +100 rupees.
|
||||
var post = await factory.GetViewerCurrencyAsync(viewerId);
|
||||
Assert.That(post.Crystals - pre.Crystals, Is.EqualTo(400UL));
|
||||
Assert.That(post.Rupees - pre.Rupees, Is.EqualTo(100UL));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GiftReceive_advances_tutorial_state_from_31_to_41()
|
||||
{
|
||||
using var factory = new SVSimTestFactory();
|
||||
await factory.SeedGlobalsAsync();
|
||||
long viewerId = await factory.SeedViewerAsync(tutorialState: 31);
|
||||
using var client = factory.CreateAuthenticatedClient(viewerId);
|
||||
|
||||
var json = $$"""{"present_id_array":["71478626"],"state":1,{{BaseAuthBlock}}}""";
|
||||
var response = await client.PostAsync("/tutorial/gift_receive",
|
||||
new StringContent(json, Encoding.UTF8, "application/json"));
|
||||
|
||||
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
|
||||
using var doc = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
|
||||
var root = doc.RootElement;
|
||||
|
||||
// Response carries the new step inline.
|
||||
Assert.That(root.GetProperty("tutorial_step").GetInt32(), Is.EqualTo(41));
|
||||
Assert.That(root.GetProperty("is_unreceived_present").GetBoolean(), Is.False);
|
||||
Assert.That(root.GetProperty("reward_list").GetArrayLength(), Is.EqualTo(1));
|
||||
|
||||
// Side effect: viewer state advanced to 41.
|
||||
Assert.That(await factory.GetViewerTutorialStateAsync(viewerId), Is.EqualTo(41));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GiftReceive_second_call_with_same_ids_does_not_double_grant()
|
||||
{
|
||||
using var factory = new SVSimTestFactory();
|
||||
await factory.SeedGlobalsAsync();
|
||||
long viewerId = await factory.SeedViewerAsync(tutorialState: 31);
|
||||
using var client = factory.CreateAuthenticatedClient(viewerId);
|
||||
|
||||
var preFirst = await factory.GetViewerCurrencyAsync(viewerId);
|
||||
var json = $$"""{"present_id_array":["71478626","71478627"],"state":1,{{BaseAuthBlock}}}""";
|
||||
|
||||
await client.PostAsync("/tutorial/gift_receive", new StringContent(json, Encoding.UTF8, "application/json"));
|
||||
var midPost = await factory.GetViewerCurrencyAsync(viewerId);
|
||||
Assert.That(midPost.Crystals - preFirst.Crystals, Is.EqualTo(400UL));
|
||||
Assert.That(midPost.Rupees - preFirst.Rupees, Is.EqualTo(100UL));
|
||||
|
||||
var second = await client.PostAsync("/tutorial/gift_receive", new StringContent(json, Encoding.UTF8, "application/json"));
|
||||
Assert.That(second.StatusCode, Is.EqualTo(HttpStatusCode.OK));
|
||||
var finalPost = await factory.GetViewerCurrencyAsync(viewerId);
|
||||
Assert.That(finalPost.Crystals, Is.EqualTo(midPost.Crystals), "Second claim of same present_ids must not re-grant.");
|
||||
Assert.That(finalPost.Rupees, Is.EqualTo(midPost.Rupees));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user