[clubs] fix home 404

This commit is contained in:
Devin Zuczek
2026-10-13 10:48:52 -04:00
parent c48cefda26
commit 7d509f6230
2 changed files with 21 additions and 18 deletions
+7 -7
View File
@@ -214,9 +214,9 @@ const app = new Hono<App>()
.notFound(withNotFound()) .notFound(withNotFound())
// The player's home club — the one whose clubhouse they spawn into, stored on their // The player's home club — the one whose clubhouse they spawn into, stored on their
// account. Auth-gated. 404 when they have no home club, the club is gone, or it has // account. Auth-gated. A literal JSON `null` (200) when they have no home club, the
// no clubhouse room: the client expects a 404 for "no home club" and errors on an // club is gone, or it has no clubhouse room — not a 404, and not an empty object.
// empty object. Returns the bare club (not the envelope), as the reference does. // Returns the bare club (not the envelope), as the reference does.
.get( .get(
'/club/home/me', '/club/home/me',
describeRoute({ describeRoute({
@@ -224,9 +224,9 @@ const app = new Hono<App>()
summary: 'The player’s home club', summary: 'The player’s home club',
description: [ description: [
'The club whose clubhouse the player spawns into (a field on their account row).', 'The club whose clubhouse the player spawns into (a field on their account row).',
'404 when they have no home club, the club is gone, or it has no clubhouse room —', 'A literal JSON `null` when they have no home club, the club is gone, or it has no',
'the client expects a 404 for “no home club” and errors on an empty object. Returns', 'clubhouse room — not a 404, and not an empty object. Returns the bare club, not',
'the bare club, not the envelope, as the reference does.', 'the envelope, as the reference does.',
].join(' '), ].join(' '),
security: AUTHED, security: AUTHED,
responses: { responses: {
@@ -239,7 +239,7 @@ const app = new Hono<App>()
const id = await authedId(c) const id = await authedId(c)
if (id === null) return c.body(null, 401) if (id === null) return c.body(null, 401)
const club = await getHomeClub(c.env.DB, id) const club = await getHomeClub(c.env.DB, id)
return club === null ? c.notFound() : c.json(club) return c.json(club)
} }
) )
+14 -11
View File
@@ -78,10 +78,11 @@ describe('clubs endpoints', () => {
expect(res.status).toBe(401) expect(res.status).toBe(401)
}) })
test('GET /club/home/me 404s when the player has no home club', async () => { test('GET /club/home/me answers a literal null when the player has no home club', async () => {
// The client expects a 404 here, and errors on an empty object. // Not a 404, and not an empty object.
const res = await exports.default.fetch(`${ORIGIN}/club/home/me`, { headers: await bearer() }) const res = await exports.default.fetch(`${ORIGIN}/club/home/me`, { headers: await bearer() })
expect(res.status).toBe(404) expect(res.status).toBe(200)
expect(await res.text()).toBe('null')
}) })
test('GET /subscription/details/:subscription returns an empty object', async () => { test('GET /subscription/details/:subscription returns an empty object', async () => {
@@ -777,11 +778,12 @@ describe('clubs endpoints', () => {
}) })
const clubId = ((await create.json()) as { value: { ClubId: number } }).value.ClubId const clubId = ((await create.json()) as { value: { ClubId: number } }).value.ClubId
// No home club yet → 404. // No home club yet → null.
const before = await exports.default.fetch(`${ORIGIN}/club/home/me`, { const before = await exports.default.fetch(`${ORIGIN}/club/home/me`, {
headers: await bearer('9100'), headers: await bearer('9100'),
}) })
expect(before.status).toBe(404) expect(before.status).toBe(200)
expect(await before.json()).toBeNull()
// You must be a member of the club you're making your home. // You must be a member of the club you're making your home.
expect((await form('/club/home/me', 'PUT', `clubId=${clubId}`, '9101')).status).toBe(403) expect((await form('/club/home/me', 'PUT', `clubId=${clubId}`, '9101')).status).toBe(403)
@@ -793,11 +795,11 @@ describe('clubs endpoints', () => {
expect(set.status).toBe(200) expect(set.status).toBe(200)
expect(await set.json()).toMatchObject({ error: '', success: true }) expect(await set.json()).toMatchObject({ error: '', success: true })
// The club has no clubhouse room yet, so there's still nowhere to spawn → 404. // The club has no clubhouse room yet, so there's still nowhere to spawn → null.
const noClubhouse = await exports.default.fetch(`${ORIGIN}/club/home/me`, { const noClubhouse = await exports.default.fetch(`${ORIGIN}/club/home/me`, {
headers: await bearer('9100'), headers: await bearer('9100'),
}) })
expect(noClubhouse.status).toBe(404) expect(await noClubhouse.json()).toBeNull()
// Give it a clubhouse → the home club now resolves. // Give it a clubhouse → the home club now resolves.
const clubhouse = await form(`/club/${clubId}/clubhouse`, 'PUT', 'roomId=77', '9100') const clubhouse = await form(`/club/${clubId}/clubhouse`, 'PUT', 'roomId=77', '9100')
@@ -825,7 +827,7 @@ describe('clubs endpoints', () => {
const cleared = await exports.default.fetch(`${ORIGIN}/club/home/me`, { const cleared = await exports.default.fetch(`${ORIGIN}/club/home/me`, {
headers: await bearer('9100'), headers: await bearer('9100'),
}) })
expect(cleared.status).toBe(404) expect(await cleared.json()).toBeNull()
// DELETE clears it too, ignoring any body it's sent. // DELETE clears it too, ignoring any body it's sent.
await form(`/club/${clubId}/clubhouse`, 'PUT', 'roomId=88', '9100') await form(`/club/${clubId}/clubhouse`, 'PUT', 'roomId=88', '9100')
@@ -846,9 +848,10 @@ describe('clubs endpoints', () => {
expect(dropped.status).toBe(200) expect(dropped.status).toBe(200)
expect(await dropped.json()).toEqual({ error: '', success: true, value: null }) expect(await dropped.json()).toEqual({ error: '', success: true, value: null })
expect( expect(
(await exports.default.fetch(`${ORIGIN}/club/home/me`, { headers: await bearer('9100') })) await (
.status await exports.default.fetch(`${ORIGIN}/club/home/me`, { headers: await bearer('9100') })
).toBe(404) ).json()
).toBeNull()
// Still a member of the club they'd made their home. // Still a member of the club they'd made their home.
const mine = (await ( const mine = (await (
await exports.default.fetch(`${ORIGIN}/club/mine/member`, { headers: await bearer('9100') }) await exports.default.fetch(`${ORIGIN}/club/mine/member`, { headers: await bearer('9100') })