text: "use strict";
  var __importDefault = (this && this.__importDefault) || function (mod) {
      return (mod && mod.__esModule) ? mod : { "default": mod };
  };
  Object.defineProperty(exports, "__esModule", { value: true });
  const fs_extra_1 = __importDefault(require("fs-extra"));
  const path_1 = __importDefault(require("path"));
  const atob_1 = __importDefault(require("atob"));
  const minimatch_1 = __importDefault(require("minimatch"));
  const logger_1 = __importDefault(require("@wdio/logger"));
  const _1 = __importDefault(require("."));
  const __1 = require("..");
  const constants_1 = require("../../constants");
  const log = logger_1.default('webdriverio');
  class DevtoolsInterception extends _1.default {
      static handleRequestInterception(client, mocks) {
          return async (event) => {
              const isRequest = !event.responseHeaders;
              const eventResponseHeaders = event.responseHeaders || [];
              const responseHeaders = eventResponseHeaders.reduce((headers, { name, value }) => {
                  headers[name] = value;
                  return headers;
              }, {});
              const { requestId, request, responseStatusCode = 200 } = event;
              for (const mock of mocks) {
                  if (isRequest && (mock.respondOverwrites.length === 0 ||
                      (!mock.respondOverwrites[0].errorReason &&
                          mock.respondOverwrites[0].params &&
                          mock.respondOverwrites[0].params.fetchResponse !== false))) {
                      continue;
                  }
                  if (!minimatch_1.default(request.url, mock.url)) {
                      continue;
                  }
                  request.statusCode = responseStatusCode;
                  request.responseHeaders = { ...responseHeaders };
                  if (filterMethod(request.method, mock.filterOptions.method) ||
                      filterHeaders(request.headers, mock.filterOptions.requestHeaders) ||
                      filterHeaders(responseHeaders, mock.filterOptions.headers) ||
                      filterRequest(request.postData, mock.filterOptions.postData) ||
                      filterStatusCode(responseStatusCode, mock.filterOptions.statusCode)) {
                      continue;
                  }
                  const { body, base64Encoded = undefined } = isRequest ? { body: '' } : await client.send('Fetch.getResponseBody', { requestId }).catch(() => ({}));
                  request.body = base64Encoded ? atob_1.default(body) : body;
                  const contentTypeHeader = Object.keys(responseHeaders).find(h => h.toLowerCase() === 'content-type') || '';
                  const responseContentType = responseHeaders[contentTypeHeader];
                  request.body = responseContentType && responseContentType.includes('application/json')
                      ? tryParseJson(request.body)
                      : request.body;
                  mock.matches.push(request);
                  if (mock.respondOverwrites.length === 0) {
                      continue;
                  }
                  const { errorReason, overwrite, params } = mock.respondOverwrites[0].sticky
                      ? mock.respondOverwrites[0]
                      : mock.respondOverwrites.shift() || {};
                  if (overwrite !== undefined) {
                      let newBody = overwrite;
                      if (typeof overwrite === 'function') {
                          newBody = await overwrite(request, client);
                      }
                      const isBodyUndefined = typeof newBody === 'undefined';
                      if (isBodyUndefined) {
                          newBody = '';
                      }
                      if (typeof newBody !== 'string') {
                          newBody = JSON.stringify(newBody);
                      }
                      let responseCode = (params === null || params === void 0 ? void 0 : params.statusCode) || responseStatusCode;
                      let responseHeaders = [
                          ...eventResponseHeaders,
                          ...Object.entries((params === null || params === void 0 ? void 0 : params.headers) || {}).map(([name, value]) => ({ name, value }))
                      ];
                      const responseFilePath = path_1.default.isAbsolute(newBody) ? newBody : path_1.default.join(process.cwd(), newBody);
                      if (newBody.length > 0 && await fs_extra_1.default.pathExists(responseFilePath) && await canAccess(responseFilePath)) {
                          newBody = await fs_extra_1.default.readFile(responseFilePath);
                      }
                      else if (newBody.startsWith('http')) {
                          responseCode = 301;
                          responseHeaders = responseHeaders.filter(({ name }) => name.toLowerCase() !== 'location');
                          responseHeaders.push({ name: 'Location', value: newBody });
                      }
                      request.mockedResponse = newBody;
                      return client.send('Fetch.fulfillRequest', {
                          requestId,
                          responseCode,
                          responseHeaders,
                          body: isBodyUndefined ? undefined : (newBody instanceof Buffer ? newBody : Buffer.from(newBody, 'utf8')).toString('base64')
                      }).catch(logFetchError);
                  }
                  if (errorReason) {
                      return client.send('Fetch.failRequest', {
                          requestId,
                          errorReason
                      }).catch(logFetchError);
                  }
              }
              return client.send('Fetch.continueRequest', { requestId }).catch(logFetchError);
          };
      }
      get calls() {
          return this.matches;
      }
      clear() {
          this.matches = [];
      }
      restore() {
          this.clear();
          this.respondOverwrites = [];
      }
      respond(overwrite, params = {}) {
          this.respondOverwrites.push({ overwrite, params, sticky: true });
      }
      respondOnce(overwrite, params = {}) {
          this.respondOverwrites.push({ overwrite, params });
      }
      abort(errorReason, sticky = true) {
          if (typeof errorReason !== 'string' || !constants_1.ERROR_REASON.includes(errorReason)) {
              throw new Error(`Invalid value for errorReason, allowed are: ${constants_1.ERROR_REASON.join(', ')}`);
          }
          this.respondOverwrites.push({ errorReason, sticky });
      }
      abortOnce(errorReason) {
          this.abort(errorReason, false);
      }
  }
  exports.default = DevtoolsInterception;
  const filterMethod = (method, expected) => {
      if (typeof expected === 'undefined') {
          return false;
      }
      if (typeof expected === 'function') {
          return expected(method) !== true;
      }
      return expected.toLowerCase() !== method.toLowerCase();
  };
  const filterHeaders = (responseHeaders, expected) => {
      if (typeof expected === 'undefined') {
          return false;
      }
      if (typeof expected === 'function') {
          return expected(responseHeaders) !== true;
      }
      return !__1.containsHeaderObject(responseHeaders, expected);
  };
  const filterRequest = (postData, expected) => {
      if (typeof expected === 'undefined') {
          return false;
      }
      if (typeof expected === 'function') {
          return expected(postData) !== true;
      }
      return postData !== expected;
  };
  const filterStatusCode = (statusCode, expected) => {
      if (typeof expected === 'undefined') {
          return false;
      }
      if (typeof expected === 'function') {
          return expected(statusCode) !== true;
      }
      return statusCode !== expected;
  };
  const canAccess = async (filepath) => {
      try {
          await fs_extra_1.default.access(filepath);
          return true;
      }
      catch (_a) {
          return false;
      }
  };
  const tryParseJson = (body) => {
      try {
          return JSON.parse(body) || body;
      }
      catch (_a) {
          return body;
      }
  };
  const logFetchError = (err) => {
      log.debug(err === null || err === void 0 ? void 0 : err.message);
  };
  