diff --git a/CHANGELOG.md b/CHANGELOG.md index b97188447..b7c04ed83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ + +## [3.1.2](https://github.com/karma-runner/karma/compare/v3.1.1...v3.1.2) (2018-12-01) + + +### Bug Fixes + +* **browser:** report errors to console during singleRun=false ([#3209](https://github.com/karma-runner/karma/issues/3209)) ([30ff73b](https://github.com/karma-runner/karma/commit/30ff73b)), closes [#3131](https://github.com/karma-runner/karma/issues/3131) +* **changelog:** remove release which does not exist ([#3214](https://github.com/karma-runner/karma/issues/3214)) ([4e87902](https://github.com/karma-runner/karma/commit/4e87902)) +* **dep:** Bump useragent to fix HeadlessChrome version ([#3201](https://github.com/karma-runner/karma/issues/3201)) ([240209f](https://github.com/karma-runner/karma/commit/240209f)), closes [#2762](https://github.com/karma-runner/karma/issues/2762) +* **deps:** upgrade sinon-chai 2.x -> 3.x ([#3207](https://github.com/karma-runner/karma/issues/3207)) ([dc5f5de](https://github.com/karma-runner/karma/commit/dc5f5de)) +* **file-list:** do not preprocess up-to-date files ([#3196](https://github.com/karma-runner/karma/issues/3196)) ([5334d1a](https://github.com/karma-runner/karma/commit/5334d1a)), closes [#2829](https://github.com/karma-runner/karma/issues/2829) +* **package:** bump lodash version ([#3203](https://github.com/karma-runner/karma/issues/3203)) ([d38f344](https://github.com/karma-runner/karma/commit/d38f344)), closes [#3177](https://github.com/karma-runner/karma/issues/3177) +* **server:** use flatted for json.stringify ([#3220](https://github.com/karma-runner/karma/issues/3220)) ([fb05fb1](https://github.com/karma-runner/karma/commit/fb05fb1)), closes [#3215](https://github.com/karma-runner/karma/issues/3215) + + +### Features + +* **docs:** callout the key debug strategies. ([#3219](https://github.com/karma-runner/karma/issues/3219)) ([2682bff](https://github.com/karma-runner/karma/commit/2682bff)) + + + ## [3.1.1](https://github.com/karma-runner/karma/compare/v3.1.0...v3.1.1) (2018-10-23) @@ -57,23 +78,6 @@ - -## [2.0.6](https://github.com/karma-runner/karma/compare/v2.0.5...v2.0.6) (2018-08-09) - - -### Bug Fixes - -* **config:** wait 20s for browser activity. ([#3087](https://github.com/karma-runner/karma/issues/3087)) ([88b977f](https://github.com/karma-runner/karma/commit/88b977f)) -* **config:** Wait 30s for browser activity per Travis. ([#3091](https://github.com/karma-runner/karma/issues/3091)) ([f6d2f0e](https://github.com/karma-runner/karma/commit/f6d2f0e)) -* **init:** add "ChromeHeadless" to the browsers' options ([#3096](https://github.com/karma-runner/karma/issues/3096)) ([56fda53](https://github.com/karma-runner/karma/commit/56fda53)) -* **server:** Exit clean on unhandledRejections. ([#3092](https://github.com/karma-runner/karma/issues/3092)) ([02f54c6](https://github.com/karma-runner/karma/commit/02f54c6)), closes [#3064](https://github.com/karma-runner/karma/issues/3064) -* **travis:** Up the socket timeout 2->20s. ([#3103](https://github.com/karma-runner/karma/issues/3103)) ([732396a](https://github.com/karma-runner/karma/commit/732396a)), closes [#3102](https://github.com/karma-runner/karma/issues/3102) -* **travis:** use the value not the key name. ([#3097](https://github.com/karma-runner/karma/issues/3097)) ([90f5546](https://github.com/karma-runner/karma/commit/90f5546)) -* **travis:** validate TRAVIS_COMMIT if TRAVIS_PULL_REQUEST_SHA is not set. ([#3094](https://github.com/karma-runner/karma/issues/3094)) ([fba5d36](https://github.com/karma-runner/karma/commit/fba5d36)) -* **travis:** Validate TRAVIS_PULL_REQUEST_SHA rather than TRAVIS_COMMIT. ([#3093](https://github.com/karma-runner/karma/issues/3093)) ([a58fa45](https://github.com/karma-runner/karma/commit/a58fa45)) - - - ## [2.0.5](https://github.com/karma-runner/karma/compare/v2.0.4...v2.0.5) (2018-07-24) diff --git a/docs/intro/05-troubleshooting.md b/docs/intro/05-troubleshooting.md index 7d53fbff7..eab53a458 100644 --- a/docs/intro/05-troubleshooting.md +++ b/docs/intro/05-troubleshooting.md @@ -1,9 +1,16 @@ pageTitle: Troubleshooting menuTitle: Troubleshooting -Here you'll find a list of the most common problems and how to solve it. +### How Do I Debug a karma issue? + +Many issues can be solved by reading the `debug log` or by using the `browsers devtools`: + +#### Use `--log-level debug` to investigate server-side issues, especially configuration issues. +The `DEBUG` log includes a copy of the final 'config': note that plugins can alter the config and sometimes the settings you applied do not give the result you expected. The log includes both core `karma` lines and lines from plugins: use the logging prefix to determine if your issue may need to be reported to a karma plugin. + +#### Use `--no-single-run` to investigate browser-side issues, especially global errors in test files. +The `--no-single-run` option causes the server to print a URL and wait. Open the URL in a browser and use the browsers devtools to investigate the problem. Typically you will want to open the URL, then click the DEBUG link in the upper right corner. That opens a new window with cleaner code for debugging. -Note: If you can't find the solution for your issue here you can also ask for help in the [mailing-list](https://groups.google.com/d/forum/karma-users) or [Stack Overflow](http://stackoverflow.com/questions/tagged/karma-runner). ### I'm getting an error during the installation related to the ```ws``` module, how can I solve it? This is a common Windows [issue](https://github.com/einaros/ws/issues/178), the compilation of the native [ws](https://www.npmjs.org/package/ws) module fails. Anyways, ```ws``` has a fallback JS implementation which NPM should take care using it. All you need to do is make sure that you're using an up-to-date version of NPM. To do that you can: @@ -41,3 +48,6 @@ Try to remove `karma` and `karma-*` modules from your `node_modules` first (for ### My tests are running really slow. What's going on? Make sure the Karma's tab is active. Browsers give inactive tabs only minimum CPU. + +Note: If you can't find the solution for your issue here you can also ask for help in the [mailing-list](https://groups.google.com/d/forum/karma-users) or [Stack Overflow](http://stackoverflow.com/questions/tagged/karma-runner). + diff --git a/lib/browser.js b/lib/browser.js index 1301c93a5..81865395a 100644 --- a/lib/browser.js +++ b/lib/browser.js @@ -4,11 +4,11 @@ const BrowserResult = require('./browser_result') const helper = require('./helper') const logger = require('./logger') -const CONNECTED = 1 // The browser is connected but not yet been commanded to execute tests. -const CONFIGURING = 2 // The browser has been told to execute tests; it is configuring before tests execution. -const EXECUTING = 3 // The browser is executing the tests. -const EXECUTING_DISCONNECTED = 4 // The browser is executing the tests, but temporarily disconnect (waiting for reconnecting). -const DISCONNECTED = 5 // The browser got permanently disconnected (being removed from the collection and destroyed). +const CONNECTED = 'CONNECTED' // The browser is connected but not yet been commanded to execute tests. +const CONFIGURING = 'CONFIGURING' // The browser has been told to execute tests; it is configuring before tests execution. +const EXECUTING = 'EXECUTING' // The browser is executing the tests. +const EXECUTING_DISCONNECTED = 'EXECUTING_DISCONNECTED' // The browser is executing the tests, but temporarily disconnect (waiting for reconnecting). +const DISCONNECTED = 'DISCONNECTED' // The browser got permanently disconnected (being removed from the collection and destroyed). class Browser { constructor (id, fullName, collection, emitter, socket, timer, disconnectDelay, noActivityTimeout) { @@ -40,28 +40,31 @@ class Browser { this.emitter.emit('browser_register', this) } + setState (toState) { + this.log.debug(`${this.state} -> ${toState}`) + this.state = toState + } + onKarmaError (error) { if (this.isNotConnected()) { this.lastResult.error = true - this.emitter.emit('browser_error', this, error) - this.refreshNoActivityTimeout() } + this.emitter.emit('browser_error', this, error) + this.refreshNoActivityTimeout() } onInfo (info) { - if (this.isNotConnected()) { - if (helper.isDefined(info.dump)) { - this.emitter.emit('browser_log', this, info.dump, 'dump') - } - - if (helper.isDefined(info.log)) { - this.emitter.emit('browser_log', this, info.log, info.type) - } else if (!helper.isDefined(info.dump)) { - this.emitter.emit('browser_info', this, info) - } + if (helper.isDefined(info.dump)) { + this.emitter.emit('browser_log', this, info.dump, 'dump') + } - this.refreshNoActivityTimeout() + if (helper.isDefined(info.log)) { + this.emitter.emit('browser_log', this, info.log, info.type) + } else if (!helper.isDefined(info.dump)) { + this.emitter.emit('browser_info', this, info) } + + this.refreshNoActivityTimeout() } onStart (info) { @@ -70,14 +73,14 @@ class Browser { } this.lastResult = new BrowserResult(info.total) - this.state = EXECUTING + this.setState(EXECUTING) this.emitter.emit('browser_start', this, info) this.refreshNoActivityTimeout() } onComplete (result) { if (this.isNotConnected()) { - this.state = CONNECTED + this.setState(CONNECTED) this.lastResult.totalTimeEnd() if (!this.lastResult.success) { @@ -103,7 +106,7 @@ class Browser { this.disconnect(`Client disconnected from CONNECTED state (${reason})`) } else if ([CONFIGURING, EXECUTING].includes(this.state)) { this.log.debug(`Disconnected during run, waiting ${this.disconnectDelay}ms for reconnecting.`) - this.state = EXECUTING_DISCONNECTED + this.setState(EXECUTING_DISCONNECTED) this.pendingDisconnect = this.timer.setTimeout(() => { this.lastResult.totalTimeEnd() @@ -119,12 +122,12 @@ class Browser { reconnect (newSocket) { if (this.state === EXECUTING_DISCONNECTED) { this.log.debug(`Reconnected on ${newSocket.id}.`) - this.state = EXECUTING + this.setState(EXECUTING) } else if ([CONNECTED, CONFIGURING, EXECUTING].includes(this.state)) { this.log.debug(`New connection ${newSocket.id} (already have ${this.getActiveSocketsIds()})`) } else if (this.state === DISCONNECTED) { this.log.info(`Connected on socket ${newSocket.id} with id ${this.id}`) - this.state = CONNECTED + this.setState(CONNECTED) this.collection.add(this) this.emitter.emit('browser_register', this) @@ -155,7 +158,7 @@ class Browser { execute (config) { this.activeSockets.forEach((socket) => socket.emit('execute', config)) - this.state = CONFIGURING + this.setState(CONFIGURING) this.refreshNoActivityTimeout() } @@ -165,7 +168,7 @@ class Browser { disconnect (reason) { this.log.warn(`Disconnected (${this.disconnectsCount} times)${reason || ''}`) - this.state = DISCONNECTED + this.setState(DISCONNECTED) this.disconnectsCount++ this.emitter.emit('browser_error', this, `Disconnected${reason || ''}`) this.collection.remove(this) diff --git a/lib/file-list.js b/lib/file-list.js index a6dac0f25..f175a86e3 100644 --- a/lib/file-list.js +++ b/lib/file-list.js @@ -102,6 +102,12 @@ class FileList { return Promise.resolve(file) } + const prevFile = this._findFile(path, patternObject) + if (prevFile && file.mtime <= prevFile.mtime) { + log.debug(`Not preprocessing "${path}" as file hasn't been changed since the last preprocessing`) + return Promise.resolve(prevFile) + } + return this._preprocess(file).then(() => file) }) .then((files) => { diff --git a/lib/server.js b/lib/server.js index b4c62196e..9624d4c6b 100644 --- a/lib/server.js +++ b/lib/server.js @@ -8,8 +8,10 @@ const spawn = require('child_process').spawn const tmp = require('tmp') const fs = require('fs') const path = require('path') + const BundleUtils = require('./utils/bundle-utils') const NetUtils = require('./utils/net-utils') +const JsonUtils = require('./utils/json-utils') const root = global || window || this const cfg = require('./config') @@ -63,7 +65,7 @@ class Server extends KarmaEventEmitter { const config = cfg.parseConfig(cliOptions.configFile, cliOptions) - this.log.debug('Final config', JSON.stringify(config, null, 2)) + this.log.debug('Final config', JsonUtils.stringify(config, null, 2)) let modules = [{ helper: ['value', helper], diff --git a/lib/utils/json-utils.js b/lib/utils/json-utils.js new file mode 100644 index 000000000..a6bb481a9 --- /dev/null +++ b/lib/utils/json-utils.js @@ -0,0 +1,10 @@ + +const {stringify} = require('flatted/cjs') + +const JsonUtils = { + stringify (obj) { + return stringify(obj) + } +} + +module.exports = JsonUtils diff --git a/package.json b/package.json index ebbb9ea72..66fa534bb 100644 --- a/package.json +++ b/package.json @@ -36,93 +36,94 @@ "taichi ", "Liam Newman ", "lukasz ", - "Todd Wolfson ", "Michał Gołębiowski-Owczarek ", + "Todd Wolfson ", "Mark Trostler ", "Ciro Nunes ", "Shyam Seshadri ", "Robo ", - "Christian Budde Christensen ", "Tim Cuthbertson ", "Pawel Kozlowski ", - "Mark Ethan Trostler ", - "Daniel Compton ", + "Christian Budde Christensen ", "Mourad ", + "Daniel Compton ", + "Mark Ethan Trostler ", + "Kim Joar Bekkelund ", + "Brian Di Palma ", + "vivganes ", + "Nick Malaguti ", "joshjb84 ", "Georgii Dolzhykov ", - "Nick Malaguti ", - "vivganes ", - "Brian Di Palma ", - "Kim Joar Bekkelund ", - "ywong ", - "Chris Hunt ", "David Souther ", - "Brian Ford ", - "Daniel Aleksandersen ", - "Pieter Mees ", - "Marcello Nuccio ", - "Ilya Volodin ", + "Chris Hunt ", "Iristyle ", - "Jeff Jewiss ", - "Jake Champion ", - "Aymeric Beaumet ", + "Daniel Aleksandersen ", "pavelgj ", - "Andrew Martin ", + "Ilya Volodin ", "sylvain-hamel ", "Chris Casola ", + "Brian Ford ", + "ywong ", + "Jake Champion ", + "Andrew Martin ", + "Aymeric Beaumet ", + "Jeff Jewiss ", + "Marcello Nuccio ", + "Pieter Mees ", "Jérémy Judéaux ", - "Ruben Bridgewater ", - "David Pärsson ", + "rdodev ", "Réda Housni Alaoui ", - "DarthCharles ", + "Matt Lewis ", "Bulat Shakirzyanov ", "Sammy Jelin ", - "Sergei Startsev ", "Jonas Pommerening ", + "Sergei Startsev ", "Jonathan Freeman ", - "Shane Russell ", - "Josh ", "Andrew Morris ", + "Josh ", "Greenkeeper ", + "Shane Russell ", "Aseem Bansal ", "ChangZhuo Chen (陳昌倬) ", "Stefan Dragnev ", "Steve Mao ", "Steve Mao ", "Steve Van Opstal ", - "Sylvain Hamel ", "KJ Tsanaktsidis ", - "Terry ", + "Sylvain Hamel ", "Hugues Malphettes ", - "Thomas Parisot ", + "Terry ", "Igor Minar ", - "Tom Erik Støwer ", "Igor Minar ", + "Thomas Parisot ", + "Tom Erik Støwer ", "Kelly Jensen ", "Kevin Huang ", - "Vivek Ganesan ", - "Vladimir Starkov ", + "Bryan Smith ", "Kevin WENNER ", "Parashuram ", + "Vivek Ganesan ", + "Vladimir Starkov ", "Pat Tullmann ", - "Bryan Smith ", + "DarthCharles ", "PatrickJS ", "Levi Thomason ", - "Matt Lewis ", "James Ford ", - "comdiv ", "David Herges ", - "Luke Page ", "James Talmage ", + "Luke Page ", + "comdiv ", "Ethan J. Brown ", - "Richard Harrington ", "Ezra Brooks ", + "Richard Harrington ", + "Filipe Guerra ", "karmarunnerbot ", "Roarke Gaskill ", - "Filipe Guerra ", + "David Pärsson ", "Robin Liang ", "ngiebel ", - "rdodev ", + "Ruben Bridgewater ", + "Jurko Gospodnetić ", "Justin Ridgewell ", "KahWee Teng ", "Karl Lindmark ", @@ -193,6 +194,7 @@ "Piper Chester ", "Rafal Lindemann ", "Remy Sharp ", + "Rich Kuzsma ", "Richard Herrera ", "Roarke Gaskill ", "Rob Cherry ", @@ -206,6 +208,7 @@ "Saugat Acharya ", "Schmulik Raskin ", "Sergey Kruk ", + "Sergey Simonchik ", "Sergey Simonchik ", "Seth Rhodes ", "Shahar Mor ", @@ -363,10 +366,10 @@ "Jon Bretman ", "Jonathan ES Lin ", "Jonathan Felchlin ", + "Jonathan Niles ", "Josh Lory ", "João Marcos Duarte ", - "Julian Connor ", - "Jurko Gospodnetić " + "Julian Connor " ], "dependencies": { "bluebird": "^3.3.0", @@ -383,7 +386,7 @@ "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^4.17.4", + "lodash": "^4.17.5", "log4js": "^3.0.0", "mime": "^2.3.1", "minimatch": "^3.0.2", @@ -395,7 +398,7 @@ "socket.io": "2.1.1", "source-map": "^0.6.1", "tmp": "0.0.33", - "useragent": "2.2.1" + "useragent": "2.3.0" }, "devDependencies": { "LiveScript": "^1.3.0", @@ -412,6 +415,7 @@ "eslint-plugin-promise": "^3.4.2", "eslint-plugin-react": "^7.0.1", "eslint-plugin-standard": "^3.0.1", + "flatted": "^2.0.0", "grunt": "^1.0.0", "grunt-auto-release": "^0.0.7", "grunt-browserify": "^5.0.0", @@ -428,7 +432,6 @@ "http2": "^3.3.6", "husky": "^0.14.3", "jasmine-core": "^2.3.4", - "json3": "^3.3.2", "karma-browserify": "^5.0.1", "karma-browserstack-launcher": "^1.0.0", "karma-chai": "^0.1.0", @@ -458,7 +461,7 @@ "qunitjs": "^2.1.1", "requirejs": "^2.1.20", "sinon": "^6.1.5", - "sinon-chai": "^2.7.0", + "sinon-chai": "^3.0.0", "supertest": "^3.0.0", "timer-shim": "^0.3.0", "validate-commit-msg": "^2.11.1", @@ -471,7 +474,7 @@ "engines": { "node": ">= 6" }, - "version": "3.1.1", + "version": "3.1.2", "license": "MIT", "scripts": { "lint": "eslint . --ext js --ignore-pattern *.tpl.js", diff --git a/test/client/karma.spec.js b/test/client/karma.spec.js index bb933c0f6..78745962f 100644 --- a/test/client/karma.spec.js +++ b/test/client/karma.spec.js @@ -1,6 +1,5 @@ // shim all the things require('core-js/es5') -global.JSON = require('json3') var sinon = require('sinon') var assert = require('assert') diff --git a/test/e2e/browser_console.feature b/test/e2e/browser_console.feature index d760b76bd..69b3085a1 100644 --- a/test/e2e/browser_console.feature +++ b/test/e2e/browser_console.feature @@ -172,3 +172,39 @@ Feature: Browser Console Configuration . HeadlessChrome """ + Scenario: Execute logging program with singleRun + Given a configuration with: + """ + files = ['browser-console/log.js', 'browser-console/test.js']; + browsers = ['ChromeHeadlessNoSandbox']; + plugins = [ + 'karma-jasmine', + 'karma-chrome-launcher' + ]; + singleRun = false; + """ + When I runOut Karma + Then it passes with like: + """ + LOG: 'foo' + """ + Then it passes with like: + """ + DEBUG: 'bar' + """ + Then it passes with like: + """ + INFO: 'baz' + """ + Then it passes with like: + """ + WARN: 'foobar' + """ + Then it passes with like: + """ + ERROR: 'barbaz' + """ + Then it passes with like: + """ + SUCCESS + """ diff --git a/test/e2e/error.feature b/test/e2e/error.feature index 592740a3e..9d0f3d98d 100644 --- a/test/e2e/error.feature +++ b/test/e2e/error.feature @@ -18,3 +18,21 @@ Feature: Error Display """ SyntaxError: Unexpected token } """ + Scenario: Single-run Syntax Error in a test file + Given a configuration with: + """ + files = ['error/test.js', 'error/under-test.js']; + browsers = ['ChromeHeadlessNoSandbox']; + plugins = [ + 'karma-jasmine', + 'karma-chrome-launcher' + ]; + singleRun = false; + """ + When I monitor Karma + And I stop when the log contains 'SyntaxError' + Then it fails with like: + """ + SyntaxError: Unexpected token } + """ + And I stop a server programmatically diff --git a/test/e2e/step_definitions/core_steps.js b/test/e2e/step_definitions/core_steps.js index 420a38551..3d7581424 100644 --- a/test/e2e/step_definitions/core_steps.js +++ b/test/e2e/step_definitions/core_steps.js @@ -64,7 +64,7 @@ cucumber.defineSupportCode((a) => { } const runOut = command === 'runOut' - if (command === 'run' || command === 'runOut') { + if (command === 'run' || command === 'runOut' || command === 'monitor') { this.child = spawn('' + runtimePath, ['start', '--log-level', 'warn', configFile]) const done = () => { cleansingNeeded = true @@ -96,6 +96,9 @@ cucumber.defineSupportCode((a) => { } done() }) + if (command === 'monitor') { + done() + } }, 1000) }) } else { @@ -157,7 +160,7 @@ cucumber.defineSupportCode((a) => { defineParameterType({ name: 'command', - regexp: /run|runOut|start|init|stop/ + regexp: /run|runOut|start|init|stop|monitor/ }) defineParameterType({ @@ -177,6 +180,15 @@ cucumber.defineSupportCode((a) => { execKarma.apply(this, [command, undefined, proxyPort, proxyPath, callback]) }) + When('I stop when the log contains {string}', function (message, callback) { + setInterval(() => { + if (this.lastRun.stdout.includes(message)) { + this.child && this.child.kill() + callback() + } + }, 100) + }) + defineParameterType({ name: 'exact', regexp: /no\sdebug|like/ diff --git a/test/unit/browser.spec.js b/test/unit/browser.spec.js index 8c670eb97..447bb02cc 100644 --- a/test/unit/browser.spec.js +++ b/test/unit/browser.spec.js @@ -91,14 +91,11 @@ describe('Browser', () => { expect(spy).to.have.been.called }) - it('should ignore if browser not executing', () => { - const spy = sinon.spy() - emitter.on('browser_error', spy) + it('should not set lastResult if browser not executing', () => { browser.state = Browser.STATE_CONNECTED browser.onKarmaError() expect(browser.lastResult.error).to.equal(false) - expect(spy).not.to.have.been.called }) }) diff --git a/test/unit/file-list.spec.js b/test/unit/file-list.spec.js index 3bec4bc68..bd2c9241a 100644 --- a/test/unit/file-list.spec.js +++ b/test/unit/file-list.spec.js @@ -375,9 +375,15 @@ describe('FileList', () => { }) }) - it('preprocesses all files', () => { + it('preprocesses new and/or changed files', () => { return list.refresh().then((files) => { expect(preprocess.callCount).to.be.eql(5) + preprocess.resetHistory() + mg.statCache['/some/a.js'].mtime++ + return list.refresh().then((files) => { + expect(preprocess.callCount).to.be.eql(1) + mg.statCache['/some/a.js'].mtime-- + }) }) }) diff --git a/test/unit/helper.spec.js b/test/unit/helper.spec.js index 3cabf4a1c..65651dac2 100644 --- a/test/unit/helper.spec.js +++ b/test/unit/helper.spec.js @@ -75,7 +75,7 @@ describe('helper', () => { 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; SLCC1; ' + '.NET CLR 2.0.50727; .NET4.0C; .NET4.0E)' ) - .to.be.equal('IE 7.0.0 (Windows Vista 0.0.0)') + .to.be.equal('IE 7.0.0 (Windows Vista.0.0)') }) it('should parse IE8', () => { @@ -83,7 +83,7 @@ describe('helper', () => { 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; ' + 'SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E; InfoPath.3)"' ) - .to.be.equal('IE 8.0.0 (Windows 7 0.0.0)') + .to.be.equal('IE 8.0.0 (Windows 7.0.0)') }) it('should parse IE9', () => { @@ -91,7 +91,7 @@ describe('helper', () => { 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; ' + '.NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)' ) - .to.be.equal('IE 9.0.0 (Windows 7 0.0.0)') + .to.be.equal('IE 9.0.0 (Windows 7.0.0)') }) it('should parse IE10', () => { @@ -99,7 +99,7 @@ describe('helper', () => { 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0; ' + '.NET4.0E; .NET4.0C)' ) - .to.be.equal('IE 10.0.0 (Windows 8 0.0.0)') + .to.be.equal('IE 10.0.0 (Windows 8.0.0)') }) it('should parse PhantomJS', () => { @@ -118,6 +118,14 @@ describe('helper', () => { ) .to.be.equal('Android 4.2.0 (Android 4.2.0)') }) + + it('should parse Headless Chrome', () => { + expecting( + 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) ' + + 'HeadlessChrome/70.0.3538.77 Safari/537.36' + ) + .to.be.equal('HeadlessChrome 70.0.3538 (Linux 0.0.0)') + }) }) describe('isDefined', () => { diff --git a/test/unit/utils/json-utils.spec.js b/test/unit/utils/json-utils.spec.js new file mode 100644 index 000000000..aa6757e81 --- /dev/null +++ b/test/unit/utils/json-utils.spec.js @@ -0,0 +1,18 @@ +'use strict' + +const JsonUtils = require('../../../lib/utils/json-utils') + +describe('json-utils', () => { + it('stringify-s', () => { + const obj = {a: 'a', i: 1} + const json = JsonUtils.stringify(obj) + expect(json).to.be.equal('[{"a":"1","i":1},"a"]') + }) + it('stringify-s circular data', () => { + const a = [{}] + a[0].a = a + a.push(a) + + expect(JsonUtils.stringify(a)).to.be.equal('[["1","0"],{"a":"0"}]') + }) +})