ProvenPin Install

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
pinned versions7
express@5.3.0express-validator@7.3.2@types/node@26.6.5tsx@4.23.15supertest@7.3.1@types/supertest@7.2.1@types/express@5.0.6
run it
npm install --no-audit --no-fund --ignore-scripts=false
npm test
test environment
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.

package.json
{
  "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"}
}
src/app.ts
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;
}
test/app.test.ts
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.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.