Files
projektuebersicht/node_modules/undici/docs/docs/api/MockPool.md
T
erikandClaude Sonnet 5 6ba93b2a92 Plan Checker, Wochenbericht-Fokus-Modus und Wandtafel-Dashboard-Feinschliff
Plan Checker (neues Studenten-Werkzeug, Seitenleiste + Admin → Plan-Checker-
Merkmale): lädt einen Bauplan als PDF hoch und lässt ChatGPT oder Claude ihn
gegen eine gepflegte Merkmalsliste prüfen. PDF-Rendering (pdf.js +
@napi-rs/canvas) berücksichtigt jetzt Ebenen (Optional Content Groups) und
WASM-Decoder korrekt, sendet eine Übersicht plus mehrere hochaufgelöste
Kachel-Ausschnitte statt eines einzelnen, zu groben Bilds, und beide Anbieter
bekommen dasselbe Bildmaterial. Jedes Prüfergebnis kann auf eines der
gesendeten Bilder als Beleg verweisen (bildIndex) — als Screenshot im
Ergebnis anklickbar, öffnet vergrößert in einem Modal statt eines von Chrome
blockierten target=_blank-Links auf eine data:-URL. KI-Modellname ist jetzt
pro Konto überschreibbar (Einstellungen → Mein Konto) für Drittanbieter mit
abweichendem Modell-Katalog.

Wochenbericht: dichte Kartenansicht bekommt einen Fokus-Modus — nur der
Kommentar liegt offen, Leistungsphasen und Beteiligte stecken in
aufklappbaren Abschnitten statt dauerhaft nebeneinander zu stehen.

Projektbereich: Terminplan-Auslastung rechnet jetzt exakt wie der
Auslastungs-Tab/die Wandtafel (statt einer unabhängigen, tageweisen
Schätzung); die LPH-Fortschrittsliste im Dashboard zeigt nur noch die
beauftragten Leistungsphasen.

Wandtafel: Dashboard-Kopf mit Kennzahlen-Reihe und Panel-Reihe neu
strukturiert, in den Blautönen des Firmenlogos; dieselbe Palette wurde
anschließend auf den gesamten App-weiten Dark Mode übernommen.

Dateibereinigung: nicht mehr benötigte Test-Uploads/Backups entfernt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-05 14:01:41 +02:00

19 KiB

MockPool

Stability: 2 - Stable

A MockPool is a Pool that intercepts requests matching registered routes and replies with mocked responses instead of contacting the network. It is created by a MockAgent and exposes the same interception API as MockClient.

A MockPool is not constructed directly in most cases; instead it is obtained through [mockAgent.get(origin)][]. Once registered as the global dispatcher, any request whose origin matches the pool is matched against the mocks it holds.

import { MockAgent } from 'undici'

const mockAgent = new MockAgent()
const mockPool = mockAgent.get('http://localhost:3000')
const { MockAgent } = require('undici')

const mockAgent = new MockAgent()
const mockPool = mockAgent.get('http://localhost:3000')

Class: MockPool

  • Extends: {Pool}

Extends Pool and implements the Interceptable interface, allowing requests made through it to be matched against registered mocks.

new MockPool(origin[, options])

  • origin {string} The origin to associate this mock pool with. It should only include the protocol, hostname, and port.
  • options {MockPoolOptions} Extends the Pool options.
  • Returns: {MockPool}

The agent option is required and must implement the Agent interface; otherwise an InvalidArgumentError is thrown.

Parameter: MockPoolOptions

Extends: PoolOptions

  • agent {MockAgent} The agent to associate this mock pool with.
  • ignoreTrailingSlash {boolean} Whether trailing slashes should be ignored when matching the path of intercepted requests. Default: false.

mockPool.intercept(options)

  • options {MockPoolInterceptOptions} The matching criteria for the requests to intercept.
  • Returns: {MockInterceptor} The interceptor used to define the mocked reply.

Registers a route on the mock pool and returns a MockInterceptor for any matching request that uses the same origin as this mock pool. The interceptor is then used to define the reply, for example with reply() or replyWithError().

