Test Automation PlaygroundSelenium · Cypress · Playwright · WebdriverIO

Practice automation on real-world UI patterns

Twenty self-contained modules with forms, tables, waits, dialogs, frames, shadow DOM, drag and drop, file transfers and dummy REST endpoints. Every element exposes stable ids and data-testid attributes so you can focus on writing good tests.

All API calls hit dummy endpoints served by this page, so they appear in the network tab and can be intercepted or stubbed. Nothing is stored; state resets on reload. GET|POST|PATCH|DELETE https://klauders.com/automate-the-internet?api=<endpoint> Open the API reference →
01

Login & session

Authenticate against a dummy endpoint. Covers success, invalid credentials, locked account and empty-field validation.

POST ?api=auth/loginPOST ?api=auth/logout

✔ qa.engineer / Klauders#2026  ·  🔒 locked.user / any

02

Registration & validation

Client-side and server-side validation, inline field errors, a password strength meter and a conflict response for a duplicate email.

POST ?api=register

—

Plan *

Use taken@example.com to get a 409 Conflict.

03

Form controls

Checkboxes, radios, single and multi selects, slider, toggle switch, color and time inputs, plus disabled and read-only fields. The JSON panel reflects the current state.

Browsers
Environment
Headless mode

0/140


			
04

Users data table

Server-side search, filters, sorting and pagination. Row actions update status or delete a user after a confirmation modal. User #1 cannot be deleted (403).

GET ?api=usersPATCH ?api=users&id=DELETE ?api=users&id=
Actions
—
1 / 1
05

Dynamic content & waits

Elements that load after a random delay, get added or removed, change their id on every click, or become enabled asynchronously. Avoid fixed sleeps.

A. Delayed rendering (1.5–4s)

B. Add / remove elements

C. Dynamic id (use a stable locator)

current id:

D. Enable / disable asynchronously

E. Remove / restore a checkbox

