fix(guild): /guild/join returns guild_status per branch (APPLYING for approval path, JOINING otherwise)

GuildJoinTask.Parse() reads data[guild_status].ToInt() directly; hardcoding 2
for the APPROVAL path was wrong. GuildOpResult gains nullable GuildStatus; JoinAsync
sets 1 (APPLYING) for the pending-request path and 2 (JOINING) for instant joins.
Controller reads r.GuildStatus. Two new tests assert the wire value per path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-06-27 13:51:04 -04:00
parent d7f9ba8f2a
commit 771d884314
4 changed files with 59 additions and 7 deletions

View File

@@ -193,6 +193,58 @@ public class GuildJoinFlowTests
"Idempotent re-apply must not duplicate the pending row");
}
[Test]
public async Task Approval_join_response_has_guild_status_APPLYING()
{
using var factory = new SVSimTestFactory();
long viewerA = await factory.SeedViewerAsync(steamId: 76_561_198_400_000_025UL, displayName: "ApprovalLeaderStatus");
using var clientA = factory.CreateAuthenticatedClient(viewerA);
int guildId = await CreateGuildAndGetIdAsync(clientA, "ApprovalGuildStatus", joinCondition: 2);
long viewerB = await factory.SeedViewerAsync(steamId: 76_561_198_400_000_026UL, displayName: "ApprovalApplicantStatus");
using var clientB = factory.CreateAuthenticatedClient(viewerB);
// B applies to the APPROVAL guild.
var joinResp = await clientB.PostAsync("/guild/join",
JsonContent.Create(new { guild_id = guildId, from_invite = false,
viewer_id = Vid, steam_id = Sid, steam_session_ticket = Stk }));
var joinJson = await joinResp.Content.ReadAsStringAsync();
Assert.That(joinResp.IsSuccessStatusCode, Is.True, $"join HTTP failed: {joinJson}");
using var joinDoc = JsonDocument.Parse(joinJson);
// Must be APPLYING (1), NOT JOINING (2) — GuildJoinTask.Parse() reads this value directly.
Assert.That(GetStringifiedInt(joinDoc.RootElement, "guild_status"), Is.EqualTo(1),
$"APPROVAL branch must return guild_status=1 (APPLYING), got: {joinJson}");
}
[Test]
public async Task Approval_idempotent_join_response_has_guild_status_APPLYING()
{
using var factory = new SVSimTestFactory();
long viewerA = await factory.SeedViewerAsync(steamId: 76_561_198_400_000_027UL, displayName: "IdempotentApprovalLeaderStatus");
using var clientA = factory.CreateAuthenticatedClient(viewerA);
int guildId = await CreateGuildAndGetIdAsync(clientA, "IdempotentApprovalStatus", joinCondition: 2);
long viewerB = await factory.SeedViewerAsync(steamId: 76_561_198_400_000_028UL, displayName: "IdempotentApplicantStatus");
using var clientB = factory.CreateAuthenticatedClient(viewerB);
var joinPayload = new { guild_id = guildId, from_invite = false,
viewer_id = Vid, steam_id = Sid, steam_session_ticket = Stk };
// First apply.
await clientB.PostAsync("/guild/join", JsonContent.Create(joinPayload));
// Second (idempotent) apply — should still return APPLYING (1).
var join2 = await clientB.PostAsync("/guild/join", JsonContent.Create(joinPayload));
var join2Json = await join2.Content.ReadAsStringAsync();
Assert.That(join2.IsSuccessStatusCode, Is.True, $"Idempotent apply HTTP failed: {join2Json}");
using var join2Doc = JsonDocument.Parse(join2Json);
Assert.That(GetStringifiedInt(join2Doc.RootElement, "guild_status"), Is.EqualTo(1),
$"Idempotent APPROVAL branch must return guild_status=1 (APPLYING), got: {join2Json}");
}
// ─── ONLY_INVITE branch ──────────────────────────────────────────────────────
[Test]