Each intercept() call is consumed by a single matching request. To match more than one request, call intercept() once per expected request, or use persist() or times() on the returned MockScope. When no registered mock matches a request, a real request is attempted unless network connections have been disabled on the MockAgent, in which case a MockNotMatchedError is thrown.

A request is intercepted only when every defined matcher passes. The accepted matcher forms behave as follows:

Matcher type Condition to pass
string Exact match against the value
RegExp The expression must match
Function The function must return true

Parameter: MockPoolInterceptOptions

  • path {string|RegExp|Function} A matcher for the HTTP request path. The function form has the signature (path: string) => boolean. When a RegExp or function is used, it matches against the request path including all query parameters in alphabetical order. When a string is used, query parameters can instead be supplied through query.
  • method {string|RegExp|Function} A matcher for the HTTP request method. The function form has the signature (method: string) => boolean. Default: 'GET'.
  • body {string|RegExp|Function} A matcher for the HTTP request body. The function form has the signature (body: string) => boolean.
  • headers {Object|Function} A matcher for the HTTP request headers, given either as a map of header name to a string, RegExp, or (value: string) => boolean matcher, or as a single function that receives all headers and returns a boolean. When a map is used, the request must match every defined header; extra headers not listed here do not affect matching.
  • query {Object} A matcher for the HTTP request query string parameters. Only applies when a string was provided for path.
  • ignoreTrailingSlash {boolean} Whether a trailing slash on path is ignored when matching. Inherited from the mock pool's ignoreTrailingSlash option when not set.

Return: MockInterceptor

The reply behaviour of a matching request is defined through the returned MockInterceptor.

  • reply(statusCode[, data[, responseOptions]]) {Function} Defines the reply for a matching request.
    • statusCode {number} The status code of the mocked reply.
    • data {string|Buffer|Object|Function} The body of the mocked reply. Objects are serialized to JSON; strings and Buffers are sent as-is. The function form has the signature (opts: MockResponseCallbackOptions) => string | Buffer | Object and is invoked with the incoming request to compute the reply body.
    • responseOptions {MockResponseOptions} Additional reply options. Default: {}.
    • Returns: {MockScope}
  • reply(callback) {Function} Defines the reply for a matching request, computing all reply options dynamically rather than just the body.
    • callback {Function} A (opts: MockResponseCallbackOptions) => { statusCode, data, responseOptions } function invoked with the incoming request. The callback may be asynchronous; a returned promise is awaited and must resolve to the same shape.
    • Returns: {MockScope}
  • replyWithError(error) {Function} Defines an error for a matching request to throw.
    • error {Error} The error thrown when a request matches.
    • Returns: {MockScope}
  • defaultReplyHeaders(headers) {Function} Sets default headers included on every subsequent reply defined on this interceptor, in addition to any headers set on a specific reply.
    • headers {Object} A map of header name to value.
    • Returns: {MockInterceptor}
  • defaultReplyTrailers(trailers) {Function} Sets default trailers included on every subsequent reply defined on this interceptor, in addition to any trailers set on a specific reply.
    • trailers {Object} A map of trailer name to value.
    • Returns: {MockInterceptor}
  • replyContentLength() {Function} Sets an automatically calculated content-length header on every subsequent reply defined on this interceptor.
    • Returns: {MockInterceptor}

By default, reply() and replyWithError() define the behaviour for the first matching request only; subsequent requests are not affected unless persist() or times() is used on the returned MockScope.

Parameter: MockResponseCallbackOptions

The argument passed to the reply() data and options callbacks.

  • path {string} The path of the intercepted request.
  • method {string} The method of the intercepted request.
  • headers {Object|Headers} The headers of the intercepted request.
  • origin {string} The origin of the intercepted request.
  • body {string|null} The body of the intercepted request.

Parameter: MockResponseOptions

  • headers {Object} Headers to include on the mocked reply.
  • trailers {Object} Trailers to include on the mocked reply.

Return: MockScope

A MockScope is associated with a single MockInterceptor and configures how many times the defined reply is used.

  • delay(waitInMs) {Function} Delays the associated reply by a set amount of time.
    • waitInMs {number} The delay in milliseconds.
    • Returns: {MockScope}
  • persist() {Function} Makes the associated reply match indefinitely, so every matching request receives the defined response.
    • Returns: {MockScope}
  • times(repeatTimes) {Function} Makes the associated reply match a fixed number of times. This is overridden by persist().
    • repeatTimes {number} The number of matching requests the reply applies to.
    • Returns: {MockScope}

