expressjs/expressMIT9a34acfReport / request removal

Test Suite Structure

The test suite is organized around two complementary questions: does an individual Express API surface behave correctly, and does a complete example application behave correctly over HTTP? Unit-style files sit under test/, while acceptance files sit under test/acceptance/ and load applications from examples/.

This split exists because isolated tests can focus on one API contract, while acceptance tests verify that routing, middleware, request handling, and response generation work together in a real request/response cycle. The shared helpers in test/support/ keep repeated response checks and environment-specific conditions out of individual test cases.

Sources: test/res.cookie.js:278-291, test/support/utils.js:28-36, test/support/utils.js:45-49, test/support/utils.js:79-85

Core concepts

API-surface test file

An API-surface test file names the Express behavior it exercises, such as res.cookie.js for response cookies or res.status.js for response status handling.

Sources: test/res.cookie.js:278-291, test/res.status.js:20-43

Acceptance test

An acceptance test loads an application from examples/ and drives it with supertest, rather than constructing only the smallest possible unit under test.

Sources: test/acceptance/hello-world.js:2, test/acceptance/hello-world.js:3

Shared support helper

A shared support helper is a reusable assertion or compatibility function in test/support/utils.js, such as a body matcher, header matcher, or Node-version gate.

Sources: test/support/utils.js:28-36, test/support/utils.js:45-49, test/support/utils.js:79-85

Test subject

The test subject is either the package imported as express or an example application imported as app. Unit files import the package through require('..'), while acceptance files can import a specific application from ../../examples/....

Sources: test/app.js:4, test/acceptance/hello-world.js:2

How files map to behavior

The naming convention is API-oriented: the filename identifies the surface under test, and the test body creates an application, sends a request, and asserts the result. The shown res.cookie.js file exercises a signed cookie response, while res.status.js checks valid response status codes such as 101 and 201.

Test fileBehavior named by the fileObservable check
res.cookie.jsResponse cookie behaviorExact Set-Cookie header and status 200
res.status.jsResponse status behaviorStatus 101 or 201
app.jsApplication-level behaviorUses express and supertest
config.jsConfiguration behaviorDefines callback functions used by configuration tests

The file name is therefore a navigation aid, not merely a descriptive label: an engineer looking for cookie behavior can start at test/res.cookie.js, while status behavior is grouped in test/res.status.js. The excerpts show the tests using express() to create an application, registering behavior with app.use, and sending a request through request(app).

Unit-level files also cover configuration and application behavior through the package entry point. test/app.js imports assert, express, and request, and test/config.js imports assert and express; the catalog also shows several callback fixtures named fn, fn1, and fn2.

Sources: test/res.cookie.js:278-291, test/res.status.js:20-43, test/app.js:3, test/app.js:4, test/app.js:5, test/config.js:49, test/config.js:123, test/config.js:124, test/config.js:3, test/config.js:4

How acceptance tests reuse examples

An acceptance file begins by requiring an application from examples/ and requiring supertest. In test/acceptance/hello-world.js, the application comes from ../../examples/hello-world; the same structure appears in test/acceptance/vhost.js, which loads ../../examples/vhost.

The test then sends HTTP-shaped requests against the loaded application. The vhost acceptance test performs GET /, sets the Host header to example.com, and expects status 200 with a body matching hello; its /foo case uses the same host and expects the body requested foo.

This is a real request/response exercise because the test supplies method, path, and headers to supertest, then verifies the returned status and body. The example application remains the assembled subject, so the acceptance test checks the behavior that emerges from the example’s route and host configuration rather than only checking one isolated function.

The setup relationship is summarized below.

Acceptance test setup — How does an acceptance file connect an example app to HTTP assertions?

Evidence

The workflow shows the boundary between the acceptance file, the example application, and the request client: the file imports both pieces, then the client is used to observe the application’s HTTP result.

Sources: test/acceptance/hello-world.js:2, test/acceptance/hello-world.js:3, test/acceptance/vhost.js:1-3, test/acceptance/vhost.js:7-21

What shared support provides

The support module centralizes response assertions so individual tests can express expectations without repeating buffer conversion, header-name normalization, or absence checks. shouldHaveBody accepts a buffer and returns a response callback; it uses res.body when available, otherwise converts res.text with Buffer.from, then compares hexadecimal representations.

Header assertions follow the same callback pattern. shouldHaveHeader checks for a lowercased header name in res.headers, while shouldNotHaveHeader asserts that the header is absent; this keeps positive and negative header checks symmetrical.

The support module also provides negative body checking through shouldNotHaveBody, which accepts a response and asserts that res.text is either an empty string or undefined.

Finally, getMajorVersion and shouldSkipQuery isolate a runtime compatibility rule. getMajorVersion extracts the first dot-separated part of a version string, and shouldSkipQuery converts that result to a number and returns whether it is below 22.

The helper call shape is deliberately small: each assertion helper returns a function that receives res, allowing it to fit into request assertions while keeping the detailed comparison in one place.

Shared response matcher — What does a support matcher do before an assertion completes?

Evidence

The sequence captures the helper’s visible contract: a test obtains a matcher, the matcher receives res, and the matcher delegates the result check to assert.

Sources: test/support/utils.js:28-36, test/support/utils.js:45-49, test/support/utils.js:69-73, test/support/utils.js:57-61, test/support/utils.js:75-77, test/support/utils.js:79-85, test/support/utils.js:7

How it connects

Unit tests connect directly to the Express package entry point through require('..'), while acceptance tests connect to concrete applications under examples/. This makes the suite a companion to Express Overview and Repository Layout & Contributing: the first explains the package entry point, and the second explains where tests and examples fit in the repository.

The request client and response assertions connect this page to Acceptance Test Suite, which covers how example applications are booted and exercised end to end. The API-focused files connect to Response: Headers, Cookies & Redirects and Response: Sending Data, because the examples shown here validate response headers, cookies, bodies, and status codes.

The support helpers also provide the test vocabulary used while checking request and response behavior, complementing The Request Object and Utility Helpers. Their Node-version condition specifically affects tests for the QUERY method, so it belongs with the suite’s compatibility behavior rather than with an individual API file.

Sources: test/app.js:4, test/acceptance/hello-world.js:2, test/support/utils.js:79-85

Key takeaways

  • API-focused files use names such as res.cookie.js and res.status.js to identify the behavior under test.
  • Acceptance files load applications from examples/ and use supertest to drive HTTP-shaped requests.
  • Host, path, status, and body assertions can verify a complete example request/response cycle.
  • test/support/utils.js centralizes body, header, and compatibility checks.

Sources: test/res.cookie.js:278-291, test/res.status.js:20-43, test/acceptance/hello-world.js:2, test/acceptance/hello-world.js:3, test/acceptance/vhost.js:7-21, test/support/utils.js:28-36, test/support/utils.js:45-49, test/support/utils.js:57-61, test/support/utils.js:69-73, test/support/utils.js:79-85

Want this for your repos?

Try Angada AI Wiki