From 5c72f0e81db68fd370b41ae15611fabcb6644515 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:43:48 +0200 Subject: [PATCH 01/36] Use prebuild docker images, update ubuntu, added README --- docker/README.md | 15 +++++++++++++++ docker/docker-compose.yml | 12 +++--------- docker/dockerfiles/dockerfile-saltmaster | 17 ++++++++++------- docker/dockerfiles/dockerfile-saltminion-debian | 13 +++++++------ docker/dockerfiles/dockerfile-saltminion-ubuntu | 17 +++++++++-------- 5 files changed, 44 insertions(+), 30 deletions(-) create mode 100644 docker/README.md diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 000000000..758b18346 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,15 @@ +Versions +-------- +These docker images are build with Ubuntu 18.04 (bionic) and Debian 9 (stretch). They use the following repositories to install saltstack: +- https://repo.saltstack.com/apt/debian/9/amd64/latest +- http://repo.saltstack.com/py3/ubuntu/18.04/amd64/latest + +Version of all salt packages installed: *2018.3.2+ds-1* + +Docker images +------------- +Commands used to build these docker images:: + + docker build -f dockerfiles/dockerfile-saltmaster -t maerteijn/saltgui-saltmaster . + docker build -f dockerfiles/dockerfile-saltminion-debian -t maerteijn/saltgui-saltminion-debian . + docker build -f dockerfiles/dockerfile-saltminion-ubuntu -t maerteijn/saltgui-saltminion-ubuntu . diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 67ab65fd1..5e0197e18 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,9 +1,7 @@ version: '3' services: saltmaster-local: - build: - context: . - dockerfile: ./dockerfiles/dockerfile-saltmaster + image: maerteijn/saltgui-saltmaster ports: - 4505:4505 - 4506:4506 @@ -14,18 +12,14 @@ services: entrypoint: /usr/bin/supervisord saltminion-ubuntu: - build: - context: . - dockerfile: ./dockerfiles/dockerfile-saltminion-ubuntu + image: maerteijn/saltgui-saltminion-ubuntu depends_on: - saltmaster-local restart: on-failure command: /usr/bin/salt-minion saltminion-debian: - build: - context: . - dockerfile: ./dockerfiles/dockerfile-saltminion-debian + image: maerteijn/saltgui-saltminion-debian depends_on: - saltmaster-local restart: on-failure diff --git a/docker/dockerfiles/dockerfile-saltmaster b/docker/dockerfiles/dockerfile-saltmaster index 6c55097be..156f846c7 100644 --- a/docker/dockerfiles/dockerfile-saltmaster +++ b/docker/dockerfiles/dockerfile-saltmaster @@ -1,16 +1,16 @@ -FROM ubuntu +FROM ubuntu:18.04 MAINTAINER Martijn Jacobs -ENV REFRESHED_ON "7 Mar 2018" +ENV REFRESHED_ON "24 Jul 2018" ENV DEBIAN_FRONTEND noninteractive -# add saltstack key and install gnupg2 -RUN apt-get update && apt-get install curl --yes && apt-get install gnupg2 --yes -RUN curl --fail --silent --show-error --location https://repo.saltstack.com/apt/ubuntu/16.04/amd64/latest/SALTSTACK-GPG-KEY.pub | apt-key add - -RUN echo 'deb http://repo.saltstack.com/apt/ubuntu/16.04/amd64/latest xenial main' > /etc/apt/sources.list.d/saltstack.list +# add saltstack key and install dependencies +RUN apt-get update && apt-get install curl net-tools gnupg2 --yes +RUN curl --fail --silent --show-error --location https://repo.saltstack.com/py3/ubuntu/18.04/amd64/latest/SALTSTACK-GPG-KEY.pub | apt-key add - +RUN echo 'deb http://repo.saltstack.com/py3/ubuntu/18.04/amd64/latest bionic main' > /etc/apt/sources.list.d/saltstack.list # install salt-master and salt-api, dependencies -RUN apt-get update && apt-get install salt-master --yes && apt-get install salt-api --yes +RUN apt-get update && apt-get install salt-master salt-api --yes # add a user for the frontend salt:salt RUN useradd -m -s/bin/bash -p $(openssl passwd -1 salt) salt @@ -25,3 +25,6 @@ ADD ./conf/supervisord.conf /etc/supervisor/conf.d/supervisord.conf # some volume configuration for the saltmaster VOLUME ["/pki","/var/cache/salt","/var/log/salt"] EXPOSE 3333 4505 4506 + +# show which versions are installed +RUN dpkg -l | grep salt\- diff --git a/docker/dockerfiles/dockerfile-saltminion-debian b/docker/dockerfiles/dockerfile-saltminion-debian index a651dd744..04306c50c 100644 --- a/docker/dockerfiles/dockerfile-saltminion-debian +++ b/docker/dockerfiles/dockerfile-saltminion-debian @@ -1,13 +1,11 @@ -FROM debian +FROM debian:9 MAINTAINER Martijn Jacobs -ENV REFRESHED_ON "7 Mar 2018" +ENV REFRESHED_ON "24 Jul 2018" ENV DEBIAN_FRONTEND noninteractive -# some handy stuff to have -RUN apt-get update && apt-get install curl --yes && apt-get install gnupg --yes - -# add saltstack key +# add saltstack key and install dependencies +RUN apt-get update && apt-get install curl gnupg net-tools --yes RUN curl --fail --silent --show-error --location https://repo.saltstack.com/apt/debian/9/amd64/latest/SALTSTACK-GPG-KEY.pub | apt-key add - RUN echo 'deb http://repo.saltstack.com/apt/debian/9/amd64/latest stretch main' > /etc/apt/sources.list.d/saltstack.list @@ -16,3 +14,6 @@ RUN apt-get update && apt-get install salt-minion --yes # copy the minion configuration ADD ./conf/minion /etc/salt/minion + +# show which versions are installed +RUN dpkg -l | grep salt\- diff --git a/docker/dockerfiles/dockerfile-saltminion-ubuntu b/docker/dockerfiles/dockerfile-saltminion-ubuntu index 09cf070f2..a40b25fae 100644 --- a/docker/dockerfiles/dockerfile-saltminion-ubuntu +++ b/docker/dockerfiles/dockerfile-saltminion-ubuntu @@ -1,18 +1,19 @@ -FROM ubuntu +FROM ubuntu:18.04 MAINTAINER Martijn Jacobs -ENV REFRESHED_ON "7 Mar 2018" +ENV REFRESHED_ON "24 Jul 2018" ENV DEBIAN_FRONTEND noninteractive -# some handy stuff to have and install gnupg2 -RUN apt-get update && apt-get install curl --yes && apt-get install iproute2 --yes && apt-get install gnupg2 --yes - -# add saltstack key -RUN curl --fail --silent --show-error --location https://repo.saltstack.com/apt/ubuntu/16.04/amd64/latest/SALTSTACK-GPG-KEY.pub | apt-key add - -RUN echo 'deb http://repo.saltstack.com/apt/ubuntu/16.04/amd64/latest xenial main' > /etc/apt/sources.list.d/saltstack.list +# add saltstack key and install dependencies +RUN apt-get update && apt-get install curl gnupg2 net-tools --yes +RUN curl --fail --silent --show-error --location https://repo.saltstack.com/py3/ubuntu/18.04/amd64/latest/SALTSTACK-GPG-KEY.pub | apt-key add - +RUN echo 'deb http://repo.saltstack.com/py3/ubuntu/18.04/amd64/latest bionic main' > /etc/apt/sources.list.d/saltstack.list # install salt-minion RUN apt-get update && apt-get install salt-minion --yes # copy the minion configuration ADD ./conf/minion /etc/salt/minion + +# show which versions are installed +RUN dpkg -l | grep salt\- From 77b1d2a99972baa21bd9eec51edb596b110d9f7d Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:45:11 +0200 Subject: [PATCH 02/36] Added nightmare.js, chai, mocha and wait-on for testing --- package.json | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 94088197e..d86fd3061 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,15 @@ { - "name": "saltgui-linter", - "description": "Simple check for JSHint (Code Linting)", + "name": "saltgui-test", + "description": "Code linting and testing package for SaltGUI", "author": "Martijn Jacobs", "version": "0.0.1", + "license": "MIT", "devDependencies": { - "jshint": "^2.9.5" + "chai": "^4.1.2", + "jshint": "^2.9.5", + "mocha": "^5.2.0", + "nightmare": "^3.0.1", + "wait-on": "^2.1.0" }, "jshintConfig": { "esversion": 6 From a58cba569427980139e9e0612aa925a069d3a3a0 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:47:55 +0200 Subject: [PATCH 03/36] Added helperscript to wait for the dockersetup to be ready --- tests/helpers/wait-for-docker.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/helpers/wait-for-docker.js diff --git a/tests/helpers/wait-for-docker.js b/tests/helpers/wait-for-docker.js new file mode 100644 index 000000000..bfd0e7bd3 --- /dev/null +++ b/tests/helpers/wait-for-docker.js @@ -0,0 +1,19 @@ +const waitOn = require('wait-on'); + +console.log("waiting for docker setup to be ready"); + +var resources = { + resources: [ + 'http://localhost:3333/', + ], + timeout: 30000, + followAllRedirects: true, + followRedirect: true, +}; + +waitOn(resources, error => { + if (error) + console.error(error); + else + console.log("docker setup is ready"); +}); From 392ff57c248f32929ee575125ed9d76004c09b97 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:49:12 +0200 Subject: [PATCH 04/36] Added id to submit button so we can select it in js --- saltgui/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/saltgui/index.html b/saltgui/index.html index 8316484b3..201f91730 100644 --- a/saltgui/index.html +++ b/saltgui/index.html @@ -54,7 +54,7 @@

