mocha-webdriver-runner
Advanced tools
Comparing version 0.4.0 to 0.5.0
/// <reference types="mocha" /> | ||
import { RemoteRunnerOptions } from "./RemoteRunnerProtocol"; | ||
export declare let queryStringRunnerOptions: RemoteRunnerOptions | undefined; | ||
/** | ||
@@ -7,17 +9,21 @@ * Adds mocha instance which will send test events, when ran. | ||
* | ||
* Note, default `Mocha` instance i.e `(global|window|self).mocha` is added by default, so | ||
* there is no reason to use this funciton manually, see [[initializeMochaWebDriverClient]]. | ||
* | ||
* May be used both in "main" thread or in web worker thread. When executed in worker, it's | ||
* expected that worker instance in main thread is also registered for forwarding using | ||
* [[addWorkerSource]]. | ||
* | ||
* Example: | ||
* | ||
* mocha.setup(...); | ||
* MochaWebdriverClient.addMochaSource(mocha); | ||
* // load tests | ||
* mocha.run(); | ||
*/ | ||
export declare function addMochaSource(mocha: Mocha): void; | ||
export declare function delayMochaRun(mocha: Mocha): void; | ||
/** | ||
* Initialize Mocha Webdriver Browser side. | ||
* | ||
* Checks `window.location.search` for specific `RemoteRunnerOptions` and if | ||
* `useMochaWebDriverRunner` flag is detected applies them to default `mocha` instance. | ||
*/ | ||
export declare function initializeMochaWebDriverClient(): void; | ||
/** | ||
* @deprecated use [[addMochaSource]] | ||
*/ | ||
export declare const install: typeof addMochaSource; |
@@ -5,2 +5,3 @@ "use strict"; | ||
var RemoteCommon_1 = require("./RemoteCommon"); | ||
var qs = require("qs"); | ||
/** | ||
@@ -11,12 +12,8 @@ * Adds mocha instance which will send test events, when ran. | ||
* | ||
* Note, default `Mocha` instance i.e `(global|window|self).mocha` is added by default, so | ||
* there is no reason to use this funciton manually, see [[initializeMochaWebDriverClient]]. | ||
* | ||
* May be used both in "main" thread or in web worker thread. When executed in worker, it's | ||
* expected that worker instance in main thread is also registered for forwarding using | ||
* [[addWorkerSource]]. | ||
* | ||
* Example: | ||
* | ||
* mocha.setup(...); | ||
* MochaWebdriverClient.addMochaSource(mocha); | ||
* // load tests | ||
* mocha.run(); | ||
*/ | ||
@@ -26,4 +23,12 @@ function addMochaSource(mocha) { | ||
mocha.reporter(MochaRemoteReporter_1.MochaRemoteReporter); | ||
var originalMochaRun = mocha.run; | ||
mocha.globals(["__pageEventQueue", "__pageEventCallback", "__driverCommandCallback", "__driverCommandQueue"]); | ||
if (exports.queryStringRunnerOptions !== undefined) { | ||
RemoteCommon_1.applyMochaOptions(mocha, exports.queryStringRunnerOptions); | ||
} | ||
else { | ||
delayMochaRun(mocha); | ||
} | ||
} | ||
exports.addMochaSource = addMochaSource; | ||
function delayMochaRun(mocha) { | ||
// | ||
@@ -37,2 +42,3 @@ // HACK NOTE: | ||
mocha.timeout(RemoteCommon_1.MAGIC_TIMEOUT); | ||
var originalMochaRun = mocha.run; | ||
mocha.run = function (fn) { | ||
@@ -53,12 +59,48 @@ RemoteCommon_1.runnerBackChannel.addEventListener("message", function (event) { | ||
}); | ||
RemoteCommon_1.runnerBackChannel.postMessage({ | ||
type: "mocha-ready" | ||
}); | ||
return undefined; | ||
}; | ||
RemoteCommon_1.runnerBackChannel.postMessage({ | ||
type: "mocha-ready" | ||
}); | ||
} | ||
exports.addMochaSource = addMochaSource; | ||
exports.delayMochaRun = delayMochaRun; | ||
/** | ||
* Initialize Mocha Webdriver Browser side. | ||
* | ||
* Checks `window.location.search` for specific `RemoteRunnerOptions` and if | ||
* `useMochaWebDriverRunner` flag is detected applies them to default `mocha` instance. | ||
*/ | ||
function initializeMochaWebDriverClient() { | ||
if (typeof window !== "undefined") { | ||
var queryString = window.location.search; | ||
if (!queryString) { | ||
return; | ||
} | ||
var parsed = qs.parse(queryString.substr(1)); | ||
if (!parsed.useMochaWebDriverRunner) { | ||
return; | ||
} | ||
var mochaOptions = {}; | ||
if (typeof parsed.timeout === "string") { | ||
mochaOptions.timeout = parseInt(parsed.timeout, 10); | ||
} | ||
if (typeof parsed.grep === "string") { | ||
mochaOptions.grep = parsed.grep; | ||
} | ||
if (typeof parsed.captureConsoleLog === "string") { | ||
mochaOptions.captureConsoleLog = parsed.captureConsoleLog !== "false"; | ||
} | ||
if (typeof parsed.captureConsoleLog === "string") { | ||
mochaOptions.captureConsoleLog = parsed.captureConsoleLog !== ""; | ||
} | ||
exports.queryStringRunnerOptions = mochaOptions; | ||
} | ||
if (typeof mocha !== "undefined") { | ||
addMochaSource(mocha); | ||
} | ||
} | ||
exports.initializeMochaWebDriverClient = initializeMochaWebDriverClient; | ||
/** | ||
* @deprecated use [[addMochaSource]] | ||
*/ | ||
exports.install = addMochaSource; |
@@ -31,2 +31,3 @@ #!/usr/bin/env node | ||
} | ||
var globalCapabilities = {}; | ||
function collectCapabilities(val, capabilities) { | ||
@@ -52,6 +53,12 @@ if (!val) { | ||
} | ||
capabilities = capabilities || {}; | ||
lodash_1.set(capabilities, key, value); | ||
return capabilities; | ||
lodash_1.set(globalCapabilities, key, value); | ||
return globalCapabilities; | ||
} | ||
function looksLikeUrl(val) { | ||
return val.startsWith("http:") || val.startsWith("https:") || val.startsWith("file:"); | ||
} | ||
function createLocalFileUrl(testPagePath) { | ||
var absoluteTestPagePath = path.resolve(process.cwd(), testPagePath); | ||
return "file://" + absoluteTestPagePath; | ||
} | ||
var version = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8")).version; | ||
@@ -67,2 +74,55 @@ commander | ||
.option("-g, --grep <pattern>", "only run tests/suites that match pattern"); | ||
var shortcuts = { | ||
"chrome": { | ||
doc: "use Chrome", | ||
capabilities: { | ||
browserName: "chrome" | ||
} | ||
}, | ||
"headless-chrome": { | ||
doc: "use headless Chrome", | ||
capabilities: { | ||
browserName: "chrome", | ||
chromeOptions: { | ||
args: ["--headless"] | ||
} | ||
} | ||
}, | ||
"firefox": { | ||
doc: "use Firefox", | ||
capabilities: { | ||
browserName: "firefox" | ||
} | ||
}, | ||
"headless-firefox": { | ||
doc: "use headless Firefox", | ||
capabilities: { | ||
browserName: "firefox", | ||
"moz:firefoxOptions": { | ||
args: ["-headless"] | ||
} | ||
} | ||
}, | ||
"safari": { | ||
doc: "use Safari", | ||
capabilities: { | ||
browserName: "safari" | ||
} | ||
}, | ||
"edge": { | ||
doc: "use Edge", | ||
capabilities: { | ||
browserName: "MicrosoftEdge" | ||
} | ||
} | ||
}; | ||
var _loop_1 = function (name_1) { | ||
var entry = shortcuts[name_1]; | ||
commander.option("--" + name_1, entry.doc, function () { | ||
Object.assign(globalCapabilities, entry.capabilities); | ||
}); | ||
}; | ||
for (var name_1 in shortcuts) { | ||
_loop_1(name_1); | ||
} | ||
commander.parse(process.argv); | ||
@@ -74,3 +134,7 @@ var args = commander.args; | ||
} | ||
var url = commander.args.shift(); | ||
var mainScript = commander.args.shift(); | ||
var url = looksLikeUrl(mainScript) ? mainScript : createLocalFileUrl(mainScript); | ||
if (process.env.SELENIUM_REMOTE_URL && url.startsWith("file:")) { | ||
console.warn("mocha-webdriver-runner: warning: remote selenium nodes usually don't work with file:// urls"); | ||
} | ||
var cliOptions = commander.opts(); | ||
@@ -84,3 +148,3 @@ var options = { | ||
}; | ||
MochaWebDriverRunner_1.runMochaWebDriverTest(commander.capability, url, options).then(function (result) { | ||
MochaWebDriverRunner_1.runMochaWebDriverTest(globalCapabilities, url, options).then(function (result) { | ||
if (result) { | ||
@@ -87,0 +151,0 @@ process.exit(0); |
@@ -6,2 +6,3 @@ export * from "./RemoteCommon"; | ||
export * from "./MochaRemoteReporter"; | ||
export { runRemoteMochaTest } from "./MochaRemoteRunner"; | ||
export { MochaRemoteReporter as Reporter } from "./MochaRemoteReporter"; |
@@ -11,3 +11,7 @@ "use strict"; | ||
__export(require("./MochaRemoteReporter")); | ||
var MochaRemoteRunner_1 = require("./MochaRemoteRunner"); | ||
exports.runRemoteMochaTest = MochaRemoteRunner_1.runRemoteMochaTest; | ||
var MochaRemoteReporter_1 = require("./MochaRemoteReporter"); | ||
exports.Reporter = MochaRemoteReporter_1.MochaRemoteReporter; | ||
var BrowserDriver_1 = require("./BrowserDriver"); | ||
BrowserDriver_1.initializeMochaWebDriverClient(); |
@@ -36,4 +36,7 @@ "use strict"; | ||
}); | ||
runner.on("suite end", function () { | ||
forwardRunnerEvent({ type: "suite end" }); | ||
runner.on("suite end", function (suite) { | ||
forwardRunnerEvent({ | ||
type: "suite end", | ||
suite: suite | ||
}); | ||
}); | ||
@@ -40,0 +43,0 @@ runner.on("test", function (test) { |
@@ -25,3 +25,12 @@ /// <reference types="mocha" /> | ||
reporterOptions?: any; | ||
/** | ||
* If true, mocha in clients waits for `mocha-run` message with options. | ||
* | ||
* If options are passed with other channel (like query-string), mocha can start immediately | ||
* and this flag can be set to `false`. | ||
* | ||
* @default `true` | ||
*/ | ||
clientWaitsForOptions?: boolean; | ||
} | ||
export declare function runRemoteMochaTest(messagePort: MessagePort, options: Options): Promise<boolean>; |
@@ -25,3 +25,3 @@ "use strict"; | ||
else if (event.type === "suite end") { | ||
runner.emit("suite end"); | ||
runner.emit("suite end", event.suite); | ||
} | ||
@@ -58,10 +58,12 @@ else if (event.type === "test") { | ||
case "mocha-ready": | ||
messagePort.postMessage({ | ||
type: "mocha-run", | ||
mochaOptions: { | ||
grep: options.grep, | ||
captureConsoleLog: captureConsoleLog, | ||
timeout: options.timeout | ||
} | ||
}); | ||
if (options.clientWaitsForOptions !== false) { | ||
messagePort.postMessage({ | ||
type: "mocha-run", | ||
mochaOptions: { | ||
grep: options.grep, | ||
captureConsoleLog: captureConsoleLog, | ||
timeout: options.timeout | ||
} | ||
}); | ||
} | ||
break; | ||
@@ -68,0 +70,0 @@ case "log": |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -41,2 +52,3 @@ return new (P || (P = Promise))(function (resolve, reject) { | ||
var MochaRemoteRunner_1 = require("./MochaRemoteRunner"); | ||
var querystring = require("querystring"); | ||
function withWebDriver(capabilities, test) { | ||
@@ -100,3 +112,3 @@ return __awaiter(this, void 0, void 0, function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var messagePort; | ||
var passOptionsWithQueryString, queryStringParams, delimiter, messagePort; | ||
return __generator(this, function (_a) { | ||
@@ -111,2 +123,22 @@ switch (_a.label) { | ||
options = options || {}; | ||
passOptionsWithQueryString = true; | ||
if (passOptionsWithQueryString) { | ||
queryStringParams = { | ||
useMochaWebDriverRunner: 1 | ||
}; | ||
if (options.captureConsoleLog !== undefined) { | ||
queryStringParams.captureConsoleLog = options.captureConsoleLog; | ||
} | ||
if (options.delay !== undefined) { | ||
queryStringParams.delay = options.delay; | ||
} | ||
if (options.timeout !== undefined) { | ||
queryStringParams.timeout = options.timeout; | ||
} | ||
if (options.grep !== undefined) { | ||
queryStringParams.grep = options.grep; | ||
} | ||
delimiter = url.indexOf('?') === -1 ? '?' : '&'; | ||
url = url + delimiter + querystring.stringify(queryStringParams); | ||
} | ||
return [4 /*yield*/, webDriver.get(url)]; | ||
@@ -116,3 +148,3 @@ case 1: | ||
messagePort = new WebDriverMessagePort_1.WebDriverMessagePort(webDriver); | ||
return [2 /*return*/, MochaRemoteRunner_1.runRemoteMochaTest(messagePort, options)]; | ||
return [2 /*return*/, MochaRemoteRunner_1.runRemoteMochaTest(messagePort, __assign({}, options, { clientWaitsForOptions: !passOptionsWithQueryString }))]; | ||
} | ||
@@ -119,0 +151,0 @@ }); |
@@ -9,2 +9,3 @@ /// <reference types="mocha" /> | ||
export declare function applyMochaOptions(mocha: Mocha, options: RemoteRunnerOptions): void; | ||
export declare function overrideDefaultMagicTimeout(suite: Mocha.Suite, timeout: number): void; | ||
/** | ||
@@ -11,0 +12,0 @@ * Hijack `console.*` to send all logs to parent through `runnerBackChannel`. |
@@ -22,24 +22,27 @@ "use strict"; | ||
{ | ||
var timeout_1 = options.timeout !== undefined ? options.timeout : 2000; | ||
mocha.timeout(timeout_1); | ||
var overrideMagicTimeout_1 = function (obj) { | ||
if (obj.timeout() === exports.MAGIC_TIMEOUT) { | ||
obj.timeout(timeout_1); | ||
} | ||
}; | ||
var setTimeoutRecursive_1 = function (suite) { | ||
overrideMagicTimeout_1(suite); | ||
suite.tests.forEach(overrideMagicTimeout_1); | ||
suite._beforeEach.forEach(overrideMagicTimeout_1); | ||
suite._beforeAll.forEach(overrideMagicTimeout_1); | ||
suite._afterEach.forEach(overrideMagicTimeout_1); | ||
suite._afterAll.forEach(overrideMagicTimeout_1); | ||
suite.suites.forEach(function (subSuite) { | ||
setTimeoutRecursive_1(subSuite); | ||
}); | ||
}; | ||
setTimeoutRecursive_1(mocha.suite); | ||
var timeout = options.timeout !== undefined ? options.timeout : 2000; | ||
if (mocha.suite.timeout() === exports.MAGIC_TIMEOUT) { | ||
overrideDefaultMagicTimeout(mocha.suite, timeout); | ||
} | ||
mocha.timeout(timeout); | ||
} | ||
} | ||
exports.applyMochaOptions = applyMochaOptions; | ||
function overrideDefaultMagicTimeout(suite, timeout) { | ||
var overrideMagicTimeout = function (obj) { | ||
if (obj.timeout() === exports.MAGIC_TIMEOUT) { | ||
obj.timeout(timeout); | ||
} | ||
}; | ||
overrideMagicTimeout(suite); | ||
suite.tests.forEach(overrideMagicTimeout); | ||
suite._beforeEach.forEach(overrideMagicTimeout); | ||
suite._beforeAll.forEach(overrideMagicTimeout); | ||
suite._afterEach.forEach(overrideMagicTimeout); | ||
suite._afterAll.forEach(overrideMagicTimeout); | ||
suite.suites.forEach(function (subSuite) { | ||
overrideDefaultMagicTimeout(subSuite, timeout); | ||
}); | ||
} | ||
exports.overrideDefaultMagicTimeout = overrideDefaultMagicTimeout; | ||
var consoleLogSenderInstalled = false; | ||
@@ -46,0 +49,0 @@ /** |
@@ -5,2 +5,4 @@ "use strict"; | ||
var treesync_1 = require("@zbigg/treesync"); | ||
var BrowserDriver_1 = require("./BrowserDriver"); | ||
var MochaRemoteRunner_1 = require("./MochaRemoteRunner"); | ||
/** | ||
@@ -25,3 +27,11 @@ * Adds Web Worker instance which will send test events, when ran. | ||
}); | ||
var firstMessage = true; | ||
worker.addEventListener("message", function (event) { | ||
if (firstMessage && BrowserDriver_1.queryStringRunnerOptions !== undefined) { | ||
worker.postMessage({ | ||
type: "mocha-run", | ||
mochaOptions: BrowserDriver_1.queryStringRunnerOptions | ||
}); | ||
firstMessage = false; | ||
} | ||
var message = event.data; | ||
@@ -37,3 +47,10 @@ RemoteCommon_1.runnerBackChannel.postMessage(message); | ||
}); | ||
if (BrowserDriver_1.queryStringRunnerOptions === undefined) { | ||
MochaRemoteRunner_1.runRemoteMochaTest(worker, { | ||
reporter: "html", | ||
captureConsoleLog: false, | ||
clientWaitsForOptions: true | ||
}); | ||
} | ||
} | ||
exports.addWorkerSource = addWorkerSource; |
@@ -41,6 +41,2 @@ "use strict"; | ||
mocha.checkLeaks(); | ||
self.postMessage({ type: "mocha-ready" }); | ||
} | ||
function run(options) { | ||
MochaWebdriverClient.applyMochaOptions(mocha, options); | ||
mocha.run(function () { | ||
@@ -50,3 +46,3 @@ self.postMessage({ type: "mocha-finished" }); | ||
} | ||
self.onmessage = function (event) { | ||
var onMessage = function (event) { | ||
var message = event.data; | ||
@@ -56,6 +52,4 @@ try { | ||
initialize(message); | ||
self.removeEventListener('message', onMessage); | ||
} | ||
else if (message.type === "mocha-run") { | ||
run(message.mochaOptions || {}); | ||
} | ||
else { | ||
@@ -83,2 +77,3 @@ console.log("unknown message received", message); | ||
}; | ||
self.addEventListener('message', onMessage); | ||
self.postMessage({ type: "worker-ready-for-bootstrap" }); | ||
@@ -155,2 +150,4 @@ } | ||
worker.removeEventListener("message", onMessage); | ||
// pass control to normal worker handler | ||
WebWorkerDriver_1.addWorkerSource(worker); | ||
} | ||
@@ -164,4 +161,2 @@ else if (message.type === "mocha-finished") { | ||
worker.addEventListener("message", onMessage); | ||
// pass control to normal worker handler | ||
WebWorkerDriver_1.addWorkerSource(worker); | ||
}); | ||
@@ -168,0 +163,0 @@ } |
{ | ||
"name": "mocha-webdriver-runner", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "Run Mocha tests using Selenium WebDriver", | ||
@@ -53,2 +53,3 @@ "keywords": [ | ||
"@types/node": "^10.11.2", | ||
"@types/qs": "^6.5.1", | ||
"@types/selenium-webdriver": "^3.0.11", | ||
@@ -62,2 +63,3 @@ "@types/sinon": "^5.0.3", | ||
"install": "^0.12.1", | ||
"qs": "^6.5.2", | ||
"rollup": "^0.66.2", | ||
@@ -64,0 +66,0 @@ "rollup-plugin-commonjs": "^9.1.8", |
@@ -24,2 +24,4 @@ # mocha-webdriver-runner | ||
(Also ensure that you've got proper drivers or Selenium Grid available, see [Browser Driver](#browser-drivers) section below). | ||
## Usage | ||
@@ -29,13 +31,9 @@ | ||
Add `mocha-webdriver-runner` browser side client: | ||
Add `mocha-webdriver-runner` browser side client just after normal `mocha.js` `<script>` tag: | ||
<script src="../node_modules/mocha-webdriver-runner/dist/mocha-webdriver-client.js"></script> | ||
<script src="../node_modules/mocha/mocha.js"></script | ||
+ <script src="../node_modules/mocha-webdriver-runner/dist/mocha-webdriver-client.js"></script> | ||
and install `MochaWebdriverClient` in global `mocha` instance: | ||
Run the test suite against local browser: | ||
mocha.setup({ui: "bdd"}); | ||
+ MochaWebdriverClient.install(mocha); | ||
Run the test suite: | ||
SELENIUM_BROWSER=chrome npx mocha-webdriver-runner test/index.html | ||
@@ -47,2 +45,7 @@ | ||
The HTML test page works in two environments: | ||
* normal browser window - HTML report is generated in browser window as usual | ||
* when ran through `mocha-webdriver-runner`, report is forwarded to reporter running in node | ||
(default is `spec`) | ||
See `package.json` scripts and `test/sample-suite/index-headless.html` for reference. | ||
@@ -62,2 +65,13 @@ | ||
Convenience shortcuts: | ||
| Shortcut option | Resolves to | ||
| - | ---- | ||
| `--headless-chrome` | `-C browserName=chrome -C chromeOptions.args='["--headless"]'` | ||
| `--chrome` | `-C browserName=chrome` | ||
| `--headless-firefox` | `-C browserName=firefox -C moz:firefoxOptions.args='["-headless"]'` | ||
| `--firefox` | `-C browserName=firefox` | ||
| `--edge` | `-C browserName=MicrosoftEdge` | ||
| `--safari` | `-C browserName=safari` | ||
Useful links: | ||
@@ -79,2 +93,19 @@ | ||
## Browser Drivers | ||
Testing against browser that runs on your desktop requires that proper drivers are installed in your environment. | ||
* Chrome - requires `chromedriver` | ||
* available as NPM packet `chromedriver` | ||
* documentation & manual download: http://chromedriver.chromium.org/ | ||
* Firefox - requires `geckdriver` | ||
* available as NPM packet `geckodriver` | ||
* documentation & manual download: https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/ | ||
* Safari - requires `safaridriver` | ||
* SafariDriver (now) is installed by default, see https://developer.apple.com/documentation/webkit/testing_with_webdriver_in_safari | ||
For `mocha-webdriver-runner` to work, particular webdriver must be installed somwehere in `PATH`. | ||
Note, _convenience_ NPM packages -`chromedriver` and `geckdriver` - install them it to `./node_modules/.bin`, so if you run your tests via npm drivers are found automagically. | ||
## API | ||
@@ -81,0 +112,0 @@ |
Sorry, the diff of this file is too big to display
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
159082
3885
182
0
28
4