Run the bundled mock server, then automate it from REST Assured, Playwright, Python or Postman — or explore it live in the playground.
api/.htaccess serve the same routes at https://your-domain/your-folder/api/… — no port, no node. Just swap http://localhost:4000 for that base in the examples below.Both versions expose the same endpoints on http://localhost:4000.
cd automation-practice-hub/api
node mock-server.js
# -> Mock API listening on http://localhost:4000cd automation-practice-hub/api
php -S localhost:4000 mock-server.php
# -> serves the same routes on http://localhost:4000| POST | /api/login → 200 {token} for Admin/admin123, else 401 |
| GET | /api/users?page=1 → paged list |
| GET | /api/users/{id} → 200 user, or 404 |
| POST | /api/users → 201 created |
| PUT | /api/users/{id} → 200 updated |
| DELETE | /api/users/{id} → 204 |
| GET | /api/products → product list |
| GET | /api/secure → 200 with Authorization: Bearer <token>, else 401 |
| GET | /api/status/{code} → echoes that HTTP status |
import io.restassured.RestAssured;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
import org.testng.annotations.Test;
public class UsersApiTest {
@Test
public void listUsers() {
RestAssured.baseURI = "http://localhost:4000";
given()
.queryParam("page", 1)
.when()
.get("/api/users")
.then()
.statusCode(200)
.body("page", equalTo(1))
.body("data.size()", greaterThan(0))
.body("data[0].id", notNullValue());
}
}const { test, expect, request } = require('@playwright/test');
test('list users', async ({ request }) => {
const res = await request.get('http://localhost:4000/api/users?page=1');
expect(res.status()).toBe(200);
const body = await res.json();
expect(body.page).toBe(1);
expect(body.data.length).toBeGreaterThan(0);
});import requests
def test_list_users():
r = requests.get("http://localhost:4000/api/users", params={"page": 1})
assert r.status_code == 200
body = r.json()
assert body["page"] == 1
assert len(body["data"]) > 0curl -s "http://localhost:4000/api/users?page=1" | jqgiven()
.baseUri("http://localhost:4000")
.contentType("application/json")
.body("{\"name\":\"Ava\",\"job\":\"SDET\"}")
.when()
.post("/api/users")
.then()
.statusCode(201)
.body("name", equalTo("Ava"))
.body("id", notNullValue())
.body("createdAt", notNullValue());const res = await request.post('http://localhost:4000/api/users', {
data: { name: 'Ava', job: 'SDET' }
});
expect(res.status()).toBe(201);
const body = await res.json();
expect(body.name).toBe('Ava');r = requests.post("http://localhost:4000/api/users",
json={"name": "Ava", "job": "SDET"})
assert r.status_code == 201
assert r.json()["name"] == "Ava"// 1) login
String token =
given().contentType("application/json")
.body("{\"username\":\"Admin\",\"password\":\"admin123\"}")
.when().post("http://localhost:4000/api/login")
.then().statusCode(200).extract().path("token");
// 2) call the protected endpoint
given().header("Authorization", "Bearer " + token)
.when().get("http://localhost:4000/api/secure")
.then().statusCode(200).body("message", containsString("granted"));
// 3) negative: no token -> 401
given().when().get("http://localhost:4000/api/secure")
.then().statusCode(401);login = requests.post("http://localhost:4000/api/login",
json={"username": "Admin", "password": "admin123"})
token = login.json()["token"]
ok = requests.get("http://localhost:4000/api/secure",
headers={"Authorization": f"Bearer {token}"})
assert ok.status_code == 200
denied = requests.get("http://localhost:4000/api/secure")
assert denied.status_code == 401Import postman_collection.json (included in the api/ folder). Run the whole suite headless from CI with newman:
npm install -g newman
newman run api/postman_collection.json \
--env-var "baseUrl=http://localhost:4000"/api/status/{code} to force 4xx/5xx responses, and /api/users/9999 to get a real 404 — handy for asserting error bodies and retry logic.