express-validator request checks with supertest: working versions (tested 2026-10-15)
Validate Express JSON bodies and query params with express-validator, returning field errors, tested with supertest offline.
passed3 passed · 0 failed2026-10-15 15:59 UTC- Status
- passed
- Last passed
- 2026-10-15 15:59 UTC
- Tests
- 3 / 3
- Language
- TypeScript
- Runtime
- node v22.23.3
npm install --no-audit --no-fund --ignore-scripts=false npm test
node v22.23.3 linux 6.17.0-1022-azure x64 runner: github-actions 38764699834
The code
Exactly the files that passed. Your agent can pull them with get_recipe("express-validator-supertest") (install), or see them on GitHub.
{
"name": "express-validator-supertest",
"private": true,
"type": "module",
"scripts": {
"test": "node --import tsx --test test/*.test.ts"
},
"dependencies": {"express":"5.3.0","express-validator":"7.3.2"},
"devDependencies": {"@types/node":"26.6.5","tsx":"4.23.15","supertest":"7.3.1","@types/supertest":"7.2.1","@types/express":"5.0.6"}
}
import express from "express";
import { body, query, validationResult, matchedData } from "express-validator";
export function createApp() {
const app = express();
app.use(express.json());
app.post(
"/users",
body("email").isEmail().withMessage("email invalid"),
body("age").isInt({ min: 18 }).withMessage("age must be 18+").toInt(),
body("name").trim().notEmpty().withMessage("name required"),
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
return res.status(201).json({ ok: true, user: matchedData(req) });
},
);
app.get(
"/search",
query("q").trim().isLength({ min: 2 }).withMessage("q too short"),
query("limit").optional().isInt({ min: 1, max: 50 }).toInt(),
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const data = matchedData(req);
return res.json({ q: data.q, limit: data.limit ?? 10 });
},
);
return app;
}
import { test } from "node:test";
import assert from "node:assert/strict";
import request from "supertest";
import { createApp } from "../src/app.ts";
test("rejects invalid user body", async () => {
const res = await request(createApp()).post("/users").send({ email: "nope", age: 12, name: "" });
assert.equal(res.status, 400);
assert.ok(Array.isArray(res.body.errors));
assert.ok(res.body.errors.length >= 2);
});
test("creates user when valid", async () => {
const res = await request(createApp())
.post("/users")
.send({ email: "[email protected]", age: "30", name: " Ada " });
assert.equal(res.status, 201);
assert.equal(res.body.user.email, "[email protected]");
assert.equal(res.body.user.age, 30);
assert.equal(res.body.user.name, "Ada");
});
test("validates search query", async () => {
const bad = await request(createApp()).get("/search").query({ q: "a" });
assert.equal(bad.status, 400);
const ok = await request(createApp()).get("/search").query({ q: "ad", limit: "5" });
assert.equal(ok.status, 200);
assert.deepEqual(ok.body, { q: "ad", limit: 5 });
});
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.
Related stacks
Express 5 + express-session login flow, e2e-style over real HTTP with a cookie jar
Session login/logout with express-session (regenerate on login, httpOnly cookies), tested end to end against a real listening server using fetch-cookie, no browser or Playwright.
Express 5 + Helmet + express-rate-limit hardening
Add security headers with Helmet and per-IP rate limiting with express-rate-limit to an Express 5 API.
Express 5 + jsonwebtoken auth middleware
Issue HS256 JWTs on login and protect routes with a bearer-token middleware.
Express 5 + Multer 2 file uploads with limits
Accept multipart file uploads in Express 5 with Multer memory storage, size limits and a MIME type filter.
All Express recipesAll express-validator recipesAll supertest recipes