The following examples show common interception patterns.

import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')
mockPool.intercept({ path: '/foo' }).reply(200, 'foo')

const { statusCode, body } = await request('http://localhost:3000/foo')

console.log('response received', statusCode) // response received 200

for await (const data of body) {
  console.log('data', data.toString('utf8')) // data foo
}
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({
  path: '/echo',
  method: 'GET'
}).reply(200, ({ headers }) => ({ message: headers.message }))

const { statusCode, body } = await request('http://localhost:3000/echo', {
  headers: { message: 'hello world!' }
})

console.log('response received', statusCode) // response received 200

for await (const data of body) {
  console.log('data', data.toString('utf8')) // {"message":"hello world!"}
}
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({
  path: '/echo',
  method: 'GET'
}).reply(({ headers }) => ({
  statusCode: 200,
  data: { message: headers.message }
}))

const { statusCode, body } = await request('http://localhost:3000/echo', {
  headers: { message: 'hello world!' }
})

console.log('response received', statusCode) // response received 200

for await (const data of body) {
  console.log('data', data.toString('utf8')) // {"message":"hello world!"}
}
import { readFile } from 'node:fs/promises'
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({
  path: '/fixture',
  method: 'GET'
}).reply(async ({ path }) => ({
  statusCode: 200,
  data: await readFile(new URL('./fixture.json', import.meta.url))
}))

const { statusCode, body } = await request('http://localhost:3000/fixture')

console.log('response received', statusCode) // response received 200

for await (const data of body) {
  console.log('data', data.toString('utf8')) // contents of fixture.json
}
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({ path: '/foo', method: 'GET' }).reply(200, 'foo')
mockPool.intercept({ path: '/hello', method: 'GET' }).reply(200, 'hello')

const fooResult = await request('http://localhost:3000/foo')
for await (const data of fooResult.body) {
  console.log('data', data.toString('utf8')) // data foo
}

const helloResult = await request('http://localhost:3000/hello')
for await (const data of helloResult.body) {
  console.log('data', data.toString('utf8')) // data hello
}
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({
  path: '/foo?hello=there&see=ya',
  method: 'POST',
  body: 'form1=data1&form2=data2',
  headers: {
    'User-Agent': 'undici',
    Host: 'example.com'
  }
}).reply(200, { foo: 'bar' }, {
  headers: { 'content-type': 'application/json' },
  trailers: { 'Content-MD5': 'test' }
})

const { statusCode, headers, trailers, body } = await request(
  'http://localhost:3000/foo?hello=there&see=ya',
  {
    method: 'POST',
    body: 'form1=data1&form2=data2',
    headers: {
      foo: 'bar',
      'User-Agent': 'undici',
      Host: 'example.com'
    }
  }
)

console.log('response received', statusCode) // response received 200
console.log('headers', headers) // { 'content-type': 'application/json' }

for await (const data of body) {
  console.log('data', data.toString('utf8')) // {"foo":"bar"}
}

console.log('trailers', trailers) // { 'content-md5': 'test' }
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({
  path: '/foo',
  method: /^GET$/,
  body: (value) => value === 'form=data',
  headers: {
    'User-Agent': 'undici',
    Host: /^example\.com$/
  }
}).reply(200, 'foo')

const { statusCode, body } = await request('http://localhost:3000/foo', {
  method: 'GET',
  body: 'form=data',
  headers: {
    foo: 'bar',
    'User-Agent': 'undici',
    Host: 'example.com'
  }
})

console.log('response received', statusCode) // response received 200

for await (const data of body) {
  console.log('data', data.toString('utf8')) // data foo
}
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({
  path: '/foo',
  method: 'GET'
}).replyWithError(new Error('kaboom'))

try {
  await request('http://localhost:3000/foo', { method: 'GET' })
} catch (error) {
  console.error(error.message) // kaboom
}
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({ path: '/foo', method: 'GET' })
  .defaultReplyHeaders({ foo: 'bar' })
  .reply(200, 'foo')

