mockserver-client
Version:
A node client for the MockServer
999 lines (960 loc) • 164 kB
JavaScript
/*
* mockserver
* http://mock-server.com
*
* Copyright (c) 2014 James Bloom
* Licensed under the Apache License, Version 2.0
*/
var mockServerClient;
(function () {
"use strict";
// ------------------------------------------------------------------
// Inline breakpoint/callback message routing (browser-safe, no deps)
// ------------------------------------------------------------------
// These are pure functions duplicated from webSocketClient.js so they
// are available in the browser path where require() does not exist.
// The Node path (webSocketClient.js) keeps its own copy.
//
// Defined at IIFE scope (not inside the factory function) so they can
// be exported for unit testing without changing runtime behaviour.
/**
* Extract the breakpoint id and correlation id from a headers map.
* Headers may use canonical or lowercase names and values may be
* arrays or plain strings.
*/
var _extractBreakpointHeaders = function (headers) {
var breakpointId = null;
var correlationId = null;
if (headers) {
for (var hk in headers) {
if (headers.hasOwnProperty(hk)) {
if (hk === "X-MockServer-BreakpointId" || hk === "x-mockserver-breakpointid") {
breakpointId = Array.isArray(headers[hk]) ? headers[hk][0] : headers[hk];
}
if (hk === "WebSocketCorrelationId" || hk === "websocketcorrelationid") {
correlationId = Array.isArray(headers[hk]) ? headers[hk][0] : headers[hk];
}
}
}
}
return { breakpointId: breakpointId, correlationId: correlationId };
};
/**
* Pure function that routes a WebSocket breakpoint/callback message to
* the appropriate handler and produces the reply envelope.
*
* @param {Object} payload { type: string, value: string (JSON) }
* @param {Object} handlers map of handler collections
* @return {Object|null} reply envelope or null
*/
var _routeBreakpointMessage = function (payload, handlers) {
handlers = handlers || {};
var breakpointRequestHandlers = handlers.breakpointRequestHandlers || {};
var breakpointResponseHandlers = handlers.breakpointResponseHandlers || {};
var breakpointStreamFrameHandlers = handlers.breakpointStreamFrameHandlers || {};
var requestHandler = handlers.requestHandler || null;
var requestAndResponseHandler = handlers.requestAndResponseHandler || null;
if (payload.type === "org.mockserver.model.HttpRequest") {
var request = JSON.parse(payload.value);
var reqHeaders = _extractBreakpointHeaders(request.headers);
var breakpointId = reqHeaders.breakpointId;
var correlationId = reqHeaders.correlationId;
var bpReqHandler = breakpointId ? breakpointRequestHandlers[breakpointId] : null;
if (bpReqHandler) {
try {
var bpResult = bpReqHandler(request);
if (bpResult === null || bpResult === undefined) {
bpResult = request; // auto-continue
}
if (correlationId) {
if (!bpResult.headers) { bpResult.headers = {}; }
bpResult.headers["WebSocketCorrelationId"] = Array.isArray(correlationId) ? correlationId : [correlationId];
}
var bpResultType = bpResult.statusCode !== undefined
? "org.mockserver.model.HttpResponse"
: "org.mockserver.model.HttpRequest";
return {
type: bpResultType,
value: JSON.stringify(bpResult)
};
} catch (e) {
// auto-continue on error
if (!request.headers) { request.headers = {}; }
if (correlationId) {
request.headers["WebSocketCorrelationId"] = Array.isArray(correlationId) ? correlationId : [correlationId];
}
return {
type: "org.mockserver.model.HttpRequest",
value: JSON.stringify(request)
};
}
} else if (requestHandler) {
return requestHandler(request);
}
// breakpoint message with no matching handler — auto-continue
if (correlationId) {
if (!request.headers) { request.headers = {}; }
request.headers["WebSocketCorrelationId"] = Array.isArray(correlationId) ? correlationId : [correlationId];
return {
type: "org.mockserver.model.HttpRequest",
value: JSON.stringify(request)
};
}
return null;
} else if (payload.type === "org.mockserver.model.HttpRequestAndHttpResponse") {
var requestAndResponse = JSON.parse(payload.value);
var respHeaders = _extractBreakpointHeaders(
requestAndResponse.httpRequest ? requestAndResponse.httpRequest.headers : null
);
var bpId2 = respHeaders.breakpointId;
var corrId2 = respHeaders.correlationId;
var bpRespHandler = bpId2 ? breakpointResponseHandlers[bpId2] : null;
if (bpRespHandler) {
try {
var bpResp = bpRespHandler(requestAndResponse.httpRequest, requestAndResponse.httpResponse);
if (bpResp === null || bpResp === undefined) {
bpResp = requestAndResponse.httpResponse; // auto-continue
}
if (corrId2) {
if (!bpResp.headers) { bpResp.headers = {}; }
bpResp.headers["WebSocketCorrelationId"] = Array.isArray(corrId2) ? corrId2 : [corrId2];
}
return {
type: "org.mockserver.model.HttpResponse",
value: JSON.stringify(bpResp)
};
} catch (e) {
// auto-continue on error
var origResp = requestAndResponse.httpResponse || {};
if (corrId2) {
if (!origResp.headers) { origResp.headers = {}; }
origResp.headers["WebSocketCorrelationId"] = Array.isArray(corrId2) ? corrId2 : [corrId2];
}
return {
type: "org.mockserver.model.HttpResponse",
value: JSON.stringify(origResp)
};
}
} else if (requestAndResponseHandler) {
return requestAndResponseHandler(requestAndResponse);
}
// auto-continue with original response
if (corrId2) {
var origResp2 = requestAndResponse.httpResponse || {};
if (!origResp2.headers) { origResp2.headers = {}; }
origResp2.headers["WebSocketCorrelationId"] = Array.isArray(corrId2) ? corrId2 : [corrId2];
return {
type: "org.mockserver.model.HttpResponse",
value: JSON.stringify(origResp2)
};
}
return null;
} else if (payload.type === "org.mockserver.serialization.model.PausedStreamFrameDTO") {
var pausedFrame = JSON.parse(payload.value);
var sfBpId = pausedFrame.breakpointId;
var sfHandler = sfBpId ? breakpointStreamFrameHandlers[sfBpId] : null;
var decision;
if (sfHandler) {
try {
decision = sfHandler(pausedFrame);
if (decision === null || decision === undefined) {
decision = { correlationId: pausedFrame.correlationId, action: "CONTINUE" };
} else {
decision.correlationId = pausedFrame.correlationId; // ensure echoed
}
} catch (e) {
decision = { correlationId: pausedFrame.correlationId, action: "CONTINUE" };
}
} else {
// auto-continue for unknown breakpoint id
decision = { correlationId: pausedFrame.correlationId, action: "CONTINUE" };
}
return {
type: "org.mockserver.serialization.model.StreamFrameDecisionDTO",
value: JSON.stringify(decision)
};
}
// WebSocketClientIdDTO or unknown types — not routed
return null;
};
/**
* Start the client communicating at the specified host and port
*, for example:
*
* var client = mockServerClient("localhost", 1080);
*
* @param host the host for the server to communicate with
* @param port the port for the server to communicate with
* @param contextPath the context path if server was deployed as a war i.e. '/myContextPath'
* @param tls enable TLS (i.e. HTTPS) for communication to server
* @param caCertPemFilePath provide custom CA Certificate (defaults to MockServer CA Certificate)
* @param options optional control-plane auth + mTLS settings:
* {
* bearerToken, // static control-plane JWT attached as `Authorization: Bearer <token>`
* bearerTokenSupplier, // function() => string, evaluated per-request (overrides bearerToken)
* clientCertPemFilePath, // PEM client certificate for mutual TLS
* clientKeyPemFilePath // PEM private key for mutual TLS
* }
*/
mockServerClient = function (host, port, contextPath, tls, caCertPemFilePath, options) {
var runningInNode = function () {
return (typeof require !== 'undefined') && require('browser-or-node').isNode;
};
// LLM mocking builder factories (browser-safe): in Node use require,
// in the browser fall back to the global set by llm.js.
var _llm = (typeof require !== 'undefined') ? require('./llm') : (typeof window !== 'undefined' ? window.mockServerLlm : undefined);
// MCP (Model Context Protocol) mock builder factory (browser-safe): in
// Node use require, in the browser fall back to the global set by
// mcpMockBuilder.js.
var _mcpMock = (typeof require !== 'undefined') ? require('./mcpMockBuilder').mcpMock : (typeof window !== 'undefined' ? (window.mockServerMcp && window.mockServerMcp.mcpMock) : undefined);
// A2A (Agent-to-Agent) mock builder factory (browser-safe): in Node use
// require, in the browser fall back to the global set by a2aMockBuilder.js.
var _a2aMock = (typeof require !== 'undefined') ? require('./a2aMockBuilder').a2aMock : (typeof window !== 'undefined' ? (window.mockServerA2a && window.mockServerA2a.a2aMock) : undefined);
// Resolve the control-plane bearer token (static or supplier) for the
// browser (XMLHttpRequest) transport path. The Node transport resolves
// it per-request inside sendRequest.js.
var _resolveBrowserBearerToken = function () {
if (!options) {
return null;
}
var token = null;
if (typeof options.bearerTokenSupplier === 'function') {
token = options.bearerTokenSupplier();
} else if (options.bearerToken !== undefined && options.bearerToken !== null) {
token = options.bearerToken;
}
if (token === undefined || token === null || token === '') {
return null;
}
return String(token);
};
var _setBrowserAuthHeader = function (xmlhttp) {
var token = _resolveBrowserBearerToken();
if (token) {
xmlhttp.setRequestHeader("Authorization", "Bearer " + token);
}
};
var makeRequest = (runningInNode() ? require('./sendRequest').sendRequest(tls, caCertPemFilePath, options) : function (host, port, path, jsonBody) {
var body = (typeof jsonBody === "string" ? jsonBody : JSON.stringify(jsonBody || ""));
var url = (tls ? 'https' : 'http') + '://' + host + ':' + port + (contextPath ? (contextPath.indexOf("/") === 0 ? contextPath : "/" + contextPath) : "") + path;
return {
then: function (sucess, error) {
try {
var xmlhttp = new XMLHttpRequest();
xmlhttp.addEventListener("load", (function (sucess, error) {
return function () {
if (error && this.status >= 400 && this.status < 600) {
if (this.statusCode === 404) {
error("404 Not Found");
} else {
error(this.responseText);
}
} else {
if (sucess) {
sucess({
statusCode: this.status,
body: this.responseText
});
}
}
};
})(sucess, error));
xmlhttp.open('PUT', url);
xmlhttp.setRequestHeader("Content-Type", "application/json; charset=utf-8");
_setBrowserAuthHeader(xmlhttp);
xmlhttp.send(body);
} catch (e) {
if (error) {
error(e);
}
}
}
};
});
var makeGetRequest = (runningInNode() ? require('./sendRequest').sendGetRequest(tls, caCertPemFilePath, options) : function (host, port, path) {
var url = (tls ? 'https' : 'http') + '://' + host + ':' + port + (contextPath ? (contextPath.indexOf("/") === 0 ? contextPath : "/" + contextPath) : "") + path;
return {
then: function (sucess, error) {
try {
var xmlhttp = new XMLHttpRequest();
xmlhttp.addEventListener("load", (function (sucess, error) {
return function () {
if (error && this.status >= 400 && this.status < 600) {
if (this.statusCode === 404) {
error("404 Not Found");
} else {
error(this.responseText);
}
} else {
if (sucess) {
sucess({
statusCode: this.status,
body: this.responseText
});
}
}
};
})(sucess, error));
xmlhttp.open('GET', url);
_setBrowserAuthHeader(xmlhttp);
xmlhttp.send();
} catch (e) {
if (error) {
error(e);
}
}
}
};
});
var makeBinaryRequest = (runningInNode() ? require('./sendRequest').sendBinaryRequest(tls, caCertPemFilePath, options) : function (host, port, path, bodyBuffer, contentType) {
var url = (tls ? 'https' : 'http') + '://' + host + ':' + port + (contextPath ? (contextPath.indexOf("/") === 0 ? contextPath : "/" + contextPath) : "") + path;
return {
then: function (sucess, error) {
try {
var xmlhttp = new XMLHttpRequest();
xmlhttp.addEventListener("load", (function (sucess, error) {
return function () {
if (error && this.status >= 400 && this.status < 600) {
if (this.statusCode === 404) {
error("404 Not Found");
} else {
error(this.responseText);
}
} else {
if (sucess) {
sucess({
statusCode: this.status,
body: this.responseText
});
}
}
};
})(sucess, error));
xmlhttp.open('PUT', url);
xmlhttp.setRequestHeader("Content-Type", contentType || "application/octet-stream");
_setBrowserAuthHeader(xmlhttp);
xmlhttp.send(bodyBuffer);
} catch (e) {
if (error) {
error(e);
}
}
}
};
});
var makeDeleteRequest = (runningInNode() ? require('./sendRequest').sendDeleteRequest(tls, caCertPemFilePath, options) : function (host, port, path) {
var url = (tls ? 'https' : 'http') + '://' + host + ':' + port + (contextPath ? (contextPath.indexOf("/") === 0 ? contextPath : "/" + contextPath) : "") + path;
return {
then: function (sucess, error) {
try {
var xmlhttp = new XMLHttpRequest();
xmlhttp.addEventListener("load", (function (sucess, error) {
return function () {
if (error && this.status >= 400 && this.status < 600) {
if (this.statusCode === 404) {
error("404 Not Found");
} else {
error(this.responseText);
}
} else {
if (sucess) {
sucess({
statusCode: this.status,
body: this.responseText
});
}
}
};
})(sucess, error));
xmlhttp.open('DELETE', url);
_setBrowserAuthHeader(xmlhttp);
xmlhttp.send();
} catch (e) {
if (error) {
error(e);
}
}
}
};
});
// PUT that resolves {statusCode, body} for EVERY status (never rejects on
// 4xx). Used by control-plane helpers whose non-2xx responses are expected
// outcomes carrying a meaningful body (files/retrieve 404, pact/verify 406).
var makeRawRequest = (runningInNode() ? require('./sendRequest').sendRawRequest(tls, caCertPemFilePath, options) : function (host, port, path, body, contentType) {
var requestBody = (typeof body === "string" ? body : JSON.stringify(body || ""));
var url = (tls ? 'https' : 'http') + '://' + host + ':' + port + (contextPath ? (contextPath.indexOf("/") === 0 ? contextPath : "/" + contextPath) : "") + path;
return {
then: function (sucess, error) {
try {
var xmlhttp = new XMLHttpRequest();
xmlhttp.addEventListener("load", (function (sucess) {
return function () {
if (sucess) {
sucess({
statusCode: this.status,
body: this.responseText
});
}
};
})(sucess));
xmlhttp.open('PUT', url);
xmlhttp.setRequestHeader("Content-Type", contentType || "application/json; charset=utf-8");
_setBrowserAuthHeader(xmlhttp);
xmlhttp.send(requestBody);
} catch (e) {
if (error) {
error(e);
}
}
}
};
});
var cleanedContextPath = (function (contextPath) {
if (contextPath) {
if (!contextPath.endsWith("/")) {
contextPath += "/";
}
if (!contextPath.startsWith("/")) {
contextPath = "/" + contextPath;
}
return contextPath;
} else {
return '';
}
})(contextPath);
/**
* The default headers added to to the mocked response when using mockSimpleResponse(...)
*/
var defaultResponseHeaders;
var defaultRequestHeaders;
var headersUniqueConcatenate = function (arrayTarget, arraySource) {
if (!arrayTarget) {
arrayTarget = arraySource;
} else if (Array.isArray(arrayTarget) && Array.isArray(arraySource)) {
if (arraySource && arraySource.length) {
if (arrayTarget && arrayTarget.length) {
for (var i = 0; i < arraySource.length; i++) {
var arrayTargetAlreadyHasValue = false;
for (var j = 0; j < arrayTarget.length; j++) {
if (JSON.stringify(arraySource[i]) === JSON.stringify(arrayTarget[j])) {
arrayTargetAlreadyHasValue = true;
}
}
if (!arrayTargetAlreadyHasValue) {
arrayTarget.push(arraySource[i]);
}
}
} else {
arrayTarget = arraySource;
}
}
} else if (!Array.isArray(arrayTarget) && Array.isArray(arraySource)) {
arraySource.forEach(function (entry) {
arrayTarget[entry["name"]] = entry["values"];
});
} else if (Array.isArray(arrayTarget) && !Array.isArray(arraySource)) {
for (var property in arraySource) {
if (arraySource.hasOwnProperty(property)) {
arrayTarget.push({"name": property, "values": arraySource[property]});
}
}
} else if (!Array.isArray(arrayTarget) && !Array.isArray(arraySource)) {
arrayTarget = Object.assign(arrayTarget, arraySource);
}
return arrayTarget;
};
var createRequestMatcher = function (path) {
return {
method: "",
path: path,
body: "",
headers: defaultRequestHeaders,
cookies: [],
queryStringParameters: []
};
};
var createExpectation = function (path, responseBody, statusCode) {
return {
httpRequest: createRequestMatcher(path),
httpResponse: {
statusCode: statusCode || 200,
body: JSON.stringify(responseBody),
cookies: [],
headers: defaultResponseHeaders,
delay: {
timeUnit: "MICROSECONDS",
value: 0
}
},
times: {
remainingTimes: 1,
unlimited: false
}
};
};
var createExpectationWithCallback = function (requestMatcher, clientId, times, priority, timeToLive, id) {
var timesObject;
if (typeof times === 'number') {
timesObject = {
remainingTimes: times,
unlimited: false
};
} else if (typeof times === 'object') {
timesObject = times;
}
requestMatcher.headers = headersUniqueConcatenate(requestMatcher.headers, defaultRequestHeaders);
return {
id: typeof id === 'string' ? id : undefined,
priority: typeof priority === 'number' ? priority : undefined,
httpRequest: requestMatcher,
httpResponseObjectCallback: {
clientId: clientId
},
times: timesObject || {
remainingTimes: 1,
unlimited: false
},
timeToLive: typeof timeToLive === 'object' ? timeToLive : {
unlimited: true
}
};
};
var createExpectationWithForwardCallback = function (requestMatcher, clientId, times, priority, timeToLive, id) {
var timesObject;
if (typeof times === 'number') {
timesObject = {
remainingTimes: times,
unlimited: false
};
} else if (typeof times === 'object') {
timesObject = times;
}
requestMatcher.headers = headersUniqueConcatenate(requestMatcher.headers, defaultRequestHeaders);
return {
id: typeof id === 'string' ? id : undefined,
priority: typeof priority === 'number' ? priority : undefined,
httpRequest: requestMatcher,
httpForwardObjectCallback: {
clientId: clientId
},
times: timesObject || {
remainingTimes: 1,
unlimited: false
},
timeToLive: typeof timeToLive === 'object' ? timeToLive : {
unlimited: true
}
};
};
var createExpectationWithForwardAndResponseCallback = function (requestMatcher, clientId, times, priority, timeToLive, id) {
var timesObject;
if (typeof times === 'number') {
timesObject = {
remainingTimes: times,
unlimited: false
};
} else if (typeof times === 'object') {
timesObject = times;
}
requestMatcher.headers = headersUniqueConcatenate(requestMatcher.headers, defaultRequestHeaders);
return {
id: typeof id === 'string' ? id : undefined,
priority: typeof priority === 'number' ? priority : undefined,
httpRequest: requestMatcher,
httpForwardObjectCallback: {
clientId: clientId,
responseCallback: true
},
times: timesObject || {
remainingTimes: 1,
unlimited: false
},
timeToLive: typeof timeToLive === 'object' ? timeToLive : {
unlimited: true
}
};
};
var WebSocketClient = (runningInNode() ? require('./webSocketClient').webSocketClient(tls, caCertPemFilePath) : function (host, port, contextPath) {
var clientId;
var clientIdHandler;
var requestHandler;
var requestAndResponseHandler;
var breakpointRequestHandlers = {};
var breakpointResponseHandlers = {};
var breakpointStreamFrameHandlers = {};
var browserWebSocket;
return {
then: function (sucess, error) {
try {
if (typeof (window) !== "undefined") {
if (window.WebSocket) {
browserWebSocket = window.WebSocket;
} else if (window.MozWebSocket) {
browserWebSocket = window.MozWebSocket;
} else {
error("Your browser does not support web sockets.");
}
}
if (browserWebSocket) {
var webSocketLocation = (tls ? "wss" : "ws") + "://" + host + ":" + port + contextPath + "/_mockserver_callback_websocket";
var socket = new WebSocket(webSocketLocation);
socket.onmessage = function (event) {
var message = JSON.parse(event.data);
// Handle client-id registration directly
if (message.type === "org.mockserver.serialization.model.WebSocketClientIdDTO") {
var registration = JSON.parse(message.value);
if (registration.clientId) {
clientId = registration.clientId;
if (clientIdHandler) {
clientIdHandler(clientId);
}
}
return;
}
// Route breakpoint / callback messages via the shared pure function
var reply = _routeBreakpointMessage(message, {
breakpointRequestHandlers: breakpointRequestHandlers,
breakpointResponseHandlers: breakpointResponseHandlers,
breakpointStreamFrameHandlers: breakpointStreamFrameHandlers,
requestHandler: requestHandler,
requestAndResponseHandler: requestAndResponseHandler
});
if (reply && socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify(reply));
}
};
socket.onopen = function (event) {
};
socket.onclose = function (event) {
};
}
sucess({
requestCallback: function requestCallback(callback) {
requestHandler = callback;
},
requestAndResponseCallback: function requestAndResponseCallback(callback) {
requestAndResponseHandler = callback;
},
clientIdCallback: function clientIdCallback(callback) {
clientIdHandler = callback;
if (clientId) {
clientIdHandler(clientId);
}
},
setBreakpointRequestHandler: function (breakpointId, handler) {
if (breakpointId && handler) { breakpointRequestHandlers[breakpointId] = handler; }
},
setBreakpointResponseHandler: function (breakpointId, handler) {
if (breakpointId && handler) { breakpointResponseHandlers[breakpointId] = handler; }
},
setBreakpointStreamFrameHandler: function (breakpointId, handler) {
if (breakpointId && handler) { breakpointStreamFrameHandlers[breakpointId] = handler; }
},
removeBreakpointHandlers: function (breakpointId) {
if (breakpointId) {
delete breakpointRequestHandlers[breakpointId];
delete breakpointResponseHandlers[breakpointId];
delete breakpointStreamFrameHandlers[breakpointId];
}
},
clearBreakpointHandlers: function () {
breakpointRequestHandlers = {};
breakpointResponseHandlers = {};
breakpointStreamFrameHandlers = {};
}
});
} catch (e) {
if (error) {
error(e);
}
}
}
};
});
/**
* Override:
*
* - default headers that are used to specify the response headers in mockSimpleResponse(...)
* (note: if you use mockAnyResponse(...) the default headers are not used)
*
* - headers added to every request matcher, this is particularly useful for running tests in parallel
*
*, for example:
*
* client.setDefaultHeaders([
* {"name": "Content-Type", "values": ["application/json; charset=utf-8"]},
* {"name": "Cache-Control", "values": ["no-cache, no-store"]}
* ],[
* {"name": "sessionId", "values": ["786fcf9b-606e-605f-181d-c245b55e5eac"]}
* ])
*
* @param responseHeaders the default headers to be added to every response
* @param requestHeaders the default headers to be added to every request matcher
*/
var setDefaultHeaders = function (responseHeaders, requestHeaders) {
if (responseHeaders) {
defaultResponseHeaders = responseHeaders;
}
if (requestHeaders) {
defaultRequestHeaders = requestHeaders;
}
return _this;
};
var addDefaultRequestMatcherHeaders = function (pathOrRequestMatcher) {
var requestMatcher;
if (typeof pathOrRequestMatcher === "string") {
requestMatcher = {
path: pathOrRequestMatcher
};
} else if (typeof pathOrRequestMatcher === "object") {
requestMatcher = pathOrRequestMatcher;
} else {
requestMatcher = {};
}
if (defaultRequestHeaders) {
if (requestMatcher.httpRequest) {
requestMatcher.httpRequest.headers = headersUniqueConcatenate(requestMatcher.httpRequest.headers, defaultRequestHeaders);
} else {
requestMatcher.headers = headersUniqueConcatenate(requestMatcher.headers, defaultRequestHeaders);
}
}
return requestMatcher;
};
var addDefaultResponseMatcherHeaders = function (response) {
var responseMatcher;
if (typeof response === "object") {
responseMatcher = response;
} else {
responseMatcher = {};
}
if (defaultResponseHeaders) {
if (responseMatcher.httpResponse) {
responseMatcher.httpResponse.headers = headersUniqueConcatenate(responseMatcher.httpResponse.headers, defaultResponseHeaders);
} else {
responseMatcher.headers = headersUniqueConcatenate(responseMatcher.headers, defaultResponseHeaders);
}
}
return responseMatcher;
};
var addDefaultExpectationHeaders = function (expectation) {
if (Array.isArray(expectation)) {
for (var i = 0; i < expectation.length; i++) {
expectation[i].httpRequest = addDefaultRequestMatcherHeaders(expectation[i].httpRequest);
if (!expectation[i].httpResponseTemplate && !expectation[i].httpResponseClassCallback && !expectation[i].httpResponseObjectCallback && !expectation[i].httpForward && !expectation[i].httpForwardTemplate && !expectation[i].httpForwardClassCallback && !expectation[i].httpForwardObjectCallback && !expectation[i].httpOverrideForwardedRequest && !expectation[i].httpError && !expectation[i].httpSseResponse && !expectation[i].httpWebSocketResponse && !expectation[i].grpcStreamResponse && !expectation[i].binaryResponse && !expectation[i].dnsResponse && !expectation[i].httpLlmResponse) {
expectation[i].httpResponse = addDefaultResponseMatcherHeaders(expectation[i].httpResponse);
}
}
} else {
expectation.httpRequest = addDefaultRequestMatcherHeaders(expectation.httpRequest);
if (!expectation.httpResponseTemplate && !expectation.httpResponseClassCallback && !expectation.httpResponseObjectCallback && !expectation.httpForward && !expectation.httpForwardTemplate && !expectation.httpForwardClassCallback && !expectation.httpForwardObjectCallback && !expectation.httpOverrideForwardedRequest && !expectation.httpError && !expectation.httpSseResponse && !expectation.httpWebSocketResponse && !expectation.grpcStreamResponse && !expectation.binaryResponse && !expectation.dnsResponse && !expectation.httpLlmResponse) {
expectation.httpResponse = addDefaultResponseMatcherHeaders(expectation.httpResponse);
}
}
return expectation;
};
/**
* Setup an expectation by specifying an expectation object
*, for example:
*
* client.mockAnyResponse(
* {
* 'httpRequest': {
* 'path': '/somePath',
* 'body': {
* 'type': "STRING",
* 'value': 'someBody'
* }
* },
* 'httpResponse': {
* 'statusCode': 200,
* 'body': Base64.encode(JSON.stringify({ name: 'first_body' })),
* 'delay': {
* 'timeUnit': 'MILLISECONDS',
* 'value': 250
* }
* },
* 'times': {
* 'remainingTimes': 1,
* 'unlimited': false
* }
* }
* );
*
* @param expectation the expectation to setup on the MockServer
*/
var mockAnyResponse = function (expectation) {
return makeRequest(host, port, "/mockserver/expectation", addDefaultExpectationHeaders(expectation));
};
/**
* Setup one or more LLM mock expectations. Accepts a single expectation
* object, an array of expectations, or an LLM builder (the result of
* client.llm.llmMock(...), .conversation(), or .llmFailover()); builders
* are built via their .build() method. Equivalent to the Java client's
* builder.applyTo(mockServerClient).
*
*, for example:
*
* client.mockWithLLM(
* client.llm.llmMock("/v1/messages")
* .withProvider(client.llm.Provider.ANTHROPIC)
* .withModel("claude-sonnet-4")
* .respondingWith(
* client.llm.completion().withText("Paris.")
* )
* );
*
* @param expectationOrBuilder an expectation, array of expectations, or LLM builder
*/
var mockWithLLM = function (expectationOrBuilder) {
var expectation = (expectationOrBuilder && typeof expectationOrBuilder.build === "function")
? expectationOrBuilder.build()
: expectationOrBuilder;
return makeRequest(host, port, "/mockserver/expectation", addDefaultExpectationHeaders(expectation));
};
/**
* Setup an expectation by specifying an OpenAPI expectation
*, for example:
*
* client.openAPIExpectation(
* {
* "specUrlOrPayload": "https://raw.githubusercontent.com/mock-server/mockserver-monorepo/master/mockserver/mockserver-integration-testing/src/main/resources/org/mockserver/openapi/openapi_petstore_example.json",
* "operationsAndResponses": {
* "showPetById": "200",
* "createPets": "500"
* }
* }
* );
*
* @param expectation the OpenAPI expectation to setup on the MockServer
*/
var openAPIExpectation = function (expectation) {
return makeRequest(host, port, "/mockserver/openapi", expectation);
};
/**
* Setup an expectation by specifying a request matcher, and
* a local request handler function. The request handler function receives each
* request (that matches the request matcher) and returns the response that will be returned for this expectation.
*
*, for example:
*
* client.mockWithCallback(
* {
* path: '/somePath',
* body: 'some_request_body'
* },
* function (request) {
* var response = {
* statusCode: 200,
* body: 'some_response_body'
* };
* return response
* }
* ).then(
* function () {
* alert('expectation sent');
* },
* function (error) {
* alert('error');
* }
* );
*
* @param requestMatcher the request matcher for the expectation
* @param requestHandler the function to be called back when the request is matched
* @param times the number of times the requestMatcher should be matched
* @param priority the priority with which this expectation is used to match requests compared to other expectations (high first)
* @param timeToLive the time this expectation should be used to match requests
* @param id the unique expectation id
*/
var mockWithCallback = function (requestMatcher, requestHandler, times, priority, timeToLive, id) {
return {
then: function (sucess, error) {
try {
var webSocketClientPromise = new WebSocketClient(host, port, cleanedContextPath);
webSocketClientPromise.then(function (webSocketClient) {
webSocketClient.requestCallback(function (request) {
var response = requestHandler(request);
response.headers = headersUniqueConcatenate(response.headers, [
{
"name": "WebSocketCorrelationId",
"values": request.headers["WebSocketCorrelationId"] || request.headers["websocketcorrelationid"]
}
]);
return {
type: "org.mockserver.model.HttpResponse",
value: JSON.stringify(response)
};
});
webSocketClient.clientIdCallback(function (clientId) {
return makeRequest(host, port, "/mockserver/expectation", createExpectationWithCallback(requestMatcher, clientId, times, priority, timeToLive, id)).then(sucess, error);
});
}, error);
} catch (e) {
if (error) {
error(e);
}
}
}
};
};
var mockWithForwardCallback = function (requestMatcher, forwardHandler, times, priority, timeToLive, id) {
return {
then: function (sucess, error) {
try {
var webSocketClientPromise = new WebSocketClient(host, port, cleanedContextPath);
webSocketClientPromise.then(function (webSocketClient) {
webSocketClient.requestCallback(function (request) {
var forwardRequest = forwardHandler(request);
forwardRequest.headers = headersUniqueConcatenate(forwardRequest.headers, [
{
"name": "WebSocketCorrelationId",
"values": request.headers["WebSocketCorrelationId"] || request.headers["websocketcorrelationid"]
}
]);
return {
type: "org.mockserver.model.HttpRequest",
value: JSON.stringify(forwardRequest)
};
});
webSocketClient.clientIdCallback(function (clientId) {
return makeRequest(host, port, "/mockserver/expectation", createExpectationWithForwardCallback(requestMatcher, clientId, times, priority, timeToLive, id)).then(sucess, error);
});
}, error);
} catch (e) {
if (error) {
error(e);
}
}
}
};
};
var mockWithForwardAndResponseCallback = function (requestMatcher, forwardHandler, responseHandler, times, priority, timeToLive, id) {
return {
then: function (sucess, error) {
try {
var webSocketClientPromise = new WebSocketClient(host, port, cleanedContextPath);
webSocketClientPromise.then(function (webSocketClient) {
webSocketClient.requestCallback(function (request) {
var forwardRequest = forwardHandler(request);
forwardRequest.headers = headersUniqueConcatenate(forwardRequest.headers, [
{
"name": "WebSocketCorrelationId",
"values": request.headers["WebSocketCorrelationId"] || request.headers["websocketcorrelationid"]
}
]);
return {
type: "org.mockserver.model.HttpRequest",
value: JSON.stringify(forwardRequest)
};
});
webSocketClient.requestAndResponseCallback(function (requestAndResponse) {
var response = responseHandler(requestAndResponse.httpRequest, requestAndResponse.httpResponse);
var correlationId;
if (requestAndResponse.httpRequest && requestAndResponse.httpRequest.headers) {
correlationId = requestAndResponse.httpRequest.headers["WebSocketCorrelationId"] || requestAndResponse.httpRequest.headers["websocketcorrelationid"];
}
if (correlationId) {
response.headers = headersUniqueConcatenate(response.headers, [
{
"name": "WebSocketCorrelationId",
"values": correlationId
}