From 8f6770e8a0052c431371d4a571300be07ecf48a4 Mon Sep 17 00:00:00 2001 From: hensm Date: Sat, 12 Jan 2019 02:18:21 +0000 Subject: [PATCH] Proxy Jasmine output to terminal --- package-lock.json | 213 +++++++++++++++++++++++++++++-- package.json | 2 +- test/SpecRunner.html | 3 + test/driver.js | 108 ++++++++++++---- test/{test.html => polling.html} | 3 +- test/reporterProxy.js | 29 +++++ 6 files changed, 319 insertions(+), 39 deletions(-) rename test/{test.html => polling.html} (68%) create mode 100644 test/reporterProxy.js diff --git a/package-lock.json b/package-lock.json index 396c76d..44fb854 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2,6 +2,21 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -18,6 +33,59 @@ "concat-map": "0.0.1" } }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-spinners": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz", + "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==", + "dev": true + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -36,12 +104,27 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, "es6-promise": { "version": "3.0.2", "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=", "dev": true }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, "fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -79,6 +162,12 @@ "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, "immediate": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", @@ -107,22 +196,20 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "jasmine": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.3.0.tgz", - "integrity": "sha512-haZzMvmoWSI2VCKfDgPqyEOPBQA7C1fgtIMgKNU4hVMcrVkWU5NPOWQqOTA6mVFyKcSUUrnkXu/ZEgY0bRnd6A==", + "jasmine-console-reporter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jasmine-console-reporter/-/jasmine-console-reporter-3.1.0.tgz", + "integrity": "sha512-fNP6XlgkIyNvfr6JVMJudZL9qWNY2K7l934Ojj4k8J09/QXf4xYf2Mc7MUgcsDhqIb2zTkLd2LsBJWFvJz41/w==", "dev": true, "requires": { - "glob": "^7.0.6", - "jasmine-core": "~3.3.0" + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "ci-info": "^1.4.0", + "node-emoji": "^1.8.1", + "ora": "^3.0.0", + "perfy": "^1.1.5" } }, - "jasmine-core": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.3.0.tgz", - "integrity": "sha512-3/xSmG/d35hf80BEN66Y6g9Ca5l/Isdeg/j6zvbTYlTzeKinzmaTM4p9am5kYqOmE05D7s1t8FGjzdSnbUbceA==", - "dev": true - }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -154,6 +241,27 @@ "immediate": "~3.0.5" } }, + "lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -163,6 +271,15 @@ "brace-expansion": "^1.1.7" } }, + "node-emoji": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.8.1.tgz", + "integrity": "sha512-+ktMAh1Jwas+TnGodfCfjUbJKoANqPaJFN0z0iqh41eqD8dvguNzcitVSBSVK1pidz0AqGbLKcoVuVLRVZ/aVg==", + "dev": true, + "requires": { + "lodash.toarray": "^4.4.0" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -172,6 +289,29 @@ "wrappy": "1" } }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "ora": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.0.0.tgz", + "integrity": "sha512-LBS97LFe2RV6GJmXBi6OKcETKyklHNMV0xw7BtsVn2MlsgsydyZetSCbCANr+PFLmDyv4KV88nn0eCKza665Mg==", + "dev": true, + "requires": { + "chalk": "^2.3.1", + "cli-cursor": "^2.1.0", + "cli-spinners": "^1.1.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^4.0.0", + "wcwidth": "^1.0.1" + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -190,6 +330,12 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "perfy": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/perfy/-/perfy-1.1.5.tgz", + "integrity": "sha512-/ieVBpMaPTJf83YTUl2TImsSwMEJ23qGP2w27pE6aX+NrB/ZRGqOnQZpl7J719yFwd+ebDiHguPNFeMSamyK7w==", + "dev": true + }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", @@ -210,6 +356,16 @@ "util-deprecate": "~1.0.1" } }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -243,12 +399,36 @@ "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, "tmp": { "version": "0.0.30", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", @@ -270,6 +450,15 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 9364961..1d80607 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ }, "devDependencies": { "fs-extra": "^7.0.1", - "jasmine": "^3.3.0", + "jasmine-console-reporter": "^3.1.0", "selenium-webdriver": "^4.0.0-alpha.1", "semver": "^5.6.0" } diff --git a/test/SpecRunner.html b/test/SpecRunner.html index 85c43b0..f111e0d 100644 --- a/test/SpecRunner.html +++ b/test/SpecRunner.html @@ -8,6 +8,9 @@ + + + diff --git a/test/driver.js b/test/driver.js index 1898a08..ce55acf 100644 --- a/test/driver.js +++ b/test/driver.js @@ -3,15 +3,21 @@ const path = require("path"); const glob = require("glob"); const fs = require("fs"); +const EventEmitter = require("events"); + +const JasmineConsoleReporter = require("jasmine-console-reporter"); const webdriver = require("selenium-webdriver"); const firefox = require("selenium-webdriver/firefox"); const chrome = require("selenium-webdriver/chrome"); +// Webdriver shorthands +const { By, until } = webdriver; + + const { __extensionName , __extensionVersion } = require("../ext/package.json"); - const extensionArchivePath = path.join( path.join(__dirname, "../dist/ext/") , `${__extensionName}-${__extensionVersion}.xpi`); @@ -22,7 +28,8 @@ if (!fs.existsSync(extensionArchivePath)) { } -const TEST_PAGE_URL = `file:///${__dirname}/test.html`; +const TEST_PAGE_URL = `file:///${__dirname}/SpecRunner.html`; +const POLLING_PAGE_URL = `file:///${__dirname}/polling.html`; const firefoxOptions = new firefox.Options() .setBinary(firefox.Channel.NIGHTLY) @@ -47,8 +54,11 @@ function waitUntilDefined ( , pollingTimeout = 10000 , pollingFrequency = 100) { - return new Promise(async (resolve, reject) => { - let time = pollingFrequency; + return new Promise(async (resolve, reject) => { + let elapsedTime = pollingFrequency; + + // Navigate to polling page + await driver.get(POLLING_PAGE_URL); const interval = setInterval(async () => { await driver.navigate().refresh(); @@ -57,18 +67,61 @@ function waitUntilDefined ( return window.chrome.cast !== undefined; }); - time += pollingFrequency; + elapsedTime += pollingFrequency; if (isDefined) { clearInterval(interval); resolve(); - } else if (time >= pollingTimeout) { + } else if (elapsedTime >= pollingTimeout) { + clearInterval(interval); reject("Timed out"); } }, pollingFrequency); }); } +/** + * Jasmine runs in browser context, but reporters for terminal + * output run in node context. Need to forward reporter output + * from Jasmine in the browser context to node context to use + * reporters here. + * + * reporter.js is loaded on the test page and adds reporter + * messages to the DOM which we listen for here. + */ +class ReporterProxy extends EventEmitter { + constructor (driver) { + super(); + this._driver = driver; + this._wait(); + } + + async _wait () { + const elementFilter = By.id("__msg"); + + // Wait for message element + await this._driver.wait(until.elementLocated(elementFilter)) + + // Get message content + const messageElement = this._driver.findElement(elementFilter); + const messageContent = JSON.parse(await messageElement.getText()); + + // Remove message element + await this._driver.executeScript(() => { + document.getElementById("__msg").remove(); + }); + + // Send event + this.emit(messageContent.subject, messageContent.data); + + // Wait for next event + if (messageContent.subject !== "jasmineDone") { + this._wait(); + } + } +} + + (async () => { const driver = new webdriver.Builder() .forBrowser("firefox") @@ -76,28 +129,35 @@ function waitUntilDefined ( .setChromeOptions(chromeOptions) .build(); - // Navigate to test page - await driver.get(TEST_PAGE_URL); - const capabilties = await driver.getCapabilities(); - switch (capabilties.get("browserName")) { - // Need to wait for cast extension on Chrome - case "chrome": - console.log("Waiting for cast extension..."); - await waitUntilDefined(driver); - console.log("Cast extension loaded!"); + const browserName = capabilties.get("browserName"); - break; - - case "firefox": - break; + // Need to wait for cast extension on Chrome + if (browserName === "chrome") { + console.log("Waiting for cast extension..."); + await waitUntilDefined(driver); + console.log("Cast extension loaded!"); } - // Load Jasmine - await driver.executeScript(() => { - const iframe = document.querySelector("iframe"); - iframe.setAttribute("src", "SpecRunner.html"); - }); + + // Create console reporter and reporter proxy. + const reporter = new JasmineConsoleReporter(); + const reporterProxy = new ReporterProxy(driver); + + /** + * Forward events from Jasmine standlone via reporter proxy to + * console reporter. + */ + reporterProxy.on("jasmineDone" , result => reporter.jasmineDone(result)); + reporterProxy.on("jasmineStarted" , result => reporter.jasmineStarted(result)); + reporterProxy.on("specDone" , result => reporter.specDone(result)); + reporterProxy.on("specStarted" , result => reporter.specStarted(result)); + reporterProxy.on("suiteDone" , result => reporter.suiteDone(result)); + reporterProxy.on("suiteStarted" , result => reporter.suiteStarted(result)); + + + // Load Jasmine test page + await driver.get(TEST_PAGE_URL); })(); // Keep process alive diff --git a/test/test.html b/test/polling.html similarity index 68% rename from test/test.html rename to test/polling.html index e4b2538..ddc6e61 100644 --- a/test/test.html +++ b/test/polling.html @@ -4,7 +4,6 @@ -

TEST PAGE

- +

WAITING FOR CAST EXTENSION...

diff --git a/test/reporterProxy.js b/test/reporterProxy.js new file mode 100644 index 0000000..c481ac4 --- /dev/null +++ b/test/reporterProxy.js @@ -0,0 +1,29 @@ +function sendMessage (message) { + const msgElement = document.createElement("div"); + msgElement.setAttribute("id", "__msg"); + msgElement.textContent = JSON.stringify(message); + document.body.appendChild(msgElement); +} + +const reporterMethods = [ + "jasmineDone" + , "jasmineStarted" + , "specDone" + , "specStarted" + , "suiteDone" + , "suiteStarted" +]; + +const customReporter = {}; + +// Populate reporter methods +for (const method of reporterMethods) { + customReporter[method] = function (result) { + sendMessage({ + subject: method + , data: result + }); + } +} + +jasmine.getEnv().addReporter(customReporter);