UNPKG

mockserver-client

Version:

A node client for the MockServer

999 lines (960 loc) 164 kB
/* * 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 }