SaltGUI

- +
SaltGUI v1.2.0
From 1f8a4f3f38c8b0370dc8ea580e187121a8589ebc Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:49:31 +0200 Subject: [PATCH 05/36] Added a unittest for elapsedToString --- tests/unit/utils.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/unit/utils.js diff --git a/tests/unit/utils.js b/tests/unit/utils.js new file mode 100644 index 000000000..ed8f5855b --- /dev/null +++ b/tests/unit/utils.js @@ -0,0 +1,43 @@ +const assert = require('chai').assert; + +// so we can import the utils for testing +global.window = new Object({}); +require('../../saltgui/static/scripts/utils'); + + +describe('Unittests for utils.js', function() { + + it('test elapsedToString', done => { + var now = new Date(); + var result = window.elapsedToString(now); + + assert.equal(result, "A few moments ago"); + + now.setSeconds(now.getSeconds() - 110); + result = window.elapsedToString(now); + assert.equal(result, "A few minutes ago"); + + now.setMinutes(now.getMinutes() - 1); + result = window.elapsedToString(now); + assert.equal(result, "3 minutes ago"); + + now.setHours(now.getHours() - 2); + result = window.elapsedToString(now); + assert.equal(result, "2 hours ago"); + + now.setHours(now.getHours() - 24); + result = window.elapsedToString(now); + assert.equal(result, "Yesterday"); + + now.setHours(now.getHours() - 240); + result = window.elapsedToString(now); + assert.equal(result, "11 days ago"); + + now.setHours(now.getHours() - 2400); + result = window.elapsedToString(now); + assert.equal(result, "A long time ago, in a galaxy far, far away"); + + done(); + }); + +}); From 25a735b154d9e19d496fc21304ebc17c22818583 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:51:02 +0200 Subject: [PATCH 06/36] forEach expects an array (at least in Node.js) --- saltgui/static/scripts/router.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/saltgui/static/scripts/router.js b/saltgui/static/scripts/router.js index 29e0313c4..b87a7588e 100644 --- a/saltgui/static/scripts/router.js +++ b/saltgui/static/scripts/router.js @@ -45,9 +45,9 @@ class Router { var router = this; route.getPageElement().style.display = ""; - document.querySelectorAll(".menu_item_active").forEach( - function (e){ e.classList.remove("menu_item_active"); } - ); + Array.from(document.querySelectorAll(".menu_item_active")).forEach( + function (e){ e.classList.remove("menu_item_active"); } + ); var elem = route.getMenuItemElement(); if(elem) elem.classList.add("menu_item_active"); From 30738267f3760ed60efecc8e875c313470c4e8ba Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:51:35 +0200 Subject: [PATCH 07/36] _callMethod already returns a promise --- saltgui/static/scripts/api.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/saltgui/static/scripts/api.js b/saltgui/static/scripts/api.js index 75506e12b..9b573e78a 100644 --- a/saltgui/static/scripts/api.js +++ b/saltgui/static/scripts/api.js @@ -105,13 +105,11 @@ class API { var params = { }; - return new Promise(function(resolve, reject) { - api._callMethod("POST", "/logout", params) - .then(function(data) { - window.sessionStorage.removeItem("token"); - window.location.replace("/"); - resolve(); - }, reject); + return api._callMethod("POST", "/logout", params).then(response => { + window.sessionStorage.removeItem("token"); + window.location.replace("/"); + }).catch(error => { + console.error("_logout", error); }); } From 1acf4cf3ed3767e5bdc7d739138879eff8217473 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:52:13 +0200 Subject: [PATCH 08/36] Added first tests with nightmarejs --- tests/functional/login.js | 60 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 tests/functional/login.js diff --git a/tests/functional/login.js b/tests/functional/login.js new file mode 100644 index 000000000..10ba30892 --- /dev/null +++ b/tests/functional/login.js @@ -0,0 +1,60 @@ +const Nightmare = require('nightmare'); +const assert = require('chai').assert; + +const url = 'http://localhost:3333/'; + + +describe('Login tests', function() { + + this.timeout('10s'); + + let browser = null; + + beforeEach( () => { + browser = new Nightmare({ + // uncomment this to show the browser and the debug window + // openDevTools: { + // mode: "detach" + // }, + // show: true + }); + browser + .goto(url); + }); + + describe('Login', () => { + + it('we should be redirected to the login page', done => { + browser + .end() + .evaluate( () => { return document; } ) + .then(function (document) { + assert.equal(document.location.href, 'http://localhost:3333/login'); + done(); + }) + .catch(done); + }); + + it('we cannot login with false credentials', done => { + var selector = '.notice-wrapper'; + browser + .type('#username', 'sald') + .type('#password', 'sald') + .click('#login-submit') + .wait('.notice') + .end() + .evaluate(selector => { + return document.querySelector('.notice-wrapper div').textContent; + }, selector) + .then(function (message) { + assert.equal(message, 'Authentication failed'); + done() ; + }) + .catch(error => { + console.log(error); + }); + }); + + }); + +}); From 152993e4bba174d8805ef52747c983f94ebae1b5 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:53:22 +0200 Subject: [PATCH 09/36] Update package.json with more testing scripts --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d86fd3061..b08690107 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,8 @@ "esversion": 6 }, "scripts": { - "test": "jshint saltgui/" + "lint": "jshint saltgui/ tests/", + "wait-for-docker": "node tests/helpers/wait-for-docker.js", + "test": "mocha --trace-warnings --reporter spec tests/unit/" } } From 7cb28983802485aed2295dbb106a1d38f1877730 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:52:32 +0200 Subject: [PATCH 10/36] Added a testscript to run all tests --- runtests.sh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100755 runtests.sh diff --git a/runtests.sh b/runtests.sh new file mode 100755 index 000000000..a30587bb9 --- /dev/null +++ b/runtests.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e +# add testing packages +yarn + +# first see if we write es6 compatible js +yarn lint + +# start a salt master, two salt minions and saltgui to run tests on +docker-compose -f docker/docker-compose.yml up -d + +# wait until all are up +yarn wait-for-docker + +# run the unittests/nightmare.js functional tests +yarn test + +# cleanup the docker images for 100% reproducable testresults +docker-compose -f docker/docker-compose.yml rm -f -s + +set +e From 22df9b0539ccd6150a1e76812506540c2750dbdd Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:52:53 +0200 Subject: [PATCH 11/36] added docker environment to travis and call runtests.sh --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 24cf6203a..3b493d09c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,9 @@ language: node_js node_js: - "node" +services: + - docker before_script: - cd $TRAVIS_BUILD_DIR +script: + - ./runtests.sh From 0809c69f83770d2fcff97705345ed4c813c2bcb3 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:56:07 +0200 Subject: [PATCH 12/36] Updated README and added testing documentation --- README.MD | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/README.MD b/README.MD index 88f76ab38..23c2003f1 100644 --- a/README.MD +++ b/README.MD @@ -2,10 +2,12 @@ A new open source web interface for managing a SaltStack server. Built using vanilla ES6 and implemented as a wrapper around the rest_cherrypy server. + ## Screenshots ![overview](/docs/overview.png) ![job](/docs/job.png) + ## Features - Login via PAM or any other supported authentication by Salt - View minions and easily copy IPs @@ -13,6 +15,7 @@ A new open source web interface for managing a SaltStack server. Built using van - View the seven most recent jobs run on Salt - Manually run any Salt function and see the output + ## Quick start using PAM as authentication method - Install `salt-api` - this is available in the Salt PPA package which should already been installed if you're using Salt - Open the master config /etc/salt/master @@ -59,8 +62,16 @@ docker-compose up ``` Then browse to [http://localhost:3333/](http://localhost:3333/), you can login with `salt:salt`. + +## Testing +We also provide some [nightmare.js](https://github.com/segmentio/nightmare) and unittests. They use the docker setup to run some functional tests. You will also need [yarn](https://yarnpkg.com) and [node.js](https://nodejs.org/en/) to run them. When you have docker, yarn and node.js installed, you can run the tests from the root of the repository like this: +``` +./runtests.sh +``` + ## Contributing -- Just open a PR! Try to use no dependencies where possible, as vanilla JS is the aim. Any libraries will need to be heavily considered first. +Open a PR! Try to use no dependencies where possible, as vanilla JS is the aim. Any libraries will need to be heavily considered first. Please see the section above as PR's won't be reviewed if they don't pass the tests. + ## Credits This excellent frontend is originally written by [Oliver Dunk](https://github.com/oliverdunk). @@ -89,8 +100,8 @@ This excellent frontend is originally written by [Oliver Dunk](https://github.co ## 1.0.1 (2018-05-16) - Fixed position of popup when main window has scrolled (erwindon) - Sort minions by hostname (erwindon) -- Fixed OS description in minion overview (No lsb_distrib_description) [#5](https://github.com/maerteijn/SaltGUI/issues/5) (erwindon) -- Now sort the jobs correctly on StartDate in the overview window [#6](https://github.com/maerteijn/SaltGUI/issues/6) +- Fixed OS description in minion overview (No lsb_distrib_description)(erwindon) +- Now sort the jobs correctly on ``StartDate`` in the overview window ## 1.0.0 (2018-03-07) -Original release with some styling fixes and with enabled the highstate functionality. +- Original release with some styling fixes and with enabled highstate functionality. From f46bc160ef7838dd41a8f31171f4fbaf08e6ba65 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Thu, 2 Aug 2018 21:56:21 +0200 Subject: [PATCH 13/36] Updated yarn.lock --- yarn.lock | 1205 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1205 insertions(+) create mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..79bcbf08b --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1205 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/node@^8.0.24": + version "8.10.23" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.23.tgz#e5ccfdafff42af5397c29669b6d7d65f7d629a00" + +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assertion-error@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + dependencies: + tweetnacl "^0.14.3" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + +builtin-modules@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +chai@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c" + dependencies: + assertion-error "^1.0.1" + check-error "^1.0.1" + deep-eql "^3.0.0" + get-func-name "^2.0.0" + pathval "^1.0.0" + type-detect "^4.0.0" + +check-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + +cli@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cli/-/cli-1.0.1.tgz#22817534f24bfa4950c34d532d48ecbc621b8c14" + dependencies: + exit "0.1.2" + glob "^7.1.1" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +combined-stream@1.0.6, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" + dependencies: + delayed-stream "~1.0.0" + +commander@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/commander/-/commander-1.0.4.tgz#5edeb1aee23c4fb541a6b70d692abef19669a2d3" + dependencies: + keypress "0.1.x" + +commander@2.15.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +console-browserify@1.1.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + dependencies: + date-now "^0.1.4" + +core-js@^2.4.1: + version "2.5.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + dependencies: + array-find-index "^1.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + +debug@2.6.9, debug@^2.1.3, debug@^2.2.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + +decamelize@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deep-defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/deep-defaults/-/deep-defaults-1.0.4.tgz#1a9762e2b6c8d6a4e9931b8ee7ff8cdcee1d1750" + dependencies: + lodash "3.0.x" + +deep-eql@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + dependencies: + type-detect "^4.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + +defaults@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + dependencies: + clone "^1.0.2" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + +dom-serializer@0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +domelementtype@1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" + dependencies: + domelementtype "1" + +domutils@1.5: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + dependencies: + dom-serializer "0" + domelementtype "1" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +electron-download@^3.0.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-3.3.0.tgz#2cfd54d6966c019c4d49ad65fbe65cc9cdef68c8" + dependencies: + debug "^2.2.0" + fs-extra "^0.30.0" + home-path "^1.0.1" + minimist "^1.2.0" + nugget "^2.0.0" + path-exists "^2.1.0" + rc "^1.1.2" + semver "^5.3.0" + sumchecker "^1.2.0" + +electron@^1.8.4: + version "1.8.7" + resolved "https://registry.yarnpkg.com/electron/-/electron-1.8.7.tgz#373c1dc4589d7ab4acd49aff8db4a1c0a6c3bcc1" + dependencies: + "@types/node" "^8.0.24" + electron-download "^3.0.1" + extract-zip "^1.0.3" + +enqueue@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/enqueue/-/enqueue-1.0.2.tgz#9014e9bce570ee93ca96e6c8e63ad54c192b6bc8" + dependencies: + sliced "0.0.5" + +entities@1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" + +entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + +error-ex@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + dependencies: + is-arrayish "^0.2.1" + +es6-promise@^4.0.5: + version "4.2.4" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" + +escape-string-regexp@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +exit@0.1.2, exit@0.1.x: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + +extend@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + +extract-zip@^1.0.3: + version "1.6.7" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9" + dependencies: + concat-stream "1.6.2" + debug "2.6.9" + mkdirp "0.5.1" + yauzl "2.4.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fd-slicer@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" + dependencies: + pend "~1.2.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + dependencies: + asynckit "^0.4.0" + combined-stream "1.0.6" + mime-types "^2.1.12" + +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +function-source@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/function-source/-/function-source-0.1.0.tgz#d9104bf3e46788b55468c02bf1b2fabcf8fc19af" + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob@7.1.2, glob@^7.0.5, glob@^7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + +hoek@4.x.x: + version "4.2.1" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" + +home-path@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/home-path/-/home-path-1.0.6.tgz#d549dc2465388a7f8667242c5b31588d29af29fc" + +hosted-git-info@^2.1.4: + version "2.7.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + +htmlparser2@3.8.x: + version "3.8.3" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" + dependencies: + domelementtype "1" + domhandler "2.3" + domutils "1.5" + entities "1.0" + readable-stream "1.1" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + dependencies: + repeating "^2.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isemail@2.x.x: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isemail/-/isemail-2.2.1.tgz#0353d3d9a62951080c262c2aa0a42b8ea8e9e2a6" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +items@2.x.x: + version "2.1.1" + resolved "https://registry.yarnpkg.com/items/-/items-2.1.1.tgz#8bd16d9c83b19529de5aea321acaada78364a198" + +joi@^9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-9.2.0.tgz#3385ac790192130cbe230e802ec02c9215bbfeda" + dependencies: + hoek "4.x.x" + isemail "2.x.x" + items "2.x.x" + moment "2.x.x" + topo "2.x.x" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jsesc@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +jshint@^2.9.5: + version "2.9.5" + resolved "https://registry.yarnpkg.com/jshint/-/jshint-2.9.5.tgz#1e7252915ce681b40827ee14248c46d34e9aa62c" + dependencies: + cli "~1.0.0" + console-browserify "1.1.x" + exit "0.1.x" + htmlparser2 "3.8.x" + lodash "3.7.x" + minimatch "~3.0.2" + shelljs "0.3.x" + strip-json-comments "1.0.x" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + optionalDependencies: + graceful-fs "^4.1.6" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +keypress@0.1.x: + version "0.1.0" + resolved "https://registry.yarnpkg.com/keypress/-/keypress-0.1.0.tgz#4a3188d4291b66b4f65edb99f806aa9ae293592a" + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + optionalDependencies: + graceful-fs "^4.1.9" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +lodash@3.0.x: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.0.1.tgz#14d49028a38bc740241d11e2ecd57ec06d73c19a" + +lodash@3.7.x: + version "3.7.0" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.7.0.tgz#3678bd8ab995057c07ade836ed2ef087da811d45" + +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + +meow@^3.1.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + +mime-db@~1.35.0: + version "1.35.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" + +mime-types@^2.1.12, mime-types@~2.1.17: + version "2.1.19" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0" + dependencies: + mime-db "~1.35.0" + +minimatch@3.0.4, minimatch@^3.0.4, minimatch@~3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minstache@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minstache/-/minstache-1.2.0.tgz#ff1cc403ac2844f68dbf18c662129be7eb0efc41" + dependencies: + commander "1.0.4" + +mkdirp@0.5.1, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + dependencies: + browser-stdout "1.3.1" + commander "2.15.1" + debug "3.1.0" + diff "3.5.0" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.5" + he "1.1.1" + minimatch "3.0.4" + mkdirp "0.5.1" + supports-color "5.4.0" + +moment@2.x.x: + version "2.22.2" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +multiline@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/multiline/-/multiline-1.0.2.tgz#69b1f25ff074d2828904f244ddd06b7d96ef6c93" + dependencies: + strip-indent "^1.0.0" + +nightmare@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/nightmare/-/nightmare-3.0.1.tgz#a474761b2f0e08c2b75af24a66c201668e5c53d3" + dependencies: + debug "^2.2.0" + deep-defaults "^1.0.3" + defaults "^1.0.2" + electron "^1.8.4" + enqueue "^1.0.2" + function-source "^0.1.0" + jsesc "^0.5.0" + minstache "^1.2.0" + mkdirp "^0.5.1" + multiline "^1.0.2" + once "^1.3.3" + rimraf "^2.4.3" + sliced "1.0.1" + split2 "^2.0.1" + +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +nugget@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/nugget/-/nugget-2.0.1.tgz#201095a487e1ad36081b3432fa3cada4f8d071b0" + dependencies: + debug "^2.1.3" + minimist "^1.1.0" + pretty-bytes "^1.0.2" + progress-stream "^1.1.0" + request "^2.45.0" + single-line-log "^1.1.2" + throttleit "0.0.2" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + +once@^1.3.0, once@^1.3.3: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +path-exists@^2.0.0, path-exists@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +pathval@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pretty-bytes@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-1.0.4.tgz#0a22e8210609ad35542f8c8d5d2159aff0751c84" + dependencies: + get-stdin "^4.0.1" + meow "^3.1.0" + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + +progress-stream@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/progress-stream/-/progress-stream-1.2.0.tgz#2cd3cfea33ba3a89c9c121ec3347abe9ab125f77" + dependencies: + speedometer "~0.1.2" + through2 "~0.2.3" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +qs@~6.5.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + +rc@^1.1.2: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +readable-stream@1.1: + version "1.1.13" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.1.5, readable-stream@^2.2.2: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +request@^2.45.0, request@^2.78.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +rimraf@^2.2.8, rimraf@^2.4.3: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +rx@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" + +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +safer-buffer@^2.0.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + +"semver@2 || 3 || 4 || 5", semver@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +shelljs@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +single-line-log@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/single-line-log/-/single-line-log-1.1.2.tgz#c2f83f273a3e1a16edb0995661da0ed5ef033364" + dependencies: + string-width "^1.0.1" + +sliced@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/sliced/-/sliced-0.0.5.tgz#5edc044ca4eb6f7816d50ba2fc63e25d8fe4707f" + +sliced@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41" + +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" + +speedometer@~0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d" + +split2@^2.0.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493" + dependencies: + through2 "^2.0.2" + +sshpk@^1.7.0: + version "1.14.2" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + safer-buffer "^2.0.2" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + +strip-indent@^1.0.0, strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + dependencies: + get-stdin "^4.0.1" + +strip-json-comments@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +sumchecker@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-1.3.1.tgz#79bb3b4456dd04f18ebdbc0d703a1d1daec5105d" + dependencies: + debug "^2.2.0" + es6-promise "^4.0.5" + +supports-color@5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + +throttleit@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" + +through2@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +through2@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f" + dependencies: + readable-stream "~1.1.9" + xtend "~2.1.1" + +topo@2.x.x: + version "2.0.2" + resolved "https://registry.yarnpkg.com/topo/-/topo-2.0.2.tgz#cd5615752539057c0dc0491a621c3bc6fbe1d182" + dependencies: + hoek "4.x.x" + +tough-cookie@~2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + dependencies: + punycode "^1.4.1" + +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-detect@^4.0.0: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +uuid@^3.1.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + +validate-npm-package-license@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +wait-on@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-2.1.0.tgz#3c4ace1f57266ca5be7fa25e0c15803b889ca46a" + dependencies: + core-js "^2.4.1" + joi "^9.2.0" + minimist "^1.2.0" + request "^2.78.0" + rx "^4.1.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + dependencies: + object-keys "~0.4.0" + +xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +yauzl@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" + dependencies: + fd-slicer "~1.0.1" From 4ce400eaeb4f01c9e6f88c95fcdeb21fa4917942 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Fri, 3 Aug 2018 12:12:42 +0200 Subject: [PATCH 14/36] Added more unittests and fix global window hack And improved elapsedToString according to the tests fsdfsfs --- saltgui/static/scripts/utils.js | 45 +++++++++++++++++++-------------- tests/unit/parsecmdline.js | 26 +++++++++++++++++++ tests/unit/utils.js | 25 +++++++++++++++--- 3 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 tests/unit/parsecmdline.js diff --git a/saltgui/static/scripts/utils.js b/saltgui/static/scripts/utils.js index 4030f20a3..ec2360ec8 100644 --- a/saltgui/static/scripts/utils.js +++ b/saltgui/static/scripts/utils.js @@ -1,28 +1,35 @@ window.elapsedToString = function(date) { - var secondsPassed = (new Date().getTime() / 1000) - (date.getTime() / 1000); - if(secondsPassed < 20) return "A few moments ago"; - if(secondsPassed < 120) return "A few minutes ago"; + try { + var secondsPassed = (new Date().getTime() / 1000) - (date.getTime() / 1000); - if(secondsPassed < 60 * 60) { - var minutes = Math.round(secondsPassed / 60); - return minutes + " minutes ago"; - } + if(secondsPassed < 0) return "Magic happened in the future"; + if(secondsPassed < 20) return "A few moments ago"; + if(secondsPassed < 120) return "A few minutes ago"; - if(secondsPassed < 60 * 60 * 24) { - var hours = Math.round(secondsPassed / 60 / 60); - return hours + " hours ago"; - } + if(secondsPassed < 60 * 60) { + var minutes = Math.round(secondsPassed / 60); + return minutes + " minutes ago"; + } - if(secondsPassed < 60 * 60 * 24 * 2) { - return "Yesterday"; - } + if(secondsPassed < 60 * 60 * 24) { + var hours = Math.round(secondsPassed / 60 / 60); + return hours + " hours ago"; + } - if(secondsPassed < 60 * 60 * 24 * 30) { - var days = Math.round(secondsPassed / 60 / 60 / 24); - return days + " days ago"; - } + if(secondsPassed < 60 * 60 * 24 * 2) { + return "Yesterday"; + } - return "A long time ago, in a galaxy far, far away"; + if(secondsPassed < 60 * 60 * 24 * 30) { + var days = Math.round(secondsPassed / 60 / 60 / 24); + return days + " days ago"; + } + + return "A long time ago, in a galaxy far, far away"; + } + catch(err) { + return "It did happen, when I don't know"; + } }; window.createElement = function(type, className, content) { diff --git a/tests/unit/parsecmdline.js b/tests/unit/parsecmdline.js new file mode 100644 index 000000000..3609a69dd --- /dev/null +++ b/tests/unit/parsecmdline.js @@ -0,0 +1,26 @@ +const assert = require('chai').assert; + +// create a global window so we can unittest the window. functions +if (!global.window) + global.window = new Object({}); + +require('../../saltgui/static/scripts/parsecmdline'); + + +describe('Unittests for parsecmdline.js', function() { + + it('test parseCommandLine', done => { + // null means: it was all ok + result = window.parseCommandLine("test", ["something"]); + assert.isNull(result); + + // broken json will return a readable error message + result = window.parseCommandLine("{'test'"); + assert.equal(result, "No valid dictionary found"); + + // ... please add MUCH MORE tests here + + done(); + }); + +}); diff --git a/tests/unit/utils.js b/tests/unit/utils.js index ed8f5855b..2bf6da4c2 100644 --- a/tests/unit/utils.js +++ b/tests/unit/utils.js @@ -1,13 +1,15 @@ -const assert = require('chai').assert; + const assert = require('chai').assert; + +// create a global window so we can unittest the window. functions +if (!global.window) + global.window = new Object({}); -// so we can import the utils for testing -global.window = new Object({}); require('../../saltgui/static/scripts/utils'); describe('Unittests for utils.js', function() { - it('test elapsedToString', done => { + it('test elapsedToString with valid values', done => { var now = new Date(); var result = window.elapsedToString(now); @@ -40,4 +42,19 @@ describe('Unittests for utils.js', function() { done(); }); + it('test elapsedToString with invalid values', done => { + var now = new Date(); + + // a time in the future? + now.setSeconds(now.getSeconds() + 110); + result = window.elapsedToString(now); + assert.equal(result, "Magic happened in the future"); + + // and something which is not a date at all + result = window.elapsedToString("I'm not a date"); + assert.equal(result, "It did happen, when I don't know"); + + done(); + }); + }); From d40f64c86e520e230db65d5f5993e8ead95c176a Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Fri, 3 Aug 2018 12:12:52 +0200 Subject: [PATCH 15/36] Bail on first error --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b08690107..6e7150143 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,6 @@ "scripts": { "lint": "jshint saltgui/ tests/", "wait-for-docker": "node tests/helpers/wait-for-docker.js", - "test": "mocha --trace-warnings --reporter spec tests/unit/" + "test": "mocha --bail --trace-warnings --reporter spec tests/unit/ tests/functional/" } } From 569bf40fe840b96288c5e53193e63d95d5e1b12c Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Fri, 3 Aug 2018 12:14:01 +0200 Subject: [PATCH 16/36] Updated readme with testing frameworks --- README.MD | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.MD b/README.MD index 23c2003f1..a0666e93b 100644 --- a/README.MD +++ b/README.MD @@ -64,11 +64,16 @@ Then browse to [http://localhost:3333/](http://localhost:3333/), you can login w ## Testing -We also provide some [nightmare.js](https://github.com/segmentio/nightmare) and unittests. They use the docker setup to run some functional tests. You will also need [yarn](https://yarnpkg.com) and [node.js](https://nodejs.org/en/) to run them. When you have docker, yarn and node.js installed, you can run the tests from the root of the repository like this: +We provide some functional tests and unit tests. They use the docker setup to run the functional tests. You will also need [yarn](https://yarnpkg.com) and [node.js](https://nodejs.org/en/) to run them. When you have docker, yarn and node.js installed, you can run the tests from the root of the repository like this: ``` ./runtests.sh ``` +We use the following testing libraries: +- [nightmare.js](https://github.com/segmentio/nightmare), for functional/browser tests +- [mocha](https://https://mochajs.org/), a well documented testing framework for javascript +- [chai](http://www.chaijs.com/), the preferred assertion library for testing + ## Contributing Open a PR! Try to use no dependencies where possible, as vanilla JS is the aim. Any libraries will need to be heavily considered first. Please see the section above as PR's won't be reviewed if they don't pass the tests. From d53fb1ca350f7c48d4332043f4c5a6117f3dad34 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Fri, 3 Aug 2018 12:50:23 +0200 Subject: [PATCH 17/36] Added a test with valid login credentials And increase the timeout as the first time it can take a while --- tests/functional/login.js | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/tests/functional/login.js b/tests/functional/login.js index 10ba30892..204c75dad 100644 --- a/tests/functional/login.js +++ b/tests/functional/login.js @@ -4,14 +4,17 @@ const assert = require('chai').assert; const url = 'http://localhost:3333/'; + describe('Login tests', function() { - this.timeout('10s'); + this.timeout('30s'); let browser = null; beforeEach( () => { browser = new Nightmare({ + // to make the typed input much faster + typeInterval: 20, // uncomment this to show the browser and the debug window // openDevTools: { // mode: "detach" @@ -50,9 +53,26 @@ describe('Login tests', function() { assert.equal(message, 'Authentication failed'); done() ; }) - .catch(error => { - console.log(error); - }); + .catch(done); + }); + + it('valid credentials will redirect us to the homepage and hide the loginform', done => { + browser + .type('#username', 'salt') + .type('#password', 'salt') + .click('#login-submit') + .wait( ()=> { + // we wait here for the loginpage to be hidden + var loginpage = document.querySelector('#page_login'); + return loginpage.style.display == 'none'; + }) + .end() + .evaluate( ()=> { return document.location.href; }) + .then(function (href) { + assert.equal(href, url); + done(); + }) + .catch(done); }); }); From 0decd18b76fc8376e75f3570d18727614ee009a8 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Fri, 3 Aug 2018 12:57:52 +0200 Subject: [PATCH 18/36] Make sure we always cleanup the docker images --- runtests.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/runtests.sh b/runtests.sh index a30587bb9..5e044b928 100755 --- a/runtests.sh +++ b/runtests.sh @@ -1,5 +1,11 @@ #!/bin/bash +# always cleanup the docker images when something goes wrong +function cleanupdocker { + docker-compose -f docker/docker-compose.yml rm -f -s +} +trap cleanupdocker EXIT + set -e # add testing packages yarn @@ -16,7 +22,4 @@ yarn wait-for-docker # run the unittests/nightmare.js functional tests yarn test -# cleanup the docker images for 100% reproducable testresults -docker-compose -f docker/docker-compose.yml rm -f -s - -set +e +set +e \ No newline at end of file From 8663c079f9ac720d553edbac66205a3d9c82ab0f Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Fri, 3 Aug 2018 13:21:44 +0200 Subject: [PATCH 19/36] Added a virtual display for running the nightmarejs tests --- .travis.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3b493d09c..e91d2037b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,22 @@ language: node_js + node_js: - "node" + services: - docker + +# so the functional tests will work +addons: + apt: + packages: + - xvfb +install: + - export DISPLAY=':99.0' + - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + before_script: - cd $TRAVIS_BUILD_DIR + script: - ./runtests.sh From c355979f4850156e5a98de2c1dfc914e7ec77b24 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Fri, 3 Aug 2018 13:28:38 +0200 Subject: [PATCH 20/36] Update test description --- tests/functional/login.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/login.js b/tests/functional/login.js index 204c75dad..84c067bd5 100644 --- a/tests/functional/login.js +++ b/tests/functional/login.js @@ -25,7 +25,7 @@ describe('Login tests', function() { .goto(url); }); - describe('Login', () => { + describe('Functional tests for login', () => { it('we should be redirected to the login page', done => { browser From 8c6e0b7cb6d2b9dec37185b0e50bc92c9e20d5a4 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Sat, 4 Aug 2018 15:00:47 +0200 Subject: [PATCH 21/36] Document minimal versions --- README.MD | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.MD b/README.MD index a0666e93b..105ee87c9 100644 --- a/README.MD +++ b/README.MD @@ -74,6 +74,12 @@ We use the following testing libraries: - [mocha](https://https://mochajs.org/), a well documented testing framework for javascript - [chai](http://www.chaijs.com/), the preferred assertion library for testing +You'll need at least: +- `docker-compose` 1.12 or above +- `nodejs` 8.11.x or above +- `yarn` 1.7.0 or above + + ## Contributing Open a PR! Try to use no dependencies where possible, as vanilla JS is the aim. Any libraries will need to be heavily considered first. Please see the section above as PR's won't be reviewed if they don't pass the tests. From a24bc2992fbc076924cc61b5c0e4b1e726b3f1fb Mon Sep 17 00:00:00 2001 From: Erwin Dondorp Date: Sat, 4 Aug 2018 23:03:07 +0200 Subject: [PATCH 22/36] json does not support single-quoted strings --- saltgui/static/scripts/parsecmdline.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/saltgui/static/scripts/parsecmdline.js b/saltgui/static/scripts/parsecmdline.js index a2383fd1d..19434222f 100644 --- a/saltgui/static/scripts/parsecmdline.js +++ b/saltgui/static/scripts/parsecmdline.js @@ -60,11 +60,9 @@ window.parseCommandLine = function(toRun, args, params) { endChar = ']'; objType = "array"; } else if(toRun[0] === '"') { + // note that json does not support single-quoted strings endChar = '"'; objType = "double-quoted-string"; - } else if(toRun[0] === '\'') { - endChar = '\''; - objType = "single-quoted-string"; } var value; From 972fca374e5851ac68d804d37c06ae1ecf569702 Mon Sep 17 00:00:00 2001 From: Erwin Dondorp Date: Sat, 4 Aug 2018 23:04:02 +0200 Subject: [PATCH 23/36] added regressiontestset for parseCommandLine --- tests/unit/parsecmdline.js | 353 ++++++++++++++++++++++++++++++++++++- 1 file changed, 349 insertions(+), 4 deletions(-) diff --git a/tests/unit/parsecmdline.js b/tests/unit/parsecmdline.js index 3609a69dd..12ed63f85 100644 --- a/tests/unit/parsecmdline.js +++ b/tests/unit/parsecmdline.js @@ -8,17 +8,362 @@ require('../../saltgui/static/scripts/parsecmdline'); describe('Unittests for parsecmdline.js', function() { - + it('test parseCommandLine', done => { + let args = [], params = {}; + + + + // GENERAL ERROR HANDLING + // null means: it was all ok - result = window.parseCommandLine("test", ["something"]); + args = []; params = {}; + result = window.parseCommandLine("test", args, params); assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], "test"); + assert.equal(Object.keys(params).length, 0); // broken json will return a readable error message - result = window.parseCommandLine("{'test'"); + args = []; params = {}; + result = window.parseCommandLine("{\"test\"", args, params); + assert.equal(result, "No valid dictionary found"); + + + + // GENERAL WHITESPACE HANDLING + + args = []; params = {}; + result = window.parseCommandLine(" name=true", args, params); + assert.isNull(result); + assert.equal(args.length, 0); + assert.equal(Object.keys(params).length, 1); + assert.equal(params.name, true); + + args = []; params = {}; + result = window.parseCommandLine("name=true ", args, params); + assert.isNull(result); + assert.equal(args.length, 0); + assert.equal(Object.keys(params).length, 1); + assert.equal(params.name, true); + + + + // NAMED PARAMETERS + + // name-value-pair without value is not ok + args = []; params = {}; + result = window.parseCommandLine("test=", args, params); + assert.equal(result, "Must have value for named parameter 'test'"); + + // name-value-pair without value is not ok + // make sure it does not confuse it with furher parameters + args = []; params = {}; + result = window.parseCommandLine("test= arg2 arg3", args, params); + assert.equal(result, "Must have value for named parameter 'test'"); + + + + // DICTIONARY + + // a regular dictionary + args = []; params = {}; + result = window.parseCommandLine("{\"a\":1}", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.deepEqual(args[0], {"a":1}); + assert.equal(Object.keys(params).length, 0); + + // a broken dictionary + args = []; params = {}; + result = window.parseCommandLine("{\"a}\":1", args, params); assert.equal(result, "No valid dictionary found"); - // ... please add MUCH MORE tests here + // a regular dictionary with } in its name + // test that the parser is not confused + args = []; params = {}; + result = window.parseCommandLine("{\"a}\":1}", args, params); + assert.equal(result, null); + + // a regular dictionary with } after its value + args = []; params = {}; + result = window.parseCommandLine("{\"a}\":1}}", args, params); + assert.equal(result, "Valid dictionary, but followed by text:}..."); + + + + // ARRAYS + + // a simple array + args = []; params = {}; + result = window.parseCommandLine("[1,2]", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.deepEqual(args[0], [1,2]); + assert.equal(Object.keys(params).length, 0); + + // a simple array that is not closed + args = []; params = {}; + result = window.parseCommandLine("[1,2", args, params); + assert.equal(result, "No valid array found"); + + + + // DOUBLE-QUOTED-STRINGS + + // a simple string + args = []; params = {}; + result = window.parseCommandLine("\"string\"", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], "string"); + assert.equal(Object.keys(params).length, 0); + + // an unclosed string + args = []; params = {}; + result = window.parseCommandLine("\"string", args, params); + assert.equal(result, "No valid double-quoted-string found"); + + + + // SINGLE-QUOTED-STRINGS (never supported!) + + // a single-quoted string is not supported + // it evalueates as a string (the whole thing) + args = []; params = {}; + result = window.parseCommandLine("\'string\'", args, params); + assert.equal(result, null); + assert.equal(args.length, 1); + assert.equal(args[0], "\'string\'"); + assert.equal(Object.keys(params).length, 0); + + // a single-quoted string is not supported + // it evalueates as a string (the whole thing) + // even when that looks rediculous + args = []; params = {}; + result = window.parseCommandLine("\'string", args, params); + assert.equal(result, null); + assert.equal(args.length, 1); + assert.equal(args[0], "\'string"); + assert.equal(Object.keys(params).length, 0); + + + + // INTEGER + + args = []; params = {}; + result = window.parseCommandLine("0", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], 0); + assert.equal(Object.keys(params).length, 0); + + + + // FLOAT + + args = []; params = {}; + result = window.parseCommandLine("0.", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], 0); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine(".0", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], 0); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("0.0", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], 0.0); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("0.0.0", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], "0.0.0"); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine(".", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], "."); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("1e99", args, params); + assert.equal(result, null); + assert.equal(args.length, 1); + assert.equal(args[0], 1e99); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("-1e99", args, params); + assert.equal(result, null); + assert.equal(args.length, 1); + assert.equal(args[0], -1e99); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("+1e99", args, params); + assert.equal(result, null); + assert.equal(args.length, 1); + assert.equal(args[0], 1e99); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("1e-99", args, params); + assert.equal(result, null); + assert.equal(args.length, 1); + assert.equal(args[0], 1e-99); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("1e+99", args, params); + assert.equal(result, null); + assert.equal(args.length, 1); + assert.equal(args[0], 1e99); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("1e999", args, params); + assert.equal(result, "Numeric argument has overflowed or is infinity"); + + + + + // NULL + + args = []; params = {}; + result = window.parseCommandLine("null", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], null); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("Null", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], null); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("NULL", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], null); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("NUll", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], "NUll"); + assert.equal(Object.keys(params).length, 0); + + + + // NONE + + args = []; params = {}; + result = window.parseCommandLine("none", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], "none"); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("None", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], null); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("NONE", args, params); + + + // GENERAL WHITESPACE HANDLING + + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], "NONE"); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("NOne", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], "NOne"); + assert.equal(Object.keys(params).length, 0); + + + + // BOOLEAN + + args = []; params = {}; + result = window.parseCommandLine("true", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], true); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("True", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], true); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("TRUE", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], true); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("TRue", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], "TRue"); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("false", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], false); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("False", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], false); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("FALSE", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], false); + assert.equal(Object.keys(params).length, 0); + + args = []; params = {}; + result = window.parseCommandLine("FAlse", args, params); + assert.isNull(result); + assert.equal(args.length, 1); + assert.equal(args[0], "FAlse"); + assert.equal(Object.keys(params).length, 0); done(); }); From 073ea0320eb02263cbad2efa59deeb9fb7eeb455 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Sun, 5 Aug 2018 16:02:58 +0200 Subject: [PATCH 24/36] Log error to console, make sure english grammar is correct --- saltgui/static/scripts/utils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/saltgui/static/scripts/utils.js b/saltgui/static/scripts/utils.js index ec2360ec8..7116a853e 100644 --- a/saltgui/static/scripts/utils.js +++ b/saltgui/static/scripts/utils.js @@ -8,12 +8,12 @@ window.elapsedToString = function(date) { if(secondsPassed < 60 * 60) { var minutes = Math.round(secondsPassed / 60); - return minutes + " minutes ago"; + return minutes + " minute(s) ago"; } if(secondsPassed < 60 * 60 * 24) { var hours = Math.round(secondsPassed / 60 / 60); - return hours + " hours ago"; + return hours + " hour(s) ago"; } if(secondsPassed < 60 * 60 * 24 * 2) { @@ -28,6 +28,7 @@ window.elapsedToString = function(date) { return "A long time ago, in a galaxy far, far away"; } catch(err) { + console.error(err); return "It did happen, when I don't know"; } }; From daf6a3e9099fd66dab2fd0ef34ac2b34c6ec6253 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Sun, 5 Aug 2018 16:29:57 +0200 Subject: [PATCH 25/36] Dropped wait-for as the script is now rewritten using requests --- package.json | 3 +-- tests/helpers/wait-for-docker.js | 29 ++++++++++++++--------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 6e7150143..4c58dabfd 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,7 @@ "chai": "^4.1.2", "jshint": "^2.9.5", "mocha": "^5.2.0", - "nightmare": "^3.0.1", - "wait-on": "^2.1.0" + "nightmare": "^3.0.1" }, "jshintConfig": { "esversion": 6 diff --git a/tests/helpers/wait-for-docker.js b/tests/helpers/wait-for-docker.js index bfd0e7bd3..410e18623 100644 --- a/tests/helpers/wait-for-docker.js +++ b/tests/helpers/wait-for-docker.js @@ -1,19 +1,18 @@ -const waitOn = require('wait-on'); +const request = require('request'); -console.log("waiting for docker setup to be ready"); +const url = 'http://localhost:3333'; -var resources = { - resources: [ - 'http://localhost:3333/', - ], - timeout: 30000, - followAllRedirects: true, - followRedirect: true, -}; +console.log("waiting for docker setup to be ready"); -waitOn(resources, error => { - if (error) - console.error(error); - else +function waitfordocker() { + request + .get(url) + .on('response', function(response) { console.log("docker setup is ready"); -}); + }) + .on('error', function(err) { + setTimeout(waitfordocker, 1000); + }); +} + +waitfordocker(); From 1f76faf15c8fb2f53d88a469d783781e4f879897 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Sun, 5 Aug 2018 16:30:16 +0200 Subject: [PATCH 26/36] Added correct versions in README.md --- README.MD | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.MD b/README.MD index 105ee87c9..709200d9a 100644 --- a/README.MD +++ b/README.MD @@ -76,8 +76,8 @@ We use the following testing libraries: You'll need at least: - `docker-compose` 1.12 or above -- `nodejs` 8.11.x or above -- `yarn` 1.7.0 or above +- `nodejs` 8.11 or above +- `yarn` 1.7 or above ## Contributing From 83a817fb1cd03e0a1d90fee60d780ac9bbfc2a69 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Sun, 5 Aug 2018 16:30:44 +0200 Subject: [PATCH 27/36] Fixed some linting suggestions --- tests/functional/login.js | 11 +++++------ tests/unit/parsecmdline.js | 26 -------------------------- 2 files changed, 5 insertions(+), 32 deletions(-) diff --git a/tests/functional/login.js b/tests/functional/login.js index 84c067bd5..80a3aa532 100644 --- a/tests/functional/login.js +++ b/tests/functional/login.js @@ -4,7 +4,6 @@ const assert = require('chai').assert; const url = 'http://localhost:3333/'; - describe('Login tests', function() { this.timeout('30s'); @@ -30,9 +29,9 @@ describe('Login tests', function() { it('we should be redirected to the login page', done => { browser .end() - .evaluate( () => { return document; } ) - .then(function (document) { - assert.equal(document.location.href, 'http://localhost:3333/login'); + .evaluate( () => { return document.location.href; } ) + .then(function (href) { + assert.equal(href, url + 'login'); done(); }) .catch(done); @@ -51,7 +50,7 @@ describe('Login tests', function() { }, selector) .then(function (message) { assert.equal(message, 'Authentication failed'); - done() ; + done(); }) .catch(done); }); @@ -61,7 +60,7 @@ describe('Login tests', function() { .type('#username', 'salt') .type('#password', 'salt') .click('#login-submit') - .wait( ()=> { + .wait( () => { // we wait here for the loginpage to be hidden var loginpage = document.querySelector('#page_login'); return loginpage.style.display == 'none'; diff --git a/tests/unit/parsecmdline.js b/tests/unit/parsecmdline.js index 12ed63f85..507b5ea49 100644 --- a/tests/unit/parsecmdline.js +++ b/tests/unit/parsecmdline.js @@ -12,8 +12,6 @@ describe('Unittests for parsecmdline.js', function() { it('test parseCommandLine', done => { let args = [], params = {}; - - // GENERAL ERROR HANDLING // null means: it was all ok @@ -29,8 +27,6 @@ describe('Unittests for parsecmdline.js', function() { result = window.parseCommandLine("{\"test\"", args, params); assert.equal(result, "No valid dictionary found"); - - // GENERAL WHITESPACE HANDLING args = []; params = {}; @@ -47,8 +43,6 @@ describe('Unittests for parsecmdline.js', function() { assert.equal(Object.keys(params).length, 1); assert.equal(params.name, true); - - // NAMED PARAMETERS // name-value-pair without value is not ok @@ -62,8 +56,6 @@ describe('Unittests for parsecmdline.js', function() { result = window.parseCommandLine("test= arg2 arg3", args, params); assert.equal(result, "Must have value for named parameter 'test'"); - - // DICTIONARY // a regular dictionary @@ -90,8 +82,6 @@ describe('Unittests for parsecmdline.js', function() { result = window.parseCommandLine("{\"a}\":1}}", args, params); assert.equal(result, "Valid dictionary, but followed by text:}..."); - - // ARRAYS // a simple array @@ -107,8 +97,6 @@ describe('Unittests for parsecmdline.js', function() { result = window.parseCommandLine("[1,2", args, params); assert.equal(result, "No valid array found"); - - // DOUBLE-QUOTED-STRINGS // a simple string @@ -124,8 +112,6 @@ describe('Unittests for parsecmdline.js', function() { result = window.parseCommandLine("\"string", args, params); assert.equal(result, "No valid double-quoted-string found"); - - // SINGLE-QUOTED-STRINGS (never supported!) // a single-quoted string is not supported @@ -147,8 +133,6 @@ describe('Unittests for parsecmdline.js', function() { assert.equal(args[0], "\'string"); assert.equal(Object.keys(params).length, 0); - - // INTEGER args = []; params = {}; @@ -158,8 +142,6 @@ describe('Unittests for parsecmdline.js', function() { assert.equal(args[0], 0); assert.equal(Object.keys(params).length, 0); - - // FLOAT args = []; params = {}; @@ -236,9 +218,6 @@ describe('Unittests for parsecmdline.js', function() { result = window.parseCommandLine("1e999", args, params); assert.equal(result, "Numeric argument has overflowed or is infinity"); - - - // NULL args = []; params = {}; @@ -269,8 +248,6 @@ describe('Unittests for parsecmdline.js', function() { assert.equal(args[0], "NUll"); assert.equal(Object.keys(params).length, 0); - - // NONE args = []; params = {}; @@ -290,7 +267,6 @@ describe('Unittests for parsecmdline.js', function() { args = []; params = {}; result = window.parseCommandLine("NONE", args, params); - // GENERAL WHITESPACE HANDLING assert.isNull(result); @@ -305,8 +281,6 @@ describe('Unittests for parsecmdline.js', function() { assert.equal(args[0], "NOne"); assert.equal(Object.keys(params).length, 0); - - // BOOLEAN args = []; params = {}; From e0cb66bcbf986fb11da73430d2ed1f7ced8f582b Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Sun, 5 Aug 2018 16:33:14 +0200 Subject: [PATCH 28/36] Update test according to new output --- tests/unit/utils.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/unit/utils.js b/tests/unit/utils.js index 2bf6da4c2..620386ba5 100644 --- a/tests/unit/utils.js +++ b/tests/unit/utils.js @@ -21,11 +21,15 @@ describe('Unittests for utils.js', function() { now.setMinutes(now.getMinutes() - 1); result = window.elapsedToString(now); - assert.equal(result, "3 minutes ago"); + assert.equal(result, "3 minute(s) ago"); - now.setHours(now.getHours() - 2); + now.setHours(now.getHours() - 1); result = window.elapsedToString(now); - assert.equal(result, "2 hours ago"); + assert.equal(result, "1 hour(s) ago"); + + now.setHours(now.getHours() - 1); + result = window.elapsedToString(now); + assert.equal(result, "2 hour(s) ago"); now.setHours(now.getHours() - 24); result = window.elapsedToString(now); From 3e17741d6c89481ba596645eef458f2277538fa8 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Sun, 5 Aug 2018 16:33:23 +0200 Subject: [PATCH 29/36] Updated lockfile --- yarn.lock | 52 +--------------------------------------------------- 1 file changed, 1 insertion(+), 51 deletions(-) diff --git a/yarn.lock b/yarn.lock index 79bcbf08b..8df3f9e38 100644 --- a/yarn.lock +++ b/yarn.lock @@ -160,10 +160,6 @@ console-browserify@1.1.x: dependencies: date-now "^0.1.4" -core-js@^2.4.1: - version "2.5.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" - core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -442,10 +438,6 @@ he@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" -hoek@4.x.x: - version "4.2.1" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" - home-path@^1.0.1: version "1.0.6" resolved "https://registry.yarnpkg.com/home-path/-/home-path-1.0.6.tgz#d549dc2465388a7f8667242c5b31588d29af29fc" @@ -531,28 +523,10 @@ isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" -isemail@2.x.x: - version "2.2.1" - resolved "https://registry.yarnpkg.com/isemail/-/isemail-2.2.1.tgz#0353d3d9a62951080c262c2aa0a42b8ea8e9e2a6" - isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -items@2.x.x: - version "2.1.1" - resolved "https://registry.yarnpkg.com/items/-/items-2.1.1.tgz#8bd16d9c83b19529de5aea321acaada78364a198" - -joi@^9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-9.2.0.tgz#3385ac790192130cbe230e802ec02c9215bbfeda" - dependencies: - hoek "4.x.x" - isemail "2.x.x" - items "2.x.x" - moment "2.x.x" - topo "2.x.x" - jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -707,10 +681,6 @@ mocha@^5.2.0: mkdirp "0.5.1" supports-color "5.4.0" -moment@2.x.x: - version "2.22.2" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -926,7 +896,7 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@^2.45.0, request@^2.78.0: +request@^2.45.0: version "2.87.0" resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" dependencies: @@ -957,10 +927,6 @@ rimraf@^2.2.8, rimraf@^2.4.3: dependencies: glob "^7.0.5" -rx@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" - safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -1117,12 +1083,6 @@ through2@~0.2.3: readable-stream "~1.1.9" xtend "~2.1.1" -topo@2.x.x: - version "2.0.2" - resolved "https://registry.yarnpkg.com/topo/-/topo-2.0.2.tgz#cd5615752539057c0dc0491a621c3bc6fbe1d182" - dependencies: - hoek "4.x.x" - tough-cookie@~2.3.3: version "2.3.4" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" @@ -1174,16 +1134,6 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -wait-on@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-2.1.0.tgz#3c4ace1f57266ca5be7fa25e0c15803b889ca46a" - dependencies: - core-js "^2.4.1" - joi "^9.2.0" - minimist "^1.2.0" - request "^2.78.0" - rx "^4.1.0" - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From 8a2803cdd2c5a7499573cc337f6fa09803bb7e1c Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Sun, 5 Aug 2018 16:34:26 +0200 Subject: [PATCH 30/36] Don't bail for now --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4c58dabfd..886ac4419 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,6 @@ "scripts": { "lint": "jshint saltgui/ tests/", "wait-for-docker": "node tests/helpers/wait-for-docker.js", - "test": "mocha --bail --trace-warnings --reporter spec tests/unit/ tests/functional/" + "test": "mocha --trace-warnings --reporter spec tests/unit/ tests/functional/" } } From 8826405f70f47a07e92a2863dbf6e9a8453b9ea4 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Sun, 5 Aug 2018 16:35:36 +0200 Subject: [PATCH 31/36] Added newline --- runtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtests.sh b/runtests.sh index 5e044b928..4d2d7c9fb 100755 --- a/runtests.sh +++ b/runtests.sh @@ -22,4 +22,4 @@ yarn wait-for-docker # run the unittests/nightmare.js functional tests yarn test -set +e \ No newline at end of file +set +e From 8e91a9065280fa30a0ff4093859ce9d11ad0eda3 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Sun, 5 Aug 2018 16:43:14 +0200 Subject: [PATCH 32/36] Increase timeout for travis --- tests/functional/login.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functional/login.js b/tests/functional/login.js index 80a3aa532..34e320d95 100644 --- a/tests/functional/login.js +++ b/tests/functional/login.js @@ -6,7 +6,7 @@ const url = 'http://localhost:3333/'; describe('Login tests', function() { - this.timeout('30s'); + this.timeout('60s'); let browser = null; From 835c72b51919a7e4c8cce9ec2255422a408700e8 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Mon, 6 Aug 2018 19:20:47 +0200 Subject: [PATCH 33/36] There are multiple timeout settings in nightmarejs --- tests/functional/login.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/functional/login.js b/tests/functional/login.js index 34e320d95..5eae06846 100644 --- a/tests/functional/login.js +++ b/tests/functional/login.js @@ -6,14 +6,17 @@ const url = 'http://localhost:3333/'; describe('Login tests', function() { - this.timeout('60s'); - let browser = null; + // the global electron timeout + this.timeout(60 * 1000); + beforeEach( () => { browser = new Nightmare({ // to make the typed input much faster typeInterval: 20, + // the wait function has a timeout as well + waitTimeout: 60 * 1000 // uncomment this to show the browser and the debug window // openDevTools: { // mode: "detach" From 688166545b1306f7ec910ec3b0fb044ec4eee73c Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Wed, 8 Aug 2018 09:33:37 +0200 Subject: [PATCH 34/36] Added a logout test --- tests/functional/login.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/functional/login.js b/tests/functional/login.js index 5eae06846..5af8b9a9d 100644 --- a/tests/functional/login.js +++ b/tests/functional/login.js @@ -77,6 +77,33 @@ describe('Login tests', function() { .catch(done); }); + it('check that we can logout', done => { + browser + .type('#username', 'salt') + .type('#password', 'salt') + .click('#login-submit') + .wait( ()=> { + // we wait here for the loginpage to be hidden + var loginpage = document.querySelector('#page_login'); + return loginpage.style.display == 'none'; + }) + .click('#button_logout') + .wait( ()=> { + // we wait here for the loginpage to be shown + var loginpage = document.querySelector('#page_login'); + console.log(loginpage.style.display); + return loginpage.style.display === ''; + }) + .end() + .evaluate( ()=> { return document.location.href; }) + .then(function (href) { + // and we a redirected to the login page + assert.equal(href,'http://localhost:3333/login'); + done(); + }) + .catch(done); + }); + }); }); From 4eb6d42cf239e89619bccb49af302d0aec3af283 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Wed, 8 Aug 2018 09:34:54 +0200 Subject: [PATCH 35/36] Added logout test, fixed some linting --- tests/functional/login.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/functional/login.js b/tests/functional/login.js index 5af8b9a9d..96bc316a4 100644 --- a/tests/functional/login.js +++ b/tests/functional/login.js @@ -66,10 +66,10 @@ describe('Login tests', function() { .wait( () => { // we wait here for the loginpage to be hidden var loginpage = document.querySelector('#page_login'); - return loginpage.style.display == 'none'; + return loginpage.style.display === 'none'; }) .end() - .evaluate( ()=> { return document.location.href; }) + .evaluate( () => { return document.location.href; }) .then(function (href) { assert.equal(href, url); done(); @@ -82,20 +82,20 @@ describe('Login tests', function() { .type('#username', 'salt') .type('#password', 'salt') .click('#login-submit') - .wait( ()=> { + .wait( () => { // we wait here for the loginpage to be hidden var loginpage = document.querySelector('#page_login'); return loginpage.style.display == 'none'; }) .click('#button_logout') - .wait( ()=> { + .wait( () => { // we wait here for the loginpage to be shown var loginpage = document.querySelector('#page_login'); console.log(loginpage.style.display); return loginpage.style.display === ''; }) .end() - .evaluate( ()=> { return document.location.href; }) + .evaluate( () => { return document.location.href; }) .then(function (href) { // and we a redirected to the login page assert.equal(href,'http://localhost:3333/login'); From 2bb18db80d7a48b0fa68c1d2fe30f24951b123e1 Mon Sep 17 00:00:00 2001 From: Martijn Jacobs Date: Sun, 19 Aug 2018 10:50:41 +0200 Subject: [PATCH 36/36] Use a environment variable to show the browser/debug window --- README.MD | 5 +++++ tests/functional/login.js | 19 ++++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/README.MD b/README.MD index 709200d9a..933eebfb6 100644 --- a/README.MD +++ b/README.MD @@ -69,6 +69,11 @@ We provide some functional tests and unit tests. They use the docker setup to ru ./runtests.sh ``` +To show the browser window + a debugger while running the functional tests you can run: +``` +NIGHTMARE_DEBUG=1 ./runtests.sh +``` + We use the following testing libraries: - [nightmare.js](https://github.com/segmentio/nightmare), for functional/browser tests - [mocha](https://https://mochajs.org/), a well documented testing framework for javascript diff --git a/tests/functional/login.js b/tests/functional/login.js index 96bc316a4..150d961f1 100644 --- a/tests/functional/login.js +++ b/tests/functional/login.js @@ -12,17 +12,22 @@ describe('Login tests', function() { this.timeout(60 * 1000); beforeEach( () => { - browser = new Nightmare({ + let options = { // to make the typed input much faster typeInterval: 20, // the wait function has a timeout as well waitTimeout: 60 * 1000 - // uncomment this to show the browser and the debug window - // openDevTools: { - // mode: "detach" - // }, - // show: true - }); + }; + + if (process.env.NIGHTMARE_DEBUG === '1') { + // show the browser and the debug window + options.openDevTools = { + mode: "detach" + }; + options.show = true; + } + + browser = new Nightmare(options); browser .goto(url); });