From dc76efc418e9bcff5941596307b9997bcd03b21f Mon Sep 17 00:00:00 2001 From: Maurice Date: Fri, 30 Oct 2026 23:14:32 +0000 Subject: [PATCH] admin: a withdrawal that went through is reported even when the state re-read fails --- .../components/Admin/usePlaceContrib.test.ts | 31 +++++++++++++++++++ .../src/components/Admin/usePlaceContrib.ts | 3 +- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 client/src/components/Admin/usePlaceContrib.test.ts diff --git a/client/src/components/Admin/usePlaceContrib.test.ts b/client/src/components/Admin/usePlaceContrib.test.ts new file mode 100644 index 000000000..46e4588dc --- /dev/null +++ b/client/src/components/Admin/usePlaceContrib.test.ts @@ -0,0 +1,31 @@ +// FE-ADMIN-CONTRIBHOOK-001 +import { act, renderHook, waitFor } from '@testing-library/react'; +import type { PlaceContribState } from '@trek/shared'; +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { placeContribRepo } from '../../repo/placeContribRepo'; +import { usePlaceContrib } from './usePlaceContrib'; + +const STATE = { ineligibleReason: null, active: true } as unknown as PlaceContribState; + +afterEach(() => { + vi.restoreAllMocks(); +}); + +describe('usePlaceContrib', () => { + it('FE-ADMIN-CONTRIBHOOK-001: a withdrawal that went through is answered even when the state cannot be read again', async () => { + const state = vi.spyOn(placeContribRepo, 'state').mockResolvedValueOnce(STATE); + vi.spyOn(placeContribRepo, 'withdraw').mockResolvedValue({ withdrawn: { website: 2 }, cleared: 1 }); + const { result } = renderHook(() => usePlaceContrib()); + await waitFor(() => expect(result.current.state).toBe(STATE)); + + state.mockRejectedValueOnce(new Error('offline')); + let answer: unknown; + await act(async () => { + answer = await result.current.withdraw(); + }); + + expect(answer).toEqual({ withdrawn: { website: 2 }, cleared: 1 }); + expect(result.current.state).toBe(STATE); + expect(result.current.busy).toBe(false); + }); +}); diff --git a/client/src/components/Admin/usePlaceContrib.ts b/client/src/components/Admin/usePlaceContrib.ts index 9effb198b..b3dddbba7 100644 --- a/client/src/components/Admin/usePlaceContrib.ts +++ b/client/src/components/Admin/usePlaceContrib.ts @@ -53,7 +53,8 @@ export function usePlaceContrib() { setBusy(true); try { const result = await placeContribRepo.withdraw(); - setState(await placeContribRepo.state()); + // The withdrawal went through; a failed re-read keeps the old state rather than reporting it failed. + await placeContribRepo.state().then(setState, () => undefined); return result; } finally { setBusy(false);