F. Disappearing element (one link is missing on random loads)

    06

    Async job & polling

    Start a report export that returns 202 Accepted, then poll the job status until it completes (~6s). Ideal for testing polling, progress bars and timeouts.

    POST ?api=jobsGET ?api=jobs&id=
    Status: idle0%

    07

    Native browser dialogs

    JavaScript alert, confirm and prompt. Practice switching to the alert, accepting, dismissing and sending text.

    Result: —

    08

    Modals, toasts & cookie banner

    An accessible modal with focus handling and Escape to close, auto-dismissing toast notifications, and a cookie banner that appears on first visit and can block clicks.

    Modal result: —

    09

    iFrames & new windows

    Switch into an iframe to fill a form that posts a message back to the parent page. Open a link in a new tab and a popup window to practice window handles.

    Message from iframe: —

    Open in new tab ↗
    10

    Shadow DOM

    A web component with an open shadow root. Its inner input and button are not reachable with normal CSS selectors; pierce the shadow boundary.

    Light DOM mirror: —

    11

    Drag & drop board

    An HTML5 drag-and-drop kanban. Move test cases between columns and assert the counters and order. Selenium may need a JavaScript workaround for native HTML5 drag events.

    To do0

    In progress0

    Done0

    
    			
    12

    Hover, tooltips & context menu

    Captions revealed on hover, a tooltip on hover or focus, a nested hover menu and a custom right-click context menu.

    AG
    name: ana.garcia View profile
    LM
    name: luis.martinez View profile
    SL
    name: sofia.lopez View profile
    Right-click inside this box

    Last action: —

    13

    Tabs & accordion

    ARIA tabs with arrow-key navigation and an accordion with expandable panels. Assert visibility and aria-expanded / aria-selected states.

    248 tests · 241 passed · 4 failed · 3 skipped · 6m 12s

    14

    Autocomplete search

    A debounced combobox that queries the API as you type. Select with the mouse or with arrow keys and Enter; Escape closes the list.

    GET ?api=search&q=

    Selected: —

    15

    Cart & checkout flow

    An end-to-end purchase journey: load products, add to cart, change quantities, apply a coupon and place the order. Includes an out-of-stock item and stock limit errors.

    GET ?api=productsGET ?api=coupon&code=POST ?api=orders

    Loading products…

    Coupons: QA10 (10%), KLAUDERS20 (20%), EXPIRED (410 Gone), anything else (404).

    16

    File upload & download

    Upload through a file input or drag-and-drop zone (max 2 MB, multipart/form-data) and download CSV or JSON exports served with Content-Disposition headers.

    POST ?api=uploadGET ?api=export&format=
    Drop a file here or

    17

    Keyboard events

    Send key presses and modifier combinations. The page reports the last key and keeps a short log. Press Ctrl/⌘ + K anywhere to focus the field.

    You entered: —

      18

      Infinite scroll

      A scrollable activity feed that fetches the next page when you reach the bottom, until the end of the feed (60 items).

      GET ?api=feed&page=
        Loading…

        Loaded items: 0

        19

        API status console

        Trigger specific HTTP status codes, slow responses, a flaky endpoint (40% 503) and a client-side timeout. Use it to test error states, retries and request interception.

        GET ?api=status&code=GET ?api=slow&delay=GET ?api=flaky
        Status: — Time: —
        // Click a button to send a request
        20

        Network log

        Every request made by this page is listed here with method, endpoint, status and duration, which helps you compare what the UI did with what your test intercepted.

        0 requests
        MethodEndpointStatusTime
        { }

        API reference

        Every dummy endpoint can be called directly from RestAssured, Postman, Playwright APIRequestContext, Cypress cy.request or curl. All of them share one base URL; the endpoint goes in the api query parameter.

        Base URL
        https://klauders.com/automate-the-internet
        • JSON responses include Content-Type: application/json, Cache-Control: no-store and an X-Request-Id header that matches the requestId field in the body.
        • Every response is delayed a random 150–650 ms on purpose (except slow and export), so keep time assertions loose.
        • Errors share one shape: {"error", "message", "requestId"}. A wrong HTTP method returns 405 with an Allow header, and an unknown api value returns 404 unknown_endpoint.
        • Nothing is stored. PATCH and DELETE answer as if they worked, but a later GET returns the original data. No endpoint requires the login token.

        Authentication & registration

        Method Endpoint & query params Request body Response example Status codes
        POST
        https://klauders.com/automate-the-internet?api=auth/login

        Valid user: qa.engineer / Klauders#2026. Username locked.user returns 423; empty fields return 422.

        {
            "username": "qa.engineer",
            "password": "Klauders#2026"
        }
        {
            "token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJxYS5lbmdpbmVlciJ9.4f1c9a2b7d3e8a10",
            "expiresIn": 3600,
            "user": {
                "id": 7,
                "username": "qa.engineer",
                "name": "QA Engineer",
                "role": "QA Engineer"
            },
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK
        401invalid_credentials
        422validation_error
        423account_locked
        POST
        https://klauders.com/automate-the-internet?api=auth/logout

        Always returns 200. There is no real session to close.

        No body
        {
            "message": "Session closed.",
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK
        POST
        https://klauders.com/automate-the-internet?api=register

        Password needs 8+ characters, one uppercase letter and one number. plan: starter | team | enterprise. taken@example.com returns 409; 422 includes an errors object per field.

        {
            "fullName": "Ana Garcia",
            "email": "ana@example.com",
            "password": "Secret123",
            "country": "MX",
            "plan": "team",
            "terms": true
        }
        {
            "message": "Account created.",
            "userId": 4821,
            "email": "ana@example.com",
            "plan": "team",
            "requestId": "req_3f9a1c2b7d4e"
        }
        201Created
        409email_taken
        422validation_error

        Users

        Method Endpoint & query params Request body Response example Status codes
        GET
        https://klauders.com/automate-the-internet?api=users&page=1&perPage=8
        • q — text in name or email
        • role — Admin | QA Engineer | Developer | Product Owner | Viewer
        • status — active | inactive | pending
        • sort — id | name | email | role | status | createdAt (default id)
        • order — asc | desc (default asc)
        • page — default 1
        • perPage — 1–50 (default 8)

        48 users in total. Filters combine with AND. The response includes a meta object for pagination.

        No body
        {
            "data": [
                {
                    "id": 1,
                    "name": "Jorge Ramirez",
                    "email": "jorge.ramirez1@example.com",
                    "role": "Admin",
                    "status": "active",
                    "createdAt": "2025-01-07"
                }
            ],
            "meta": {
                "page": 1,
                "perPage": 8,
                "total": 48,
                "totalPages": 6,
                "sort": "id",
                "order": "asc"
            },
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK
        GET
        https://klauders.com/automate-the-internet?api=users&id=2
        • id — user id, 1–48

        Returns one user inside data.

        No body
        {
            "data": {
                "id": 2,
                "name": "Ana Diaz",
                "email": "ana.diaz2@example.com",
                "role": "QA Engineer",
                "status": "inactive",
                "createdAt": "2025-01-13"
            },
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK
        404not_found
        PATCH
        https://klauders.com/automate-the-internet?api=users&id=2
        • id — user id, 1–48

        status must be active, inactive or pending; any other value returns 422.

        {
            "status": "active"
        }
        {
            "data": {
                "id": 2,
                "name": "Ana Diaz",
                "email": "ana.diaz2@example.com",
                "role": "QA Engineer",
                "status": "active",
                "createdAt": "2025-01-13"
            },
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK
        404not_found
        422validation_error
        DELETE
        https://klauders.com/automate-the-internet?api=users&id=2
        • id — user id, 1–48

        User 1 is the primary admin and returns 403.

        No body
        {
            "deleted": true,
            "id": 2,
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK
        403forbidden
        404not_found

        Feed & search

        Method Endpoint & query params Request body Response example Status codes
        GET
        https://klauders.com/automate-the-internet?api=feed&page=1
        • page — 1–6 have data (10 items each)

        60 items in 6 pages. Page 7 and later return an empty data array with hasMore: false.

        No body
        {
            "data": [
                {
                    "id": 1,
                    "author": "Ana Rivera",
                    "text": "fixed a flaky test",
                    "minutesAgo": 7
                }
            ],
            "meta": {
                "page": 1,
                "hasMore": true
            },
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK
        GET
        https://klauders.com/automate-the-internet?api=search&q=sel
        • q — search text, case-insensitive

        Returns up to 8 matching tool names. An empty q returns an empty list.

        No body
        {
            "query": "sel",
            "data": [
                "Selenium WebDriver",
                "Selenium Grid"
            ],
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK

        Shop

        Method Endpoint & query params Request body Response example Status codes
        GET
        https://klauders.com/automate-the-internet?api=products

        6 products, KL-001 to KL-006. KL-005 has stock 0.

        No body
        {
            "data": [
                {
                    "sku": "KL-001",
                    "name": "Selenium Grid Hours (10h)",
                    "category": "Infrastructure",
                    "price": 49.0,
                    "stock": 25
                }
            ],
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK
        GET
        https://klauders.com/automate-the-internet?api=coupon&code=QA10
        • code — QA10 | KLAUDERS20 | EXPIRED

        The code is case-insensitive. EXPIRED returns 410; an unknown code returns 404.

        No body
        {
            "code": "QA10",
            "type": "percent",
            "value": 10,
            "expired": false,
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK
        404invalid_coupon
        410coupon_expired
        POST
        https://klauders.com/automate-the-internet?api=orders

        An empty items array returns 422 empty_cart. An unknown SKU or qty < 1 returns 400. qty above stock returns 409.

        {
            "items": [
                {
                    "sku": "KL-001",
                    "qty": 2
                }
            ],
            "customer": {
                "name": "Ana Garcia",
                "email": "ana@example.com"
            },
            "coupon": "QA10",
            "paymentMethod": "card"
        }
        {
            "orderId": "KL-9F3A1C2B",
            "status": "confirmed",
            "subtotal": 98.0,
            "discount": 9.8,
            "total": 88.2,
            "paymentMethod": "card",
            "requestId": "req_3f9a1c2b7d4e"
        }
        201Created
        400invalid_item
        409insufficient_stock
        422empty_cart / validation_error

        Jobs, files & export

        Method Endpoint & query params Request body Response example Status codes
        POST
        https://klauders.com/automate-the-internet?api=jobs

        Returns 202 Accepted with the job id to poll.

        No body
        {
            "id": "job_1759850000000",
            "status": "queued",
            "progress": 0,
            "requestId": "req_3f9a1c2b7d4e"
        }
        202Accepted
        GET
        https://klauders.com/automate-the-internet?api=jobs&id=job_1759850000000
        • id — id returned by POST ?api=jobs

        status moves from queued to running to completed in about 6.6 s; progress goes 0–100. downloadUrl appears only when completed.

        No body
        {
            "id": "job_1759850000000",
            "status": "completed",
            "progress": 100,
            "downloadUrl": "automate-the-internet.php?api=export&format=csv",
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK
        404not_found
        POST
        https://klauders.com/automate-the-internet?api=upload

        Send the file in a multipart field named file. Files over 2 MB return 413. The file is not stored; only its metadata is returned.

        Content-Type: multipart/form-data
        
        file: <binary, max 2 MB>
        {
            "fileName": "report.pdf",
            "size": 48213,
            "mimeType": "application/pdf",
            "sha1": "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
            "requestId": "req_3f9a1c2b7d4e"
        }
        201Created
        400no_file
        413file_too_large
        GET
        https://klauders.com/automate-the-internet?api=export&format=csv
        • format — csv | json (default csv)

        Returns a file download (CSV or JSON) with a Content-Disposition header instead of the usual JSON envelope.

        No body
        Content-Disposition: attachment; filename="users-export.csv"
        
        id,name,email,role,status,createdAt
        1,"Jorge Ramirez",jorge.ramirez1@example.com,Admin,active,2025-01-07
        …
        200OK

        Errors & timing

        Method Endpoint & query params Request body Response example Status codes
        GET
        https://klauders.com/automate-the-internet?api=status&code=404
        • code — 200 201 204 400 401 403 404 409 422 429 500 502 503

        Accepts any HTTP method. 204 has no body; 429 adds a Retry-After: 30 header.

        No body
        {
            "status": 404,
            "message": "Not Found",
            "requestId": "req_3f9a1c2b7d4e"
        }
        2xx–5xxrequested code
        400unsupported_code
        GET
        https://klauders.com/automate-the-internet?api=slow&delay=3
        • delay — seconds, 1–8 (default 3)

        Accepts any HTTP method. Use it to test client timeouts.

        No body
        {
            "message": "Responded after 3s.",
            "delay": 3,
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK
        GET
        https://klauders.com/automate-the-internet?api=flaky

        Accepts any HTTP method. Returns 503 about 40% of the time; use it to test retries.

        No body
        {
            "message": "Success this time.",
            "requestId": "req_3f9a1c2b7d4e"
        }
        200OK
        503service_unavailable

        Example with RestAssured (Java)

        RestAssured.baseURI = "https://klauders.com/automate-the-internet";
        
        String token =
        given()
            .contentType(ContentType.JSON)
            .queryParam("api", "auth/login")
            .body("{\"username\":\"qa.engineer\",\"password\":\"Klauders#2026\"}")
        .when()
            .post()
        .then()
            .statusCode(200)
            .header("X-Request-Id", startsWith("req_"))
            .body("user.username", equalTo("qa.engineer"))
            .extract().path("token");
        
        given()
            .queryParam("api", "users")
            .queryParam("role", "Admin")
            .queryParam("perPage", 5)
        .when()
            .get()
        .then()
            .statusCode(200)
            .body("meta.perPage", equalTo(5))
            .body("data.role", everyItem(equalTo("Admin")));

        Need a test automation framework that scales?

        Klauders designs maintainable UI and API automation with Selenium, Cypress and Playwright, integrated into your CI pipeline.

        Talk to our QA team