Persiste proposal, specs delta (auth, api-client, access-requests, platform-shell, testing), design con 8 ADRs, tasks (27 items en 10 fases), verify-report (28 tests, 0 críticos, 0 warnings tras el cierre) y archive-report final. Cierra el ciclo SDD del cleanup de deuda técnica del console.
5.0 KiB
Testing Baseline Specification
New Spec for: Testing Infrastructure — console-tech-debt-cleanup
Purpose
Establishes Vitest + Testing Library as the test runner in services/frontend-console and defines the minimum baseline suite that must pass before any P0/P1 change is merged.
Requirements
Requirement: Vitest + Testing Library Configured
services/frontend-console MUST have Vitest and @testing-library/react installed and configured. The configuration MUST mirror services/frontend-admin (jsdom environment, setupTests.ts importing @testing-library/jest-dom). pnpm test MUST execute the suite and exit non-zero on failure. pnpm test:watch MUST run in watch mode.
Scenario: pnpm test runs green on a clean checkout
- GIVEN a developer runs
pnpm install && pnpm testinsideservices/frontend-console - WHEN all baseline tests pass
- THEN the process exits with code 0
- AND no test is skipped
Scenario: pnpm test fails on a broken test
- GIVEN a test assertion fails
- WHEN
pnpm testis run - THEN the process exits with non-zero code
- AND the failing test name and assertion are printed to stdout
Requirement: SessionCoordinator Refresh Deduplication Test
The test suite MUST include a test that verifies SessionCoordinator.refresh() calls fetch (the HTTP POST to /auth/refresh) exactly once when two concurrent invocations are made.
Scenario: Two concurrent refresh calls share one HTTP request
- GIVEN
fetchis mocked to resolve after a short delay with{ access_token: "new-token", role: "platform_admin", email: "op@x.com" } - WHEN
SessionCoordinator.refresh()is called twice concurrently (without awaiting the first) - THEN
fetchmock is called exactly once - AND both calls resolve with the same token string
Requirement: apiClient 401 Retry Path Test
The test suite MUST include tests for apiClient's 401 handling covering: single refresh-and-retry success, and refresh failure leading to logout + redirect.
Scenario: apiClient retries after 401 and resolves on success
- GIVEN
fetchreturns 401 on first call and 200 with body on retry - AND
SessionCoordinator.refreshresolves with a new token - WHEN
apiClient('/resource', { method: 'GET' })is called - THEN the resolved value equals the parsed body from the 200 response
- AND
fetchwas called twice total
Scenario: apiClient calls logout on refresh failure
- GIVEN
fetchreturns 401 andSessionCoordinator.refreshreturns null - WHEN
apiClient('/resource', { method: 'GET' })is called - THEN
useAuthStore.getState().logoutis called - AND the function throws
Requirement: Auth Store setSession and logout Tests
The test suite MUST cover setSession writing to accessToken (and only accessToken for the token), and logout resetting accessToken and user to null.
Scenario: setSession writes accessToken
- GIVEN the store is freshly initialized
- WHEN
setSession({ accessToken: 'tok', refreshToken: null, role: 'platform_admin', email: 'op@x.com' })is called - THEN
getState().accessTokenequals'tok' - AND
getState().userequals{ email: 'op@x.com', role: 'platform_admin' } - AND there is no
tokenfield with a non-null value on the state (field absent or null)
Scenario: logout clears state
- GIVEN the store has a non-null
accessTokenanduser - WHEN
logout()is called - THEN
getState().accessTokenis null - AND
getState().useris null
Requirement: AccessRequestsPage Mutation Baseline Tests
The test suite MUST include component tests for AccessRequestsPage covering the happy path and error path for each of the three mutations (approve, reject, mark-as-review).
Scenario: Approve mutation — success toast and invalidation
- GIVEN
AccessRequestsPagerenders with a request inpendingstatus - WHEN the operator selects that request and clicks "Aprobar"
- AND
approveAccessRequestresolves successfully - THEN
toast.successis called with a message containing "aprobada" - AND
queryClient.invalidateQueriesis called with key['platform-access-requests']
Scenario: Reject mutation — success toast, modal closes, invalidation
- GIVEN the rejection modal is open with a valid reason
- WHEN
rejectAccessRequestresolves successfully - THEN
toast.successis called with a message containing "rechazada" - AND the rejection modal is no longer visible
- AND the query cache is invalidated
Scenario: Review mutation — success toast and invalidation
- GIVEN a request with
status = 'pending'is selected - WHEN the operator clicks "Revisar"
- AND
markAccessRequestInReviewresolves successfully - THEN
toast.successis called with a message containing "revision" - AND the query cache is invalidated
Scenario: Mutation error — error toast, no invalidation
- GIVEN any mutation is triggered
- WHEN the API call rejects with
new Error('Network error') - THEN
toast.erroris called with'Network error' - AND
queryClient.invalidateQueriesis NOT called