NATHANOAK / QA / PLAYGROUND

Automation element playground

Prefer accessible roles and labels in tests. Use data-testid when the control has no stable user-facing identity.

Search, filter, sort and paginate

12 products found

Filtered product catalog
IDProductCategoryPriceStatusRatingAction
P-1001Aurora KeyboardAccessories£89In stock4.7
P-1002Beacon WebcamCameras£129In stock4.4
P-1003Cedar Laptop StandAccessories£54Back order4.2
P-1004Drift Noise-Cancelling HeadsetAudio£199In stock4.8
P-1005Ember USB MicrophoneAudio£149In stock4.5

Complete and validate a form

Contact preference
No file selected

Dynamic states and overlays

A visible panel for basic tab assertions.
How should I locate elements?

Start with role and accessible name, then label or text. Use test IDs for implementation-neutral hooks. Avoid CSS classes and DOM position.

Ready

FRAMEWORK-NEUTRAL API LAB

Test the same APIs with TypeScript or Java

The API is the system under test; Playwright and REST Assured are independent test clients. Use either framework—or separate repositories for both—against the same endpoints and expected contracts.

Authentication used here: signed session cookie, not JWT

  1. POST credentials to /api/qa/auth/login.
  2. Extract the nathanoak_qa_session cookie from Set-Cookie.
  3. Send that cookie to protected endpoints and assert the authenticated response.
  4. Log out, then assert that the same protected request returns 401.

Keep credentials in environment variables or a CI secret store. Never commit passwords, cookies or authentication-state files.

Available API exercises
MethodEndpointWhat to practise
GET/api/qa/healthAvailability, response headers and a simple 200 response.
GET/api/qa/productsQuery parameters, filtering, sorting, pagination and validation errors.
GET/api/qa/products/{productId}Path parameter, nested detail JSON and a 404 problem response.
GET/api/qa/customersPagination links, nested objects, arrays, booleans and nullable fields.
GET/api/qa/customers/{customerId}Resource links, ETag caching and a conditional 304 response.
GET/api/qa/customers/{customerId}/ordersExtract a customer ID, then discover related order IDs.
GET/api/qa/orders/{orderId}Nested line items, totals, timestamps, enums and null tracking data.
POST/api/qa/auth/loginCredentials in the request body and an HttpOnly signed session cookie.
GET/api/qa/auth/sessionA protected read that proves the session cookie is being reused.
POST/api/qa/profileAuthenticated request-body validation and a synthetic 201 response.
PUT/api/qa/customers/{customerId}/preferencesFull replacement, 401 authentication and 422 validation.
POST/api/qa/quotesPass customer and product IDs from earlier calls and assert calculated totals.
POST/api/qa/ordersPass the quote ID, add an Idempotency-Key and follow the Location header.
PATCH/api/qa/orders/{orderId}Partial update plus valid, invalid and conflicting state transitions.
DELETE/api/qa/orders/{orderId}Assert an empty 204 response or a 409 business-rule conflict.
POST/api/qa/reportsStart asynchronous work and extract a polling URL from a 202 response.
GET/api/qa/reports/{jobId}Poll a job and assert nested aggregate/map response values.
GET/api/qa/reports/orders/exportContent negotiation: JSON, CSV download or 406 Not Acceptable.
POST/api/qa/auth/logoutSession termination and verification that later requests return 401.

Chained commercial-style scenarios

Do not hard-code IDs returned by discovery endpoints. Extract them, store them in a typed model or scenario context, and pass them to the next client call.

Customer-to-order traversal

GET customers → extract data[0].id → GET customer detail → follow links.orders → extract an order ID → GET order detail.

Authenticated purchase

Login → GET a customer → GET products → POST quote with extracted IDs → extract quoteId → POST order with Idempotency-Key → assert Location.

Asynchronous report

Login → POST report → assert 202 and Retry-After → follow Location → assert completed aggregates → follow export link.

Cache validation

GET customer → capture ETag → repeat with If-None-Match → assert 304 and an empty response body.

Negative state transition

Login → GET a shipped order → PATCH or DELETE it → assert the 409 application/problem+json contract.

Content negotiation

Request the export as application/json and text/csv, then request an unsupported media type and assert 406.

Playwright API — TypeScript

Best for one TypeScript portfolio containing browser and API tests. Its request context maintains cookies automatically.

const login = await request.post('/api/qa/auth/login', {
  data: { username: process.env.QA_USERNAME, password: process.env.QA_PASSWORD }
});
expect(login.status()).toBe(200);
expect(login.headers()['set-cookie']).toContain('HttpOnly');

// The same request context automatically reuses the cookie.
const session = await request.get('/api/qa/auth/session');
expect(session.status()).toBe(200);

REST Assured — Java

Use a separate Maven or Gradle test project. Extract the cookie at login and explicitly attach it to later requests.

String sessionCookie = given()
  .contentType(ContentType.JSON)
  .body(Map.of("username", username, "password", password))
.when()
  .post("/api/qa/auth/login")
.then()
  .statusCode(200)
  .header("Set-Cookie", containsString("HttpOnly"))
  .extract().cookie("nathanoak_qa_session");

given().cookie("nathanoak_qa_session", sessionCookie)
.when().get("/api/qa/auth/session")
.then().statusCode(200)
  .body("authenticated", equalTo(true));

Functional assertions

Assert status, body values, headers, content type, pagination, sorting and response time.

Negative and security tests

Try missing fields, invalid parameters, bad credentials, no cookie, rejected origins and rate limits. Use only synthetic data.

Contract tests

Validate responses against the OpenAPI 3.1 specification. Add Zod in TypeScript, JSON Schema in Java, and Pact when practising consumer-driven contracts.

OOP framework design you can practise

Keep assertions in tests and HTTP mechanics in reusable clients. Apply patterns only where they reduce duplication or make change safer.

Encapsulation

BaseApiClient owns base URL, headers, logging and request execution.

Inheritance

CustomerClient, OrderClient and ReportClient extend shared behaviour sparingly.

Abstraction

Expose methods such as createQuote() instead of request-library details.

Polymorphism

Implement AuthStrategy for cookie, bearer-token or anonymous requests.

Models

Use TypeScript interfaces or Java records/POJOs for requests and responses.

Builders

Build valid quote/profile payloads and override one field for boundary tests.

Factories

Create clients, test data and authentication contexts for each environment.

Composition

A workflow service composes customer, product, quote and order clients for chained journeys.

Suggested layers: config → HTTP client → auth strategy → domain clients → models/builders → workflows → schema validators → tests.

Response shapes represented in this lab

Objects, arrays, empty arrays, nested objects, string-keyed maps, integers, decimals, booleans, nulls, enums, ISO timestamps, pagination metadata, hypermedia links, standard JSON, problem JSON, CSV text and empty bodies.

Formats such as SOAP/XML, GraphQL, WebSocket and server-sent events are different API paradigms and should be separate focused modules rather than pretending they are ordinary REST endpoints.

Commercial-style checklist for every endpoint
  • Happy path, required fields, boundary values and invalid input.
  • Status code, content type, important headers and response schema.
  • Authorised, unauthorised and post-logout behaviour where applicable.
  • Data-driven tests for query combinations without duplicating test code.
  • No secrets in source control and no production load or destructive test data.