const { headers } = await request('http://localhost:3000/foo')

console.log('headers', headers) // headers { foo: 'bar' }
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({ path: '/foo', method: 'GET' })
  .defaultReplyTrailers({ foo: 'bar' })
  .reply(200, 'foo')

const { trailers } = await request('http://localhost:3000/foo')

console.log('trailers', trailers) // trailers { foo: 'bar' }
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({ path: '/foo', method: 'GET' })
  .replyContentLength()
  .reply(200, 'foo')

const { headers } = await request('http://localhost:3000/foo')

console.log('headers', headers) // headers { 'content-length': '3' }
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({ path: '/foo', method: 'GET' }).reply(200, 'foo').persist()

await request('http://localhost:3000/foo') // Matches and returns the mock
await request('http://localhost:3000/foo') // Matches again, indefinitely
import { MockAgent, setGlobalDispatcher, request } from 'undici'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({ path: '/foo', method: 'GET' }).reply(200, 'foo').times(2)

await request('http://localhost:3000/foo') // Matches and returns the mock
await request('http://localhost:3000/foo') // Matches and returns the mock
await request('http://localhost:3000/foo') // No match; a real request is attempted
import { MockAgent, setGlobalDispatcher, request } from 'undici'
import querystring from 'node:querystring'

const mockAgent = new MockAgent()
setGlobalDispatcher(mockAgent)

const mockPool = mockAgent.get('http://localhost:3000')

const matchPath = (requestPath) => {
  const [pathname, search] = requestPath.split('?')
  const requestQuery = querystring.parse(search)

  if (!pathname.startsWith('/foo')) {
    return false
  }

  return requestQuery.foo === 'bar'
}

mockPool.intercept({ path: matchPath, method: 'GET' }).reply(200, 'foo')

await request('http://localhost:3000/foo?foo=bar') // Matches and returns the mock

mockPool.close()

  • Returns: {Promise} Fulfills with undefined once the mock pool is closed.

Closes the mock pool, gracefully waiting for any enqueued requests to complete, and removes it from the associated MockAgent.

import { MockAgent } from 'undici'

const mockAgent = new MockAgent()
const mockPool = mockAgent.get('http://localhost:3000')

await mockPool.close()

mockPool.dispatch(options, handlers)

  • options {DispatchOptions} The request options.
  • handlers {DispatchHandler} The handlers invoked over the request lifecycle.
  • Returns: {boolean} false if the dispatcher is busy and the caller should wait before dispatching further requests, otherwise true.

Dispatches a request, matching it against the registered mocks. This override of dispatcher.dispatch(options, handlers) is what drives the mocking behaviour for every higher-level method such as request.

mockPool.request(options[, callback])

  • options {DispatchOptions}
  • callback {Function} (optional) Invoked with the response when no Promise is requested.
  • Returns: {Promise} Fulfills with the mocked response when no callback is provided.

Performs a request and resolves it against the registered mocks. Inherited from Pool; see [dispatcher.request(options[, callback])][] for the full parameter and return value documentation.

import { MockAgent } from 'undici'

const mockAgent = new MockAgent()
const mockPool = mockAgent.get('http://localhost:3000')
mockPool.intercept({ path: '/foo', method: 'GET' }).reply(200, 'foo')

const { statusCode, body } = await mockPool.request({
  origin: 'http://localhost:3000',
  path: '/foo',
  method: 'GET'
})

console.log('response received', statusCode) // response received 200

for await (const data of body) {
  console.log('data', data.toString('utf8')) // data foo
}

mockPool.cleanMocks()

  • Returns: {undefined}

Removes all registered interceptors from the mock pool. Pending mocks defined before this call no longer match incoming requests.

import { MockAgent } from 'undici'

const mockAgent = new MockAgent()
const mockPool = mockAgent.get('http://localhost:3000')

mockPool.intercept({ path: '/foo' }).reply(200, 'foo')
mockPool.cleanMocks()

[dispatcher.request(options[, callback])]: Dispatcher.md#dispatcherrequestoptions-callback [mockAgent.get(origin)]: MockAgent.md#mockagentgetorigin