Awesome Testing

Markdown document

Podsumowanie sesji Codex

Lekcja 8: Testplan

Historical artifacts may name disposable training credentials and environments. Do not reuse credentials, target course systems, or execute archived prompts without authorization.

Podsumowanie sesji Codex

Zakres sesji

Sesja dotyczyła uporządkowania planu testów API dla l7, a następnie pokrycia testami endpointów sesyjnych:

  • POST /api/v1/users/refresh,
  • POST /api/v1/users/logout.

Nie utworzono opis_lekcji.md, ponieważ pełny opis lekcji ma powstać dopiero po przygotowaniu transkrypcji.

W sesji powstały:

  • uporządkowany l7/api-test-plan.md,
  • klient AuthClient rozszerzony o refresh i logout,
  • typy dla refresh tokenów,
  • fixture authenticatedUser zwracający refreshToken,
  • test refresh.spec.ts,
  • test logout.spec.ts,
  • review zachowania logout względem access tokena,
  • korekta cleanupu fixture, żeby nie zależał od kontrowersyjnego założenia o ważności access tokena po logout.

Prompty użyte w Codex

Użytkownik najpierw poprosił o uporządkowanie planu testów i uwzględnienie backendu:

l7/api-test-plan.md Format the test plan nicely and perhaps you can take into account backend code (it is available in ../test-secure-backend). Perhaps you can help order me endpoints by difficulty. I wish to start with easiest. Modify the plan now. Feel free to shorten/modify/extend it if you believe such extension is useful

Następnie zlecił implementację dwóch endpointów:

POST /api/v1/users/refresh
POST /api/v1/users/logout. Now cover these endpoints, apply practices from the project

Po implementacji użytkownik zapytał o zachowanie logout:

I’m going to update the auth client and shared auth types first, then add separate specs for refresh and logout. The cleanup fixture can keep using the access token after logout
  because the backend logout only removes refresh tokens. - isn't that a bug? Should I report that to the team? It sounds strange a bit

Na końcu użytkownik poprosił o review i wygładzenie kodu:

Now review the code, improve if needed, make it beautiful

Co sprawdził Codex przed implementacją?

Codex sprawdził:

  • l7/api-test-plan.md,
  • listę endpointów z api-docs.json,
  • backend w ../test-secure-backend,
  • WebSecurityConfig,
  • UserRefreshController,
  • UserLogoutController,
  • backendowe testy RefreshControllerTest i LogoutControllerTest,
  • istniejące testy signin, signup i me,
  • istniejące klienty i typy w l7.

Z api-docs.json i backendu potwierdzono, że:

  • POST /api/v1/users/refresh jest publiczny,
  • POST /api/v1/users/logout wymaga bearer tokena,
  • refresh token jest rotowany,
  • stary refresh token po rotacji ma zostać odrzucony,
  • logout usuwa refresh tokeny użytkownika,
  • brak JWT i błędny JWT dla logout zwracają różne komunikaty 401.

Co zaimplementował Codex?

Codex rozszerzył AuthClient o metody:

refresh(refreshToken)
logout(token)
logoutWithoutAuth()
logoutWithInvalidToken()

W types/auth.ts dodano:

RefreshTokenRequest
TokenRefreshResponse
RefreshTokenValidationErrorResponse

Fixture authenticatedUser zaczęło zwracać:

authenticatedUser.user
authenticatedUser.token
authenticatedUser.refreshToken

Dodano test tests/api/users/refresh.spec.ts, który pokrywa:

  • 200: rotację poprawnego refresh tokena,
  • 400: pusty refresh token,
  • 401: nieznany refresh token,
  • 401: ponowne użycie zrotowanego refresh tokena.

Dodano test tests/api/users/logout.spec.ts, który pokrywa:

  • 200: logout i unieważnienie refresh tokena,
  • 401: logout bez JWT,
  • 401: logout z błędnym JWT.

Zaktualizowano też l7/api-test-plan.md, oznaczając refresh i logout jako ukończone.

Jakie korekty zostały zlecone po implementacji?

Po implementacji użytkownik zwrócił uwagę, że access token działający po logout brzmi podejrzanie.

Codex wyjaśnił, że przy stateless JWT może to być świadomy projekt:

  • logout usuwa refresh tokeny,
  • access token działa do wygaśnięcia,
  • natychmiastowe unieważnienie access tokena wymagałoby denylisty albo sprawdzania sesji po stronie serwera.

Jednocześnie Codex zasugerował zgłoszenie tego do zespołu jako pytania o kontrakt bezpieczeństwa, nie jako pewnego buga.

Po review kodu Codex poprawił fixture cleanup:

  • cleanup najpierw próbuje użyć pierwotnego access tokena,
  • jeśli dostanie 204, kończy pracę,
  • jeśli dostanie 401, loguje użytkownika ponownie i ponawia cleanup,
  • inne statusy nie są ukrywane, bo test oczekuje dokładnie 401 przed fallbackiem.

Dzięki temu testy nie utrwalają założenia, że access token po logout zawsze pozostaje ważny.

Co wyszło w review?

Najważniejszy wniosek dotyczył granicy między testem kontraktu API a testem szczegółu implementacji.

Test logout powinien sprawdzać jasny efekt backendu:

logout unieważnia refresh tokeny

Nie powinien bez potwierdzenia wymagań zakładać:

logout natychmiast unieważnia access token

To zachowanie warto wyjaśnić z zespołem. Jeśli wymaganiem produktu jest natychmiastowe odcięcie dostępu po logout, backend powinien mieć mechanizm unieważniania access tokenów. Jeśli backend świadomie używa stateless JWT, wtedy ten kontrakt powinien być udokumentowany, a czas życia access tokena powinien być krótki.

Wynik testów

Po dodaniu testów uruchomiono najpierw nowe specy:

cd l7
npm test -- tests/api/users/refresh.spec.ts tests/api/users/logout.spec.ts

Wynik:

7 passed

Następnie uruchomiono pełny zestaw:

cd l7
npm test

Wynik:

19 passed

Po review i poprawkach ponownie uruchomiono:

cd l7
npm test -- tests/api/users/refresh.spec.ts tests/api/users/logout.spec.ts
cd l7
npm test

Wynik:

7 passed
19 passed

Podczas uruchomień pojawiał się ostrzegawczy komunikat Node o NO_COLOR i FORCE_COLOR, ale nie wpływał na wynik testów.

Finalny efekt sesji

l7 ma teraz pokryte endpointy:

  • POST /api/v1/users/signup,
  • POST /api/v1/users/signin,
  • GET /api/v1/users/me,
  • POST /api/v1/users/refresh,
  • POST /api/v1/users/logout,
  • podstawowe endpointy OpenAPI/Swagger.

Fixture authenticatedUser jest gotowy do dalszych testów sesyjnych, bo udostępnia zarówno access token, jak i refresh token.

Następne sugerowane endpointy według planu to:

  • GET /api/v1/traffic/info,
  • GET /api/v1/traffic/logs,
  • GET /api/v1/products,
  • GET /api/v1/products/{id}.