test(06-05): add failing SessionExpiredError detection tests
This commit is contained in:
@@ -10,10 +10,157 @@
|
|||||||
* - eventFormMode: 'create'|'edit', defaults 'create'
|
* - eventFormMode: 'create'|'edit', defaults 'create'
|
||||||
* - eventFormUid: string|null, defaults null
|
* - eventFormUid: string|null, defaults null
|
||||||
* - setEventForm: setter for all three
|
* - setEventForm: setter for all three
|
||||||
|
*
|
||||||
|
* Plan 06-05: SessionExpiredError detection tests (D-11)
|
||||||
|
* - fetchEvents / createEvent / updateEvent / deleteEvent with opaqueredirect → SessionExpiredError
|
||||||
|
* - fetchEvents / createEvent / updateEvent / deleteEvent with 401 → SessionExpiredError
|
||||||
|
* - 500 response does NOT produce SessionExpiredError
|
||||||
|
* - fetchMe's existing opaqueredirect/401 path now throws SessionExpiredError (unified)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
||||||
|
|
||||||
|
// ── Plan 06-05: SessionExpiredError detection tests ───────────────────────────
|
||||||
|
|
||||||
|
describe('SessionExpiredError — fetchEvents (06-05)', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.stubGlobal('fetch', vi.fn())
|
||||||
|
})
|
||||||
|
afterEach(() => {
|
||||||
|
vi.unstubAllGlobals()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws SessionExpiredError on opaqueredirect', async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValueOnce({
|
||||||
|
ok: false,
|
||||||
|
type: 'opaqueredirect',
|
||||||
|
status: 0,
|
||||||
|
} as unknown as Response)
|
||||||
|
|
||||||
|
const { fetchEvents, SessionExpiredError } = await import('./client.js')
|
||||||
|
await expect(fetchEvents('2026-06-01', '2026-06-30')).rejects.toBeInstanceOf(SessionExpiredError)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws SessionExpiredError on 401', async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValueOnce({
|
||||||
|
ok: false,
|
||||||
|
type: 'basic',
|
||||||
|
status: 401,
|
||||||
|
} as unknown as Response)
|
||||||
|
|
||||||
|
const { fetchEvents, SessionExpiredError } = await import('./client.js')
|
||||||
|
await expect(fetchEvents('2026-06-01', '2026-06-30')).rejects.toBeInstanceOf(SessionExpiredError)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws a generic Error (not SessionExpiredError) on 500', async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValueOnce({
|
||||||
|
ok: false,
|
||||||
|
type: 'basic',
|
||||||
|
status: 500,
|
||||||
|
} as unknown as Response)
|
||||||
|
|
||||||
|
const { fetchEvents, SessionExpiredError } = await import('./client.js')
|
||||||
|
await expect(fetchEvents('2026-06-01', '2026-06-30')).rejects.toSatisfy(
|
||||||
|
(e: unknown) => e instanceof Error && !(e instanceof SessionExpiredError),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('SessionExpiredError — createEvent (06-05)', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.stubGlobal('fetch', vi.fn())
|
||||||
|
})
|
||||||
|
afterEach(() => {
|
||||||
|
vi.unstubAllGlobals()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws SessionExpiredError on 401', async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValueOnce({
|
||||||
|
ok: false,
|
||||||
|
type: 'basic',
|
||||||
|
status: 401,
|
||||||
|
} as unknown as Response)
|
||||||
|
|
||||||
|
const { createEvent, SessionExpiredError } = await import('./client.js')
|
||||||
|
await expect(
|
||||||
|
createEvent({ title: 'Test', allDay: false, start: '2026-06-15T10:00:00', end: '2026-06-15T11:00:00' }),
|
||||||
|
).rejects.toBeInstanceOf(SessionExpiredError)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('SessionExpiredError — updateEvent (06-05)', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.stubGlobal('fetch', vi.fn())
|
||||||
|
})
|
||||||
|
afterEach(() => {
|
||||||
|
vi.unstubAllGlobals()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws SessionExpiredError on 401', async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValueOnce({
|
||||||
|
ok: false,
|
||||||
|
type: 'basic',
|
||||||
|
status: 401,
|
||||||
|
} as unknown as Response)
|
||||||
|
|
||||||
|
const { updateEvent, SessionExpiredError } = await import('./client.js')
|
||||||
|
await expect(
|
||||||
|
updateEvent('uid-123', { title: 'Test', allDay: false, start: '2026-06-15T10:00:00', end: '2026-06-15T11:00:00' }),
|
||||||
|
).rejects.toBeInstanceOf(SessionExpiredError)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('SessionExpiredError — deleteEvent (06-05)', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.stubGlobal('fetch', vi.fn())
|
||||||
|
})
|
||||||
|
afterEach(() => {
|
||||||
|
vi.unstubAllGlobals()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws SessionExpiredError on 401', async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValueOnce({
|
||||||
|
ok: false,
|
||||||
|
type: 'basic',
|
||||||
|
status: 401,
|
||||||
|
} as unknown as Response)
|
||||||
|
|
||||||
|
const { deleteEvent, SessionExpiredError } = await import('./client.js')
|
||||||
|
await expect(deleteEvent('uid-to-delete')).rejects.toBeInstanceOf(SessionExpiredError)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('SessionExpiredError — fetchMe unified (06-05)', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.stubGlobal('fetch', vi.fn())
|
||||||
|
})
|
||||||
|
afterEach(() => {
|
||||||
|
vi.unstubAllGlobals()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws SessionExpiredError (instanceof) on opaqueredirect — unified with other wrappers', async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValueOnce({
|
||||||
|
ok: false,
|
||||||
|
type: 'opaqueredirect',
|
||||||
|
status: 0,
|
||||||
|
} as unknown as Response)
|
||||||
|
|
||||||
|
const { fetchMe, SessionExpiredError } = await import('./client.js')
|
||||||
|
await expect(fetchMe()).rejects.toBeInstanceOf(SessionExpiredError)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws SessionExpiredError on 401 — unified', async () => {
|
||||||
|
vi.mocked(fetch).mockResolvedValueOnce({
|
||||||
|
ok: false,
|
||||||
|
type: 'basic',
|
||||||
|
status: 401,
|
||||||
|
} as unknown as Response)
|
||||||
|
|
||||||
|
const { fetchMe, SessionExpiredError } = await import('./client.js')
|
||||||
|
await expect(fetchMe()).rejects.toBeInstanceOf(SessionExpiredError)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
// ── createEvent tests ─────────────────────────────────────────────────────────
|
// ── createEvent tests ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
describe('createEvent', () => {
|
describe('createEvent', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user