{"version":3,"file":"ProxiedSession.js","sourceRoot":"","sources":["../../../src/lib/ProxiedSession.ts"],"names":[],"mappings":"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","sourcesContent":["import Session from '@theintern/leadfoot/Session';\nimport { Task, CancellablePromise } from '@theintern/common';\n\nimport Node from './executors/Node';\n\n/* istanbul ignore next: client-side code */\nfunction getCoverageData(coverageVariable: string) {\n  let coverageData = (function(this: any) {\n    return this;\n  })()[coverageVariable];\n  return coverageData && JSON.stringify(coverageData);\n}\n\n/**\n * A ProxiedSession object represents a WebDriver session that interacts with\n * the Intern instrumenting server. It collects code instrumentation data from\n * pages and converts local filesystem paths into URLs for use with\n * `leadfoot/Session#get`.\n */\nexport default class ProxiedSession extends Session {\n  /**\n   * The base URL for relative URLs.\n   */\n  baseUrl = '';\n\n  /**\n   * The name of the global variable used to store coverage data.\n   */\n  coverageVariable = '';\n\n  /**\n   * The Executor hosting this session.\n   */\n  executor!: Node;\n\n  private _heartbeatIntervalHandle: { remove: Function } | undefined;\n\n  get coverageEnabled() {\n    return this.executor.config.coverage !== false;\n  }\n\n  /**\n   * Navigates the browser to a new URL like `leadfoot/Session#get`, but\n   * retrieves any code coverage data recorded by the browser prior to\n   * navigation.\n   */\n  get(url: string) {\n    // At least two letters are required in the scheme to avoid Windows\n    // paths being misinterpreted as URLs\n    if (!/^[A-Za-z][A-Za-z0-9+.-]+:/.test(url)) {\n      if (url.indexOf(this.executor.config.basePath) === 0) {\n        url = url.slice(this.executor.config.basePath.length);\n      }\n\n      url = this.baseUrl + url;\n    }\n\n    if (!this.coverageEnabled) {\n      return super.get(url);\n    }\n\n    return this._getCoverage().finally(() => {\n      return super.get(url);\n    });\n  }\n\n  /**\n   * Quits the browser like `leadfoot/Session#quit`, but retrieves any code\n   * coverage data recorded by the browser prior to quitting.\n   */\n  quit() {\n    this.executor.log('Quitting', this.sessionId);\n    return this.setHeartbeatInterval(0)\n      .then(() => {\n        if (this.coverageEnabled) {\n          return this._getCoverage();\n        }\n      })\n      .finally(() => super.quit());\n  }\n\n  /**\n   * Sets up a timer to send no-op commands to the remote server on an\n   * interval to prevent long-running unit tests from causing the session to\n   * time out.\n   *\n   * @param delay Amount of time to wait between heartbeats. Setting the delay\n   * to 0 will disable heartbeats.\n   */\n  setHeartbeatInterval(delay: number): CancellablePromise<void> {\n    this._heartbeatIntervalHandle && this._heartbeatIntervalHandle.remove();\n\n    if (delay) {\n      // A heartbeat command is sent immediately when the interval is set\n      // because it is unknown how long ago the last command was sent and\n      // it simplifies the implementation by requiring only one call to\n      // `setTimeout`\n      const sendHeartbeat = () => {\n        let timeoutId: NodeJS.Timer;\n        let cancelled = false;\n        let startTime = Date.now();\n\n        this._heartbeatIntervalHandle = {\n          remove: function() {\n            cancelled = true;\n            clearTimeout(timeoutId);\n          }\n        };\n\n        this.getCurrentUrl()\n          .then(() => {\n            if (!cancelled) {\n              timeoutId = global.setTimeout(\n                sendHeartbeat,\n                delay - (Date.now() - startTime)\n              );\n            }\n          })\n          .catch(error => this.executor.emit('error', error));\n      };\n\n      sendHeartbeat();\n    }\n\n    return Task.resolve();\n  }\n\n  protected _getCoverage() {\n    let shouldGetPromise: CancellablePromise<boolean>;\n\n    // At least Safari 9 will not inject user scripts for non http/https\n    // URLs, so we can't get coverage data.\n    if (this.capabilities.brokenExecuteForNonHttpUrl) {\n      shouldGetPromise = Task.resolve(\n        this.getCurrentUrl().then(url => /^https?:/i.test(url))\n      );\n    } else {\n      shouldGetPromise = Task.resolve(true);\n    }\n\n    return shouldGetPromise.then(shouldGetCoverage => {\n      if (shouldGetCoverage) {\n        return this.execute<string>(getCoverageData, [\n          this.coverageVariable\n        ]).then(coverageData => {\n          // Emit coverage retrieved from a remote session\n          this.executor.log('Got coverage data for', this.sessionId);\n          if (coverageData) {\n            return this.executor.emit('coverage', {\n              sessionId: this.sessionId,\n              source: 'remote session',\n              coverage: JSON.parse(coverageData)\n            });\n          }\n        });\n      }\n    });\n  }\n}\n"]}