[platformnotifications] fix endpoint

This commit is contained in:
Devin Zuczek
2026-08-24 18:51:09 -04:00
parent 55ac92670f
commit b8d5103d57
2 changed files with 34 additions and 19 deletions
@@ -21,9 +21,9 @@ function unauthorized(c: Context<App>) {
} }
/** /**
* The notification categories `GET /config/categories` serves — a STUB standing in for the * The notification categories `GET /config/categories` serves as its `Results` — a STUB
* real list until something here actually defines categories and stores preferences against * standing in for the real list until something here actually defines categories and stores
* them. * preferences against them.
* *
* `CategoryId` is the client's own id for the category, `Importance` its ranking (0 being * `CategoryId` is the client's own id for the category, `Importance` its ranking (0 being
* the lowest observed), and `IsMuteable` whether the player may switch it off at all. The * the lowest observed), and `IsMuteable` whether the player may switch it off at all. The
@@ -74,9 +74,15 @@ const app = new Hono<App>()
}) })
// The notification categories a player can be shown toggles for — the "what may we notify // The notification categories a player can be shown toggles for — the "what may we notify
// you about" list. A bare array of PascalCase categories, no envelope. No auth: the list // you about" list. A `{ Results, TotalResults }` PAGE of PascalCase categories, the same
// is server-side config, the same for every player, and a caller's own preferences are // envelope the other paged reads on this server use — not the bare array this once
// the per-account routes above. // served. No auth: the list is server-side config, the same for every player, and a
// caller's own preferences are the per-account routes above.
//
// `TotalResults` counts the whole list rather than the page, and there is only ever one
// page here — nothing pages a list this short — so it is the array's own length. Counting
// it rather than writing the number keeps the two from disagreeing when a category is
// added.
// //
// STUB. Nothing here defines categories or stores a preference against one, so this is // STUB. Nothing here defines categories or stores a preference against one, so this is
// one hand-written entry standing in for the real list — the toggle it draws does // one hand-written entry standing in for the real list — the toggle it draws does
@@ -84,7 +90,10 @@ const app = new Hono<App>()
// the field the client renders, so the stub is visible in-game instead of looking like // the field the client renders, so the stub is visible in-game instead of looking like
// a real (and broken) setting. `Name` is left clean in case the client keys off it. // a real (and broken) setting. `Name` is left clean in case the client keys off it.
.get('/config/categories', async (c) => { .get('/config/categories', async (c) => {
return c.json(NOTIFICATION_CATEGORIES) return c.json({
Results: NOTIFICATION_CATEGORIES,
TotalResults: NOTIFICATION_CATEGORIES.length,
})
}) })
// The caller's CRM configuration — the campaign/messaging settings the client fetches on // The caller's CRM configuration — the campaign/messaging settings the client fetches on
@@ -75,27 +75,33 @@ it('401s the gameplay-invites check without a bearer token', async () => {
}) })
it('serves the stub notification categories', async () => { it('serves the stub notification categories', async () => {
// A bare array of PascalCase categories, and no auth — the list is server-side config // A `{ Results, TotalResults }` page of PascalCase categories — not a bare array — and no
// rather than anything per-player. // auth: the list is server-side config rather than anything per-player.
const res = await SELF.fetch(`${ORIGIN}/config/categories`) const res = await SELF.fetch(`${ORIGIN}/config/categories`)
expect(res.status).toBe(200) expect(res.status).toBe(200)
const categories = (await res.json()) as Array<{ const page = (await res.json()) as {
CategoryId: number Results: Array<{
Importance: number CategoryId: number
Name: string Importance: number
Description: string Name: string
IsMuteable: boolean Description: string
}> IsMuteable: boolean
expect(categories).toHaveLength(1) }>
expect(categories[0]).toMatchObject({ TotalResults: number
}
expect(page.Results).toHaveLength(1)
expect(page.Results[0]).toMatchObject({
CategoryId: 2, CategoryId: 2,
Importance: 0, Importance: 0,
Name: 'Friends', Name: 'Friends',
IsMuteable: true, IsMuteable: true,
}) })
// The total counts the whole list, and this list is served in one page — so it has to
// agree with what came back rather than being a number of its own.
expect(page.TotalResults).toBe(page.Results.length)
// The stub marker is in the DISPLAYED text, so a category that does nothing says so // The stub marker is in the DISPLAYED text, so a category that does nothing says so
// in-game rather than looking like a real setting. Keep it there while this is a stub. // in-game rather than looking like a real setting. Keep it there while this is a stub.
expect(categories[0].Description).toContain('STUB') expect(page.Results[0].Description).toContain('STUB')
}) })
it('serves the callers notification preferences', async () => { it('serves the callers notification preferences', async () => {