UNPKG

17 kBSource Map (JSON)View Raw
1{"version":3,"file":"RemoteSuite.js","sourceRoot":"","sources":["../../../src/lib/RemoteSuite.ts"],"names":[],"mappings":"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","sourcesContent":["import { parse } from 'url';\nimport { relative } from 'path';\nimport { stringify as stringifyQuery } from 'querystring';\nimport { Handle, Task, CancellablePromise } from '@theintern/common';\n\nimport Suite, { SuiteOptions } from './Suite';\nimport { InternError } from './types';\nimport Node, { NodeEvents } from './executors/Node';\nimport { Config } from './common/config';\nimport Browser from './executors/Browser';\nimport { stringify } from './common/util';\nimport Deferred from './Deferred';\n\n// This is used for the `execute` config block\ndeclare const intern: Browser;\n\n/**\n * RemoteSuite is a class that acts as a local server for one or more unit test\n * suites being run in a remote browser.\n */\nexport default class RemoteSuite extends Suite {\n // @ts-ignore\n executor!: Node;\n\n constructor(options?: Partial<SuiteOptions>) {\n options = options || {};\n if (options.name == null) {\n options.name = 'remote unit tests';\n }\n\n super(<SuiteOptions>options);\n\n if (this.timeout == null) {\n this.timeout = Infinity;\n }\n }\n\n /**\n * Override Suite#id to exclude the RemoteSuite's name from the generated ID\n * since the RemoteSuite is just a proxy for a remote suite.\n */\n get id() {\n let name: string[] = [];\n let suite: Suite = this.parent!;\n\n do {\n suite.name != null && name.unshift(suite.name);\n } while ((suite = suite.parent!));\n\n return name.join(' - ');\n }\n\n /**\n * Run a suite in a remote browser.\n */\n run(): CancellablePromise<any> {\n const remote = this.remote;\n const sessionId = remote.session.sessionId;\n const server = this.executor.server!;\n let listenerHandle: Handle;\n let connectTimer: NodeJS.Timer;\n\n return new Task(\n (resolve, reject) => {\n const handleError = (error: InternError) => {\n this.error = error;\n reject(error);\n };\n\n const config = this.executor.config;\n\n // This is a deferred that will resolve when the remote sends\n // back a 'remoteConfigured' message\n const pendingConnection = new Deferred<void>();\n\n // If the remote takes to long to connect, reject the connection\n // promise\n const connectTimeout = config.connectTimeout;\n connectTimer = global.setTimeout(() => {\n const error = new Error('Timed out waiting for remote to connect');\n error.name = 'TimeoutError';\n pendingConnection.reject(error);\n }, connectTimeout);\n\n // Subscribe to messages received by the server for a particular\n // remote session ID.\n listenerHandle = server.subscribe(\n sessionId,\n (eventName: string, data: any) => {\n const name = <keyof RemoteEvents>eventName;\n let suite: Suite;\n\n switch (name) {\n case 'remoteStatus':\n if (data === 'initialized') {\n clearTimeout(connectTimer);\n pendingConnection.resolve();\n }\n break;\n\n case 'suiteStart':\n suite = data;\n if (!suite.hasParent) {\n // This suite from the browser is a root\n // suite; add its tests to the local suite\n this.tests.push(...suite.tests);\n\n // Tell the executor that the local suite\n // has started\n return this.executor.emit('suiteStart', this);\n } else {\n // If suite from the browser isn't a root\n // (i.e., it's a nested suite), just forward\n // the start event\n return this.executor.emit(name, data);\n }\n\n case 'suiteEnd':\n suite = data;\n this.skipped = suite.skipped;\n\n if (!suite.hasParent) {\n // When the remote root suite has finished,\n // replace the local test objects with the\n // incoming test data since it will include\n // final results.\n suite.tests.forEach((test, index) => {\n this.tests[index] = test;\n });\n\n if (suite.error) {\n handleError(suite.error);\n }\n } else {\n // If suite from the browser isn't a root,\n // just forward the end event\n return this.executor.emit(name, data);\n }\n break;\n\n case 'beforeRun':\n case 'afterRun':\n case 'runStart':\n // Consume these events -- they shouldn't be\n // forwarded to any local listeners\n break;\n\n case 'runEnd':\n // Consume this event, and do some\n // post-processing\n let promise = remote.setHeartbeatInterval(0);\n if (this.executor.hasCoveredFiles) {\n // get about:blank to always collect code\n // coverage data from the page in case it is\n // navigated away later by some other\n // process; this happens during self-testing\n // when the Leadfoot library takes over\n promise = promise.get('about:blank');\n }\n return promise.then(resolve, reject);\n\n case 'error':\n // Ignore summary suite error messages\n if (!/One or more suite errors/.test(data.message)) {\n handleError(data);\n }\n break;\n\n default:\n return this.executor.emit(name, data);\n }\n }\n );\n\n const serverUrl = parse(config.serverUrl);\n\n // Intern runs unit tests on the remote Selenium server by\n // navigating to the client runner HTML page. No real commands\n // are issued after the call to remote.get() below until all\n // unit tests are complete, so we need to make sure that we\n // periodically send no-ops through the channel to ensure the\n // remote server does not treat the session as having timed out\n const timeout = config.heartbeatInterval!;\n if (timeout >= 1 && timeout < Infinity) {\n remote.setHeartbeatInterval((timeout - 1) * 1000);\n }\n\n // These are options that will be passed as query params to the\n // test harness page\n const queryOptions: Partial<RemoteConfig> = {\n basePath: serverUrl.pathname ?? undefined,\n runInSync: config.runInSync || false,\n serverUrl: serverUrl.href,\n sessionId: sessionId,\n socketPort: server.socketPort,\n socketTimeout: config.socketTimeout,\n };\n\n // Do some pre-serialization of the options\n const queryParams: { [key: string]: any } = {};\n Object.keys(queryOptions)\n .filter((option) => {\n const key = <keyof RemoteConfig>option;\n return queryOptions[key] != null;\n })\n .forEach((option) => {\n const key = <keyof RemoteConfig>option;\n let value = queryOptions[key];\n if (typeof value === 'object') {\n value = JSON.stringify(value);\n }\n queryParams[key] = value;\n });\n\n const query = stringifyQuery(queryParams);\n const harness = `${config.serverUrl}__intern/browser/remote.html`;\n\n // Determine the relative path from basePath to internPath. This\n // will be used to derive the internPath sent to the remote. The\n // remote will figure out its own basePath.\n const internPath = relative(config.basePath, config.internPath);\n\n // These are options that will be POSTed to the remote page and\n // used to configure intern. Stringify and parse them to ensure\n // that the config can be properly transmitted.\n const disableDomUpdates =\n config.remoteOptions && config.remoteOptions.disableDomUpdates;\n const remoteReporters = disableDomUpdates ? [] : [{ name: 'dom' }];\n const remoteConfig: Partial<RemoteConfig> = {\n debug: config.debug,\n internPath: `${serverUrl.pathname}${internPath}`,\n name: this.id,\n reporters: remoteReporters,\n };\n\n // Don't overwrite any config data we've already set\n const excludeKeys: { [key: string]: boolean } = {\n basePath: true,\n internPath: true,\n name: true,\n reporters: true,\n serverUrl: true,\n sessionId: true,\n socketPort: true,\n socketTimeout: true,\n };\n\n // Pass all non-excluded keys to the remote config\n Object.keys(config)\n .filter((key) => !excludeKeys[key])\n .forEach((property) => {\n const key = <keyof RemoteConfig>property;\n (remoteConfig as any)[key] = config[key];\n });\n\n this.executor.log(\n 'Configuring remote \"',\n this.name,\n '\" with',\n remoteConfig\n );\n\n remote\n .get(`${harness}?${query}`)\n .then(() => pendingConnection.promise)\n // Send the config data in an execute block to avoid sending\n // very large query strings\n .execute(\n /* istanbul ignore next */ function (configString: string) {\n const options = JSON.parse(configString);\n intern.configure(options);\n intern.run().catch((_error) => {});\n },\n [stringify(remoteConfig)]\n )\n // If there's an error loading the page, kill the heartbeat\n // and fail\n .catch((error) =>\n remote.setHeartbeatInterval(0).finally(() => handleError(error))\n );\n },\n // Canceller\n () => remote.setHeartbeatInterval(0)\n )\n .catch((error) => {\n if (!this.error) {\n this.error = error;\n }\n throw error;\n })\n .finally(() => {\n if (connectTimer) {\n clearTimeout(connectTimer);\n }\n listenerHandle.destroy();\n })\n .finally(() => this.executor.emit('suiteEnd', this));\n }\n}\n\nexport interface RemoteEvents extends NodeEvents {\n remoteStatus: string;\n}\n\nexport interface RemoteConfig extends Config {\n serverUrl: string;\n sessionId: string;\n runInSync: boolean;\n socketPort?: number;\n socketTimeout?: number;\n}\n"]}
\No newline at end of file