UNPKG

testplane

Version:

Tests framework based on mocha and wdio

261 lines 12 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WSDriverRequestAgent = void 0; const http_1 = require("http"); const node_util_1 = require("node:util"); const debug_1 = require("./debug"); const error_1 = require("./error"); const constants_1 = require("./constants"); const types_1 = require("./types"); const logger = __importStar(require("../../utils/logger")); const ws_connection_1 = require("../../ws-connection"); const constants_2 = require("../../ws-connection/constants"); const error_2 = require("../../ws-connection/error"); const response_1 = require("./response"); const request_1 = require("./request"); const utils_1 = require("../../ws-connection/utils"); class WSDriverRequestAgent { constructor(wsdWsEndpoint, { sessionId, headers, requestTimeout, clientSupportedCompressionTypes }) { headers ||= {}; headers[constants_1.WSD_ACCEPT_ENCODING_HEADER] = clientSupportedCompressionTypes.join(", "); this._wsConnection = new ws_connection_1.WsConnection(wsdWsEndpoint, { headers, debugFn: debug_1.debugWSDriver, retries: { count: constants_1.WSD_CONNECTION_RETRIES, baseDelay: constants_1.WSD_CONNECTION_RETRY_BASE_DELAY, }, timeouts: { request: requestTimeout, createSession: constants_1.WSD_CONNECTION_TIMEOUT, }, errors: { ConnectionEstablishment: error_1.WSDriverRequestAgentEstablishmentError, ConnectionBreak: error_1.WSDriverRequestAgentBreakError, ConnectionTerminated: error_1.WSDriverRequestAgentTerminatedError, ConnectionTimeout: error_1.WSDriverRequestAgentTimeoutError, RequestTimeout: error_1.WSDriverRequestTimeoutError, }, onMessage: this._onMessage.bind(this), }); this._clientSupportedCompressionTypes = clientSupportedCompressionTypes; this._sessionId = sessionId; this._sessionPrefix = `/session/${sessionId}/`; } /** @description Creates WSDriverRequestAgent without establishing it */ static create({ sessionId, sessionCaps, headers = {}, browserConfig, }) { if (!sessionCaps["se:wsdriver"]) { throw new error_1.WSDriverError({ message: "Couldn't determine wsdriver endpoint" }); } if (!sessionCaps["se:wsdriverVersion"]) { throw new error_1.WSDriverError({ message: "Couldn't determine wsdriver supported versions" }); } const wsdriverEndpoint = sessionCaps["se:wsdriver"]; const wsdriverSupportedVersions = sessionCaps["se:wsdriverVersion"].split(", ").map(Number).filter(Boolean); const requestTimeout = browserConfig.httpTimeout; const supportedVersions = wsdriverSupportedVersions.reduce((acc, val) => { acc[val] = true; return acc; }, {}); const clientSupportedCompressionTypes = ["zstd" in process.versions ? "zstd" : null, "gzip"].filter(Boolean); return new this(wsdriverEndpoint, { sessionId, headers, requestTimeout, clientSupportedCompressionTypes, supportedVersions, }); } close() { this._wsConnection.close(); } async _onMessage(data, isBinary) { if (!isBinary) { this._wsConnection.forceReconnect(`Unsupported data type: Expected binary, received text: ${(0, node_util_1.inspect)(data)}`); return; } const incomingMessage = await (0, response_1.parseWsDriverIncomingMessage)(data).catch((err) => err); if (!incomingMessage) { // Valid, but unsupported return; } if (incomingMessage instanceof Error) { // Invalid message this._wsConnection.forceReconnect(incomingMessage.message); return; } const message = incomingMessage; if (debug_1.debugWSDriver.enabled) { const header = message.rawBody.readUint8(1); (0, debug_1.debugWSDriver)(`< ${(0, node_util_1.inspect)({ sessionId: this._sessionId, requestId: message.requestId, header: header.toString(2).padStart(8, "0"), statusCode: message.statusCode, body: message.body, }, { depth: 3, maxStringLength: 150, breakLength: Infinity, compact: true, })}`); } if (message.isProtocolError) { logger.error("wsdriver: Protocol error occured while parsing message:", message); this._wsConnection.provideResponseFor(message.requestId, new error_1.WSDriverRequestError({ message: "Protocol error: " + (0, node_util_1.inspect)(message.body), requestId: message.requestId, code: constants_2.WS_ERROR_CODE.PROTOCOL_ERROR, })); this._wsConnection.forceReconnect("Protocol error: " + (0, node_util_1.inspect)(message.body)); return; } if (message.body instanceof Error) { logger.error("wsdriver: Malformed response:", message.body); this._wsConnection.provideResponseFor(message.requestId, new error_1.WSDriverRequestError({ message: message.body.message, requestId: message.requestId, code: constants_2.WS_ERROR_CODE.MALFORMED_RESPONSE, })); } this._wsConnection.provideResponseFor(message.requestId, message); } async _getRequestCompressionType() { if (typeof this._serverSupportedCompressionType !== "undefined") { return this._serverSupportedCompressionType; } const { responseHeaders } = await this._getConnectionProperties(); if (!responseHeaders || !responseHeaders[constants_1.WSD_ACCEPT_ENCODING_HEADER]) { return (this._serverSupportedCompressionType = types_1.WsDriverCompression.None); } const serverAcceptEncodingHeaders = responseHeaders[constants_1.WSD_ACCEPT_ENCODING_HEADER].concat(", "); const serverAcceptEncodings = serverAcceptEncodingHeaders.split(", "); for (const clientSupportedEncoding of this._clientSupportedCompressionTypes) { if (serverAcceptEncodings.includes(clientSupportedEncoding)) { if (clientSupportedEncoding === "zstd") { return (this._serverSupportedCompressionType = types_1.WsDriverCompression.ZSTD); } else if (clientSupportedEncoding === "gzip") { return (this._serverSupportedCompressionType = types_1.WsDriverCompression.GZIP); } } } return (this._serverSupportedCompressionType = types_1.WsDriverCompression.None); } _getConnectionProperties() { return this._wsConnection.getConnectionProperties(); } /** @description Performs high-level WSDriver request with timeout */ async request(url, options) { let requestId; let result; for (let retriesLeft = constants_1.WSD_REQUEST_RETRIES; retriesLeft >= 0; retriesLeft--) { requestId = this._wsConnection.getRequestId(); const requestMessage = await (0, request_1.constructWsDriverRequest)(url, options, { requestId, sessionPrefix: this._sessionPrefix, compressionType: await this._getRequestCompressionType(), }); if (debug_1.debugWSDriver.enabled) { const header = requestMessage.readUint8(1); const commandEndIdx = requestMessage.indexOf(0, 8); const command = requestMessage.subarray(8, commandEndIdx).toString(); (0, debug_1.debugWSDriver)(`> ${(0, node_util_1.inspect)({ sessionId: this._sessionId, requestId, header: header.toString(2).padStart(8, "0"), method: options.method, command, body: options.json, }, { depth: 3, maxStringLength: 150, breakLength: Infinity, compact: true, })}`); } result = (await this._wsConnection.makeRequest(requestId, requestMessage).catch((err) => err)); if (result instanceof error_1.WSDriverRequestTimeoutError) { const requestError = new Error(result.message); requestError.stack = result.stack; // error code should be "ETIMEDOUT" for webdriver to be able to retry requestError.code = "ETIMEDOUT"; throw requestError; } if (!(result instanceof error_2.WsError) || !result.isRetryable() || retriesLeft <= 0) { break; } if (debug_1.debugWSDriver.enabled) { const header = requestMessage.readUint8(1); const commandEndIdx = requestMessage.indexOf(0, 8); const command = requestMessage.subarray(8, commandEndIdx).toString(); (0, debug_1.debugWSDriver)(`⟳ ${(0, node_util_1.inspect)({ sessionId: this._sessionId, requestId, header: header.toString(2).padStart(8, "0"), method: options.method, command, body: options.json, errorMessage: result.message, retriesLeft: retriesLeft, })}`); } await (0, utils_1.exponentiallyWait)({ baseDelay: constants_1.WSD_REQUEST_RETRY_BASE_DELAY, attempt: constants_1.WSD_REQUEST_RETRIES - retriesLeft, }); } if (result instanceof error_2.WsError) { throw result; } const response = { url: url.toString(), method: options.method, requestId, statusCode: result.statusCode, statusMessage: http_1.STATUS_CODES[result.statusCode], req: { id: requestId, method: options.method, path: options.path, host: url.host, }, request: { id: requestId, options, requestUrl: url, }, ok: result.statusCode >= 200 && result.statusCode < 300, rawBody: result.rawBody, body: result.body, }; response.req.res = response; response.request.response = response; return response; } } exports.WSDriverRequestAgent = WSDriverRequestAgent; //# sourceMappingURL=index.js.map