diff --git a/.eslintignore b/.eslintignore index 599f7e731..7325a517f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,7 +1,17 @@ examples/blogs__e2e-snapshots/snapshots.js examples/blogs__element-coverage/src -examples/preprocessors__typescript-webpack/dist -node_modules +examples/preprocessors__flow-browserify +examples/blogs__testing-redux-store/src +**/node_modules **/vendor # don't ignore hidden files, useful for formatting json config files !.* +# most TS configs have comments, which generates lint warnings +tsconfig.json +# generated files +.cache +examples/blogs__testing-redux-store/dist +examples/preprocessors__typescript-webpack/dist +# a couple of problematic JSON files +examples/logging-in__jwt/server/config.json +examples/logging-in__using-app-code/server/config.json diff --git a/.gitignore b/.gitignore index b4ff8a285..305f3a74e 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ screenshots videos out.js examples/*/cypress/logs +snapshots.js diff --git a/Development.md b/Development.md index 5022bcfbb..467902ec3 100644 --- a/Development.md +++ b/Development.md @@ -13,6 +13,13 @@ $ npx eslint examples/blogs__vue-vuex-rest/cypress $ npx eslint examples/blogs__vue-vuex-rest/cypress --fix ``` +There are NPM scripts for linting code and JSON files + +```shell +npm run lint +npm run lint:json +``` + ### Testing in specific browser You can test some examples using a specific browser. For example, to run just some folders using Brave browser, call diff --git a/circle.yml b/circle.yml index f6c409b6a..283b4daa2 100644 --- a/circle.yml +++ b/circle.yml @@ -79,20 +79,8 @@ jobs: steps: - attach_workspace: at: ~/ - - run: | - npx eslint examples/blogs__a11y \ - examples/blogs__application-actions \ - examples/blogs__codepen-demo \ - examples/blogs__direct-control-angular \ - examples/blogs__e2e-api-testing \ - examples/blogs__e2e-snapshots \ - examples/blogs__element-coverage \ - examples/blogs__testing-redux-store/cypress \ - examples/blogs__vue-vuex-rest/cypress \ - examples/preprocessors__grep \ - examples/preprocessors__typescript-browserify \ - examples/preprocessors__typescript-webpack \ - examples/unit-testing__react + - run: npm run lint:json + - run: npm run lint # dummy job running after all end-to-end tests after-tests: diff --git a/examples/blogs__a11y/package.json b/examples/blogs__a11y/package.json index 4831b5c7f..45bb0725c 100644 --- a/examples/blogs__a11y/package.json +++ b/examples/blogs__a11y/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "Testing accessibility of a page", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", "test:ci": "../../node_modules/.bin/cypress run" } } diff --git a/examples/blogs__application-actions/package.json b/examples/blogs__application-actions/package.json index dadaa3c90..4aeff0c35 100644 --- a/examples/blogs__application-actions/package.json +++ b/examples/blogs__application-actions/package.json @@ -4,17 +4,17 @@ "description": "Testing Redux store using Cypress", "private": true, "scripts": { - "start": "../../node_modules/.bin/http-server -p 8888 --silent -c-1", - "start:win": "bin-up serve -l 8888 --no-clipboard", - "dev": "../../node_modules/.bin/start-test 8888 cypress:open", + "cypress:open": "../../node_modules/.bin/cypress open", "cypress:run": "../../node_modules/.bin/cypress run", - "cypress:run:win": "bin-up cypress run", "cypress:run:chrome": "../../node_modules/.bin/cypress run --browser chrome", "cypress:run:firefox": "../../node_modules/.bin/cypress run --browser firefox", - "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run:win": "bin-up cypress run", + "dev": "../../node_modules/.bin/start-test 8888 cypress:open", + "start": "../../node_modules/.bin/http-server -p 8888 --silent -c-1", + "start:win": "bin-up serve -l 8888 --no-clipboard", "test:ci": "../../node_modules/.bin/start-test 8888 cypress:run", - "test:ci:windows": "bin-up start-test start:win http://localhost:8888 cypress:run:win", "test:ci:chrome": "../../node_modules/.bin/start-test 8888 cypress:run:chrome", - "test:ci:firefox": "../../node_modules/.bin/start-test 8888 cypress:run:firefox" + "test:ci:firefox": "../../node_modules/.bin/start-test 8888 cypress:run:firefox", + "test:ci:windows": "bin-up start-test start:win http://localhost:8888 cypress:run:win" } } diff --git a/examples/blogs__codepen-demo/package.json b/examples/blogs__codepen-demo/package.json index 7aa2a3c21..6f4cfed7e 100644 --- a/examples/blogs__codepen-demo/package.json +++ b/examples/blogs__codepen-demo/package.json @@ -3,9 +3,9 @@ "version": "1.0.0", "description": "Demo of E2E testing HyperApp.js counter app running on Codepen.io", "scripts": { - "start": "echo", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", + "start": "echo", "test:ci": "npm run cypress:run", "test:ci:chrome": "npm run cypress:run -- --browser chrome" } diff --git a/examples/blogs__direct-control-angular/package.json b/examples/blogs__direct-control-angular/package.json index 1b4dc7d0c..fdd44edbb 100644 --- a/examples/blogs__direct-control-angular/package.json +++ b/examples/blogs__direct-control-angular/package.json @@ -3,9 +3,9 @@ "version": "1.0.0", "description": "Example showing direct control of Angular 1.x application from E2E tests", "scripts": { - "start": "echo", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", + "start": "echo", "test:ci": "npm run cypress:run" } } diff --git a/examples/blogs__e2e-api-testing/package.json b/examples/blogs__e2e-api-testing/package.json index 1fb1093c2..d6cb729ff 100644 --- a/examples/blogs__e2e-api-testing/package.json +++ b/examples/blogs__e2e-api-testing/package.json @@ -3,9 +3,9 @@ "version": "1.0.0", "description": "Cypress E2E runner can also test Rest and other APIs", "scripts": { + "cypress:open": "../../node_modules/.bin/cypress open", "cypress:run": "../../node_modules/.bin/cypress run", "cypress:run:windows": "bin-up cypress run", - "cypress:open": "../../node_modules/.bin/cypress open", "start": "../../node_modules/.bin/json-server db.json --port 7081 --quiet", "start:windows": "bin-up json-server db.json --port 7081 --quiet", "test:ci": "../../node_modules/.bin/start-test 7081 cypress:run", diff --git a/examples/blogs__e2e-snapshots/cypress/fixtures/example.json b/examples/blogs__e2e-snapshots/cypress/fixtures/example.json index 8dd3f2907..41d959017 100644 --- a/examples/blogs__e2e-snapshots/cypress/fixtures/example.json +++ b/examples/blogs__e2e-snapshots/cypress/fixtures/example.json @@ -1,17 +1,22 @@ -[{ - "id": "1", - "title": "do first thing", - "completed": false -}, { - "id": "2", - "title": "do second thing", - "completed": true -}, { - "id": "3", - "title": "one more thing", - "completed": false -}, { - "id": "4", - "title": "last item on the agenda", - "completed": false -}] +[ + { + "id": "1", + "title": "do first thing", + "completed": false + }, + { + "id": "2", + "title": "do second thing", + "completed": true + }, + { + "id": "3", + "title": "one more thing", + "completed": false + }, + { + "id": "4", + "title": "last item on the agenda", + "completed": false + } +] diff --git a/examples/blogs__e2e-snapshots/package.json b/examples/blogs__e2e-snapshots/package.json index e8b6742a7..d56e9db61 100644 --- a/examples/blogs__e2e-snapshots/package.json +++ b/examples/blogs__e2e-snapshots/package.json @@ -3,12 +3,12 @@ "version": "1.0.0", "description": "End-to-end snapshots for Cypress", "scripts": { - "start": "../../node_modules/.bin/json-server -p 3700 --static . data.json --middlewares ../../node_modules/json-server-reset", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "reset:db": "node reset-db.js", + "cypress:run": "../../node_modules/.bin/cypress run", + "dev": "../../node_modules/.bin/start-test 3700 cypress:open", "reset": "node reset-db.js", - "test:ci": "../../node_modules/.bin/start-test 3700 cypress:run", - "dev": "../../node_modules/.bin/start-test 3700 cypress:open" + "reset:db": "node reset-db.js", + "start": "../../node_modules/.bin/json-server -p 3700 --static . data.json --middlewares ../../node_modules/json-server-reset", + "test:ci": "../../node_modules/.bin/start-test 3700 cypress:run" } } diff --git a/examples/blogs__element-coverage/package.json b/examples/blogs__element-coverage/package.json index 9ea874988..4dc9c7866 100644 --- a/examples/blogs__element-coverage/package.json +++ b/examples/blogs__element-coverage/package.json @@ -4,11 +4,11 @@ "description": "Showing elements the test has interacted with", "private": true, "scripts": { - "start": "../../node_modules/.bin/react-scripts start", - "wait-on": "../../node_modules/.bin/wait-on http://localhost:3000", - "cypress:run": "npm run wait-on && ../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "test:ci": "../../node_modules/.bin/start-test 3000 cypress:run" + "cypress:run": "npm run wait-on && ../../node_modules/.bin/cypress run", + "start": "../../node_modules/.bin/react-scripts start", + "test:ci": "../../node_modules/.bin/start-test 3000 cypress:run", + "wait-on": "../../node_modules/.bin/wait-on http://localhost:3000" }, "browserslist": [ ">0.2%", diff --git a/examples/blogs__testing-redux-store/package.json b/examples/blogs__testing-redux-store/package.json index 45903fb96..b94d61b9b 100644 --- a/examples/blogs__testing-redux-store/package.json +++ b/examples/blogs__testing-redux-store/package.json @@ -4,18 +4,18 @@ "description": "Testing Redux store using Cypress", "private": true, "scripts": { - "start": "../../node_modules/.bin/react-scripts start", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", + "start": "../../node_modules/.bin/react-scripts start", "test:ci": "../../node_modules/.bin/start-test 3000 cypress:run" }, + "devDependencies": { + "cypress-plugin-snapshots": "1.0.6" + }, "browserslist": [ ">0.2%", "not dead", "not ie <= 11", "not op_mini all" - ], - "devDependencies": { - "cypress-plugin-snapshots": "1.0.6" - } + ] } diff --git a/examples/blogs__vue-vuex-rest/app.js b/examples/blogs__vue-vuex-rest/app.js index 8c5dee338..1f023e590 100644 --- a/examples/blogs__vue-vuex-rest/app.js +++ b/examples/blogs__vue-vuex-rest/app.js @@ -1,4 +1,4 @@ -/* global Vue, Vuex, axios, FileReader, window, Promise */ +/* global Vue, Vuex, axios, FileReader, window */ /* eslint-disable no-console */ (function () { Vue.use(Vuex) @@ -36,6 +36,7 @@ }, REMOVE_TODO (state, todo) { let todos = state.todos + todos.splice(todos.indexOf(todo), 1) }, CLEAR_NEW_TODO (state) { @@ -68,11 +69,13 @@ // do not add empty todos return } + const todo = { title: state.newTodo, completed: false, id: randomId(), } + axios.post('/todos', todo).then(() => { commit('ADD_TODO', todo) }) @@ -95,6 +98,7 @@ completed: false, id: randomId(), } + commit('ADD_TODO', todo) resolve() }, milliseconds) @@ -161,12 +165,15 @@ // or read it off the native event const f = this.file || e.target.files[0] const reader = new FileReader() + reader.onload = (e) => { const list = JSON.parse(e.target.result) + list.forEach((todo) => { this.$store.commit('ADD_TODO', todo) }) } + reader.readAsText(f) }, }, diff --git a/examples/blogs__vue-vuex-rest/cypress/fixtures/example.json b/examples/blogs__vue-vuex-rest/cypress/fixtures/example.json index 8dd3f2907..41d959017 100644 --- a/examples/blogs__vue-vuex-rest/cypress/fixtures/example.json +++ b/examples/blogs__vue-vuex-rest/cypress/fixtures/example.json @@ -1,17 +1,22 @@ -[{ - "id": "1", - "title": "do first thing", - "completed": false -}, { - "id": "2", - "title": "do second thing", - "completed": true -}, { - "id": "3", - "title": "one more thing", - "completed": false -}, { - "id": "4", - "title": "last item on the agenda", - "completed": false -}] +[ + { + "id": "1", + "title": "do first thing", + "completed": false + }, + { + "id": "2", + "title": "do second thing", + "completed": true + }, + { + "id": "3", + "title": "one more thing", + "completed": false + }, + { + "id": "4", + "title": "last item on the agenda", + "completed": false + } +] diff --git a/examples/blogs__vue-vuex-rest/cypress/fixtures/todos.json b/examples/blogs__vue-vuex-rest/cypress/fixtures/todos.json index 7308d8c38..2479765d5 100644 --- a/examples/blogs__vue-vuex-rest/cypress/fixtures/todos.json +++ b/examples/blogs__vue-vuex-rest/cypress/fixtures/todos.json @@ -1,12 +1,12 @@ [ - { - "title": "mock first", - "completed": false, - "id": "1" - }, - { - "title": "mock second", - "completed": true, - "id": "2" - } - ] + { + "title": "mock first", + "completed": false, + "id": "1" + }, + { + "title": "mock second", + "completed": true, + "id": "2" + } +] diff --git a/examples/blogs__vue-vuex-rest/package.json b/examples/blogs__vue-vuex-rest/package.json index 264ffd0fe..c9d066585 100644 --- a/examples/blogs__vue-vuex-rest/package.json +++ b/examples/blogs__vue-vuex-rest/package.json @@ -3,12 +3,12 @@ "version": "1.0.0", "description": "Testing Vue + Vuex + REST TodoMVC using Cypress", "scripts": { - "start": "../../node_modules/.bin/json-server --static . data.json --middlewares ../../node_modules/json-server-reset", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "reset:db": "node reset-db.js", - "reset": "node reset-db.js", + "cypress:run": "../../node_modules/.bin/cypress run", "dev": "../../node_modules/.bin/start-test 3000 cypress:open", + "reset": "node reset-db.js", + "reset:db": "node reset-db.js", + "start": "../../node_modules/.bin/json-server --static . data.json --middlewares ../../node_modules/json-server-reset", "test:ci": "../../node_modules/.bin/start-test 3000 cypress:run" } } diff --git a/examples/blogs__vue-vuex-rest/reset-db.js b/examples/blogs__vue-vuex-rest/reset-db.js index f90fd1bac..014702be5 100644 --- a/examples/blogs__vue-vuex-rest/reset-db.js +++ b/examples/blogs__vue-vuex-rest/reset-db.js @@ -6,9 +6,10 @@ const resetDatabase = () => { // for simple cases, can just overwrite the data file const data = { - todos: [] + todos: [], } - const str = JSON.stringify(data, null, 2) + '\n' + const str = `${JSON.stringify(data, null, 2)}\n` + write('./data.json', str) } diff --git a/examples/extending-cypress__chai-assertions/cypress/integration/extending-chai-assertion-plugins-spec.js b/examples/extending-cypress__chai-assertions/cypress/integration/extending-chai-assertion-plugins-spec.js index 88ae21e9b..0f48a75fa 100644 --- a/examples/extending-cypress__chai-assertions/cypress/integration/extending-chai-assertion-plugins-spec.js +++ b/examples/extending-cypress__chai-assertions/cypress/integration/extending-chai-assertion-plugins-spec.js @@ -1,3 +1,4 @@ +/* global chai */ /// /// diff --git a/examples/extending-cypress__chai-assertions/cypress/support/index.js b/examples/extending-cypress__chai-assertions/cypress/support/index.js index b172573e5..17259f667 100644 --- a/examples/extending-cypress__chai-assertions/cypress/support/index.js +++ b/examples/extending-cypress__chai-assertions/cypress/support/index.js @@ -1,3 +1,4 @@ +/* global chai */ // because this file is imported from cypress/support/index.js // that means all other spec files will have this assertion plugin // available to them because the supportFile is bundled and served @@ -32,5 +33,6 @@ const isFoo = (_chai, utils) => { _chai.Assertion.addMethod('foo', assertIsFoo) } + // registers our assertion function "isFoo" with Chai chai.use(isFoo) diff --git a/examples/extending-cypress__chai-assertions/package.json b/examples/extending-cypress__chai-assertions/package.json index 22f192595..5edca6fad 100644 --- a/examples/extending-cypress__chai-assertions/package.json +++ b/examples/extending-cypress__chai-assertions/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", "test:ci": "../../node_modules/.bin/cypress run" } } diff --git a/examples/file-upload-react/cypress/integration/spec.js b/examples/file-upload-react/cypress/integration/spec.js index 03ec4771e..08abb16ae 100644 --- a/examples/file-upload-react/cypress/integration/spec.js +++ b/examples/file-upload-react/cypress/integration/spec.js @@ -27,6 +27,7 @@ describe('File upload', () => { // save stub under an alias cy.stub(axios, 'post').as('file-upload') }) + // load mock data from a fixture or construct here const testFile = new File(['data to upload'], 'upload.txt') diff --git a/examples/file-upload-react/package.json b/examples/file-upload-react/package.json index c7300d0ac..0f48fdf70 100644 --- a/examples/file-upload-react/package.json +++ b/examples/file-upload-react/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "Unit testing file upload in React app", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", "start": "echo nothing to start, this recipe does not run server", "test:ci": "../../node_modules/.bin/cypress run", "test:ci:windows": "bin-up cypress run" diff --git a/examples/fundamentals__add-custom-command/cypress/integration/spec.js b/examples/fundamentals__add-custom-command/cypress/integration/spec.js index 770da790a..907b57f30 100644 --- a/examples/fundamentals__add-custom-command/cypress/integration/spec.js +++ b/examples/fundamentals__add-custom-command/cypress/integration/spec.js @@ -12,28 +12,30 @@ */ Cypress.Commands.add('dataCy', (value) => cy.get(`[data-cy=${value}]`)) -it('finds element using data-cy custom command', () => { - cy.visit('index.html') - // use custom command we have defined above - cy.dataCy('greeting').should('be.visible') -}) +describe('finds', () => { + it('element using data-cy custom command', () => { + cy.visit('index.html') + // use custom command we have defined above + cy.dataCy('greeting').should('be.visible') + }) -it('finds element using h1', () => { - cy.visit('index.html') - // sanity check that h1 element has "data-cy" attribute - // with expected value - cy.get('h1') - .should('be.visible') - .and('have.attr', 'data-cy', 'greeting') -}) + it('element using h1', () => { + cy.visit('index.html') + // sanity check that h1 element has "data-cy" attribute + // with expected value + cy.get('h1') + .should('be.visible') + .and('have.attr', 'data-cy', 'greeting') + }) -it('finds dynamically added element', () => { - cy.visit('index.html') - // another custom command, this one comes from external module - // load https://github.com/NoriSte/cypress-wait-until - cy.waitUntil(() => - cy - .window() - .then((win) => Boolean(win.document.querySelector('[data-cy=dynamic]'))) - ) + it('dynamically added element', () => { + cy.visit('index.html') + // another custom command, this one comes from external module + // load https://github.com/NoriSte/cypress-wait-until + cy.waitUntil(() => { + return cy + .window() + .then((win) => Boolean(win.document.querySelector('[data-cy=dynamic]'))) + }) + }) }) diff --git a/examples/fundamentals__add-custom-command/package.json b/examples/fundamentals__add-custom-command/package.json index ea4dffd74..8784bb90d 100644 --- a/examples/fundamentals__add-custom-command/package.json +++ b/examples/fundamentals__add-custom-command/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "Write your own Cypress commands", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", "test:ci": "../../node_modules/.bin/cypress run" } } diff --git a/examples/fundamentals__custom-browsers/cypress/integration/spec.js b/examples/fundamentals__custom-browsers/cypress/integration/spec.js index 972fdb8ac..70452001c 100644 --- a/examples/fundamentals__custom-browsers/cypress/integration/spec.js +++ b/examples/fundamentals__custom-browsers/cypress/integration/spec.js @@ -1,9 +1,12 @@ /// -it('works', () => { - cy.log( - `Running in browser **${Cypress.browser.displayName} v${ - Cypress.browser.majorVersion - }**` - ) - cy.task('echo', { browser: Cypress.browser }) +describe('browser', () => { + it('works', () => { + cy.log( + `Running in browser **${Cypress.browser.displayName} v${ + Cypress.browser.majorVersion + }**` + ) + + cy.task('echo', { browser: Cypress.browser }) + }) }) diff --git a/examples/fundamentals__custom-browsers/package.json b/examples/fundamentals__custom-browsers/package.json index 23a0b14c1..60393ad69 100644 --- a/examples/fundamentals__custom-browsers/package.json +++ b/examples/fundamentals__custom-browsers/package.json @@ -3,9 +3,9 @@ "version": "1.0.0", "description": "Customizes list of browsers", "scripts": { - "start": "echo nothing to start", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", + "start": "echo nothing to start", "test:ci": "../../node_modules/.bin/cypress run", "test:ci:brave": "../../node_modules/.bin/cypress run --config pluginsFile=cypress/plugins/brave.js --browser brave" } diff --git a/examples/fundamentals__dynamic-tests/package.json b/examples/fundamentals__dynamic-tests/package.json index aeb0693e3..e4b31b746 100644 --- a/examples/fundamentals__dynamic-tests/package.json +++ b/examples/fundamentals__dynamic-tests/package.json @@ -3,9 +3,9 @@ "version": "1.0.0", "description": "Create Cypress tests dynamically from data", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "test:ci:windows": "bin-up cypress run", - "test:ci": "npm run cypress:run" + "cypress:run": "../../node_modules/.bin/cypress run", + "test:ci": "npm run cypress:run", + "test:ci:windows": "bin-up cypress run" } } diff --git a/examples/fundamentals__fixtures/cypress/integration/load-fixtures-spec.js b/examples/fundamentals__fixtures/cypress/integration/load-fixtures-spec.js index 5c227997d..c46d2ab00 100644 --- a/examples/fundamentals__fixtures/cypress/integration/load-fixtures-spec.js +++ b/examples/fundamentals__fixtures/cypress/integration/load-fixtures-spec.js @@ -5,10 +5,11 @@ describe('Loading multiple fixtures', () => { let country beforeEach(() => { - cy.fixture('city').then(c => { + cy.fixture('city').then((c) => { city = c }) - cy.fixture('country').then(c => { + + cy.fixture('country').then((c) => { country = c }) }) @@ -16,14 +17,14 @@ describe('Loading multiple fixtures', () => { it('has loaded fixtures', () => { expect({ city, country }).to.deep.equal({ city: { name: 'Atlanta' }, - country: { name: 'United States' } + country: { name: 'United States' }, }) }) it('still has fixtures in the second test', () => { expect({ city, country }).to.deep.equal({ city: { name: 'Atlanta' }, - country: { name: 'United States' } + country: { name: 'United States' }, }) }) }) @@ -35,10 +36,11 @@ describe('Loading multiple fixtures', () => { before(() => { // load fixtures once before any tests // and they are kept in closure variables - cy.fixture('city').then(c => { + cy.fixture('city').then((c) => { city = c }) - cy.fixture('country').then(c => { + + cy.fixture('country').then((c) => { country = c }) }) @@ -46,7 +48,7 @@ describe('Loading multiple fixtures', () => { it('has loaded fixtures', () => { expect({ city, country }).to.deep.equal({ city: { name: 'Atlanta' }, - country: { name: 'United States' } + country: { name: 'United States' }, }) }) @@ -55,7 +57,7 @@ describe('Loading multiple fixtures', () => { // in the two variables and they should remain there expect({ city, country }).to.deep.equal({ city: { name: 'Atlanta' }, - country: { name: 'United States' } + country: { name: 'United States' }, }) }) }) @@ -64,10 +66,11 @@ describe('Loading multiple fixtures', () => { // notice how "beforeEach" callback uses "function" // form to make sure Mocha context points correctly at "this" beforeEach(function () { - cy.fixture('city').then(c => { + cy.fixture('city').then((c) => { this.city = c }) - cy.fixture('country').then(c => { + + cy.fixture('country').then((c) => { this.country = c }) }) @@ -105,10 +108,11 @@ describe('Loading multiple fixtures', () => { // load fixtures just once, need to store in // closure variables because Mocha context is cleared // before each test - cy.fixture('city').then(c => { + cy.fixture('city').then((c) => { city = c }) - cy.fixture('country').then(c => { + + cy.fixture('country').then((c) => { country = c }) }) diff --git a/examples/fundamentals__fixtures/cypress/integration/multiple-fixtures-spec.js b/examples/fundamentals__fixtures/cypress/integration/multiple-fixtures-spec.js index 748645f07..e14047c7c 100644 --- a/examples/fundamentals__fixtures/cypress/integration/multiple-fixtures-spec.js +++ b/examples/fundamentals__fixtures/cypress/integration/multiple-fixtures-spec.js @@ -1,18 +1,21 @@ /// +/* eslint-disable no-console */ + describe('Loading multiple fixtures', () => { it('loads fixtures one by one', () => { // pyramid of doom of fixtures - cy.fixture('city').then(city => { - cy.fixture('country').then(country => { + cy.fixture('city').then((city) => { + cy.fixture('country').then((country) => { // thanks to JavaScript closures we have access to both fixtures expect({ city, country }).to.deep.equal({ city: { name: 'Atlanta' }, - country: { name: 'United States' } + country: { name: 'United States' }, }) }) }) }) + // NOTE: test showing possible race condition it.skip('loads fixtures using Cypress.Promise.all - not recommended due to race condition', () => { // see discussion of Cypress.Promise.all in // https://github.com/cypress-io/cypress/issues/2932 diff --git a/examples/fundamentals__fixtures/package.json b/examples/fundamentals__fixtures/package.json index 4a8f73700..f2dd1ab05 100644 --- a/examples/fundamentals__fixtures/package.json +++ b/examples/fundamentals__fixtures/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "Create Cypress tests dynamically from data", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", "test:ci": "../../node_modules/.bin/cypress run", "test:ci:windows": "bin-up cypress run" } diff --git a/examples/fundamentals__module-api/cypress/support/commands.js b/examples/fundamentals__module-api/cypress/support/commands.js index cae33ce8c..d7cca3f84 100644 --- a/examples/fundamentals__module-api/cypress/support/commands.js +++ b/examples/fundamentals__module-api/cypress/support/commands.js @@ -36,4 +36,4 @@ // .then(function(){ // log.snapshot().end() // }) -// }) \ No newline at end of file +// }) diff --git a/examples/fundamentals__module-api/cypress/support/defaults.js b/examples/fundamentals__module-api/cypress/support/defaults.js index 24d28fd2f..27df9f2a2 100644 --- a/examples/fundamentals__module-api/cypress/support/defaults.js +++ b/examples/fundamentals__module-api/cypress/support/defaults.js @@ -14,4 +14,4 @@ // Cypress.Cookies.defaults({ // whitelist: ["session_id", "remember_token"] -// }) \ No newline at end of file +// }) diff --git a/examples/fundamentals__module-api/cypress/support/index.js b/examples/fundamentals__module-api/cypress/support/index.js index 515c90f4a..a7eaa6723 100644 --- a/examples/fundamentals__module-api/cypress/support/index.js +++ b/examples/fundamentals__module-api/cypress/support/index.js @@ -15,5 +15,5 @@ // Import commands.js and defaults.js // using ES2015 syntax: -import "./commands" -import "./defaults" +import './commands' +import './defaults' diff --git a/examples/fundamentals__module-api/cypress/support/utils/append_key.js b/examples/fundamentals__module-api/cypress/support/utils/append_key.js index a733c2e63..8ef4fd9a6 100644 --- a/examples/fundamentals__module-api/cypress/support/utils/append_key.js +++ b/examples/fundamentals__module-api/cypress/support/utils/append_key.js @@ -1,3 +1,3 @@ -module.exports = function(str) { - return str + "+APIkey123" +module.exports = function (str) { + return `${str}+APIkey123` } diff --git a/examples/fundamentals__module-api/e2e-tests.js b/examples/fundamentals__module-api/e2e-tests.js index 88088480b..4cc594761 100644 --- a/examples/fundamentals__module-api/e2e-tests.js +++ b/examples/fundamentals__module-api/e2e-tests.js @@ -1,10 +1,13 @@ // runs Cypress end-to-end tests using Cypress Node module API // https://on.cypress.io/module-api +/* eslint-disable no-console */ + const cypress = require('cypress') const globby = require('globby') const Promise = require('bluebird') const fs = require('fs') + require('console.table') /** @@ -12,46 +15,54 @@ require('console.table') */ const byTime = (a, b) => b.time - a.time -const sortByLastModified = filenames => { - const withTimes = filenames.map(filename => ({ - filename, - time: fs.statSync(filename).mtime.getTime() - })) +const sortByLastModified = (filenames) => { + const withTimes = filenames.map((filename) => { + return { + filename, + time: fs.statSync(filename).mtime.getTime(), + } + }) + return withTimes.sort(byTime) } -const runOneSpec = spec => - cypress.run({ +const runOneSpec = (spec) => { + return cypress.run({ config: { - video: false + video: false, }, - spec: spec.filename + spec: spec.filename, }) +} globby('./cypress/integration/*-spec.js') - .then(sortByLastModified) - .then(specs => { - console.table('Running last modified spec first', specs) - return Promise.mapSeries(specs, runOneSpec) - }) - .then(runsResults => { - // information about each test run is available - // see the full NPM API declaration in - // https://github.com/cypress-io/cypress/tree/develop/cli/types - - // you can generate your own report, - // email or post a Slack message - // rerun the failing specs, etc. - - // for now show just the summary - // by drilling down into specResults objects - const summary = runsResults - .map(oneRun => oneRun.runs[0]) - .map(run => ({ - spec: run.spec.name, - tests: run.stats.tests, - passes: run.stats.passes, - failures: run.stats.failures - })) - console.table('Test run summary', summary) +.then(sortByLastModified) +.then((specs) => { + console.table('Running last modified spec first', specs) + + return Promise.mapSeries(specs, runOneSpec) +}) +.then((runsResults) => { + // information about each test run is available + // see the full NPM API declaration in + // https://github.com/cypress-io/cypress/tree/develop/cli/types + + // you can generate your own report, + // email or post a Slack message + // rerun the failing specs, etc. + + // for now show just the summary + // by drilling down into specResults objects + const summary = runsResults + .map((oneRun) => oneRun.runs[0]) + .map((run) => { + return { + spec: run.spec.name, + tests: run.stats.tests, + passes: run.stats.passes, + failures: run.stats.failures, + } }) + + console.table('Test run summary', summary) +}) diff --git a/examples/fundamentals__module-api/package.json b/examples/fundamentals__module-api/package.json index 039f72fc7..3238259df 100644 --- a/examples/fundamentals__module-api/package.json +++ b/examples/fundamentals__module-api/package.json @@ -3,9 +3,9 @@ "version": "1.0.0", "description": "Run Cypress via its module API", "scripts": { - "start": "echo nothing to start", - "cypress:run": "node ./e2e-tests", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "node ./e2e-tests", + "start": "echo nothing to start", "test:ci": "node ./e2e-tests" } } diff --git a/examples/fundamentals__node-modules/cypress/integration/es2015-commonjs-modules-spec.js b/examples/fundamentals__node-modules/cypress/integration/es2015-commonjs-modules-spec.js index a0f9fd0b5..e37b3ebe5 100644 --- a/examples/fundamentals__node-modules/cypress/integration/es2015-commonjs-modules-spec.js +++ b/examples/fundamentals__node-modules/cypress/integration/es2015-commonjs-modules-spec.js @@ -20,30 +20,29 @@ import { upperFirst, lowerFirst } from 'lodash' // and also require node_modules from our package.json const minimist = require('minimist') -describe("Modules", function(){ - +describe('Modules', function () { // you can use ES2015 module import syntax - context('ES2015', function(){ - it('can import default function', function(){ + context('ES2015', function () { + it('can import default function', function () { expect(getSelector('checkbox')).to.eq('.my-app-checkbox') }) - it('can import upperFirst from lodash', function(){ + it('can import upperFirst from lodash', function () { expect(upperFirst('jane')).to.eq('Jane') }) - it('can import lowerFirst from lodash', function(){ + it('can import lowerFirst from lodash', function () { expect(lowerFirst('JANE')).to.eq('jANE') }) }) // you can also use node's CommonJS require syntax - context('CommonJS', function(){ - it('can require module.exports', function(){ + context('CommonJS', function () { + it('can require module.exports', function () { expect(appendKey('jane.lane@devs.com')).to.eq('jane.lane@devs.com+APIkey123') }) - it('can require minimist', function(){ + it('can require minimist', function () { // minimist is a command line argument parsing tool // that is traditionally used in node (we use it at Cypress) // @@ -54,7 +53,7 @@ describe("Modules", function(){ count: 1, foo: 'bar', quux: false, - _: [] + _: [], }) }) }) diff --git a/examples/fundamentals__node-modules/cypress/support/commands.js b/examples/fundamentals__node-modules/cypress/support/commands.js index cae33ce8c..d7cca3f84 100644 --- a/examples/fundamentals__node-modules/cypress/support/commands.js +++ b/examples/fundamentals__node-modules/cypress/support/commands.js @@ -36,4 +36,4 @@ // .then(function(){ // log.snapshot().end() // }) -// }) \ No newline at end of file +// }) diff --git a/examples/fundamentals__node-modules/cypress/support/defaults.js b/examples/fundamentals__node-modules/cypress/support/defaults.js index 24d28fd2f..27df9f2a2 100644 --- a/examples/fundamentals__node-modules/cypress/support/defaults.js +++ b/examples/fundamentals__node-modules/cypress/support/defaults.js @@ -14,4 +14,4 @@ // Cypress.Cookies.defaults({ // whitelist: ["session_id", "remember_token"] -// }) \ No newline at end of file +// }) diff --git a/examples/fundamentals__node-modules/cypress/support/index.js b/examples/fundamentals__node-modules/cypress/support/index.js index 515c90f4a..a7eaa6723 100644 --- a/examples/fundamentals__node-modules/cypress/support/index.js +++ b/examples/fundamentals__node-modules/cypress/support/index.js @@ -15,5 +15,5 @@ // Import commands.js and defaults.js // using ES2015 syntax: -import "./commands" -import "./defaults" +import './commands' +import './defaults' diff --git a/examples/fundamentals__node-modules/cypress/support/utils/append_key.js b/examples/fundamentals__node-modules/cypress/support/utils/append_key.js index a733c2e63..8ef4fd9a6 100644 --- a/examples/fundamentals__node-modules/cypress/support/utils/append_key.js +++ b/examples/fundamentals__node-modules/cypress/support/utils/append_key.js @@ -1,3 +1,3 @@ -module.exports = function(str) { - return str + "+APIkey123" +module.exports = function (str) { + return `${str}+APIkey123` } diff --git a/examples/fundamentals__node-modules/package.json b/examples/fundamentals__node-modules/package.json index 1497460aa..fc83b372d 100644 --- a/examples/fundamentals__node-modules/package.json +++ b/examples/fundamentals__node-modules/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "Use NPM modules from Cypress specs", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", "test:ci": "../../node_modules/.bin/cypress run", "test:ci:windows": "bin-up cypress run" } diff --git a/examples/logging-in__csrf-tokens/cypress/integration/logging-in-csrf-tokens-spec.js b/examples/logging-in__csrf-tokens/cypress/integration/logging-in-csrf-tokens-spec.js index a319c786d..b9afb5b37 100644 --- a/examples/logging-in__csrf-tokens/cypress/integration/logging-in-csrf-tokens-spec.js +++ b/examples/logging-in__csrf-tokens/cypress/integration/logging-in-csrf-tokens-spec.js @@ -4,22 +4,22 @@ // and shows you how to use cy.request when your backend // validates POSTs against a CSRF token // -describe('Logging In - CSRF Tokens', function(){ +describe('Logging In - CSRF Tokens', function () { const username = 'cypress' const password = 'password123' Cypress.Commands.add('loginByCSRF', (csrfToken) => { cy.request({ - method: 'POST', - url: '/login', - failOnStatusCode: false, // dont fail so we can make assertions - form: true, // we are submitting a regular form body - body: { - username, - password, - _csrf: csrfToken // insert this as part of form body - } - }) + method: 'POST', + url: '/login', + failOnStatusCode: false, // dont fail so we can make assertions + form: true, // we are submitting a regular form body + body: { + username, + password, + _csrf: csrfToken, // insert this as part of form body + }, + }) }) /** @@ -38,7 +38,7 @@ describe('Logging In - CSRF Tokens', function(){ inDashboard() } - beforeEach(function(){ + beforeEach(function () { cy.viewport(500, 380) }) @@ -47,70 +47,72 @@ describe('Logging In - CSRF Tokens', function(){ cy.location('href').should('match', /login$/) }) - it('403 status without a valid CSRF token', function(){ + it('403 status without a valid CSRF token', function () { // first show that by not providing a valid CSRF token // that we will get a 403 status code cy.loginByCSRF('invalid-token') - .its('status') - .should('eq', 403) + .its('status') + .should('eq', 403) }) - it('strategy #1: parse token from HTML', function(){ + it('strategy #1: parse token from HTML', function () { // if we cannot change our server code to make it easier // to parse out the CSRF token, we can simply use cy.request // to fetch the login page, and then parse the HTML contents // to find the CSRF token embedded in the page cy.request('/login') - .its('body') - .then((body) => { - // we can use Cypress.$ to parse the string body - // thus enabling us to query into it easily - const $html = Cypress.$(body) - const csrf = $html.find("input[name=_csrf]").val() - - cy.loginByCSRF(csrf) - .then((resp) => { - expect(resp.status).to.eq(200) - expect(resp.body).to.include("

dashboard.html

") - }) + .its('body') + .then((body) => { + // we can use Cypress.$ to parse the string body + // thus enabling us to query into it easily + const $html = Cypress.$(body) + const csrf = $html.find('input[name=_csrf]').val() + + cy.loginByCSRF(csrf) + .then((resp) => { + expect(resp.status).to.eq(200) + expect(resp.body).to.include('

dashboard.html

') }) + }) // successful "cy.request" sets all returned cookies, thus we should // be able to visit the protected page - we are logged in! visitDashboard() }) - it('strategy #2: parse token from response headers', function(){ + it('strategy #2: parse token from response headers', function () { // if we embed our csrf-token in response headers // it makes it much easier for us to pluck it out // without having to dig into the resulting HTML cy.request('/login') - .its('headers') - .then((headers) => { - const csrf = headers['x-csrf-token'] - - cy.loginByCSRF(csrf) - .then((resp) => { - expect(resp.status).to.eq(200) - expect(resp.body).to.include("

dashboard.html

") - }) + .its('headers') + .then((headers) => { + const csrf = headers['x-csrf-token'] + + cy.loginByCSRF(csrf) + .then((resp) => { + expect(resp.status).to.eq(200) + expect(resp.body).to.include('

dashboard.html

') }) + }) + visitDashboard() }) - it('strategy #3: expose CSRF via a route when not in production', function(){ + it('strategy #3: expose CSRF via a route when not in production', function () { // since we are not running in production we have exposed // a simple /csrf route which returns us the token directly // as json cy.request('/csrf') - .its('body.csrfToken') - .then((csrf) => { - cy.loginByCSRF(csrf) - .then((resp) => { - expect(resp.status).to.eq(200) - expect(resp.body).to.include("

dashboard.html

") - }) + .its('body.csrfToken') + .then((csrf) => { + cy.loginByCSRF(csrf) + .then((resp) => { + expect(resp.status).to.eq(200) + expect(resp.body).to.include('

dashboard.html

') }) + }) + visitDashboard() }) diff --git a/examples/logging-in__csrf-tokens/package.json b/examples/logging-in__csrf-tokens/package.json index 0bc2c6358..f41d907e0 100644 --- a/examples/logging-in__csrf-tokens/package.json +++ b/examples/logging-in__csrf-tokens/package.json @@ -3,10 +3,10 @@ "version": "1.0.0", "description": "", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "start": "node server.js --port 7076", + "cypress:run": "../../node_modules/.bin/cypress run", "dev": "../../node_modules/.bin/start-test 7076 cypress:open", + "start": "node server.js --port 7076", "test:ci": "../../node_modules/.bin/start-test 7076 cypress:run" } } diff --git a/examples/logging-in__csrf-tokens/server.js b/examples/logging-in__csrf-tokens/server.js index 3f439927f..b4768958f 100644 --- a/examples/logging-in__csrf-tokens/server.js +++ b/examples/logging-in__csrf-tokens/server.js @@ -1,11 +1,11 @@ -const csurf = require('csurf') -const morgan = require('morgan') -const minimist = require('minimist') +const csurf = require('csurf') +const morgan = require('morgan') +const minimist = require('minimist') const bodyParser = require('body-parser') -const session = require('express-session') -const express = require('express') +const session = require('express-session') +const express = require('express') -const app = express() +const app = express() // get port from passed in args from scripts/start.js const port = minimist(process.argv.slice(2)).port @@ -35,7 +35,7 @@ app.use(session({ name: 'cypress-session-cookie', secret: 'sekret', resave: false, - saveUninitialized: false + saveUninitialized: false, })) // app.use((req, res, next) => { @@ -55,7 +55,7 @@ app.get('/login', csrfProtection, (req, res) => { res .set('x-csrf-token', token) // set a response header .render('./login.hbs', { - csrfToken: token // and also send this part of the HTML + csrfToken: token, // and also send this part of the HTML }) }) @@ -64,14 +64,14 @@ app.get('/login', csrfProtection, (req, res) => { // the login form app.post('/login', urlencodedParser, csrfProtection, (req, res) => { // if this matches the secret username and password - if(matchesUsernameAndPassword(req.body)){ + if (matchesUsernameAndPassword(req.body)) { req.session.user = 'cypress' res.redirect('/dashboard') } else { // render login with errors res.render('./login.hbs', { - error: 'Username and password incorrect' + error: 'Username and password incorrect', }) } }) @@ -82,10 +82,10 @@ app.get('/dashboard', ensureLoggedIn, (req, res) => { // if we are not in production expose a simple // GET /csrf route to hand us back the token over JSON -if(process.env.NODE_ENV !== 'production'){ +if (process.env.NODE_ENV !== 'production') { app.get('/csrf', csrfProtection, (req, res) => { res.json({ - csrfToken: req.csrfToken() + csrfToken: req.csrfToken(), }) }) } diff --git a/examples/logging-in__html-web-forms/cypress/integration/logging-in-html-web-form-spec.js b/examples/logging-in__html-web-forms/cypress/integration/logging-in-html-web-form-spec.js index 28228b69f..bb6c633d9 100644 --- a/examples/logging-in__html-web-forms/cypress/integration/logging-in-html-web-form-spec.js +++ b/examples/logging-in__html-web-forms/cypress/integration/logging-in-html-web-form-spec.js @@ -29,6 +29,7 @@ describe('Logging In - HTML Web Form', function () { 'contain', 'You are not logged in and cannot access this page' ) + cy.url().should('include', 'unauthorized') }) @@ -105,7 +106,7 @@ describe('Logging In - HTML Web Form', function () { form: true, // indicates the body should be form urlencoded and sets Content-Type: application/x-www-form-urlencoded headers body: { username, - password + password, }, }) diff --git a/examples/logging-in__html-web-forms/package.json b/examples/logging-in__html-web-forms/package.json index c37219af0..69b259bda 100644 --- a/examples/logging-in__html-web-forms/package.json +++ b/examples/logging-in__html-web-forms/package.json @@ -3,10 +3,10 @@ "version": "1.0.0", "description": "", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "start": "node server.js --port 7077", + "cypress:run": "../../node_modules/.bin/cypress run", "dev": "../../node_modules/.bin/start-test 7077 cypress:open", + "start": "node server.js --port 7077", "test:ci": "../../node_modules/.bin/start-test 7077 cypress:run" } } diff --git a/examples/logging-in__html-web-forms/server.js b/examples/logging-in__html-web-forms/server.js index 80f65e7e6..9fd725b56 100644 --- a/examples/logging-in__html-web-forms/server.js +++ b/examples/logging-in__html-web-forms/server.js @@ -1,10 +1,10 @@ -const minimist = require('minimist') -const morgan = require('morgan') +const minimist = require('minimist') +const morgan = require('morgan') const bodyParser = require('body-parser') -const session = require('express-session') -const express = require('express') +const session = require('express-session') +const express = require('express') -const app = express() +const app = express() // get port from passed in args from scripts/start.js const port = minimist(process.argv.slice(2)).port @@ -24,7 +24,7 @@ const ensureLoggedIn = (req, res, next) => { // parse regular form submission bodies const urlencodedParser = bodyParser.urlencoded({ extended: false }) -app.use(morgan("dev")) +app.use(morgan('dev')) // store a session cookie called // 'cypress-session-cookie' @@ -32,7 +32,7 @@ app.use(session({ name: 'cypress-session-cookie', secret: 'sekret', resave: false, - saveUninitialized: false + saveUninitialized: false, })) // app.use((req, res, next) => { @@ -55,21 +55,21 @@ app.get('/login', (req, res) => { // the login form app.post('/login', urlencodedParser, (req, res) => { // if this matches the secret username and password - if(matchesUsernameAndPassword(req.body)){ + if (matchesUsernameAndPassword(req.body)) { req.session.user = 'jane.lane' res.redirect('/dashboard') } else { // render login with errors res.render('./login.hbs', { - error: 'Username and/or password is incorrect' + error: 'Username and/or password is incorrect', }) } }) app.get('/dashboard', ensureLoggedIn, (req, res) => { res.render('./dashboard.hbs', { - user: req.session.user + user: req.session.user, }) }) diff --git a/examples/logging-in__jwt/cypress/integration/spec.js b/examples/logging-in__jwt/cypress/integration/spec.js index 8960e4ba3..e677d9273 100644 --- a/examples/logging-in__jwt/cypress/integration/spec.js +++ b/examples/logging-in__jwt/cypress/integration/spec.js @@ -2,6 +2,7 @@ // login just once using API let user + before(function fetchUser () { cy.request('POST', 'http://localhost:4000/users/authenticate', { username: Cypress.env('username'), @@ -26,31 +27,33 @@ beforeEach(function setUser () { // the page should be opened and the user should be logged in }) -it('makes authenticated request', () => { +describe('JWT', () => { + it('makes authenticated request', () => { // we can make authenticated request ourselves // since we know the token - cy.request({ - url: 'http://localhost:4000/users', - auth: { - bearer: user.token, - }, + cy.request({ + url: 'http://localhost:4000/users', + auth: { + bearer: user.token, + }, + }) + .its('body') + .should('deep.equal', [ + { + id: 1, + username: 'test', + firstName: 'Test', + lastName: 'User', + }, + ]) }) - .its('body') - .should('deep.equal', [ - { - id: 1, - username: 'test', - firstName: 'Test', - lastName: 'User', - }, - ]) -}) -it('is logged in', () => { - cy.contains('Hi Test!').should('be.visible') -}) + it('is logged in', () => { + cy.contains('Hi Test!').should('be.visible') + }) -it('shows loaded user', () => { + it('shows loaded user', () => { // this user information came from authenticated XHR call - cy.contains('li', 'Test User').should('be.visible') + cy.contains('li', 'Test User').should('be.visible') + }) }) diff --git a/examples/logging-in__jwt/cypress/integration/using-ui-spec.js b/examples/logging-in__jwt/cypress/integration/using-ui-spec.js index 180538427..ed0f0f31a 100644 --- a/examples/logging-in__jwt/cypress/integration/using-ui-spec.js +++ b/examples/logging-in__jwt/cypress/integration/using-ui-spec.js @@ -1,59 +1,64 @@ /// -it('Logs in using UI', () => { - cy.visit('/') - cy.location('pathname').should('equal', '/login') - - // enter valid username and password - cy.get('[name=username]').type(Cypress.env('username')) - cy.get('[name=password]').type(Cypress.env('password')) - cy.contains('button', 'Login').click() - - // confirm we have logged in successfully - cy.location('pathname').should('equal', '/') - cy.contains('Hi Test!') - .should('be.visible') - .then(() => { +describe('logs in', () => { + it('using UI', () => { + cy.visit('/') + cy.location('pathname').should('equal', '/login') + + // enter valid username and password + cy.get('[name=username]').type(Cypress.env('username')) + cy.get('[name=password]').type(Cypress.env('password')) + cy.contains('button', 'Login').click() + + // confirm we have logged in successfully + cy.location('pathname').should('equal', '/') + cy.contains('Hi Test!') + .should('be.visible') + .then(() => { /* global window */ - const userString = window.localStorage.getItem('user') - expect(userString).to.be.a('string') - const user = JSON.parse(userString) - expect(user).to.be.an('object') - expect(user).to.have.keys([ - 'id', - 'username', - 'firstName', - 'lastName', - 'token', - ]) - expect(user.token).to.be.a('string') - }) + const userString = window.localStorage.getItem('user') - // now we can log out - cy.contains('a', 'Logout').click() - cy.location('pathname').should('equal', '/login') -}) + expect(userString).to.be.a('string') + const user = JSON.parse(userString) + + expect(user).to.be.an('object') + expect(user).to.have.keys([ + 'id', + 'username', + 'firstName', + 'lastName', + 'token', + ]) -it('fails to access protected resource', () => { - cy.request({ - url: 'http://localhost:4000/users', - failOnStatusCode: false, + expect(user.token).to.be.a('string') + }) + + // now we can log out + cy.contains('a', 'Logout').click() + cy.location('pathname').should('equal', '/login') }) - .its('status') - .should('equal', 401) -}) -it('Does not log in with invalid password', () => { - cy.visit('/') - cy.location('pathname').should('equal', '/login') + it('fails to access protected resource', () => { + cy.request({ + url: 'http://localhost:4000/users', + failOnStatusCode: false, + }) + .its('status') + .should('equal', 401) + }) - // enter valid username and password - cy.get('[name=username]').type('username') - cy.get('[name=password]').type('wrong-password') - cy.contains('button', 'Login').click() + it('Does not log in with invalid password', () => { + cy.visit('/') + cy.location('pathname').should('equal', '/login') - // still on /login page plus an error is displayed - cy.location('pathname').should('equal', '/login') - cy.contains('.alert-danger', 'Username or password is incorrect').should( - 'be.visible' - ) + // enter valid username and password + cy.get('[name=username]').type('username') + cy.get('[name=password]').type('wrong-password') + cy.contains('button', 'Login').click() + + // still on /login page plus an error is displayed + cy.location('pathname').should('equal', '/login') + cy.contains('.alert-danger', 'Username or password is incorrect').should( + 'be.visible' + ) + }) }) diff --git a/examples/logging-in__jwt/package.json b/examples/logging-in__jwt/package.json index 037709a3a..d70157169 100644 --- a/examples/logging-in__jwt/package.json +++ b/examples/logging-in__jwt/package.json @@ -3,12 +3,12 @@ "version": "1.0.0", "description": "Example of logging in using JWT", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "start:server": "node server", - "start:app": "../../node_modules/.bin/webpack-dev-server --port 8081", - "start": "../../node_modules/.bin/run-p start:server start:app", + "cypress:run": "../../node_modules/.bin/cypress run", "dev": "../../node_modules/.bin/start-test 8081 cypress:open", + "start": "../../node_modules/.bin/run-p start:server start:app", + "start:app": "../../node_modules/.bin/webpack-dev-server --port 8081", + "start:server": "node server", "test:ci": "../../node_modules/.bin/start-test 8081 cypress:run" } } diff --git a/examples/logging-in__jwt/server/_helpers/error-handler.js b/examples/logging-in__jwt/server/_helpers/error-handler.js index 648db2409..510f4714a 100644 --- a/examples/logging-in__jwt/server/_helpers/error-handler.js +++ b/examples/logging-in__jwt/server/_helpers/error-handler.js @@ -1,16 +1,16 @@ -module.exports = errorHandler; +module.exports = errorHandler -function errorHandler(err, req, res, next) { - if (typeof (err) === 'string') { - // custom application error - return res.status(400).json({ message: err }); - } +function errorHandler (err, req, res, next) { + if (typeof (err) === 'string') { + // custom application error + return res.status(400).json({ message: err }) + } - if (err.name === 'UnauthorizedError') { - // jwt authentication error - return res.status(401).json({ message: 'Invalid Token' }); - } + if (err.name === 'UnauthorizedError') { + // jwt authentication error + return res.status(401).json({ message: 'Invalid Token' }) + } - // default to 500 server error - return res.status(500).json({ message: err.message }); -} \ No newline at end of file + // default to 500 server error + return res.status(500).json({ message: err.message }) +} diff --git a/examples/logging-in__jwt/server/_helpers/jwt.js b/examples/logging-in__jwt/server/_helpers/jwt.js index 51c369ad0..7fc2a4dbf 100644 --- a/examples/logging-in__jwt/server/_helpers/jwt.js +++ b/examples/logging-in__jwt/server/_helpers/jwt.js @@ -5,6 +5,7 @@ module.exports = jwt function jwt () { const { secret } = config + return expressJwt({ secret }).unless({ path: [ // public routes that don't require authentication diff --git a/examples/logging-in__jwt/server/config.json b/examples/logging-in__jwt/server/config.json index 37c41ad53..b5cd91ee1 100644 --- a/examples/logging-in__jwt/server/config.json +++ b/examples/logging-in__jwt/server/config.json @@ -1,3 +1,3 @@ { - "secret": "Verify JWT using this secret string" + "secret": "Verify JWT using this secret string" } diff --git a/examples/logging-in__jwt/server/index.js b/examples/logging-in__jwt/server/index.js index 73dac6267..320fd6e33 100644 --- a/examples/logging-in__jwt/server/index.js +++ b/examples/logging-in__jwt/server/index.js @@ -1,4 +1,5 @@ -require('rootpath')() +/* eslint-disable no-console */ +require('rootpath')() const express = require('express') const app = express() const cors = require('cors') @@ -21,6 +22,7 @@ app.use(errorHandler) // start server const port = process.env.NODE_ENV === 'production' ? 80 : 4000 + app.listen(port, function () { console.log(`Server listening on port ${port}`) }) diff --git a/examples/logging-in__jwt/server/users/user.service.js b/examples/logging-in__jwt/server/users/user.service.js index ea50823cb..7f06d9c18 100644 --- a/examples/logging-in__jwt/server/users/user.service.js +++ b/examples/logging-in__jwt/server/users/user.service.js @@ -1,4 +1,5 @@ -const config = require('../config.json') +/* eslint-disable no-unused-vars */ +const config = require('../config.json') const jwt = require('jsonwebtoken') // users hardcoded for simplicity, store in a db for production applications @@ -8,32 +9,35 @@ const users = [ username: 'test', password: 'test', firstName: 'Test', - lastName: 'User' - } + lastName: 'User', + }, ] module.exports = { authenticate, - getAll + getAll, } async function authenticate ({ username, password }) { const user = users.find( - u => u.username === username && u.password === password + (u) => u.username === username && u.password === password ) + if (user) { const token = jwt.sign({ sub: user.id }, config.secret) const { password, ...userWithoutPassword } = user + return { ...userWithoutPassword, - token + token, } } } async function getAll () { - return users.map(u => { + return users.map((u) => { const { password, ...userWithoutPassword } = u + return userWithoutPassword }) } diff --git a/examples/logging-in__jwt/server/users/users.controller.js b/examples/logging-in__jwt/server/users/users.controller.js index c19dcfe0b..3b386b0ae 100644 --- a/examples/logging-in__jwt/server/users/users.controller.js +++ b/examples/logging-in__jwt/server/users/users.controller.js @@ -11,11 +11,11 @@ module.exports = router function authenticate (req, res, next) { userService .authenticate(req.body) - .then((user) => - user + .then((user) => { + return user ? res.json(user) : res.status(400).json({ message: 'Username or password is incorrect' }) - ) + }) .catch((err) => next(err)) } diff --git a/examples/logging-in__jwt/src/_helpers/auth-header.js b/examples/logging-in__jwt/src/_helpers/auth-header.js index a8fe5f5a7..0fe5bd132 100644 --- a/examples/logging-in__jwt/src/_helpers/auth-header.js +++ b/examples/logging-in__jwt/src/_helpers/auth-header.js @@ -1,10 +1,11 @@ -export function authHeader() { - // return authorization header with jwt token - let user = JSON.parse(localStorage.getItem('user')); +/* global localStorage */ +export function authHeader () { + // return authorization header with jwt token + let user = JSON.parse(localStorage.getItem('user')) - if (user && user.token) { - return { 'Authorization': 'Bearer ' + user.token }; - } else { - return {}; - } -} \ No newline at end of file + if (user && user.token) { + return { 'Authorization': `Bearer ${user.token}` } + } + + return {} +} diff --git a/examples/logging-in__jwt/src/_helpers/fake-backend.js b/examples/logging-in__jwt/src/_helpers/fake-backend.js index 61b7b8ccf..772d17845 100644 --- a/examples/logging-in__jwt/src/_helpers/fake-backend.js +++ b/examples/logging-in__jwt/src/_helpers/fake-backend.js @@ -1,57 +1,58 @@ -export function configureFakeBackend() { - let users = [{ id: 1, username: 'test', password: 'test', firstName: 'Test', lastName: 'User' }]; - let realFetch = window.fetch; - window.fetch = function (url, opts) { - return new Promise((resolve, reject) => { - // wrap in timeout to simulate server api call - setTimeout(() => { - - // authenticate - if (url.endsWith('/users/authenticate') && opts.method === 'POST') { - // get parameters from post request - let params = JSON.parse(opts.body); - - // find if any user matches login credentials - let filteredUsers = users.filter(user => { - return user.username === params.username && user.password === params.password; - }); - - if (filteredUsers.length) { - // if login details are valid return user details and fake jwt token - let user = filteredUsers[0]; - let responseJson = { - id: user.id, - username: user.username, - firstName: user.firstName, - lastName: user.lastName, - token: 'fake-jwt-token' - }; - resolve({ ok: true, text: () => Promise.resolve(JSON.stringify(responseJson)) }); - } else { - // else return error - reject('Username or password is incorrect'); - } - - return; - } - - // get users - if (url.endsWith('/users') && opts.method === 'GET') { - // check for fake auth token in header and return users if valid, this security is implemented server side in a real application - if (opts.headers && opts.headers.Authorization === 'Bearer fake-jwt-token') { - resolve({ ok: true, text: () => Promise.resolve(JSON.stringify(users)) }); - } else { - // return 401 not authorised if token is null or invalid - reject('Unauthorised'); - } - - return; - } - - // pass through any requests not handled above - realFetch(url, opts).then(response => resolve(response)); - - }, 500); - }); - } -} \ No newline at end of file +/* global window */ +export function configureFakeBackend () { + let users = [{ id: 1, username: 'test', password: 'test', firstName: 'Test', lastName: 'User' }] + let realFetch = window.fetch + + window.fetch = function (url, opts) { + return new Promise((resolve, reject) => { + // wrap in timeout to simulate server api call + setTimeout(() => { + // authenticate + if (url.endsWith('/users/authenticate') && opts.method === 'POST') { + // get parameters from post request + let params = JSON.parse(opts.body) + + // find if any user matches login credentials + let filteredUsers = users.filter((user) => { + return user.username === params.username && user.password === params.password + }) + + if (filteredUsers.length) { + // if login details are valid return user details and fake jwt token + let user = filteredUsers[0] + let responseJson = { + id: user.id, + username: user.username, + firstName: user.firstName, + lastName: user.lastName, + token: 'fake-jwt-token', + } + + resolve({ ok: true, text: () => Promise.resolve(JSON.stringify(responseJson)) }) + } else { + // else return error + reject('Username or password is incorrect') + } + + return + } + + // get users + if (url.endsWith('/users') && opts.method === 'GET') { + // check for fake auth token in header and return users if valid, this security is implemented server side in a real application + if (opts.headers && opts.headers.Authorization === 'Bearer fake-jwt-token') { + resolve({ ok: true, text: () => Promise.resolve(JSON.stringify(users)) }) + } else { + // return 401 not authorised if token is null or invalid + reject('Unauthorised') + } + + return + } + + // pass through any requests not handled above + realFetch(url, opts).then((response) => resolve(response)) + }, 500) + }) + } +} diff --git a/examples/logging-in__jwt/src/_helpers/index.js b/examples/logging-in__jwt/src/_helpers/index.js index 43f11c45f..026af2d12 100644 --- a/examples/logging-in__jwt/src/_helpers/index.js +++ b/examples/logging-in__jwt/src/_helpers/index.js @@ -1,3 +1,5 @@ -export * from './fake-backend'; -export * from './router'; -export * from './auth-header'; \ No newline at end of file +export * from './fake-backend' + +export * from './router' + +export * from './auth-header' diff --git a/examples/logging-in__jwt/src/_helpers/router.js b/examples/logging-in__jwt/src/_helpers/router.js index 99e127ffa..a500d1f75 100644 --- a/examples/logging-in__jwt/src/_helpers/router.js +++ b/examples/logging-in__jwt/src/_helpers/router.js @@ -1,10 +1,11 @@ -import Vue from 'vue'; -import Router from 'vue-router'; +/* global localStorage */ +import Vue from 'vue' +import Router from 'vue-router' import HomePage from '../home/HomePage' import LoginPage from '../login/LoginPage' -Vue.use(Router); +Vue.use(Router) export const router = new Router({ mode: 'history', @@ -13,19 +14,19 @@ export const router = new Router({ { path: '/login', component: LoginPage }, // otherwise redirect to home - { path: '*', redirect: '/' } - ] -}); + { path: '*', redirect: '/' }, + ], +}) router.beforeEach((to, from, next) => { // redirect to login page if not logged in and trying to access a restricted page - const publicPages = ['/login']; - const authRequired = !publicPages.includes(to.path); - const loggedIn = localStorage.getItem('user'); + const publicPages = ['/login'] + const authRequired = !publicPages.includes(to.path) + const loggedIn = localStorage.getItem('user') if (authRequired && !loggedIn) { - return next('/login'); + return next('/login') } - next(); -}) \ No newline at end of file + next() +}) diff --git a/examples/logging-in__jwt/src/_services/index.js b/examples/logging-in__jwt/src/_services/index.js index e17ee5c7a..1f1302dc5 100644 --- a/examples/logging-in__jwt/src/_services/index.js +++ b/examples/logging-in__jwt/src/_services/index.js @@ -1 +1 @@ -export * from './user.service'; +export * from './user.service' diff --git a/examples/logging-in__jwt/src/_services/user.service.js b/examples/logging-in__jwt/src/_services/user.service.js index 6f6801d04..aad72bdbc 100644 --- a/examples/logging-in__jwt/src/_services/user.service.js +++ b/examples/logging-in__jwt/src/_services/user.service.js @@ -1,60 +1,63 @@ -import config from 'config'; -import { authHeader } from '../_helpers'; +/* global fetch, localStorage, location */ +import config from 'config' +import { authHeader } from '../_helpers' export const userService = { - login, - logout, - getAll -}; - -function login(username, password) { - const requestOptions = { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ username, password }) - }; - - return fetch(`${config.apiUrl}/users/authenticate`, requestOptions) - .then(handleResponse) - .then(user => { - // login successful if there's a jwt token in the response - if (user.token) { - // store user details and jwt token in local storage to keep user logged in between page refreshes - localStorage.setItem('user', JSON.stringify(user)); - } - - return user; - }); + login, + logout, + getAll, } -function logout() { - // remove user from local storage to log user out - localStorage.removeItem('user'); +function login (username, password) { + const requestOptions = { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ username, password }), + } + + return fetch(`${config.apiUrl}/users/authenticate`, requestOptions) + .then(handleResponse) + .then((user) => { + // login successful if there's a jwt token in the response + if (user.token) { + // store user details and jwt token in local storage to keep user logged in between page refreshes + localStorage.setItem('user', JSON.stringify(user)) + } + + return user + }) } -function getAll() { - const requestOptions = { - method: 'GET', - headers: authHeader() - }; +function logout () { + // remove user from local storage to log user out + localStorage.removeItem('user') +} + +function getAll () { + const requestOptions = { + method: 'GET', + headers: authHeader(), + } - return fetch(`${config.apiUrl}/users`, requestOptions).then(handleResponse); + return fetch(`${config.apiUrl}/users`, requestOptions).then(handleResponse) } -function handleResponse(response) { - return response.text().then(text => { - const data = text && JSON.parse(text); - if (!response.ok) { - if (response.status === 401) { - // auto logout if 401 response returned from api - logout(); - location.reload(true); - } - - const error = (data && data.message) || response.statusText; - return Promise.reject(error); - } - - return data; - }); -} \ No newline at end of file +function handleResponse (response) { + return response.text().then((text) => { + const data = text && JSON.parse(text) + + if (!response.ok) { + if (response.status === 401) { + // auto logout if 401 response returned from api + logout() + location.reload(true) + } + + const error = (data && data.message) || response.statusText + + return Promise.reject(error) + } + + return data + }) +} diff --git a/examples/logging-in__jwt/src/_store/alert.module.js b/examples/logging-in__jwt/src/_store/alert.module.js index 960a7a768..5c0295930 100644 --- a/examples/logging-in__jwt/src/_store/alert.module.js +++ b/examples/logging-in__jwt/src/_store/alert.module.js @@ -1,32 +1,32 @@ export const alert = { - namespaced: true, - state: { - type: null, - message: null + namespaced: true, + state: { + type: null, + message: null, + }, + actions: { + success ({ commit }, message) { + commit('success', message) }, - actions: { - success({ commit }, message) { - commit('success', message); - }, - error({ commit }, message) { - commit('error', message); - }, - clear({ commit }, message) { - commit('success', message); - } + error ({ commit }, message) { + commit('error', message) }, - mutations: { - success(state, message) { - state.type = 'alert-success'; - state.message = message; - }, - error(state, message) { - state.type = 'alert-danger'; - state.message = message; - }, - clear(state) { - state.type = null; - state.message = null; - } - } + clear ({ commit }, message) { + commit('success', message) + }, + }, + mutations: { + success (state, message) { + state.type = 'alert-success' + state.message = message + }, + error (state, message) { + state.type = 'alert-danger' + state.message = message + }, + clear (state) { + state.type = null + state.message = null + }, + }, } diff --git a/examples/logging-in__jwt/src/_store/authentication.module.js b/examples/logging-in__jwt/src/_store/authentication.module.js index f32ff6fc0..bdb9e8302 100644 --- a/examples/logging-in__jwt/src/_store/authentication.module.js +++ b/examples/logging-in__jwt/src/_store/authentication.module.js @@ -1,51 +1,52 @@ -import { userService } from '../_services'; -import { router } from '../_helpers'; +/* global localStorage */ +import { userService } from '../_services' +import { router } from '../_helpers' -const user = JSON.parse(localStorage.getItem('user')); +const user = JSON.parse(localStorage.getItem('user')) const initialState = user - ? { status: { loggedIn: true }, user } - : { status: {}, user: null }; + ? { status: { loggedIn: true }, user } + : { status: {}, user: null } export const authentication = { - namespaced: true, - state: initialState, - actions: { - login({ dispatch, commit }, { username, password }) { - commit('loginRequest', { username }); + namespaced: true, + state: initialState, + actions: { + login ({ dispatch, commit }, { username, password }) { + commit('loginRequest', { username }) - userService.login(username, password) - .then( - user => { - commit('loginSuccess', user); - router.push('/'); - }, - error => { - commit('loginFailure', error); - dispatch('alert/error', error, { root: true }); - } - ); + userService.login(username, password) + .then( + (user) => { + commit('loginSuccess', user) + router.push('/') }, - logout({ commit }) { - userService.logout(); - commit('logout'); + (error) => { + commit('loginFailure', error) + dispatch('alert/error', error, { root: true }) } + ) }, - mutations: { - loginRequest(state, user) { - state.status = { loggingIn: true }; - state.user = user; - }, - loginSuccess(state, user) { - state.status = { loggedIn: true }; - state.user = user; - }, - loginFailure(state) { - state.status = {}; - state.user = null; - }, - logout(state) { - state.status = {}; - state.user = null; - } - } + logout ({ commit }) { + userService.logout() + commit('logout') + }, + }, + mutations: { + loginRequest (state, user) { + state.status = { loggingIn: true } + state.user = user + }, + loginSuccess (state, user) { + state.status = { loggedIn: true } + state.user = user + }, + loginFailure (state) { + state.status = {} + state.user = null + }, + logout (state) { + state.status = {} + state.user = null + }, + }, } diff --git a/examples/logging-in__jwt/src/_store/index.js b/examples/logging-in__jwt/src/_store/index.js index 1b7ba726a..cca08fdb0 100644 --- a/examples/logging-in__jwt/src/_store/index.js +++ b/examples/logging-in__jwt/src/_store/index.js @@ -1,16 +1,16 @@ -import Vue from 'vue'; -import Vuex from 'vuex'; +import Vue from 'vue' +import Vuex from 'vuex' -import { alert } from './alert.module'; -import { authentication } from './authentication.module'; -import { users } from './users.module'; +import { alert } from './alert.module' +import { authentication } from './authentication.module' +import { users } from './users.module' -Vue.use(Vuex); +Vue.use(Vuex) export const store = new Vuex.Store({ - modules: { - alert, - authentication, - users - } -}); + modules: { + alert, + authentication, + users, + }, +}) diff --git a/examples/logging-in__jwt/src/_store/users.module.js b/examples/logging-in__jwt/src/_store/users.module.js index 85392a7f0..425a2262c 100644 --- a/examples/logging-in__jwt/src/_store/users.module.js +++ b/examples/logging-in__jwt/src/_store/users.module.js @@ -1,30 +1,30 @@ -import { userService } from '../_services'; +import { userService } from '../_services' export const users = { - namespaced: true, - state: { - all: {} - }, - actions: { - getAll({ commit }) { - commit('getAllRequest'); + namespaced: true, + state: { + all: {}, + }, + actions: { + getAll ({ commit }) { + commit('getAllRequest') - userService.getAll() - .then( - users => commit('getAllSuccess', users), - error => commit('getAllFailure', error) - ); - } + userService.getAll() + .then( + (users) => commit('getAllSuccess', users), + (error) => commit('getAllFailure', error) + ) + }, + }, + mutations: { + getAllRequest (state) { + state.all = { loading: true } + }, + getAllSuccess (state, users) { + state.all = { items: users } + }, + getAllFailure (state, error) { + state.all = { error } }, - mutations: { - getAllRequest(state) { - state.all = { loading: true }; - }, - getAllSuccess(state, users) { - state.all = { items: users }; - }, - getAllFailure(state, error) { - state.all = { error }; - } - } + }, } diff --git a/examples/logging-in__jwt/src/index.js b/examples/logging-in__jwt/src/index.js index 474abb68a..bf4c38dd1 100755 --- a/examples/logging-in__jwt/src/index.js +++ b/examples/logging-in__jwt/src/index.js @@ -12,5 +12,5 @@ new Vue({ el: '#app', router, store, - render: h => h(App) + render: (h) => h(App), }) diff --git a/examples/logging-in__single-sign-on/app_server.js b/examples/logging-in__single-sign-on/app_server.js index 313175f80..6792683a0 100644 --- a/examples/logging-in__single-sign-on/app_server.js +++ b/examples/logging-in__single-sign-on/app_server.js @@ -1,11 +1,11 @@ -const path = require('path') -const minimist = require('minimist') -const morgan = require('morgan') -const session = require('express-session') -const express = require('express') -const debug = require('debug')('sso') +const path = require('path') +const minimist = require('minimist') +const morgan = require('morgan') +const session = require('express-session') +const express = require('express') +const debug = require('debug')('sso') -const app = express() +const app = express() // get port from passed in args from scripts/start.js const port = minimist(process.argv.slice(2)).port @@ -24,6 +24,7 @@ const ensureLoggedIn = (req, res, next) => { } else if (req.get('x-session-token')) { debug('request has x-session-token') } + next() } else { debug('nope, redirecting to /unauthorized') @@ -32,7 +33,7 @@ const ensureLoggedIn = (req, res, next) => { } app.use('/node_modules', express.static(path.join(__dirname, '..', '..', 'node_modules'))) -app.use(morgan("dev")) +app.use(morgan('dev')) // store a session cookie called // 'cypress-session-cookie' @@ -40,7 +41,7 @@ app.use(session({ name: 'cypress-session-cookie', secret: 'sekret', resave: false, - saveUninitialized: false + saveUninitialized: false, })) // app.use((req, res, next) => { @@ -72,7 +73,7 @@ app.get('/config', ensureLoggedIn, (req, res) => { res.json({ foo: 'bar', some: 'config', - loggedIn: true + loggedIn: true, }) }) @@ -83,7 +84,7 @@ app.get('/unauthorized', (req, res) => { app.get('/', (req, res) => { debug('rendering /index') - res.render("./index.hbs") + res.render('./index.hbs') }) app.listen(port, () => { diff --git a/examples/logging-in__single-sign-on/auth_server.js b/examples/logging-in__single-sign-on/auth_server.js index 3ca4c30b3..71702ceef 100644 --- a/examples/logging-in__single-sign-on/auth_server.js +++ b/examples/logging-in__single-sign-on/auth_server.js @@ -1,29 +1,30 @@ -const url = require('url') -const minimist = require('minimist') -const morgan = require('morgan') +const url = require('url') +const minimist = require('minimist') +const morgan = require('morgan') const bodyParser = require('body-parser') -const express = require('express') -const debug = require('debug')('sso') +const express = require('express') +const debug = require('debug')('sso') -const app = express() +const app = express() // get port from passed in args from scripts/start.js const port = minimist(process.argv.slice(2)).port const matchesUsernameAndPassword = (body = {}) => { debug('checking username "%s" and password "%s', body.username, body.password) + return body.username === 'jane.lane' && body.password === 'password123' } // parse regular form submission bodies const urlencodedParser = bodyParser.urlencoded({ extended: false }) -app.use(morgan("dev")) +app.use(morgan('dev')) app.post('/login', urlencodedParser, (req, res) => { debug('in /login') // if this matches the secret username and password - if(matchesUsernameAndPassword(req.body)){ + if (matchesUsernameAndPassword(req.body)) { debug('username and password match, redirecting to "%s"', req.query.redirectTo) // assume we always have this query param property const redirectTo = req.query.redirectTo @@ -33,9 +34,10 @@ app.post('/login', urlencodedParser, (req, res) => { // and add these query params to it with an arbitrary // id_token (for a simple example) - outgoing.query = { id_token: 'abc123def456'} + outgoing.query = { id_token: 'abc123def456' } const format = outgoing.format() + debug('redirecting to %o', format) res.redirect(format) diff --git a/examples/logging-in__single-sign-on/cypress/integration/logging-in-single-sign-on-spec.js b/examples/logging-in__single-sign-on/cypress/integration/logging-in-single-sign-on-spec.js index 11317231c..7d2e3b276 100644 --- a/examples/logging-in__single-sign-on/cypress/integration/logging-in-single-sign-on-spec.js +++ b/examples/logging-in__single-sign-on/cypress/integration/logging-in-single-sign-on-spec.js @@ -90,6 +90,7 @@ describe('Logging In - Single Sign on', function () { 'contain', 'You are not logged in and cannot access this page' ) + cy.url().should('include', 'unauthorized') }) @@ -175,10 +176,10 @@ describe('Logging In - Single Sign on', function () { // now go visit our app cy.visit('/', { onBeforeLoad (win) { - // and before the page finishes loading - // set the id_token in local storage - win.localStorage.setItem('id_token', id_token) - }, + // and before the page finishes loading + // set the id_token in local storage + win.localStorage.setItem('id_token', id_token) + }, }) // wait for the /config XHR diff --git a/examples/logging-in__single-sign-on/package.json b/examples/logging-in__single-sign-on/package.json index e33ddb43d..548f46443 100644 --- a/examples/logging-in__single-sign-on/package.json +++ b/examples/logging-in__single-sign-on/package.json @@ -3,10 +3,10 @@ "version": "1.0.0", "description": "Login when authentication is done on a 3rd party server", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "start": "node app_server.js --port 7074 & node auth_server.js --port 7075", + "cypress:run": "../../node_modules/.bin/cypress run", "dev": "../../node_modules/.bin/start-test 7074 cypress:open", + "start": "node app_server.js --port 7074 & node auth_server.js --port 7075", "test:ci": "../../node_modules/.bin/start-test 7074 cypress:run" } } diff --git a/examples/logging-in__using-app-code/cypress/integration/spec.js b/examples/logging-in__using-app-code/cypress/integration/spec.js index f067bd0c3..78551bb47 100644 --- a/examples/logging-in__using-app-code/cypress/integration/spec.js +++ b/examples/logging-in__using-app-code/cypress/integration/spec.js @@ -2,52 +2,53 @@ import { userService } from '../../src/_services/user.service' -// log in using application code -it('logs in by using application service', () => { - cy.log('user service login') +describe('logs in', () => { + it('by using application service', () => { + cy.log('user service login') - // see https://on.cypress.io/wrap - // cy.wrap(user promise) forces the test commands to wait until - // the user promise resolves. We also don't want to log empty "wrap {}" - // to the command log, since we already logged a good message right above - cy.wrap(userService.login(Cypress.env('username'), Cypress.env('password')), { - log: false - }).then(user => { + // see https://on.cypress.io/wrap + // cy.wrap(user promise) forces the test commands to wait until + // the user promise resolves. We also don't want to log empty "wrap {}" + // to the command log, since we already logged a good message right above + cy.wrap(userService.login(Cypress.env('username'), Cypress.env('password')), { + log: false, + }).then((user) => { // the userService.login resolves with "user" object // and we can assert its values inside .then() - // confirm general shape of the object - expect(user).to.be.an('object') - expect(user).to.have.keys([ - 'firstName', - 'lastName', - 'username', - 'id', - 'token' - ]) - // we don't know the token or id, but we know the expected names - expect(user).to.contain({ - username: 'test', - firstName: 'Test', - lastName: 'User' + // confirm general shape of the object + expect(user).to.be.an('object') + expect(user).to.have.keys([ + 'firstName', + 'lastName', + 'username', + 'id', + 'token', + ]) + + // we don't know the token or id, but we know the expected names + expect(user).to.contain({ + username: 'test', + firstName: 'Test', + lastName: 'User', + }) }) - }) - // cy.visit command will wait for the promise returned from - // the "userService.login" to resolve. Then local storage item is set - // and the visit will immediately be authenticated and logged in - cy.visit('/') - // we should be logged in - cy.contains('Hi Test!').should('be.visible') -}) + // cy.visit command will wait for the promise returned from + // the "userService.login" to resolve. Then local storage item is set + // and the visit will immediately be authenticated and logged in + cy.visit('/') + // we should be logged in + cy.contains('Hi Test!').should('be.visible') + }) -it('can assert against resolved object using .should', () => { - cy.log('user service login') + it('can assert against resolved object using .should', () => { + cy.log('user service login') - // same login promise - cy.wrap(userService.login(Cypress.env('username'), Cypress.env('password')), { - log: false - }) + // same login promise + cy.wrap(userService.login(Cypress.env('username'), Cypress.env('password')), { + log: false, + }) // but resolved value checked using implicit assertions // that can be easier to read .should('be.an', 'object') @@ -55,36 +56,37 @@ it('can assert against resolved object using .should', () => { .and('contain', { username: 'test', firstName: 'Test', - lastName: 'User' + lastName: 'User', }) - // cy.visit command will wait for the promise returned from - // the "userService.login" to resolve. Then local storage item is set - // and the visit will immediately be authenticated and logged in - cy.visit('/') - // we should be logged in - cy.contains('Hi Test!').should('be.visible') -}) + // cy.visit command will wait for the promise returned from + // the "userService.login" to resolve. Then local storage item is set + // and the visit will immediately be authenticated and logged in + cy.visit('/') + // we should be logged in + cy.contains('Hi Test!').should('be.visible') + }) -/** + /** * Custom command to log in using application method. * Commands are automatically waited on, thus we don't need extra "cy.wrap" * around the returned promise. * * @example cy.login() */ -Cypress.Commands.add( - 'login', - (username = Cypress.env('username'), password = Cypress.env('password')) => { - return userService.login(username, password) - } -) + Cypress.Commands.add( + 'login', + (username = Cypress.env('username'), password = Cypress.env('password')) => { + return userService.login(username, password) + } + ) -it('log in by wrapping application code in custom command', () => { + it('by wrapping application code in custom command', () => { // custom commands are automatically chained - cy.login() - // thus the visit will not start until the promise returned - // by the application code inside the custom command "login" resolves - cy.visit('/') - cy.contains('Hi Test!').should('be.visible') + cy.login() + // thus the visit will not start until the promise returned + // by the application code inside the custom command "login" resolves + cy.visit('/') + cy.contains('Hi Test!').should('be.visible') + }) }) diff --git a/examples/logging-in__using-app-code/cypress/plugins/index.js b/examples/logging-in__using-app-code/cypress/plugins/index.js index 5c7b721ba..718e2f099 100644 --- a/examples/logging-in__using-app-code/cypress/plugins/index.js +++ b/examples/logging-in__using-app-code/cypress/plugins/index.js @@ -1,12 +1,12 @@ const webpack = require('@cypress/webpack-preprocessor') -module.exports = on => { +module.exports = (on) => { // bundle spec files using same webpack logic as "normal" application const options = { // send in the options from your webpack.config.js, so it works the same // as your app's code webpackOptions: require('../../webpack.config'), - watchOptions: {} + watchOptions: {}, } on('file:preprocessor', webpack(options)) diff --git a/examples/logging-in__using-app-code/package.json b/examples/logging-in__using-app-code/package.json index 037709a3a..d70157169 100644 --- a/examples/logging-in__using-app-code/package.json +++ b/examples/logging-in__using-app-code/package.json @@ -3,12 +3,12 @@ "version": "1.0.0", "description": "Example of logging in using JWT", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "start:server": "node server", - "start:app": "../../node_modules/.bin/webpack-dev-server --port 8081", - "start": "../../node_modules/.bin/run-p start:server start:app", + "cypress:run": "../../node_modules/.bin/cypress run", "dev": "../../node_modules/.bin/start-test 8081 cypress:open", + "start": "../../node_modules/.bin/run-p start:server start:app", + "start:app": "../../node_modules/.bin/webpack-dev-server --port 8081", + "start:server": "node server", "test:ci": "../../node_modules/.bin/start-test 8081 cypress:run" } } diff --git a/examples/logging-in__using-app-code/server/_helpers/error-handler.js b/examples/logging-in__using-app-code/server/_helpers/error-handler.js index 648db2409..510f4714a 100644 --- a/examples/logging-in__using-app-code/server/_helpers/error-handler.js +++ b/examples/logging-in__using-app-code/server/_helpers/error-handler.js @@ -1,16 +1,16 @@ -module.exports = errorHandler; +module.exports = errorHandler -function errorHandler(err, req, res, next) { - if (typeof (err) === 'string') { - // custom application error - return res.status(400).json({ message: err }); - } +function errorHandler (err, req, res, next) { + if (typeof (err) === 'string') { + // custom application error + return res.status(400).json({ message: err }) + } - if (err.name === 'UnauthorizedError') { - // jwt authentication error - return res.status(401).json({ message: 'Invalid Token' }); - } + if (err.name === 'UnauthorizedError') { + // jwt authentication error + return res.status(401).json({ message: 'Invalid Token' }) + } - // default to 500 server error - return res.status(500).json({ message: err.message }); -} \ No newline at end of file + // default to 500 server error + return res.status(500).json({ message: err.message }) +} diff --git a/examples/logging-in__using-app-code/server/_helpers/jwt.js b/examples/logging-in__using-app-code/server/_helpers/jwt.js index 51c369ad0..7fc2a4dbf 100644 --- a/examples/logging-in__using-app-code/server/_helpers/jwt.js +++ b/examples/logging-in__using-app-code/server/_helpers/jwt.js @@ -5,6 +5,7 @@ module.exports = jwt function jwt () { const { secret } = config + return expressJwt({ secret }).unless({ path: [ // public routes that don't require authentication diff --git a/examples/logging-in__using-app-code/server/config.json b/examples/logging-in__using-app-code/server/config.json index 37c41ad53..b5cd91ee1 100644 --- a/examples/logging-in__using-app-code/server/config.json +++ b/examples/logging-in__using-app-code/server/config.json @@ -1,3 +1,3 @@ { - "secret": "Verify JWT using this secret string" + "secret": "Verify JWT using this secret string" } diff --git a/examples/logging-in__using-app-code/server/index.js b/examples/logging-in__using-app-code/server/index.js index 73dac6267..320fd6e33 100644 --- a/examples/logging-in__using-app-code/server/index.js +++ b/examples/logging-in__using-app-code/server/index.js @@ -1,4 +1,5 @@ -require('rootpath')() +/* eslint-disable no-console */ +require('rootpath')() const express = require('express') const app = express() const cors = require('cors') @@ -21,6 +22,7 @@ app.use(errorHandler) // start server const port = process.env.NODE_ENV === 'production' ? 80 : 4000 + app.listen(port, function () { console.log(`Server listening on port ${port}`) }) diff --git a/examples/logging-in__using-app-code/server/users/user.service.js b/examples/logging-in__using-app-code/server/users/user.service.js index ea50823cb..7f06d9c18 100644 --- a/examples/logging-in__using-app-code/server/users/user.service.js +++ b/examples/logging-in__using-app-code/server/users/user.service.js @@ -1,4 +1,5 @@ -const config = require('../config.json') +/* eslint-disable no-unused-vars */ +const config = require('../config.json') const jwt = require('jsonwebtoken') // users hardcoded for simplicity, store in a db for production applications @@ -8,32 +9,35 @@ const users = [ username: 'test', password: 'test', firstName: 'Test', - lastName: 'User' - } + lastName: 'User', + }, ] module.exports = { authenticate, - getAll + getAll, } async function authenticate ({ username, password }) { const user = users.find( - u => u.username === username && u.password === password + (u) => u.username === username && u.password === password ) + if (user) { const token = jwt.sign({ sub: user.id }, config.secret) const { password, ...userWithoutPassword } = user + return { ...userWithoutPassword, - token + token, } } } async function getAll () { - return users.map(u => { + return users.map((u) => { const { password, ...userWithoutPassword } = u + return userWithoutPassword }) } diff --git a/examples/logging-in__using-app-code/server/users/users.controller.js b/examples/logging-in__using-app-code/server/users/users.controller.js index c19dcfe0b..3b386b0ae 100644 --- a/examples/logging-in__using-app-code/server/users/users.controller.js +++ b/examples/logging-in__using-app-code/server/users/users.controller.js @@ -11,11 +11,11 @@ module.exports = router function authenticate (req, res, next) { userService .authenticate(req.body) - .then((user) => - user + .then((user) => { + return user ? res.json(user) : res.status(400).json({ message: 'Username or password is incorrect' }) - ) + }) .catch((err) => next(err)) } diff --git a/examples/logging-in__using-app-code/src/_helpers/auth-header.js b/examples/logging-in__using-app-code/src/_helpers/auth-header.js index a8fe5f5a7..0fe5bd132 100644 --- a/examples/logging-in__using-app-code/src/_helpers/auth-header.js +++ b/examples/logging-in__using-app-code/src/_helpers/auth-header.js @@ -1,10 +1,11 @@ -export function authHeader() { - // return authorization header with jwt token - let user = JSON.parse(localStorage.getItem('user')); +/* global localStorage */ +export function authHeader () { + // return authorization header with jwt token + let user = JSON.parse(localStorage.getItem('user')) - if (user && user.token) { - return { 'Authorization': 'Bearer ' + user.token }; - } else { - return {}; - } -} \ No newline at end of file + if (user && user.token) { + return { 'Authorization': `Bearer ${user.token}` } + } + + return {} +} diff --git a/examples/logging-in__using-app-code/src/_helpers/fake-backend.js b/examples/logging-in__using-app-code/src/_helpers/fake-backend.js index 61b7b8ccf..772d17845 100644 --- a/examples/logging-in__using-app-code/src/_helpers/fake-backend.js +++ b/examples/logging-in__using-app-code/src/_helpers/fake-backend.js @@ -1,57 +1,58 @@ -export function configureFakeBackend() { - let users = [{ id: 1, username: 'test', password: 'test', firstName: 'Test', lastName: 'User' }]; - let realFetch = window.fetch; - window.fetch = function (url, opts) { - return new Promise((resolve, reject) => { - // wrap in timeout to simulate server api call - setTimeout(() => { - - // authenticate - if (url.endsWith('/users/authenticate') && opts.method === 'POST') { - // get parameters from post request - let params = JSON.parse(opts.body); - - // find if any user matches login credentials - let filteredUsers = users.filter(user => { - return user.username === params.username && user.password === params.password; - }); - - if (filteredUsers.length) { - // if login details are valid return user details and fake jwt token - let user = filteredUsers[0]; - let responseJson = { - id: user.id, - username: user.username, - firstName: user.firstName, - lastName: user.lastName, - token: 'fake-jwt-token' - }; - resolve({ ok: true, text: () => Promise.resolve(JSON.stringify(responseJson)) }); - } else { - // else return error - reject('Username or password is incorrect'); - } - - return; - } - - // get users - if (url.endsWith('/users') && opts.method === 'GET') { - // check for fake auth token in header and return users if valid, this security is implemented server side in a real application - if (opts.headers && opts.headers.Authorization === 'Bearer fake-jwt-token') { - resolve({ ok: true, text: () => Promise.resolve(JSON.stringify(users)) }); - } else { - // return 401 not authorised if token is null or invalid - reject('Unauthorised'); - } - - return; - } - - // pass through any requests not handled above - realFetch(url, opts).then(response => resolve(response)); - - }, 500); - }); - } -} \ No newline at end of file +/* global window */ +export function configureFakeBackend () { + let users = [{ id: 1, username: 'test', password: 'test', firstName: 'Test', lastName: 'User' }] + let realFetch = window.fetch + + window.fetch = function (url, opts) { + return new Promise((resolve, reject) => { + // wrap in timeout to simulate server api call + setTimeout(() => { + // authenticate + if (url.endsWith('/users/authenticate') && opts.method === 'POST') { + // get parameters from post request + let params = JSON.parse(opts.body) + + // find if any user matches login credentials + let filteredUsers = users.filter((user) => { + return user.username === params.username && user.password === params.password + }) + + if (filteredUsers.length) { + // if login details are valid return user details and fake jwt token + let user = filteredUsers[0] + let responseJson = { + id: user.id, + username: user.username, + firstName: user.firstName, + lastName: user.lastName, + token: 'fake-jwt-token', + } + + resolve({ ok: true, text: () => Promise.resolve(JSON.stringify(responseJson)) }) + } else { + // else return error + reject('Username or password is incorrect') + } + + return + } + + // get users + if (url.endsWith('/users') && opts.method === 'GET') { + // check for fake auth token in header and return users if valid, this security is implemented server side in a real application + if (opts.headers && opts.headers.Authorization === 'Bearer fake-jwt-token') { + resolve({ ok: true, text: () => Promise.resolve(JSON.stringify(users)) }) + } else { + // return 401 not authorised if token is null or invalid + reject('Unauthorised') + } + + return + } + + // pass through any requests not handled above + realFetch(url, opts).then((response) => resolve(response)) + }, 500) + }) + } +} diff --git a/examples/logging-in__using-app-code/src/_helpers/index.js b/examples/logging-in__using-app-code/src/_helpers/index.js index 43f11c45f..026af2d12 100644 --- a/examples/logging-in__using-app-code/src/_helpers/index.js +++ b/examples/logging-in__using-app-code/src/_helpers/index.js @@ -1,3 +1,5 @@ -export * from './fake-backend'; -export * from './router'; -export * from './auth-header'; \ No newline at end of file +export * from './fake-backend' + +export * from './router' + +export * from './auth-header' diff --git a/examples/logging-in__using-app-code/src/_helpers/router.js b/examples/logging-in__using-app-code/src/_helpers/router.js index 99e127ffa..a500d1f75 100644 --- a/examples/logging-in__using-app-code/src/_helpers/router.js +++ b/examples/logging-in__using-app-code/src/_helpers/router.js @@ -1,10 +1,11 @@ -import Vue from 'vue'; -import Router from 'vue-router'; +/* global localStorage */ +import Vue from 'vue' +import Router from 'vue-router' import HomePage from '../home/HomePage' import LoginPage from '../login/LoginPage' -Vue.use(Router); +Vue.use(Router) export const router = new Router({ mode: 'history', @@ -13,19 +14,19 @@ export const router = new Router({ { path: '/login', component: LoginPage }, // otherwise redirect to home - { path: '*', redirect: '/' } - ] -}); + { path: '*', redirect: '/' }, + ], +}) router.beforeEach((to, from, next) => { // redirect to login page if not logged in and trying to access a restricted page - const publicPages = ['/login']; - const authRequired = !publicPages.includes(to.path); - const loggedIn = localStorage.getItem('user'); + const publicPages = ['/login'] + const authRequired = !publicPages.includes(to.path) + const loggedIn = localStorage.getItem('user') if (authRequired && !loggedIn) { - return next('/login'); + return next('/login') } - next(); -}) \ No newline at end of file + next() +}) diff --git a/examples/logging-in__using-app-code/src/_services/index.js b/examples/logging-in__using-app-code/src/_services/index.js index e17ee5c7a..1f1302dc5 100644 --- a/examples/logging-in__using-app-code/src/_services/index.js +++ b/examples/logging-in__using-app-code/src/_services/index.js @@ -1 +1 @@ -export * from './user.service'; +export * from './user.service' diff --git a/examples/logging-in__using-app-code/src/_services/user.service.js b/examples/logging-in__using-app-code/src/_services/user.service.js index c702efed2..aad72bdbc 100644 --- a/examples/logging-in__using-app-code/src/_services/user.service.js +++ b/examples/logging-in__using-app-code/src/_services/user.service.js @@ -1,30 +1,31 @@ +/* global fetch, localStorage, location */ import config from 'config' import { authHeader } from '../_helpers' export const userService = { login, logout, - getAll + getAll, } function login (username, password) { const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ username, password }) + body: JSON.stringify({ username, password }), } return fetch(`${config.apiUrl}/users/authenticate`, requestOptions) - .then(handleResponse) - .then(user => { - // login successful if there's a jwt token in the response - if (user.token) { - // store user details and jwt token in local storage to keep user logged in between page refreshes - localStorage.setItem('user', JSON.stringify(user)) - } + .then(handleResponse) + .then((user) => { + // login successful if there's a jwt token in the response + if (user.token) { + // store user details and jwt token in local storage to keep user logged in between page refreshes + localStorage.setItem('user', JSON.stringify(user)) + } - return user - }) + return user + }) } function logout () { @@ -35,15 +36,16 @@ function logout () { function getAll () { const requestOptions = { method: 'GET', - headers: authHeader() + headers: authHeader(), } return fetch(`${config.apiUrl}/users`, requestOptions).then(handleResponse) } function handleResponse (response) { - return response.text().then(text => { + return response.text().then((text) => { const data = text && JSON.parse(text) + if (!response.ok) { if (response.status === 401) { // auto logout if 401 response returned from api @@ -52,6 +54,7 @@ function handleResponse (response) { } const error = (data && data.message) || response.statusText + return Promise.reject(error) } diff --git a/examples/logging-in__using-app-code/src/_store/alert.module.js b/examples/logging-in__using-app-code/src/_store/alert.module.js index 960a7a768..5c0295930 100644 --- a/examples/logging-in__using-app-code/src/_store/alert.module.js +++ b/examples/logging-in__using-app-code/src/_store/alert.module.js @@ -1,32 +1,32 @@ export const alert = { - namespaced: true, - state: { - type: null, - message: null + namespaced: true, + state: { + type: null, + message: null, + }, + actions: { + success ({ commit }, message) { + commit('success', message) }, - actions: { - success({ commit }, message) { - commit('success', message); - }, - error({ commit }, message) { - commit('error', message); - }, - clear({ commit }, message) { - commit('success', message); - } + error ({ commit }, message) { + commit('error', message) }, - mutations: { - success(state, message) { - state.type = 'alert-success'; - state.message = message; - }, - error(state, message) { - state.type = 'alert-danger'; - state.message = message; - }, - clear(state) { - state.type = null; - state.message = null; - } - } + clear ({ commit }, message) { + commit('success', message) + }, + }, + mutations: { + success (state, message) { + state.type = 'alert-success' + state.message = message + }, + error (state, message) { + state.type = 'alert-danger' + state.message = message + }, + clear (state) { + state.type = null + state.message = null + }, + }, } diff --git a/examples/logging-in__using-app-code/src/_store/authentication.module.js b/examples/logging-in__using-app-code/src/_store/authentication.module.js index f32ff6fc0..bdb9e8302 100644 --- a/examples/logging-in__using-app-code/src/_store/authentication.module.js +++ b/examples/logging-in__using-app-code/src/_store/authentication.module.js @@ -1,51 +1,52 @@ -import { userService } from '../_services'; -import { router } from '../_helpers'; +/* global localStorage */ +import { userService } from '../_services' +import { router } from '../_helpers' -const user = JSON.parse(localStorage.getItem('user')); +const user = JSON.parse(localStorage.getItem('user')) const initialState = user - ? { status: { loggedIn: true }, user } - : { status: {}, user: null }; + ? { status: { loggedIn: true }, user } + : { status: {}, user: null } export const authentication = { - namespaced: true, - state: initialState, - actions: { - login({ dispatch, commit }, { username, password }) { - commit('loginRequest', { username }); + namespaced: true, + state: initialState, + actions: { + login ({ dispatch, commit }, { username, password }) { + commit('loginRequest', { username }) - userService.login(username, password) - .then( - user => { - commit('loginSuccess', user); - router.push('/'); - }, - error => { - commit('loginFailure', error); - dispatch('alert/error', error, { root: true }); - } - ); + userService.login(username, password) + .then( + (user) => { + commit('loginSuccess', user) + router.push('/') }, - logout({ commit }) { - userService.logout(); - commit('logout'); + (error) => { + commit('loginFailure', error) + dispatch('alert/error', error, { root: true }) } + ) }, - mutations: { - loginRequest(state, user) { - state.status = { loggingIn: true }; - state.user = user; - }, - loginSuccess(state, user) { - state.status = { loggedIn: true }; - state.user = user; - }, - loginFailure(state) { - state.status = {}; - state.user = null; - }, - logout(state) { - state.status = {}; - state.user = null; - } - } + logout ({ commit }) { + userService.logout() + commit('logout') + }, + }, + mutations: { + loginRequest (state, user) { + state.status = { loggingIn: true } + state.user = user + }, + loginSuccess (state, user) { + state.status = { loggedIn: true } + state.user = user + }, + loginFailure (state) { + state.status = {} + state.user = null + }, + logout (state) { + state.status = {} + state.user = null + }, + }, } diff --git a/examples/logging-in__using-app-code/src/_store/index.js b/examples/logging-in__using-app-code/src/_store/index.js index 1b7ba726a..cca08fdb0 100644 --- a/examples/logging-in__using-app-code/src/_store/index.js +++ b/examples/logging-in__using-app-code/src/_store/index.js @@ -1,16 +1,16 @@ -import Vue from 'vue'; -import Vuex from 'vuex'; +import Vue from 'vue' +import Vuex from 'vuex' -import { alert } from './alert.module'; -import { authentication } from './authentication.module'; -import { users } from './users.module'; +import { alert } from './alert.module' +import { authentication } from './authentication.module' +import { users } from './users.module' -Vue.use(Vuex); +Vue.use(Vuex) export const store = new Vuex.Store({ - modules: { - alert, - authentication, - users - } -}); + modules: { + alert, + authentication, + users, + }, +}) diff --git a/examples/logging-in__using-app-code/src/_store/users.module.js b/examples/logging-in__using-app-code/src/_store/users.module.js index 85392a7f0..425a2262c 100644 --- a/examples/logging-in__using-app-code/src/_store/users.module.js +++ b/examples/logging-in__using-app-code/src/_store/users.module.js @@ -1,30 +1,30 @@ -import { userService } from '../_services'; +import { userService } from '../_services' export const users = { - namespaced: true, - state: { - all: {} - }, - actions: { - getAll({ commit }) { - commit('getAllRequest'); + namespaced: true, + state: { + all: {}, + }, + actions: { + getAll ({ commit }) { + commit('getAllRequest') - userService.getAll() - .then( - users => commit('getAllSuccess', users), - error => commit('getAllFailure', error) - ); - } + userService.getAll() + .then( + (users) => commit('getAllSuccess', users), + (error) => commit('getAllFailure', error) + ) + }, + }, + mutations: { + getAllRequest (state) { + state.all = { loading: true } + }, + getAllSuccess (state, users) { + state.all = { items: users } + }, + getAllFailure (state, error) { + state.all = { error } }, - mutations: { - getAllRequest(state) { - state.all = { loading: true }; - }, - getAllSuccess(state, users) { - state.all = { items: users }; - }, - getAllFailure(state, error) { - state.all = { error }; - } - } + }, } diff --git a/examples/logging-in__using-app-code/src/index.js b/examples/logging-in__using-app-code/src/index.js index 474abb68a..bf4c38dd1 100755 --- a/examples/logging-in__using-app-code/src/index.js +++ b/examples/logging-in__using-app-code/src/index.js @@ -12,5 +12,5 @@ new Vue({ el: '#app', router, store, - render: h => h(App) + render: (h) => h(App), }) diff --git a/examples/logging-in__xhr-web-forms/cypress/integration/custom-command-spec.js b/examples/logging-in__xhr-web-forms/cypress/integration/custom-command-spec.js index c190a0330..60a1bb4ab 100644 --- a/examples/logging-in__xhr-web-forms/cypress/integration/custom-command-spec.js +++ b/examples/logging-in__xhr-web-forms/cypress/integration/custom-command-spec.js @@ -8,49 +8,49 @@ Cypress.Commands.add('loginByJSON', (username, password) => { Cypress.log({ name: 'login by JSON', - message: username + ' | ' + password + message: `${username} | ${password}`, }) return cy.request({ method: 'POST', url: '/login', body: { - username: username, - password: password - } + username, + password, + }, }) }) -context('Reusable "login" custom command', function(){ +context('Reusable "login" custom command', function () { const username = 'jane.lane' const password = 'password123' - beforeEach(function(){ + beforeEach(function () { // login before each test cy.loginByJSON(username, password) }) - it('can visit /dashboard', function(){ + it('can visit /dashboard', function () { cy.visit('/dashboard') cy.get('h1').should('contain', 'jane.lane') }) - it('can visit /users', function(){ + it('can visit /users', function () { cy.visit('/users') cy.get('h1').should('contain', 'Users') }) - it('can simply request other authenticated pages', function(){ + it('can simply request other authenticated pages', function () { // instead of visiting each page and waiting for all // the associated resources to load, we can instead // just issue a simple HTTP request and make an // assertion about the response body cy.request('/admin') - .its('body') - .should('include', '

Admin

') + .its('body') + .should('include', '

Admin

') }) - it('can visit other authenticated pages', function(){ + it('can visit other authenticated pages', function () { cy.visit('/admin') cy.contains('h1', 'Admin') }) diff --git a/examples/logging-in__xhr-web-forms/cypress/integration/logging-in-xhr-web-form-spec.js b/examples/logging-in__xhr-web-forms/cypress/integration/logging-in-xhr-web-form-spec.js index 09a30c6fc..dce4381bc 100644 --- a/examples/logging-in__xhr-web-forms/cypress/integration/logging-in-xhr-web-form-spec.js +++ b/examples/logging-in__xhr-web-forms/cypress/integration/logging-in-xhr-web-form-spec.js @@ -13,15 +13,15 @@ // Be sure to run `npm start` to start the server // before running the tests below. -describe('Logging In - XHR Web Form', function(){ +describe('Logging In - XHR Web Form', function () { // normally sensitive information like username and password // should be passed via environment variables // https://on.cypress.io/env const username = 'jane.lane' const password = 'password123' - context('XHR form submission', function(){ - beforeEach(function(){ + context('XHR form submission', function () { + beforeEach(function () { cy.visit('/login') }) @@ -37,7 +37,7 @@ describe('Logging In - XHR Web Form', function(){ cy.get('h1').should('contain', 'jane.lane') }) - it('displays errors on login', function(){ + it('displays errors on login', function () { // we can observe both the UI and the network XHR call // during unsuccessful login attempt cy.server() @@ -56,14 +56,14 @@ describe('Logging In - XHR Web Form', function(){ // we should have visible errors now cy.get('p.error') - .should('be.visible') - .and('contain', 'Username and/or password is incorrect') + .should('be.visible') + .and('contain', 'Username and/or password is incorrect') // and still be on the same URL cy.url().should('include', '/login') }) - it('can stub the XHR to force it to fail', function(){ + it('can stub the XHR to force it to fail', function () { // instead of letting this XHR hit our backend we can instead // control its behavior programmatically by stubbing it cy.server() @@ -71,13 +71,13 @@ describe('Logging In - XHR Web Form', function(){ // simulate the server returning 503 with // empty JSON response body cy.route({ - method: 'POST', - url: '/login', - status: 503, - response: {} - }) - // alias this route so we can wait on it later - .as('postLogin') + method: 'POST', + url: '/login', + status: 503, + response: {}, + }) + // alias this route so we can wait on it later + .as('postLogin') // incorrect username on purpose cy.get('input[name=username]').type('jane.lae') @@ -86,22 +86,22 @@ describe('Logging In - XHR Web Form', function(){ // we can even test that the correct request // body was sent in this XHR cy.wait('@postLogin') - .its('requestBody') - .should('deep.eq', { - username: 'jane.lae', - password: 'password123' - }) + .its('requestBody') + .should('deep.eq', { + username: 'jane.lae', + password: 'password123', + }) // we should have visible errors now cy.get('p.error') - .should('be.visible') - .and('contain', 'An error occurred: 503 Service Unavailable') + .should('be.visible') + .and('contain', 'An error occurred: 503 Service Unavailable') // and still be on the same URL cy.url().should('include', '/login') }) - it('redirects to /dashboard on success', function(){ + it('redirects to /dashboard on success', function () { // we can submit form using "cy.submit" command // https://on.cypress.io/submit cy.get('input[name=username]').type(username) @@ -116,7 +116,7 @@ describe('Logging In - XHR Web Form', function(){ cy.getCookie('cypress-session-cookie').should('exist') }) - it('redirects on a stubbed XHR', function(){ + it('redirects on a stubbed XHR', function () { // When we stub the XHR we will no longer have a valid // cookie which means that on our Login.onSuccess callback // when we try to navigate to /dashboard we are unauthorized @@ -125,26 +125,26 @@ describe('Logging In - XHR Web Form', function(){ // and test that its called with the right data. // cy.window() - .then(function(win){ - // stub out the Login.redirect method - // so it doesn't cause the browser to redirect - cy.stub(win.Login, 'redirect').as('redirect') - }) + .then(function (win) { + // stub out the Login.redirect method + // so it doesn't cause the browser to redirect + cy.stub(win.Login, 'redirect').as('redirect') + }) cy.server() // simulate the server returning 503 with // empty JSON response body cy.route({ - method: 'POST', - url: '/login', - response: { - // simulate a redirect to another page - redirect: '/error' - } - }) - // alias this route so we can wait on it later - .as('postLogin') + method: 'POST', + url: '/login', + response: { + // simulate a redirect to another page + redirect: '/error', + }, + }) + // alias this route so we can wait on it later + .as('postLogin') cy.get('input[name=username]').type(username) cy.get('input[name=password]').type(password) @@ -154,12 +154,12 @@ describe('Logging In - XHR Web Form', function(){ // we should not have any visible errors cy.get('p.error') - .should('not.be.visible') - .then(function(){ - // our redirect function should have been called with - // the right arguments from the stubbed routed - expect(this.redirect).to.be.calledWith('/error') - }) + .should('not.be.visible') + .then(function () { + // our redirect function should have been called with + // the right arguments from the stubbed routed + expect(this.redirect).to.be.calledWith('/error') + }) }) }) }) diff --git a/examples/logging-in__xhr-web-forms/cypress/integration/logging-via-request-spec.js b/examples/logging-in__xhr-web-forms/cypress/integration/logging-via-request-spec.js index 03b2e2e18..b2439618f 100644 --- a/examples/logging-in__xhr-web-forms/cypress/integration/logging-via-request-spec.js +++ b/examples/logging-in__xhr-web-forms/cypress/integration/logging-via-request-spec.js @@ -1,11 +1,10 @@ /// -describe('Logging in using XHR request', function(){ - +describe('Logging in using XHR request', function () { const username = 'jane.lane' const password = 'password123' - it('can bypass the UI and yet still log in', function(){ + it('can bypass the UI and yet still log in', function () { // oftentimes once we have a proper e2e test around logging in // there is NO more reason to actually use our UI to log in users // doing so wastes a huge amount of time, as our entire page has to load @@ -20,8 +19,8 @@ describe('Logging in using XHR request', function(){ url: '/login', // baseUrl will be prepended to this url body: { username, - password - } + password, + }, }) // just to prove we have a session diff --git a/examples/logging-in__xhr-web-forms/cypress/integration/slow-login-spec.js b/examples/logging-in__xhr-web-forms/cypress/integration/slow-login-spec.js index b46a17f9f..b5d276751 100644 --- a/examples/logging-in__xhr-web-forms/cypress/integration/slow-login-spec.js +++ b/examples/logging-in__xhr-web-forms/cypress/integration/slow-login-spec.js @@ -1,7 +1,6 @@ /// -describe('Logging in when XHR is slow', function(){ - +describe('Logging in when XHR is slow', function () { const username = 'jane.lane' const password = 'password123' @@ -16,19 +15,20 @@ describe('Logging in when XHR is slow', function(){ url: '/slow-login', body: { username, - password - } + password, + }, }) + // cy.getCookie automatically waits for the previous // command cy.request to finish // we ensure we have a valid cookie value and // save it in the test context object "this.sessionCookie" // that's why we use "function () { ... }" callback form cy.getCookie(sessionCookieName) - .should('exist') - .its('value') - .should('be.a', 'string') - .as('sessionCookie') + .should('exist') + .its('value') + .should('be.a', 'string') + .as('sessionCookie') }) beforeEach(function () { @@ -39,12 +39,12 @@ describe('Logging in when XHR is slow', function(){ cy.setCookie(sessionCookieName, this.sessionCookie) }) - it('loads the dashboard as an authenticated user', function(){ + it('loads the dashboard as an authenticated user', function () { cy.visit('/dashboard') cy.contains('h1', 'jane.lane') }) - it('loads the admin view as an authenticated user', function(){ + it('loads the admin view as an authenticated user', function () { cy.visit('/admin') cy.contains('h1', 'Admin') }) diff --git a/examples/logging-in__xhr-web-forms/package.json b/examples/logging-in__xhr-web-forms/package.json index 7f3942936..5fac7493c 100644 --- a/examples/logging-in__xhr-web-forms/package.json +++ b/examples/logging-in__xhr-web-forms/package.json @@ -3,10 +3,10 @@ "version": "1.0.0", "description": "Log into the server using XHR from end-to-end tests", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "start": "node server.js --port 7079", + "cypress:run": "../../node_modules/.bin/cypress run", "dev": "../../node_modules/.bin/start-test 7079 cypress:open", + "start": "node server.js --port 7079", "test:ci": "../../node_modules/.bin/start-test 7079 cypress:run" } } diff --git a/examples/logging-in__xhr-web-forms/server.js b/examples/logging-in__xhr-web-forms/server.js index 9a223ce90..c4465d2b7 100644 --- a/examples/logging-in__xhr-web-forms/server.js +++ b/examples/logging-in__xhr-web-forms/server.js @@ -1,11 +1,11 @@ -const path = require('path') -const minimist = require('minimist') -const morgan = require('morgan') +const path = require('path') +const minimist = require('minimist') +const morgan = require('morgan') const bodyParser = require('body-parser') -const session = require('express-session') -const express = require('express') +const session = require('express-session') +const express = require('express') -const app = express() +const app = express() // get port from passed in args from scripts/start.js const port = minimist(process.argv.slice(2)).port @@ -26,7 +26,7 @@ const ensureLoggedIn = (req, res, next) => { const jsonParser = bodyParser.json() app.use('/node_modules', express.static(path.join(__dirname, '..', '..', 'node_modules'))) -app.use(morgan("dev")) +app.use(morgan('dev')) // store a session cookie called // 'cypress-session-cookie' @@ -34,7 +34,7 @@ app.use(session({ name: 'cypress-session-cookie', secret: 'sekret', resave: false, - saveUninitialized: false + saveUninitialized: false, })) // app.use((req, res, next) => { @@ -56,44 +56,44 @@ app.get('/login', (req, res) => { // used on the one route when its coming from a JSON request app.post('/login', jsonParser, (req, res) => { // if this matches the secret username and password - if(matchesUsernameAndPassword(req.body)){ + if (matchesUsernameAndPassword(req.body)) { req.session.user = 'jane.lane' // respond with how we should redirect - res.json({redirect: "/dashboard"}) + res.json({ redirect: '/dashboard' }) } else { // else send back JSON error // with unprocessable entity // status code res.status(422).json({ - error: "Username and/or password is incorrect" + error: 'Username and/or password is incorrect', }) } }) app.post('/slow-login', jsonParser, (req, res) => { // if this matches the secret username and password - if(matchesUsernameAndPassword(req.body)){ + if (matchesUsernameAndPassword(req.body)) { // login the user after a delay setTimeout(function () { req.session.user = 'jane.lane' // respond with how we should redirect - res.json({redirect: "/dashboard"}) + res.json({ redirect: '/dashboard' }) }, 2000) } else { // else send back JSON error // with unprocessable entity // status code res.status(422).json({ - error: "Username and/or password is incorrect" + error: 'Username and/or password is incorrect', }) } }) app.get('/dashboard', ensureLoggedIn, (req, res) => { res.render('./dashboard.hbs', { - user: req.session.user + user: req.session.user, }) }) diff --git a/examples/preprocessors__flow-browserify/package.json b/examples/preprocessors__flow-browserify/package.json index 46380f3bf..45b1f3e54 100644 --- a/examples/preprocessors__flow-browserify/package.json +++ b/examples/preprocessors__flow-browserify/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "", "scripts": { - "start": "echo", + "cypress:open": "../../node_modules/.bin/cypress open", "cypress:run": "../../node_modules/.bin/cypress run", - "cypress:open": "../../node_modules/.bin/cypress open" + "start": "echo" } } diff --git a/examples/preprocessors__grep/package.json b/examples/preprocessors__grep/package.json index 5e3281ee7..086f6f06e 100644 --- a/examples/preprocessors__grep/package.json +++ b/examples/preprocessors__grep/package.json @@ -3,9 +3,9 @@ "version": "1.0.0", "description": "Selecting specs and tests to run using grep", "scripts": { - "start": "echo", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", + "start": "echo", "test:ci": "../../node_modules/.bin/cypress run" } } diff --git a/examples/preprocessors__typescript-browserify/package.json b/examples/preprocessors__typescript-browserify/package.json index 52f773e54..6de28906b 100644 --- a/examples/preprocessors__typescript-browserify/package.json +++ b/examples/preprocessors__typescript-browserify/package.json @@ -3,9 +3,9 @@ "version": "1.0.0", "description": "", "scripts": { - "start": "echo", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", + "start": "echo", "test:ci": "../../node_modules/.bin/cypress run" } } diff --git a/examples/preprocessors__typescript-webpack/package-lock.json b/examples/preprocessors__typescript-webpack/package-lock.json deleted file mode 100644 index 620102f11..000000000 --- a/examples/preprocessors__typescript-webpack/package-lock.json +++ /dev/null @@ -1,5407 +0,0 @@ -{ - "name": "cypress-example-typescript-webpack", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@cypress/webpack-preprocessor": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@cypress/webpack-preprocessor/-/webpack-preprocessor-2.0.1.tgz", - "integrity": "sha512-T5u8XGhYTU6vtFMwdA7m6GWanNaEBqt61C4uCwqY3EFW2VLIDQFZMzLZQM2dzttIt9cy1ekE9VYDoxJoZ5v78A==", - "dev": true, - "requires": { - "babel-core": "6.26.0", - "babel-loader": "7.1.4", - "babel-preset-env": "1.6.0", - "babel-preset-react": "6.24.1", - "bluebird": "3.5.0", - "debug": "3.1.0", - "lodash.clonedeep": "4.5.0", - "webpack": "4.16.1" - } - }, - "@webassemblyjs/ast": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.5.13.tgz", - "integrity": "sha512-49nwvW/Hx9i+OYHg+mRhKZfAlqThr11Dqz8TsrvqGKMhdI2ijy3KBJOun2Z4770TPjrIJhR6KxChQIDaz8clDA==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/wast-parser": "1.5.13", - "debug": "3.1.0", - "mamacro": "0.0.3" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.5.13.tgz", - "integrity": "sha512-vrvvB18Kh4uyghSKb0NTv+2WZx871WL2NzwMj61jcq2bXkyhRC+8Q0oD7JGVf0+5i/fKQYQSBCNMMsDMRVAMqA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.5.13.tgz", - "integrity": "sha512-dBh2CWYqjaDlvMmRP/kudxpdh30uXjIbpkLj9HQe+qtYlwvYjPRjdQXrq1cTAAOUSMTtzqbXIxEdEZmyKfcwsg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.5.13.tgz", - "integrity": "sha512-v7igWf1mHcpJNbn4m7e77XOAWXCDT76Xe7Is1VQFXc4K5jRcFrl9D0NrqM4XifQ0bXiuTSkTKMYqDxu5MhNljA==", - "dev": true, - "requires": { - "debug": "3.1.0" - } - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.5.13.tgz", - "integrity": "sha512-yN6ScQQDFCiAXnVctdVO/J5NQRbwyTbQzsGzEgXsAnrxhjp0xihh+nNHQTMrq5UhOqTb5LykpJAvEv9AT0jnAQ==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.5.13" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.5.13.tgz", - "integrity": "sha512-hSIKzbXjVMRvy3Jzhgu+vDd/aswJ+UMEnLRCkZDdknZO3Z9e6rp1DAs0tdLItjCFqkz9+0BeOPK/mk3eYvVzZg==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.5.13.tgz", - "integrity": "sha512-zxJXULGPLB7r+k+wIlvGlXpT4CYppRz8fLUM/xobGHc9Z3T6qlmJD9ySJ2jknuktuuiR9AjnNpKYDECyaiX+QQ==", - "dev": true, - "requires": { - "debug": "3.1.0", - "mamacro": "0.0.3" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.5.13.tgz", - "integrity": "sha512-0n3SoNGLvbJIZPhtMFq0XmmnA/YmQBXaZKQZcW8maGKwLpVcgjNrxpFZHEOLKjXJYVN5Il8vSfG7nRX50Zn+aw==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.5.13.tgz", - "integrity": "sha512-IJ/goicOZ5TT1axZFSnlAtz4m8KEjYr12BNOANAwGFPKXM4byEDaMNXYowHMG0yKV9a397eU/NlibFaLwr1fbw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-buffer": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/wasm-gen": "1.5.13", - "debug": "3.1.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.5.13.tgz", - "integrity": "sha512-TseswvXEPpG5TCBKoLx9tT7+/GMACjC1ruo09j46ULRZWYm8XHpDWaosOjTnI7kr4SRJFzA6MWoUkAB+YCGKKg==", - "dev": true, - "requires": { - "ieee754": "1.1.12" - } - }, - "@webassemblyjs/leb128": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.5.13.tgz", - "integrity": "sha512-0NRMxrL+GG3eISGZBmLBLAVjphbN8Si15s7jzThaw1UE9e5BY1oH49/+MA1xBzxpf1OW5sf9OrPDOclk9wj2yg==", - "dev": true, - "requires": { - "long": "4.0.0" - }, - "dependencies": { - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", - "dev": true - } - } - }, - "@webassemblyjs/utf8": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.5.13.tgz", - "integrity": "sha512-Ve1ilU2N48Ew0lVGB8FqY7V7hXjaC4+PeZM+vDYxEd+R2iQ0q+Wb3Rw8v0Ri0+rxhoz6gVGsnQNb4FjRiEH/Ng==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.5.13.tgz", - "integrity": "sha512-X7ZNW4+Hga4f2NmqENnHke2V/mGYK/xnybJSIXImt1ulxbCOEs/A+ZK/Km2jgihjyVxp/0z0hwIcxC6PrkWtgw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-buffer": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/helper-wasm-section": "1.5.13", - "@webassemblyjs/wasm-gen": "1.5.13", - "@webassemblyjs/wasm-opt": "1.5.13", - "@webassemblyjs/wasm-parser": "1.5.13", - "@webassemblyjs/wast-printer": "1.5.13", - "debug": "3.1.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.5.13.tgz", - "integrity": "sha512-yfv94Se8R73zmr8GAYzezFHc3lDwE/lBXQddSiIZEKZFuqy7yWtm3KMwA1uGbv5G1WphimJxboXHR80IgX1hQA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/ieee754": "1.5.13", - "@webassemblyjs/leb128": "1.5.13", - "@webassemblyjs/utf8": "1.5.13" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.5.13.tgz", - "integrity": "sha512-IkXSkgzVhQ0QYAdIayuCWMmXSYx0dHGU8Ah/AxJf1gBvstMWVnzJnBwLsXLyD87VSBIcsqkmZ28dVb0mOC3oBg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-buffer": "1.5.13", - "@webassemblyjs/wasm-gen": "1.5.13", - "@webassemblyjs/wasm-parser": "1.5.13", - "debug": "3.1.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.5.13.tgz", - "integrity": "sha512-XnYoIcu2iqq8/LrtmdnN3T+bRjqYFjRHqWbqK3osD/0r/Fcv4d9ecRzjVtC29ENEuNTK4mQ9yyxCBCbK8S/cpg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-api-error": "1.5.13", - "@webassemblyjs/helper-wasm-bytecode": "1.5.13", - "@webassemblyjs/ieee754": "1.5.13", - "@webassemblyjs/leb128": "1.5.13", - "@webassemblyjs/utf8": "1.5.13" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.5.13.tgz", - "integrity": "sha512-Lbz65T0LQ1LgzKiUytl34CwuhMNhaCLgrh0JW4rJBN6INnBB8NMwUfQM+FxTnLY9qJ+lHJL/gCM5xYhB9oWi4A==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/floating-point-hex-parser": "1.5.13", - "@webassemblyjs/helper-api-error": "1.5.13", - "@webassemblyjs/helper-code-frame": "1.5.13", - "@webassemblyjs/helper-fsm": "1.5.13", - "long": "3.2.0", - "mamacro": "0.0.3" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.5.13", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.5.13.tgz", - "integrity": "sha512-QcwogrdqcBh8Z+eUF8SG+ag5iwQSXxQJELBEHmLkk790wgQgnIMmntT2sMAMw53GiFNckArf5X0bsCA44j3lWQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/wast-parser": "1.5.13", - "long": "3.2.0" - } - }, - "acorn": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", - "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", - "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", - "dev": true, - "requires": { - "acorn": "5.7.1" - } - }, - "ajv": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz", - "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==", - "dev": true, - "requires": { - "fast-deep-equal": "2.0.1", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.4.1", - "uri-js": "4.2.2" - } - }, - "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", - "dev": true - }, - "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "3.1.10", - "normalize-path": "2.1.1" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "1.0.3" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" - } - }, - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, - "requires": { - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, - "atob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", - "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - } - }, - "babel-core": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", - "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "babel-generator": "6.26.1", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.26.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "convert-source-map": "1.5.1", - "debug": "2.6.9", - "json5": "0.5.1", - "lodash": "4.17.10", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.8", - "slash": "1.0.0", - "source-map": "0.5.7" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "requires": { - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "detect-indent": "4.0.0", - "jsesc": "1.3.0", - "lodash": "4.17.10", - "source-map": "0.5.7", - "trim-right": "1.0.1" - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-builder-react-jsx": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "esutils": "2.0.2" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.10" - } - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.10" - } - }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true, - "requires": { - "babel-helper-optimise-call-expression": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-loader": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.4.tgz", - "integrity": "sha512-/hbyEvPzBJuGpk9o80R0ZyTej6heEOr59GoEUtn8qFKbnx4cJm9FWES6J/iv644sYgrtVw9JJQkjaLW/bqb5gw==", - "dev": true, - "requires": { - "find-cache-dir": "1.0.0", - "loader-utils": "1.1.0", - "mkdirp": "0.5.1" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true - }, - "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", - "dev": true - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true - }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "lodash": "4.17.10" - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "requires": { - "babel-helper-define-map": "6.26.0", - "babel-helper-function-name": "6.24.1", - "babel-helper-optimise-call-expression": "6.24.1", - "babel-helper-replace-supers": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "6.24.1", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "6.24.1", - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.26.0", - "babel-template": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, - "requires": { - "babel-helper-regex": "6.26.0", - "babel-runtime": "6.26.0", - "regexpu-core": "2.0.0" - } - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", - "babel-plugin-syntax-exponentiation-operator": "6.13.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, - "requires": { - "babel-plugin-syntax-flow": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true, - "requires": { - "babel-helper-builder-react-jsx": "6.26.0", - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-jsx-self": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.26.0" - } - }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, - "requires": { - "regenerator-transform": "0.10.1" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0" - } - }, - "babel-preset-env": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.0.tgz", - "integrity": "sha512-OVgtQRuOZKckrILgMA5rvctvFZPv72Gua9Rt006AiPoB0DJKGN07UmaQA+qRrYgK71MVct8fFhT0EyNWYorVew==", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.26.0", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-regenerator": "6.26.0", - "browserslist": "2.11.3", - "invariant": "2.2.4", - "semver": "5.5.0" - } - }, - "babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true, - "requires": { - "babel-plugin-transform-flow-strip-types": "6.22.0" - } - }, - "babel-preset-react": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-plugin-transform-react-display-name": "6.25.0", - "babel-plugin-transform-react-jsx": "6.24.1", - "babel-plugin-transform-react-jsx-self": "6.22.0", - "babel-plugin-transform-react-jsx-source": "6.22.0", - "babel-preset-flow": "6.23.0" - } - }, - "babel-register": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", - "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", - "dev": true, - "requires": { - "babel-core": "6.26.0", - "babel-runtime": "6.26.0", - "core-js": "2.5.7", - "home-or-tmp": "2.0.0", - "lodash": "4.17.10", - "mkdirp": "0.5.1", - "source-map-support": "0.4.18" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "2.5.7", - "regenerator-runtime": "0.11.1" - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-traverse": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "lodash": "4.17.10" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "babylon": "6.18.0", - "debug": "2.6.9", - "globals": "9.18.0", - "invariant": "2.2.4", - "lodash": "4.17.10" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "esutils": "2.0.2", - "lodash": "4.17.10", - "to-fast-properties": "1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.1", - "pascalcase": "0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "1.0.2" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - } - } - }, - "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", - "dev": true - }, - "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", - "dev": true - }, - "binary-extensions": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", - "dev": true - }, - "bluebird": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", - "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=", - "dev": true - }, - "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "repeat-element": "1.1.2", - "snapdragon": "0.8.2", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "inherits": "2.0.3", - "safe-buffer": "5.1.2" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "1.2.0", - "browserify-des": "1.0.2", - "evp_bytestokey": "1.0.3" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.0", - "inherits": "2.0.3", - "safe-buffer": "5.1.2" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "randombytes": "2.0.6" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "elliptic": "6.4.0", - "inherits": "2.0.3", - "parse-asn1": "5.1.1" - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "1.0.6" - } - }, - "browserslist": { - "version": "2.11.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", - "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", - "dev": true, - "requires": { - "caniuse-lite": "1.0.30000865", - "electron-to-chromium": "1.3.52" - } - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "1.3.0", - "ieee754": "1.1.12", - "isarray": "1.0.0" - } - }, - "buffer-from": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", - "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "cacache": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", - "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", - "dev": true, - "requires": { - "bluebird": "3.5.1", - "chownr": "1.0.1", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "lru-cache": "4.1.3", - "mississippi": "2.0.0", - "mkdirp": "0.5.1", - "move-concurrently": "1.0.1", - "promise-inflight": "1.0.1", - "rimraf": "2.6.2", - "ssri": "5.3.0", - "unique-filename": "1.1.0", - "y18n": "4.0.0" - }, - "dependencies": { - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", - "dev": true - } - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "1.0.0", - "component-emitter": "1.2.1", - "get-value": "2.0.6", - "has-value": "1.0.0", - "isobject": "3.0.1", - "set-value": "2.0.0", - "to-object-path": "0.3.0", - "union-value": "1.0.0", - "unset-value": "1.0.0" - } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30000865", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz", - "integrity": "sha512-vs79o1mOSKRGv/1pSkp4EXgl4ZviWeYReXw60XfacPU64uQWZwJT6vZNmxRF9O+6zu71sJwMxLK5JXxbzuVrLw==", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "chardet": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.5.0.tgz", - "integrity": "sha512-9ZTaoBaePSCFvNlNGrsyI8ZVACP2svUtq0DkM7t4K2ClAa96sqOIRjAzDTc8zXzFt1cZR46rRzLTiHFSJ+Qw0g==", - "dev": true - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "2.0.0", - "async-each": "1.0.1", - "braces": "2.3.2", - "fsevents": "1.2.4", - "glob-parent": "3.1.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "4.0.0", - "lodash.debounce": "4.0.8", - "normalize-path": "2.1.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0", - "upath": "1.1.0" - } - }, - "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", - "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", - "dev": true, - "requires": { - "tslib": "1.9.3" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.2" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - } - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" - } - }, - "color-convert": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", - "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", - "dev": true, - "requires": { - "color-name": "1.1.1" - } - }, - "color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", - "dev": true - }, - "commander": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", - "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "1.1.0", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "typedarray": "0.0.6" - } - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "0.1.4" - } - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "convert-source-map": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", - "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", - "dev": true - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "1.2.0", - "fs-write-stream-atomic": "1.0.10", - "iferr": "0.1.5", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "run-queue": "1.0.3" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "elliptic": "6.4.0" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.3", - "md5.js": "1.3.4", - "ripemd160": "2.0.2", - "sha.js": "2.4.11" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.2.0", - "inherits": "2.0.3", - "ripemd160": "2.0.2", - "safe-buffer": "5.1.2", - "sha.js": "2.4.11" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "1.0.4", - "path-key": "2.0.1", - "semver": "5.5.0", - "shebang-command": "1.2.0", - "which": "1.3.1" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "1.0.1", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.3", - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "diffie-hellman": "5.0.3", - "inherits": "2.0.3", - "pbkdf2": "3.0.16", - "public-encrypt": "4.0.2", - "randombytes": "2.0.6", - "randomfill": "1.0.4" - } - }, - "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", - "dev": true - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", - "dev": true, - "requires": { - "xregexp": "4.0.0" - } - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - } - } - }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" - } - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "2.0.1" - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "miller-rabin": "4.0.1", - "randombytes": "2.0.6" - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, - "duplexify": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", - "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", - "dev": true, - "requires": { - "end-of-stream": "1.4.1", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "stream-shift": "1.0.0" - } - }, - "electron-to-chromium": { - "version": "1.3.52", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.52.tgz", - "integrity": "sha1-0tnxJwuko7lnuDHEDvcftNmrXOA=", - "dev": true - }, - "elliptic": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", - "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0", - "hash.js": "1.1.5", - "hmac-drbg": "1.0.1", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1", - "minimalistic-crypto-utils": "1.0.1" - } - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", - "dev": true - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "1.4.0" - } - }, - "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "memory-fs": "0.4.1", - "tapable": "1.0.0" - } - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "1.0.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint-scope": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", - "dev": true, - "requires": { - "esrecurse": "4.2.1", - "estraverse": "4.2.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "4.2.0" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "1.3.4", - "safe-buffer": "5.1.2" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "4.1.3", - "shebang-command": "1.2.0", - "which": "1.3.1" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "external-editor": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.0.tgz", - "integrity": "sha512-mpkfj0FEdxrIhOC04zk85X7StNtr0yXnG7zCb+8ikO8OJi2jsHh5YGoknNTyXgsbHOf1WOOcVU3kPFWT2WgCkQ==", - "dev": true, - "requires": { - "chardet": "0.5.0", - "iconv-lite": "0.4.23", - "tmp": "0.0.33" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "1.0.2" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - } - } - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "find-cache-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", - "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", - "dev": true, - "requires": { - "commondir": "1.0.1", - "make-dir": "1.3.0", - "pkg-dir": "2.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "2.0.0" - } - }, - "flush-write-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "0.2.2" - } - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "iferr": "0.1.5", - "imurmurhash": "0.1.4", - "readable-stream": "2.3.6" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", - "dev": true, - "optional": true, - "requires": { - "nan": "2.10.0", - "node-pre-gyp": "0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "2.2.4" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "2.1.2" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "5.1.1", - "yallist": "3.0.2" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "2.2.4" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "2.6.9", - "iconv-lite": "0.4.21", - "sax": "1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "1.0.3", - "mkdirp": "0.5.1", - "needle": "2.2.0", - "nopt": "4.0.1", - "npm-packlist": "1.1.10", - "npmlog": "4.1.2", - "rc": "1.2.7", - "rimraf": "2.6.2", - "semver": "5.5.0", - "tar": "4.4.1" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.3" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "0.5.1", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "1.0.2", - "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.2" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "1.0.1", - "fs-minipass": "1.2.5", - "minipass": "2.2.4", - "minizlib": "1.1.0", - "mkdirp": "0.5.1", - "safe-buffer": "5.1.1", - "yallist": "3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true - } - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - } - } - }, - "global-modules-path": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/global-modules-path/-/global-modules-path-2.3.0.tgz", - "integrity": "sha512-HchvMJNYh9dGSCy8pOQ2O8u/hoXaL+0XhnrwH0RyLiSXMMTl9W3N6KUU73+JFOg5PGjtzl6VZzUQsnrpm7Szag==", - "dev": true - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.2" - } - }, - "hash.js": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", - "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "1.1.5", - "minimalistic-assert": "1.0.1", - "minimalistic-crypto-utils": "1.0.1" - } - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", - "dev": true, - "requires": { - "safer-buffer": "2.1.2" - } - }, - "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", - "dev": true - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "import-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", - "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", - "dev": true, - "requires": { - "pkg-dir": "2.0.0", - "resolve-cwd": "2.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "inquirer": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.0.0.tgz", - "integrity": "sha512-tISQWRwtcAgrz+SHPhTH7d3e73k31gsOy6i1csonLc0u1dVK/wYvuOnFeiWqC5OXFIYbmrIFInef31wbT8MEJg==", - "dev": true, - "requires": { - "ansi-escapes": "3.1.0", - "chalk": "2.4.1", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "3.0.0", - "figures": "2.0.0", - "lodash": "4.17.10", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rxjs": "6.2.2", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.2" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "1.4.0" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "1.11.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, - "requires": { - "argparse": "1.0.10", - "esprima": "4.0.1" - } - }, - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "1.0.0" - } - }, - "loader-runner": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", - "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", - "dev": true - }, - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "3.2.0", - "emojis-list": "2.1.0", - "json5": "0.5.1" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" - } - }, - "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true - }, - "long": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz", - "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=", - "dev": true - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "3.0.2" - } - }, - "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", - "dev": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "3.0.0" - } - }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", - "dev": true - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "1.0.1" - } - }, - "md5.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", - "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", - "dev": true, - "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" - } - }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "1.2.0" - } - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "0.1.7", - "readable-stream": "2.3.6" - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.13", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "brorand": "1.1.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mississippi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", - "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", - "dev": true, - "requires": { - "concat-stream": "1.6.2", - "duplexify": "3.6.0", - "end-of-stream": "1.4.1", - "flush-write-stream": "1.0.3", - "from2": "2.3.0", - "parallel-transform": "1.1.0", - "pump": "2.0.1", - "pumpify": "1.5.1", - "stream-each": "1.2.2", - "through2": "2.0.3" - } - }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, - "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "1.2.0", - "copy-concurrently": "1.0.5", - "fs-write-stream-atomic": "1.0.10", - "mkdirp": "0.5.1", - "rimraf": "2.6.2", - "run-queue": "1.0.3" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "fragment-cache": "0.2.1", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" - } - }, - "neo-async": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", - "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==", - "dev": true - }, - "nice-try": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", - "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", - "dev": true - }, - "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", - "dev": true, - "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.2.0", - "buffer": "4.9.1", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.12.0", - "domain-browser": "1.2.0", - "events": "1.1.1", - "https-browserify": "1.0.0", - "os-browserify": "0.3.0", - "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "readable-stream": "2.3.6", - "stream-browserify": "2.0.1", - "stream-http": "2.8.3", - "string_decoder": "1.1.1", - "timers-browserify": "2.0.10", - "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.4", - "vm-browserify": "0.0.4" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "1.1.0" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "2.0.1" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "3.0.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "1.2.0" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "0.7.0", - "lcid": "1.0.0", - "mem": "1.1.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "1.3.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", - "dev": true - }, - "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", - "dev": true, - "requires": { - "cyclist": "0.2.2", - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "parse-asn1": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", - "dev": true, - "requires": { - "asn1.js": "4.10.1", - "browserify-aes": "1.2.0", - "create-hash": "1.2.0", - "evp_bytestokey": "1.0.3", - "pbkdf2": "3.0.16" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "pbkdf2": { - "version": "3.0.16", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", - "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", - "dev": true, - "requires": { - "create-hash": "1.2.0", - "create-hmac": "1.1.7", - "ripemd160": "2.0.2", - "safe-buffer": "5.1.2", - "sha.js": "2.4.11" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "2.1.0" - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "public-encrypt": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", - "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", - "dev": true, - "requires": { - "bn.js": "4.11.8", - "browserify-rsa": "4.0.1", - "create-hash": "1.2.0", - "parse-asn1": "5.1.1", - "randombytes": "2.0.6" - } - }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "1.4.1", - "once": "1.4.0" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "3.6.0", - "inherits": "2.0.3", - "pump": "2.0.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "2.0.6", - "safe-buffer": "5.1.2" - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.2", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.6", - "set-immediate-shim": "1.0.1" - } - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, - "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", - "dev": true, - "requires": { - "babel-runtime": "6.26.0", - "babel-types": "6.26.0", - "private": "0.1.8" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "3.0.2", - "safe-regex": "1.1.0" - } - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true, - "requires": { - "regenerate": "1.4.0", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true, - "requires": { - "jsesc": "0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "1.0.2" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "requires": { - "resolve-from": "3.0.0" - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "7.1.2" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "3.0.4", - "inherits": "2.0.3" - } - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "2.1.0" - } - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "1.2.0" - } - }, - "rxjs": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.2.tgz", - "integrity": "sha512-0MI8+mkKAXZUF9vMrEoPnaoHkfzBPP4IGwUYRJhIRJF6/w3uByO1e91bEHn8zd43RdkTMKiooYKmwz7RH6zfOQ==", - "dev": true, - "requires": { - "tslib": "1.9.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "0.1.15" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "schema-utils": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", - "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", - "dev": true, - "requires": { - "ajv": "6.5.2", - "ajv-keywords": "3.2.0" - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true - }, - "serialize-javascript": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", - "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.2", - "use": "3.1.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "1.0.2" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "6.0.2" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "source-list-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "2.1.1", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" - } - }, - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "requires": { - "source-map": "0.5.7" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "3.0.2" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "ssri": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", - "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "0.1.6" - } - } - } - }, - "stream-browserify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.6" - } - }, - "stream-each": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz", - "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", - "dev": true, - "requires": { - "end-of-stream": "1.4.1", - "stream-shift": "1.0.0" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "3.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.6", - "to-arraybuffer": "1.0.1", - "xtend": "4.0.1" - } - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "tapable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", - "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "requires": { - "readable-stream": "2.3.6", - "xtend": "4.0.1" - } - }, - "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", - "dev": true, - "requires": { - "setimmediate": "1.0.5" - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "1.0.2" - } - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "regex-not": "1.0.2", - "safe-regex": "1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" - } - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "ts-loader": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-4.4.2.tgz", - "integrity": "sha512-Z3Y1a7A0KZZ1s/mAZkt74l1NAF7Y5xUhD1V9VB8/1eUlUOk8Qa/oo46tO2Uu5kQ3wXypOlbv77lLQySjXEDcdw==", - "dev": true, - "requires": { - "chalk": "2.4.1", - "enhanced-resolve": "4.1.0", - "loader-utils": "1.1.0", - "micromatch": "3.1.10", - "semver": "5.5.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.2" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "dev": true - }, - "tslint": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz", - "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=", - "dev": true, - "requires": { - "babel-code-frame": "6.26.0", - "builtin-modules": "1.1.1", - "chalk": "2.4.1", - "commander": "2.13.0", - "diff": "3.5.0", - "glob": "7.1.2", - "js-yaml": "3.12.0", - "minimatch": "3.0.4", - "resolve": "1.8.1", - "semver": "5.5.0", - "tslib": "1.9.3", - "tsutils": "2.28.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.2" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "tsutils": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.28.0.tgz", - "integrity": "sha512-bh5nAtW0tuhvOJnx1GLRn5ScraRLICGyJV5wJhtRWOLsxW70Kk5tZtpK3O/hW6LDnqKS9mlUMPZj9fEMJ0gxqA==", - "dev": true, - "requires": { - "tslib": "1.9.3" - } - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz", - "integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==", - "dev": true - }, - "uglify-es": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", - "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", - "dev": true, - "requires": { - "commander": "2.13.0", - "source-map": "0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "uglifyjs-webpack-plugin": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.7.tgz", - "integrity": "sha512-1VicfKhCYHLS8m1DCApqBhoulnASsEoJ/BvpUpP4zoNAPpKzdH+ghk0olGJMmwX2/jprK2j3hAHdUbczBSy2FA==", - "dev": true, - "requires": { - "cacache": "10.0.4", - "find-cache-dir": "1.0.0", - "schema-utils": "0.4.5", - "serialize-javascript": "1.5.0", - "source-map": "0.6.1", - "uglify-es": "3.3.9", - "webpack-sources": "1.1.0", - "worker-farm": "1.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "0.1.1" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" - } - } - } - }, - "unique-filename": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", - "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", - "dev": true, - "requires": { - "unique-slug": "2.0.0" - } - }, - "unique-slug": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", - "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", - "dev": true, - "requires": { - "imurmurhash": "0.1.4" - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "2.1.1" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "v8-compile-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz", - "integrity": "sha512-qNdTUMaCjPs4eEnM3W9H94R3sU70YCuT+/ST7nUf+id1bVOrdjrpUaeZLqPBPRph3hsgn4a4BvwpxhHZx+oSDg==", - "dev": true - }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } - }, - "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true, - "requires": { - "chokidar": "2.0.4", - "graceful-fs": "4.1.11", - "neo-async": "2.5.1" - } - }, - "webpack": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.16.1.tgz", - "integrity": "sha512-6jpzObU18y7lXDJz7XCLvzgrqcJ0rZ2jhKvnTivza9gM2GvPW93xxtmEll2GgmdC0zVQAtbHrH/9BtyMjSDZfA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.5.13", - "@webassemblyjs/helper-module-context": "1.5.13", - "@webassemblyjs/wasm-edit": "1.5.13", - "@webassemblyjs/wasm-opt": "1.5.13", - "@webassemblyjs/wasm-parser": "1.5.13", - "acorn": "5.7.1", - "acorn-dynamic-import": "3.0.0", - "ajv": "6.5.2", - "ajv-keywords": "3.2.0", - "chrome-trace-event": "1.0.0", - "enhanced-resolve": "4.1.0", - "eslint-scope": "4.0.0", - "json-parse-better-errors": "1.0.2", - "loader-runner": "2.3.0", - "loader-utils": "1.1.0", - "memory-fs": "0.4.1", - "micromatch": "3.1.10", - "mkdirp": "0.5.1", - "neo-async": "2.5.1", - "node-libs-browser": "2.1.0", - "schema-utils": "0.4.5", - "tapable": "1.0.0", - "uglifyjs-webpack-plugin": "1.2.7", - "watchpack": "1.6.0", - "webpack-sources": "1.1.0" - } - }, - "webpack-cli": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.1.0.tgz", - "integrity": "sha512-p5NeKDtYwjZozUWq6kGNs9w+Gtw/CPvyuXjXn2HMdz8Tie+krjEg8oAtonvIyITZdvpF7XG9xDHwscLr2c+ugQ==", - "dev": true, - "requires": { - "chalk": "2.4.1", - "cross-spawn": "6.0.5", - "enhanced-resolve": "4.1.0", - "global-modules-path": "2.3.0", - "import-local": "1.0.0", - "inquirer": "6.0.0", - "interpret": "1.1.0", - "loader-utils": "1.1.0", - "supports-color": "5.4.0", - "v8-compile-cache": "2.0.0", - "yargs": "12.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "1.9.2" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.1", - "escape-string-regexp": "1.0.5", - "supports-color": "5.4.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "3.0.0" - } - } - } - }, - "webpack-sources": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", - "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", - "dev": true, - "requires": { - "source-list-map": "2.0.0", - "source-map": "0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "worker-farm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", - "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", - "dev": true, - "requires": { - "errno": "0.1.7" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.1.tgz", - "integrity": "sha512-B0vRAp1hRX4jgIOWFtjfNjd9OA9RWYZ6tqGA9/I/IrTMsxmKvtWy+ersM+jzpQqbC3YfLzeABPdeTgcJ9eu1qQ==", - "dev": true, - "requires": { - "cliui": "4.1.0", - "decamelize": "2.0.0", - "find-up": "3.0.0", - "get-caller-file": "1.0.3", - "os-locale": "2.1.0", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "2.1.1", - "which-module": "2.0.0", - "y18n": "4.0.0", - "yargs-parser": "10.1.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "3.0.0", - "path-exists": "3.0.0" - } - }, - "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", - "dev": true, - "requires": { - "p-try": "2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "2.0.0" - } - }, - "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", - "dev": true - } - } - }, - "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", - "dev": true, - "requires": { - "camelcase": "4.1.0" - } - } - } -} diff --git a/examples/preprocessors__typescript-webpack/package.json b/examples/preprocessors__typescript-webpack/package.json index a4e0b321d..4a4011232 100644 --- a/examples/preprocessors__typescript-webpack/package.json +++ b/examples/preprocessors__typescript-webpack/package.json @@ -3,13 +3,13 @@ "version": "1.0.0", "description": "Example showing TypeScript tests with Cypress", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", - "cypress:open": "../../node_modules/.bin/cypress open", "build": "../../node_modules/.bin/webpack --output-filename out.js --entry ./cypress/integration/*.ts", + "cypress:open": "../../node_modules/.bin/cypress open", + "precypress:run": "npm run lint", + "cypress:run": "../../node_modules/.bin/cypress run", "lint": "../../node_modules/.bin/tslint --project ./tsconfig.json", "postlint": "npm run tsc", - "tsc": "../../node_modules/.bin/tsc --pretty --noEmit", "test:ci": "../../node_modules/.bin/cypress run", - "precypress:run": "npm run lint" + "tsc": "../../node_modules/.bin/tsc --pretty --noEmit" } } diff --git a/examples/server-communication__bootstrapping-your-app/cypress/integration/bootstrapping_your_app_spec.js b/examples/server-communication__bootstrapping-your-app/cypress/integration/bootstrapping_your_app_spec.js index 9205216f2..4a7f5e64c 100644 --- a/examples/server-communication__bootstrapping-your-app/cypress/integration/bootstrapping_your_app_spec.js +++ b/examples/server-communication__bootstrapping-your-app/cypress/integration/bootstrapping_your_app_spec.js @@ -40,6 +40,7 @@ describe('Bootstrapping App Test Data', function () { win._bootstrappedData = data }, }) + cy.get('pre') .invoke('text') .should('eq', JSON.stringify(data)) @@ -94,6 +95,7 @@ describe('Bootstrapping App Test Data', function () { url: '/data.json', response: data, }).as('getData') + cy.visit('/xhr.html') cy.wait('@getData') cy.get('pre') diff --git a/examples/server-communication__bootstrapping-your-app/package.json b/examples/server-communication__bootstrapping-your-app/package.json index dc3ea2736..99174369e 100644 --- a/examples/server-communication__bootstrapping-your-app/package.json +++ b/examples/server-communication__bootstrapping-your-app/package.json @@ -3,10 +3,10 @@ "version": "1.0.0", "description": "Shows how end-to-end tests can inject data into the application", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "start": "node server.js --port 7070", + "cypress:run": "../../node_modules/.bin/cypress run", "dev": "../../node_modules/.bin/start-test http://localhost:7070/bootstrap.html cypress:open", + "start": "node server.js --port 7070", "test:ci": "../../node_modules/.bin/start-test http://localhost:7070/bootstrap.html cypress:run" } } diff --git a/examples/server-communication__bootstrapping-your-app/server.js b/examples/server-communication__bootstrapping-your-app/server.js index 35b9c8ccb..60a0c5465 100644 --- a/examples/server-communication__bootstrapping-your-app/server.js +++ b/examples/server-communication__bootstrapping-your-app/server.js @@ -8,7 +8,7 @@ const port = minimist(process.argv.slice(2)).port const data = { env: 'development', - api: 'https://api.company.com' + api: 'https://api.company.com', } app.set('views', __dirname) @@ -19,7 +19,7 @@ app.use('/node_modules', express.static(path.join(__dirname, '..', '..', 'node_m app.get('/bootstrap.html', (req, res) => { res.render('./bootstrap.hbs', { - data: JSON.stringify(data) + data: JSON.stringify(data), }) }) diff --git a/examples/server-communication__env-variables/cypress/plugins/index.js b/examples/server-communication__env-variables/cypress/plugins/index.js index 79f38a8fa..a73708813 100644 --- a/examples/server-communication__env-variables/cypress/plugins/index.js +++ b/examples/server-communication__env-variables/cypress/plugins/index.js @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ // *********************************************************** // This example plugins/index.js can be used to load plugins // @@ -20,5 +21,6 @@ module.exports = (on, config) => { config.env.FOO = process.env.FOO config.env.BAR = process.env.BAR console.log('extended config.env with process.env.{FOO, BAR}') + return config } diff --git a/examples/server-communication__env-variables/package.json b/examples/server-communication__env-variables/package.json index d6863cc33..b7a15a0c4 100644 --- a/examples/server-communication__env-variables/package.json +++ b/examples/server-communication__env-variables/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "Collecting process environment variables", "scripts": { - "cypress:run": "../../node_modules/.bin/cross-env FOO=42 BAR=baz CYPRESS_ping=123 ../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cross-env FOO=42 BAR=baz CYPRESS_ping=123 ../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cross-env FOO=42 BAR=baz CYPRESS_ping=123 ../../node_modules/.bin/cypress run", "test:ci": "npm run cypress:run" } } diff --git a/examples/server-communication__seeding-database-in-node/cypress/integration/seeding_database_in_node_spec.js b/examples/server-communication__seeding-database-in-node/cypress/integration/seeding_database_in_node_spec.js index f08e2edfa..993f7bd6e 100644 --- a/examples/server-communication__seeding-database-in-node/cypress/integration/seeding_database_in_node_spec.js +++ b/examples/server-communication__seeding-database-in-node/cypress/integration/seeding_database_in_node_spec.js @@ -1,11 +1,11 @@ // This recipe shows you how to seed your database using node.js -describe('Seeding Database in Node', function(){ - beforeEach(function(){ +describe('Seeding Database in Node', function () { + beforeEach(function () { cy.fixture('seed').as('seed') }) - it('can use fixture data to seed database', function(){ + it('can use fixture data to seed database', function () { // We can use cy.task to communicate with node via the pluginsFile // See cypress/plugins/main.js for the implementation of the 'seed:db' task cy.task('seed:db', this.seed) @@ -14,7 +14,7 @@ describe('Seeding Database in Node', function(){ cy.get('#posts li').first().find('h2').should('have.text', 'Cypress is going open source!') }) - it('can directly seed data to test empty state', function(){ + it('can directly seed data to test empty state', function () { cy.task('seed:db', { posts: [] }) cy.visit('/index.html') cy.get('#posts').should('have.text', 'No posts') diff --git a/examples/server-communication__seeding-database-in-node/cypress/plugins/main.js b/examples/server-communication__seeding-database-in-node/cypress/plugins/main.js index fff6ec745..146aa9f29 100644 --- a/examples/server-communication__seeding-database-in-node/cypress/plugins/main.js +++ b/examples/server-communication__seeding-database-in-node/cypress/plugins/main.js @@ -7,6 +7,6 @@ export default (on) => { return seed(data).then(() => { return data }) - } + }, }) } diff --git a/examples/server-communication__seeding-database-in-node/package.json b/examples/server-communication__seeding-database-in-node/package.json index 2429e56f8..0c983a9ff 100644 --- a/examples/server-communication__seeding-database-in-node/package.json +++ b/examples/server-communication__seeding-database-in-node/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", "start": "node server/index.js --port 7082", "test:ci": "../../node_modules/.bin/start-test 7082 cypress:run" } diff --git a/examples/server-communication__xhr-assertions/cypress/integration/clock-control.js b/examples/server-communication__xhr-assertions/cypress/integration/clock-control.js index 1d019e880..7c2b0e5b4 100644 --- a/examples/server-communication__xhr-assertions/cypress/integration/clock-control.js +++ b/examples/server-communication__xhr-assertions/cypress/integration/clock-control.js @@ -1,18 +1,20 @@ /// -it('speeds up application by controlling clock', () => { +describe('clock', () => { + it('speeds up application by controlling clock', () => { // before loading application start mocking the app's clock // https://on.cypress.io/clock - cy.clock() - cy.visit('index.html') + cy.clock() + cy.visit('index.html') - // before the request goes out we need to set up spying - // see https://on.cypress.io/network-requests - cy.server() - cy.route('POST', '/posts').as('post') + // before the request goes out we need to set up spying + // see https://on.cypress.io/network-requests + cy.server() + cy.route('POST', '/posts').as('post') - cy.get('#delayed-load').click() - // force the application to pass 1 second really quickly - // https://on.cypress.io/tick - cy.tick(1001) - cy.wait('@post').should('have.property', 'status', 201) + cy.get('#delayed-load').click() + // force the application to pass 1 second really quickly + // https://on.cypress.io/tick + cy.tick(1001) + cy.wait('@post').should('have.property', 'status', 201) + }) }) diff --git a/examples/server-communication__xhr-assertions/cypress/integration/multiple-requests.js b/examples/server-communication__xhr-assertions/cypress/integration/multiple-requests.js index f27f42729..9d7c29456 100644 --- a/examples/server-communication__xhr-assertions/cypress/integration/multiple-requests.js +++ b/examples/server-communication__xhr-assertions/cypress/integration/multiple-requests.js @@ -1,31 +1,34 @@ /// -it('waits for multiple requests to finish', () => { - cy.visit('index.html') - cy.server() - cy.route('POST', '/posts').as('post') +describe('waits', () => { + it('for multiple requests to finish', () => { + cy.visit('index.html') + cy.server() + cy.route('POST', '/posts').as('post') - // click both buttons - there will be 2 XHR requests going out - cy.get('#load').click() - cy.get('#delayed-load').click() + // click both buttons - there will be 2 XHR requests going out + cy.get('#load').click() + cy.get('#delayed-load').click() - // there are two XHR calls matching our route - // wait for both to complete - cy.wait('@post').wait('@post') + // there are two XHR calls matching our route + // wait for both to complete + cy.wait('@post').wait('@post') - // we can retrieve all matching requests using the following syntax - // cy.get('.all') - cy.get('@post.all').should('have.length', 2) - .then((xhrs) => { + // we can retrieve all matching requests using the following syntax + // cy.get('.all') + cy.get('@post.all').should('have.length', 2) + .then((xhrs) => { // xhrs is an array of network call objects - expect(xhrs[0], 'first request status').to.have.property('status', 201) - expect(xhrs[1], 'second request status').to.have.property('status', 201) - }) + expect(xhrs[0], 'first request status').to.have.property('status', 201) + expect(xhrs[1], 'second request status').to.have.property('status', 201) + }) + + // and we can make assertions about each separate call + // by retrieving it like this (index starts with 1) + // cy.get('.') + cy.get('@post.1').should((xhr1) => { + expect(xhr1, 'first request').to.have.property('status', 201) + }) - // and we can make assertions about each separate call - // by retrieving it like this (index starts with 1) - // cy.get('.') - cy.get('@post.1').should((xhr1) => { - expect(xhr1, 'first request').to.have.property('status', 201) + cy.get('@post.2').its('response.body.id').should('equal', 101) }) - cy.get('@post.2').its('response.body.id').should('equal', 101) }) diff --git a/examples/server-communication__xhr-assertions/cypress/integration/spec.js b/examples/server-communication__xhr-assertions/cypress/integration/spec.js index 89b07392a..704fbfdd6 100644 --- a/examples/server-communication__xhr-assertions/cypress/integration/spec.js +++ b/examples/server-communication__xhr-assertions/cypress/integration/spec.js @@ -1,116 +1,119 @@ /// /* eslint-disable no-console */ -it('sends XHR to the server and gets expected response', () => { - cy.visit('index.html') +describe('XHR', () => { + it('sends XHR to the server and gets expected response', () => { + cy.visit('index.html') - // before the request goes out we need to set up spying - // see https://on.cypress.io/network-requests - cy.server() - cy.route('POST', '/posts').as('post') + // before the request goes out we need to set up spying + // see https://on.cypress.io/network-requests + cy.server() + cy.route('POST', '/posts').as('post') - cy.get('#load').click() - // make sure the XHR completes and the UI changes - cy.contains('#output', '"title": "example post"').should('be.visible') + cy.get('#load').click() + // make sure the XHR completes and the UI changes + cy.contains('#output', '"title": "example post"').should('be.visible') - // because the UI has changed, we know the XHR has completed - // and we can retrieve it using cy.get() - // see https://on.cypress.io/get + // because the UI has changed, we know the XHR has completed + // and we can retrieve it using cy.get() + // see https://on.cypress.io/get - // tip: log the request object to see everything it has in the console - cy.get('@post').then(console.log) -}) - -it('gets the expected response', () => { - cy.visit('index.html') - - // before the request goes out we need to set up spying - // see https://on.cypress.io/network-requests - cy.server() - cy.route('POST', '/posts').as('post') - - cy.get('#load').click() - // make sure the XHR completes and the UI changes - cy.contains('#output', '"title": "example post"').should('be.visible') - - // because the UI has changed, we know the XHR has completed - // and we can retrieve it using cy.get() - // see https://on.cypress.io/get - - // tip: log the request object to see everything it has in the console - cy.get('@post').then(console.log) - - // you can retrieve the XHR multiple times - returns the same object - // confirm the request status - cy.get('@post').should('have.property', 'status', 201) - - // we cannot chain any more assertions to the above request object - // because the "have.property" assertion yields the property's value - // so let's just grab the request object again and run multiple assertions - cy.get('@post').should((req) => { - expect(req.method).to.equal('POST') - expect(req.url).to.match(/\/posts$/) - // it is good practice to add message to the assertion - expect(req, 'has duration in ms').to.have.property('duration').and.be.a('number') + // tip: log the request object to see everything it has in the console + cy.get('@post').then(console.log) }) - // let's confirm the request sent to the server - cy.get('@post').its('request.body').should('deep.equal', { - title: 'example post', - body: 'this is a post sent to the server', - userId: 1, - }) - // get the same request object again and confirm the response - cy.get('@post').its('response').then((res) => { - // because the response object is not going to change - // we can use cy.then() callback to run assertions just once - // without retrying - // see https://on.cypress.io/then and https://on.cypress.io/retry-ability - expect(res.headers).to.include({ - 'cache-control': 'no-cache', - expires: '-1', - 'content-type': 'application/json; charset=utf-8', - location: 'http://jsonplaceholder.cypress.io/posts/101', + it('gets the expected response', () => { + cy.visit('index.html') + + // before the request goes out we need to set up spying + // see https://on.cypress.io/network-requests + cy.server() + cy.route('POST', '/posts').as('post') + + cy.get('#load').click() + // make sure the XHR completes and the UI changes + cy.contains('#output', '"title": "example post"').should('be.visible') + + // because the UI has changed, we know the XHR has completed + // and we can retrieve it using cy.get() + // see https://on.cypress.io/get + + // tip: log the request object to see everything it has in the console + cy.get('@post').then(console.log) + + // you can retrieve the XHR multiple times - returns the same object + // confirm the request status + cy.get('@post').should('have.property', 'status', 201) + + // we cannot chain any more assertions to the above request object + // because the "have.property" assertion yields the property's value + // so let's just grab the request object again and run multiple assertions + cy.get('@post').should((req) => { + expect(req.method).to.equal('POST') + expect(req.url).to.match(/\/posts$/) + // it is good practice to add message to the assertion + expect(req, 'has duration in ms').to.have.property('duration').and.be.a('number') }) - // it is a good practice to add message argument to the - // assertion "expect(value, message)..." that will be shown - // in the test runner's command log - expect(res.body, 'response body').to.deep.equal({ - body: 'this is a post sent to the server', - id: 101, + // let's confirm the request sent to the server + cy.get('@post').its('request.body').should('deep.equal', { title: 'example post', + body: 'this is a post sent to the server', userId: 1, }) + + // get the same request object again and confirm the response + cy.get('@post').its('response').then((res) => { + // because the response object is not going to change + // we can use cy.then() callback to run assertions just once + // without retrying + // see https://on.cypress.io/then and https://on.cypress.io/retry-ability + expect(res.headers).to.include({ + 'cache-control': 'no-cache', + expires: '-1', + 'content-type': 'application/json; charset=utf-8', + location: 'http://jsonplaceholder.cypress.io/posts/101', + }) + + // it is a good practice to add message argument to the + // assertion "expect(value, message)..." that will be shown + // in the test runner's command log + expect(res.body, 'response body').to.deep.equal({ + body: 'this is a post sent to the server', + id: 101, + title: 'example post', + userId: 1, + }) + }) }) -}) -it('sends request after delay', () => { - cy.visit('index.html') - - // before the request goes out we need to set up spying - // see https://on.cypress.io/network-requests - cy.server() - cy.route('POST', '/posts').as('post') - - cy.get('#delayed-load').click() - - // the XHR request has NOT happened yet - we are not checking the UI - // to "wait" for it. Thus we cannot use cy.get("@post"), - // instead we need to wait for the request to happen - // using cy.wait("@post") call - // - // https://on.cypress.io/wait - cy.wait('@post').should((xhr) => { - expect(xhr.status, 'successful POST').to.equal(201) - expect(xhr.url, 'post url').to.match(/\/posts$/) + it('sends request after delay', () => { + cy.visit('index.html') + + // before the request goes out we need to set up spying + // see https://on.cypress.io/network-requests + cy.server() + cy.route('POST', '/posts').as('post') + + cy.get('#delayed-load').click() + + // the XHR request has NOT happened yet - we are not checking the UI + // to "wait" for it. Thus we cannot use cy.get("@post"), + // instead we need to wait for the request to happen + // using cy.wait("@post") call + // + // https://on.cypress.io/wait + cy.wait('@post').should((xhr) => { + expect(xhr.status, 'successful POST').to.equal(201) + expect(xhr.url, 'post url').to.match(/\/posts$/) // assert any other XHR properties - }) + }) - // if you need to assert again, retrieve the same XHR object - // using cy.get() - because by now the request has happened - cy.get('@post').its('request.body').should('deep.equal', { - title: 'example post', - body: 'this is a post sent to the server', - userId: 1, + // if you need to assert again, retrieve the same XHR object + // using cy.get() - because by now the request has happened + cy.get('@post').its('request.body').should('deep.equal', { + title: 'example post', + body: 'this is a post sent to the server', + userId: 1, + }) }) }) diff --git a/examples/server-communication__xhr-assertions/cypress/integration/spok-spec.js b/examples/server-communication__xhr-assertions/cypress/integration/spok-spec.js index 0a2726bed..1db2b1dd9 100644 --- a/examples/server-communication__xhr-assertions/cypress/integration/spok-spec.js +++ b/examples/server-communication__xhr-assertions/cypress/integration/spok-spec.js @@ -3,39 +3,95 @@ // see https://github.com/bahmutov/cy-spok const spok = require('cy-spok') -it('asserts multiple XHR properties at once using cy-spok', () => { - cy.visit('index.html') +describe('network', () => { + it('asserts multiple XHR properties at once using cy-spok', () => { + cy.visit('index.html') - // before the request goes out we need to set up spying - // see https://on.cypress.io/network-requests - cy.server() - cy.route('POST', '/posts').as('post') + // before the request goes out we need to set up spying + // see https://on.cypress.io/network-requests + cy.server() + cy.route('POST', '/posts').as('post') - cy.get('#load').click() - cy.contains('#output', '"title": "example post"').should('be.visible') + cy.get('#load').click() + cy.contains('#output', '"title": "example post"').should('be.visible') - // Spok https://github.com/thlorenz/spok is a mix between schema and value assertions - // Since it supports nested objects, in a single "should()" we can verify desired - // properties of the XHR object, its request and response nested objects. - cy.get('@post').should(spok({ - status: 201, - url: spok.endsWith('posts'), - // network request takes at least 10ms - // but should finish in less than 1 second - duration: spok.range(10, 1000), - statusMessage: spok.string, - // check the request inside XHR object - request: { + // Spok https://github.com/thlorenz/spok is a mix between schema and value assertions + // Since it supports nested objects, in a single "should()" we can verify desired + // properties of the XHR object, its request and response nested objects. + cy.get('@post').should(spok({ + status: 201, + url: spok.endsWith('posts'), + // network request takes at least 10ms + // but should finish in less than 1 second + duration: spok.range(10, 1000), + statusMessage: spok.string, + // check the request inside XHR object + request: { // using special keyword "$topic" to get // nicer indentation in the command log - $topic: 'request', - body: { - title: 'example post', - userId: 1, + $topic: 'request', + body: { + title: 'example post', + userId: 1, + }, }, - }, - response: { - $topic: 'response', + response: { + $topic: 'response', + headers: { + 'content-type': 'application/json; charset=utf-8', + 'cache-control': 'no-cache', + }, + body: { + title: 'example post', + body: spok.string, + userId: 1, + // we don't know the exact id the server assigns to the new post + // but it should be > 100 + id: spok.gt(100), + }, + }, + })) + }) + + // there is a bug in Cypress with chaining multiple assertion callbacks + // like .should(cb1).should(cb2) + // https://github.com/cypress-io/cypress/issues/4981 + // but we can use multiple callbacks by chaining .then(cb1).then(cb2) + // which works fine since our request object cannot change + it('can chain assertions using .then', () => { + cy.visit('index.html') + + cy.server() + cy.route('POST', '/posts').as('post') + + cy.get('#delayed-load').click() + // the request has gone out - let's wait for it + // and then assert some of its properties + cy.wait('@post').then(spok({ + status: 201, + })) + // let's confirm the request object + .its('request.body') + // notice that we want to confirm that the "body" field is a string + // and it starts with certain prefix. Since we cannot AND conditions + // we can split checks across 2 spoks + .then(spok({ + title: 'example post', + userId: 1, + body: spok.string, + })) + // cy.then(cb) yields its original subject + // thus the second .then(cb) can work with the same request + // https://on.cypress.io/then + .then(spok({ + body: spok.startsWith('this is a post'), + })) + + // cy.its(...) yields the property value + // so if we want to validate the response object + // we need to get the XHR object again + // by now the object exists, thus we can use cy.get() + cy.get('@post').its('response').should(spok({ headers: { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-cache', @@ -48,60 +104,6 @@ it('asserts multiple XHR properties at once using cy-spok', () => { // but it should be > 100 id: spok.gt(100), }, - }, - })) -}) - -// there is a bug in Cypress with chaining multiple assertion callbacks -// like .should(cb1).should(cb2) -// https://github.com/cypress-io/cypress/issues/4981 -// but we can use multiple callbacks by chaining .then(cb1).then(cb2) -// which works fine since our request object cannot change -it('can chain assertions using .then', () => { - cy.visit('index.html') - - cy.server() - cy.route('POST', '/posts').as('post') - - cy.get('#delayed-load').click() - // the request has gone out - let's wait for it - // and then assert some of its properties - cy.wait('@post').then(spok({ - status: 201, - })) - // let's confirm the request object - .its('request.body') - // notice that we want to confirm that the "body" field is a string - // and it starts with certain prefix. Since we cannot AND conditions - // we can split checks across 2 spoks - .then(spok({ - title: 'example post', - userId: 1, - body: spok.string, - })) - // cy.then(cb) yields its original subject - // thus the second .then(cb) can work with the same request - // https://on.cypress.io/then - .then(spok({ - body: spok.startsWith('this is a post'), - })) - - // cy.its(...) yields the property value - // so if we want to validate the response object - // we need to get the XHR object again - // by now the object exists, thus we can use cy.get() - cy.get('@post').its('response').should(spok({ - headers: { - 'content-type': 'application/json; charset=utf-8', - 'cache-control': 'no-cache', - }, - body: { - title: 'example post', - body: spok.string, - userId: 1, - // we don't know the exact id the server assigns to the new post - // but it should be > 100 - id: spok.gt(100), - }, - })) + })) + }) }) diff --git a/examples/server-communication__xhr-assertions/cypress/integration/wait-vs-get.js b/examples/server-communication__xhr-assertions/cypress/integration/wait-vs-get.js index 560613c5d..1e74aabe0 100644 --- a/examples/server-communication__xhr-assertions/cypress/integration/wait-vs-get.js +++ b/examples/server-communication__xhr-assertions/cypress/integration/wait-vs-get.js @@ -1,43 +1,44 @@ /// -// failing test is skipped -it.skip('cy.get yields null if the network request has not happened yet', () => { - cy.visit('index.html') - - cy.server() - cy.route('POST', '/posts').as('post') - - cy.get('#delayed-load').click() - // cy.get does NOT work - // because it immediately returns null object, - // since the request has not happened yet - cy.get('@post').should('have.property', 'status', 201) -}) - +describe('XHR', () => { +// NOTE: this is a demo of failing test + it.skip('cy.get yields null if the network request has not happened yet', () => { + cy.visit('index.html') + + cy.server() + cy.route('POST', '/posts').as('post') + + cy.get('#delayed-load').click() + // cy.get does NOT work + // because it immediately returns null object, + // since the request has not happened yet + cy.get('@post').should('have.property', 'status', 201) + }) -it('cy.wait waits for the network request to happen', () => { - cy.visit('index.html') + it('cy.wait waits for the network request to happen', () => { + cy.visit('index.html') - cy.server() - cy.route('POST', '/posts').as('post') + cy.server() + cy.route('POST', '/posts').as('post') - cy.get('#delayed-load').click() - cy.wait('@post').should('have.property', 'status', 201) -}) + cy.get('#delayed-load').click() + cy.wait('@post').should('have.property', 'status', 201) + }) -it('cy.wait then cy.get to retrieve the same XHR', () => { - cy.visit('index.html') + it('cy.wait then cy.get to retrieve the same XHR', () => { + cy.visit('index.html') - cy.server() - cy.route('POST', '/posts').as('post') + cy.server() + cy.route('POST', '/posts').as('post') - cy.get('#delayed-load').click() - // there is only 1 POST request - cy.wait('@post').then((xhr1) => { + cy.get('#delayed-load').click() + // there is only 1 POST request + cy.wait('@post').then((xhr1) => { // ask for the XHR again using cy.get // by now it has happened for sure, // and cy.get should yield same XHR object - cy.get('@post').then((xhr2) => { - expect(xhr1, 'same XHR').to.equal(xhr2) + cy.get('@post').then((xhr2) => { + expect(xhr1, 'same XHR').to.equal(xhr2) + }) }) }) }) diff --git a/examples/server-communication__xhr-assertions/package.json b/examples/server-communication__xhr-assertions/package.json index 95fe70163..f776d53f6 100644 --- a/examples/server-communication__xhr-assertions/package.json +++ b/examples/server-communication__xhr-assertions/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "Checking network request and response", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", "test:ci": "npm run cypress:run" } } diff --git a/examples/stubbing-spying__console/package.json b/examples/stubbing-spying__console/package.json index ee3a64578..2c18a0b9f 100644 --- a/examples/stubbing-spying__console/package.json +++ b/examples/stubbing-spying__console/package.json @@ -3,9 +3,9 @@ "version": "1.0.0", "description": "", "scripts": { - "start": "echo", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", + "start": "echo", "test:ci": "npm run cypress:run" } } diff --git a/examples/stubbing-spying__functions/cypress/integration/unit-test-stubbing-dependencies-spec.js b/examples/stubbing-spying__functions/cypress/integration/unit-test-stubbing-dependencies-spec.js index c23bc5fce..b808156c7 100644 --- a/examples/stubbing-spying__functions/cypress/integration/unit-test-stubbing-dependencies-spec.js +++ b/examples/stubbing-spying__functions/cypress/integration/unit-test-stubbing-dependencies-spec.js @@ -40,6 +40,7 @@ describe('Stubbing Dependencies', function () { // to return a resolved promise beforeEach(function () { cy.stub(api, 'login').resolves('user-id-123') + return this.auth.login('user', 'pass') }) @@ -58,6 +59,7 @@ describe('Stubbing Dependencies', function () { beforeEach(function () { cy.stub(api, 'login').rejects(new Error('Wrong password')) cy.stub(util, 'log') + return this.auth.login('user', 'pass') }) @@ -75,6 +77,7 @@ describe('Stubbing Dependencies', function () { // easy way to call that callback beforeEach(function () { cy.stub(api, 'login').resolves('user-id-123') + return this.auth.login('user', 'pass').then(() => { api.onUnauth.yield() }) diff --git a/examples/stubbing-spying__functions/package.json b/examples/stubbing-spying__functions/package.json index dd08135c0..3050b8f06 100644 --- a/examples/stubbing-spying__functions/package.json +++ b/examples/stubbing-spying__functions/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "Shows how to control dependencies during tests using cy.spy and cy.stub", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", "start": "echo nothing to start, this recipe does not run server", "test:ci": "npm run cypress:run" } diff --git a/examples/stubbing-spying__functions/util.js b/examples/stubbing-spying__functions/util.js index db9f36f35..6da191c09 100644 --- a/examples/stubbing-spying__functions/util.js +++ b/examples/stubbing-spying__functions/util.js @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ export default { log (...args) { console.log(...args) diff --git a/examples/stubbing-spying__google-analytics/cypress/integration/google-analytics-stubbing.js b/examples/stubbing-spying__google-analytics/cypress/integration/google-analytics-stubbing.js index b538df4c9..c2328f71a 100644 --- a/examples/stubbing-spying__google-analytics/cypress/integration/google-analytics-stubbing.js +++ b/examples/stubbing-spying__google-analytics/cypress/integration/google-analytics-stubbing.js @@ -1,5 +1,3 @@ -/* global Cypress, cy */ - // in our cypress.json file we have blacklisted www.google-analytics.com // which prevents the GA script from ever loading. however because there // is still a global 'window.ga' function, that means we can stub it diff --git a/examples/stubbing-spying__google-analytics/package.json b/examples/stubbing-spying__google-analytics/package.json index 78e410dd1..3c2e064d2 100644 --- a/examples/stubbing-spying__google-analytics/package.json +++ b/examples/stubbing-spying__google-analytics/package.json @@ -3,9 +3,9 @@ "version": "1.0.0", "description": "", "scripts": { - "start": "echo", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", + "start": "echo", "test:ci": "npm run cypress:run" } } diff --git a/examples/stubbing-spying__window-fetch/cypress/integration/control-clock-spec.js b/examples/stubbing-spying__window-fetch/cypress/integration/control-clock-spec.js index b8250e04f..9cec6da91 100644 --- a/examples/stubbing-spying__window-fetch/cypress/integration/control-clock-spec.js +++ b/examples/stubbing-spying__window-fetch/cypress/integration/control-clock-spec.js @@ -32,7 +32,9 @@ describe('clock', function () { describe('when favorite fruits are returned', function () { beforeEach(function () { this.fetchFavoritesDeferred.resolve({ - json () { return ['Apple', 'Banana', 'Cantaloupe'] }, + json () { + return ['Apple', 'Banana', 'Cantaloupe'] + }, ok: true, }) }) @@ -43,8 +45,10 @@ describe('clock', function () { cy.get('@favoriteFruits').first() .should('have.text', 'Apple') + cy.get('@favoriteFruits').eq(1) .should('have.text', 'Banana') + cy.get('@favoriteFruits').eq(2) .should('have.text', 'Cantaloupe') }) @@ -54,9 +58,12 @@ describe('clock', function () { // since we aliased the window.fetch stub to 'fetchFavorites', // it becomes available as this.fetchFavorites in our tests this.fetchFavorites.onCall(1).resolves({ - json () { return ['Orange', 'Cherry', 'Raspberry', 'Pineapple'] }, + json () { + return ['Orange', 'Cherry', 'Raspberry', 'Pineapple'] + }, ok: true, }) + // move time 30 seconds and the setInterval will be triggered // that polls for the fruit cy.tick(30000) @@ -72,10 +79,13 @@ describe('clock', function () { cy.get('@favoriteFruits').first() .should('have.text', 'Orange') + cy.get('@favoriteFruits').eq(1) .should('have.text', 'Cherry') + cy.get('@favoriteFruits').eq(2) .should('have.text', 'Raspberry') + cy.get('@favoriteFruits').eq(3) .should('have.text', 'Pineapple') }) diff --git a/examples/stubbing-spying__window-fetch/cypress/integration/deferred.js b/examples/stubbing-spying__window-fetch/cypress/integration/deferred.js index f4c01985a..b18aab69f 100644 --- a/examples/stubbing-spying__window-fetch/cypress/integration/deferred.js +++ b/examples/stubbing-spying__window-fetch/cypress/integration/deferred.js @@ -1,10 +1,11 @@ // little utility for making Promise-returning stubs easier module.exports = function () { const deferred = {} - /* global Promise */ + deferred.promise = new Promise((resolve, reject) => { deferred.resolve = resolve deferred.reject = reject }) + return deferred } diff --git a/examples/stubbing-spying__window-fetch/cypress/integration/polyfill-fetch-from-tests-spec.js b/examples/stubbing-spying__window-fetch/cypress/integration/polyfill-fetch-from-tests-spec.js index 6b28c7d13..158d8e354 100644 --- a/examples/stubbing-spying__window-fetch/cypress/integration/polyfill-fetch-from-tests-spec.js +++ b/examples/stubbing-spying__window-fetch/cypress/integration/polyfill-fetch-from-tests-spec.js @@ -12,6 +12,7 @@ describe('polyfill window.fetch from tests', function () { // grab fetch polyfill from remote URL, could be also from a local package before(() => { const polyfillUrl = 'https://unpkg.com/unfetch/dist/unfetch.umd.js' + cy.request(polyfillUrl) .then((response) => { polyfill = response.body diff --git a/examples/stubbing-spying__window-fetch/cypress/integration/stub-fetch-spec.js b/examples/stubbing-spying__window-fetch/cypress/integration/stub-fetch-spec.js index b02576905..ba15b5986 100644 --- a/examples/stubbing-spying__window-fetch/cypress/integration/stub-fetch-spec.js +++ b/examples/stubbing-spying__window-fetch/cypress/integration/stub-fetch-spec.js @@ -39,7 +39,9 @@ describe('stubbing', function () { describe('when favorite fruits are returned', function () { beforeEach(function () { this.fetchFavoritesDeferred.resolve({ - json () { return ['Apple', 'Banana', 'Cantaloupe'] }, + json () { + return ['Apple', 'Banana', 'Cantaloupe'] + }, ok: true, }) }) @@ -50,8 +52,10 @@ describe('stubbing', function () { cy.get('@favoriteFruits').first() .should('have.text', 'Apple') + cy.get('@favoriteFruits').eq(1) .should('have.text', 'Banana') + cy.get('@favoriteFruits').eq(2) .should('have.text', 'Cantaloupe') }) @@ -60,7 +64,9 @@ describe('stubbing', function () { describe('when no favorite fruits are returned', function () { beforeEach(function () { this.fetchFavoritesDeferred.resolve({ - json () { return [] }, + json () { + return [] + }, ok: true, }) }) diff --git a/examples/stubbing-spying__window-fetch/cypress/support/index.js b/examples/stubbing-spying__window-fetch/cypress/support/index.js index 37a498fb5..d68db96df 100644 --- a/examples/stubbing-spying__window-fetch/cypress/support/index.js +++ b/examples/stubbing-spying__window-fetch/cypress/support/index.js @@ -14,7 +14,7 @@ // *********************************************************** // Import commands.js using ES2015 syntax: -import './commands'; +import './commands' // Alternatively you can use CommonJS syntax: // require('./commands') diff --git a/examples/stubbing-spying__window-fetch/package.json b/examples/stubbing-spying__window-fetch/package.json index f732234bc..8ccc29762 100644 --- a/examples/stubbing-spying__window-fetch/package.json +++ b/examples/stubbing-spying__window-fetch/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", "start": "node server.js --port 7080", "test:ci": "../../node_modules/.bin/start-test 7080 cypress:run" } diff --git a/examples/stubbing-spying__window-fetch/server.js b/examples/stubbing-spying__window-fetch/server.js index 36054f5d3..1721eaf46 100644 --- a/examples/stubbing-spying__window-fetch/server.js +++ b/examples/stubbing-spying__window-fetch/server.js @@ -1,10 +1,10 @@ -const _ = require('lodash') -const path = require('path') -const minimist = require('minimist') -const express = require('express') +const _ = require('lodash') +const path = require('path') +const minimist = require('minimist') +const express = require('express') -const fruits = require('./fruits') -const app = express() +const fruits = require('./fruits') +const app = express() // get port from passed in args from scripts/start.js const port = minimist(process.argv.slice(2)).port diff --git a/examples/stubbing-spying__window/cypress/integration/spec.js b/examples/stubbing-spying__window/cypress/integration/spec.js index 6401fa096..8e8ceab8a 100644 --- a/examples/stubbing-spying__window/cypress/integration/spec.js +++ b/examples/stubbing-spying__window/cypress/integration/spec.js @@ -8,6 +8,7 @@ describe('window open', function () { cy.window().then((win) => { cy.stub(win, 'open').as('windowOpen') }) + cy.get('#open-window').click() cy.get('@windowOpen').should('be.calledWith', 'page1.html') }) diff --git a/examples/stubbing-spying__window/package.json b/examples/stubbing-spying__window/package.json index ee3a64578..2c18a0b9f 100644 --- a/examples/stubbing-spying__window/package.json +++ b/examples/stubbing-spying__window/package.json @@ -3,9 +3,9 @@ "version": "1.0.0", "description": "", "scripts": { - "start": "echo", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", + "start": "echo", "test:ci": "npm run cypress:run" } } diff --git a/examples/stubbing__resources/cypress/integration/spec.js b/examples/stubbing__resources/cypress/integration/spec.js index 25cb9aaea..d2cf6a4da 100644 --- a/examples/stubbing__resources/cypress/integration/spec.js +++ b/examples/stubbing__resources/cypress/integration/spec.js @@ -36,6 +36,7 @@ describe('Stub loading of resources', () => { mutations[0].addedNodes[0].src = `data:image/png;base64,${imgStr}` }) }) + cy.get('button').click() // image element will have "naturalWidth" set when it loads @@ -44,5 +45,3 @@ describe('Stub loading of resources', () => { cy.get('#img-container > img').should(($img) => expect($img[0].naturalWidth).to.equal(100)) }) }) - - diff --git a/examples/stubbing__resources/package.json b/examples/stubbing__resources/package.json index 256b4a311..5c439f4c4 100644 --- a/examples/stubbing__resources/package.json +++ b/examples/stubbing__resources/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", "test:ci": "npm run cypress:run" } } diff --git a/examples/testing-dom__csv-table/cypress/integration/spec.js b/examples/testing-dom__csv-table/cypress/integration/spec.js index b6064c5b9..23adcf7e4 100644 --- a/examples/testing-dom__csv-table/cypress/integration/spec.js +++ b/examples/testing-dom__csv-table/cypress/integration/spec.js @@ -1,28 +1,32 @@ /// const neatCSV = require('neat-csv') -it('has table rows for each row of CSV file', () => { - cy.visit('index.html') - cy.readFile('records.csv') - .then(neatCSV) // converts text into list of objects - /* eslint-disable-next-line no-console */ - .then(console.table) // convenient method for printing list of objects in DevTools console - .then((records) => { - cy.get('table tr').should(($rows) => { +describe('CSV', () => { + it('has table rows for each row of CSV file', () => { + cy.visit('index.html') + cy.readFile('records.csv') + .then(neatCSV) // converts text into list of objects + /* eslint-disable-next-line no-console */ + .then(console.table) // convenient method for printing list of objects in DevTools console + .then((records) => { + cy.get('table tr').should(($rows) => { // go through each row and confirm it shows the right information from CSV - $rows.each((k, $row) => { - const record = records[k] - const $cells = $row.children + $rows.each((k, $row) => { + const record = records[k] + const $cells = $row.children - expect($cells[0]) - .to.have.property('innerText') - .equal(record['First name']) - expect($cells[1]) - .to.have.property('innerText') - .equal(record['Last name']) - expect($cells[2]) - .to.have.property('innerText') - .equal(record['Occupation']) + expect($cells[0]) + .to.have.property('innerText') + .equal(record['First name']) + + expect($cells[1]) + .to.have.property('innerText') + .equal(record['Last name']) + + expect($cells[2]) + .to.have.property('innerText') + .equal(record['Occupation']) + }) }) }) }) diff --git a/examples/testing-dom__csv-table/package.json b/examples/testing-dom__csv-table/package.json index 10fca3dac..955995c29 100644 --- a/examples/testing-dom__csv-table/package.json +++ b/examples/testing-dom__csv-table/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "description": "Loads CSV file and checks HTML table to have the text content matching the loaded CSV records", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", "test:ci": "npm run cypress:run" } } diff --git a/examples/testing-dom__drag-drop/cypress/integration/drag_n_drop_spec.js b/examples/testing-dom__drag-drop/cypress/integration/drag_n_drop_spec.js index 815b9fa0f..94a493fe5 100644 --- a/examples/testing-dom__drag-drop/cypress/integration/drag_n_drop_spec.js +++ b/examples/testing-dom__drag-drop/cypress/integration/drag_n_drop_spec.js @@ -5,10 +5,10 @@ // one utilizing mouse events and // one utilizing drag events -describe('Drag n Drop', function(){ +describe('Drag n Drop', function () { // This tests a puzzle that uses dragula.js, which, under the hood, // binds to mousedown, mousemove, and mouseup events - describe('puzzle using mouse events', function(){ + describe('puzzle using mouse events', function () { // A drag and drop action is made up of a mousedown event, // multiple mousemove events, and a mouseup event // (we can get by with just one mousemove event for our test, @@ -21,9 +21,9 @@ describe('Drag n Drop', function(){ // with clientX and clientY function movePiece (number, x, y) { cy.get(`.piece-${number}`) - .trigger('mousedown', { which: 1 }) - .trigger('mousemove', { clientX: x, clientY: y }) - .trigger('mouseup', {force: true}) + .trigger('mousedown', { which: 1 }) + .trigger('mousemove', { clientX: x, clientY: y }) + .trigger('mouseup', { force: true }) } function completePuzzle (correctly) { @@ -38,113 +38,114 @@ describe('Drag n Drop', function(){ movePiece(9, 480, 270) } - beforeEach(function(){ + beforeEach(function () { cy.viewport(550, 350) cy.visit('/puzzle.html') }) - it('moves the piece when dragged to valid place', function(){ + it('moves the piece when dragged to valid place', function () { movePiece(1, 340, 130) cy.get('.pieces li').eq(3).find('span').should('not.exist') cy.get('.places li').eq(0).find('span').should('have.class', 'piece-1') }) - it('does not move piece when dragged to invalid place', function(){ + it('does not move piece when dragged to invalid place', function () { movePiece(1, 0, 0) cy.get('.pieces li').eq(3).find('span').should('have.class', 'piece-1') }) - it('does not move piece when dragged to occupied place', function(){ + it('does not move piece when dragged to occupied place', function () { movePiece(1, 340, 130) movePiece(2, 340, 130) cy.get('.places li').eq(0).find('span').should('have.class', 'piece-1') cy.get('.pieces li').eq(7).find('span').should('have.class', 'piece-2') }) - it('allows moving piece back to open spot', function(){ + it('allows moving piece back to open spot', function () { movePiece(1, 340, 130) movePiece(1, 70, 180) cy.get('.pieces li').eq(3).find('span').should('have.class', 'piece-1') }) - it('shows error message when puzzle is completed incorrectly', function(){ + it('shows error message when puzzle is completed incorrectly', function () { completePuzzle(false) cy.get('.notice') - .should('have.class', 'error') - .and('have.text', 'Not quite right. Please try again') + .should('have.class', 'error') + .and('have.text', 'Not quite right. Please try again') }) - it('shows success message when puzzle is completed correctly', function(){ + it('shows success message when puzzle is completed correctly', function () { completePuzzle(true) cy.get('.notice') - .should('have.class', 'success') - .and('have.text', 'Success!') + .should('have.class', 'success') + .and('have.text', 'Success!') }) }) // This tests a simple game that utilizes the native drag events // like dragstart, dragenter, dragleave, and drop - describe('game using drag events', function(){ + describe('game using drag events', function () { function dropBallInHoop (index) { cy.get('.balls img').first() - .trigger('dragstart') + .trigger('dragstart') + cy.get('.hoop') - .trigger('drop') + .trigger('drop') } - beforeEach(function(){ + beforeEach(function () { cy.clock() cy.viewport(400, 350) cy.visit('/basketball.html') }) - it('shows error message when time runs out', function(){ + it('shows error message when time runs out', function () { cy.tick(10000) cy.get('main') - .should('have.class', 'error') - .find('p') - .should('have.text', "Time's up!") + .should('have.class', 'error') + .find('p') + .should('have.text', 'Time\'s up!') }) - it('highlights hoop when ball is dragged over it', function(){ + it('highlights hoop when ball is dragged over it', function () { cy.get('.hoop') - .trigger('dragenter') - .should('have.class', 'over') + .trigger('dragenter') + .should('have.class', 'over') }) - it('unhighlights hoop when ball is dragged out of it', function(){ + it('unhighlights hoop when ball is dragged out of it', function () { cy.get('.hoop') - .trigger('dragenter') - .should('have.class', 'over') - .trigger('dragleave') - .should('not.have.class', 'over') + .trigger('dragenter') + .should('have.class', 'over') + .trigger('dragleave') + .should('not.have.class', 'over') }) - it('unhighlights hoop when ball is dropped in it', function(){ + it('unhighlights hoop when ball is dropped in it', function () { cy.get('.hoop') - .trigger('dragenter') - .should('have.class', 'over') + .trigger('dragenter') + .should('have.class', 'over') dropBallInHoop() cy.get('.hoop') - .should('not.have.class', 'over') + .should('not.have.class', 'over') }) - it('removes ball when it is dropped in hoop', function(){ + it('removes ball when it is dropped in hoop', function () { dropBallInHoop() cy.get('.balls img').should('have.length', 3) }) - it('shows success message when all the balls are dropped in hoop', function(){ + it('shows success message when all the balls are dropped in hoop', function () { dropBallInHoop() dropBallInHoop() dropBallInHoop() dropBallInHoop() cy.get('main') - .should('have.class', 'success') - .find('p') - .should('have.text', 'Success!') + .should('have.class', 'success') + .find('p') + .should('have.text', 'Success!') }) }) }) diff --git a/examples/testing-dom__drag-drop/package.json b/examples/testing-dom__drag-drop/package.json index c8fb83990..e91585657 100644 --- a/examples/testing-dom__drag-drop/package.json +++ b/examples/testing-dom__drag-drop/package.json @@ -3,10 +3,10 @@ "version": "1.0.0", "description": "Performing Drag & Drop by triggering mouse and drag events", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "start": "node server.js --port 7071", + "cypress:run": "../../node_modules/.bin/cypress run", "dev": "../../node_modules/.bin/start-test http://localhost:7071/puzzle.html cypress:open", + "start": "node server.js --port 7071", "test:ci": "../../node_modules/.bin/start-test http://localhost:7071/puzzle.html cypress:run" } } diff --git a/examples/testing-dom__form-interactions/cypress/integration/form-interactions-spec.js b/examples/testing-dom__form-interactions/cypress/integration/form-interactions-spec.js index 5d3a1e0af..eed054081 100644 --- a/examples/testing-dom__form-interactions/cypress/integration/form-interactions-spec.js +++ b/examples/testing-dom__form-interactions/cypress/integration/form-interactions-spec.js @@ -3,13 +3,13 @@ // Eventually, this will be expanded to includes examples of interacting // with various form elements -describe('Form Interactions', function(){ - beforeEach(function(){ +describe('Form Interactions', function () { + beforeEach(function () { cy.viewport(400, 300) cy.visit('/index.html') }) - it('updates range value when moving slider', function(){ + it('updates range value when moving slider', function () { // To interact with a range input (slider), we need to set its value and // then trigger the appropriate event to signal it has changed @@ -20,9 +20,10 @@ describe('Form Interactions', function(){ // which is fired as a user moves the slider, but is not supported // by some browsers cy.get('input[type=range]').as('range') - .invoke('val', 25) - .trigger('change') + .invoke('val', 25) + .trigger('change') + cy.get('@range').siblings('p') - .should('have.text', '25') + .should('have.text', '25') }) }) diff --git a/examples/testing-dom__form-interactions/package.json b/examples/testing-dom__form-interactions/package.json index 2e476dad3..cfb4a9894 100644 --- a/examples/testing-dom__form-interactions/package.json +++ b/examples/testing-dom__form-interactions/package.json @@ -3,11 +3,11 @@ "version": "1.0.0", "description": "Shows how to change the value of a range input", "scripts": { + "cypress:open": "../../node_modules/.bin/cypress open", "cypress:run": "../../node_modules/.bin/cypress run", "cypress:run:firefox": "../../node_modules/.bin/cypress run --browser firefox", - "cypress:open": "../../node_modules/.bin/cypress open", - "start": "node server.js --port 7072", "dev": "../../node_modules/.bin/start-test 7072 cypress:open", + "start": "node server.js --port 7072", "test:ci": "../../node_modules/.bin/start-test 7072 cypress:run", "test:ci:firefox": "../../node_modules/.bin/start-test 7072 cypress:run:firefox" } diff --git a/examples/testing-dom__hover-hidden-elements/cypress/integration/hover-hidden-elements-spec.js b/examples/testing-dom__hover-hidden-elements/cypress/integration/hover-hidden-elements-spec.js index c09c34474..fdcce7d09 100644 --- a/examples/testing-dom__hover-hidden-elements/cypress/integration/hover-hidden-elements-spec.js +++ b/examples/testing-dom__hover-hidden-elements/cypress/integration/hover-hidden-elements-spec.js @@ -6,9 +6,9 @@ // Additionally we'll show you how to fire mouse events // on an element so that JavaScript event callbacks are invoked. -describe('Hover and Hidden Elements', function(){ - context('hidden elements', function(){ - beforeEach(function(){ +describe('Hover and Hidden Elements', function () { + context('hidden elements', function () { + beforeEach(function () { // In `examples/hover_hidden_elements/hidden.html`, // the html page includes an element that is hidden until // the :hover CSS psuedo selector is triggered by a mouse hover @@ -19,17 +19,17 @@ describe('Hover and Hidden Elements', function(){ cy.visit('/hidden.html') }) - it('solution #1: force events to happen', function(){ + it('solution #1: force events to happen', function () { // By default, before Cypress interacts with an element, // it checks to ensure the element is not hidden // // Some commands, like cy.click, allow you to pass 'force: true' // as an option to bypass these checks and allow the event to happen anyway - cy.get('button').click({force: true}) + cy.get('button').click({ force: true }) cy.get('#message').should('contain', 'the button was clicked') }) - it('solution #2: force the element to be visible before click', function(){ + it('solution #2: force the element to be visible before click', function () { // We get a lot of value out of letting Cypress ensure the element // is interactable and its nice to not 'force' events to happen. // @@ -45,7 +45,7 @@ describe('Hover and Hidden Elements', function(){ cy.get('#message').should('contain', 'the button was clicked') }) - it('solution #3: verify visibility prior to showing element', function(){ + it('solution #3: verify visibility prior to showing element', function () { // We can improve on solution #2 above by adding some tests // around the elements visibility. // @@ -56,8 +56,8 @@ describe('Hover and Hidden Elements', function(){ }) }) - context('mouse events', function(){ - beforeEach(function(){ + context('mouse events', function () { + beforeEach(function () { // In `examples/hover_hidden_elements/mouse.html`, // the html page includes a button that is bound to several // mouse events. This shows you how to cause those events to fire. @@ -65,9 +65,9 @@ describe('Hover and Hidden Elements', function(){ cy.visit('/mouse.html') }) - describe('if your app uses jQuery', function(){ + describe('if your app uses jQuery', function () { ['mouseover', 'mouseout', 'mouseenter', 'mouseleave'].forEach((event) => { - it(`triggers event: '${event}`, function(){ + it(`triggers event: '${event}`, function () { // if your app uses jQuery, then we can trigger a jQuery // event that causes the event callback to fire cy.get('#with-jquery').invoke('trigger', event) @@ -76,9 +76,9 @@ describe('Hover and Hidden Elements', function(){ }) }) - describe('if your app does not use jQuery', function(){ + describe('if your app does not use jQuery', function () { ['mouseover', 'mouseout', 'mouseenter', 'mouseleave'].forEach((event) => { - it(`dispatches event: '${event}`, function(){ + it(`dispatches event: '${event}`, function () { // if your app doesnt use jQuery then we use .trigger() // https://on.cypress.io/trigger diff --git a/examples/testing-dom__hover-hidden-elements/package.json b/examples/testing-dom__hover-hidden-elements/package.json index 489b255f7..dd4d176a5 100644 --- a/examples/testing-dom__hover-hidden-elements/package.json +++ b/examples/testing-dom__hover-hidden-elements/package.json @@ -3,14 +3,14 @@ "version": "1.0.0", "description": "Interact with elements that are hidden by CSS", "scripts": { + "cypress:open": "../../node_modules/.bin/cypress open", "cypress:run": "../../node_modules/.bin/cypress run", "cypress:run:chrome": "../../node_modules/.bin/cypress run --browser chrome", "cypress:run:firefox": "../../node_modules/.bin/cypress run --browser firefox", - "cypress:open": "../../node_modules/.bin/cypress open", + "dev": "../../node_modules/.bin/start-test 7073 cypress:open", "start": "node server.js --port 7073", "test:ci": "../../node_modules/.bin/start-test 7073 cypress:run", "test:ci:chrome": "../../node_modules/.bin/start-test 7073 cypress:run:chrome", - "test:ci:firefox": "../../node_modules/.bin/start-test 7073 cypress:run:firefox", - "dev": "../../node_modules/.bin/start-test 7073 cypress:open" + "test:ci:firefox": "../../node_modules/.bin/start-test 7073 cypress:run:firefox" } } diff --git a/examples/testing-dom__performance-metrics/cypress/integration/spec.js b/examples/testing-dom__performance-metrics/cypress/integration/spec.js index 1ac6d00fe..d4b6c0430 100644 --- a/examples/testing-dom__performance-metrics/cypress/integration/spec.js +++ b/examples/testing-dom__performance-metrics/cypress/integration/spec.js @@ -1,36 +1,40 @@ +/* global assert */ describe('Check some performance metrics', () => { it('check page load time', () => { cy.visit('/index.html', { - onBeforeLoad: win => { - win.performance.mark("start-loading") + onBeforeLoad: (win) => { + win.performance.mark('start-loading') }, - onLoad: win => { - win.performance.mark("end-loading") - } - }).its("performance").then(p => { - p.measure("pageLoad", "start-loading", "end-loading") - const measure = p.getEntriesByName("pageLoad")[0] + onLoad: (win) => { + win.performance.mark('end-loading') + }, + }).its('performance').then((p) => { + p.measure('pageLoad', 'start-loading', 'end-loading') + const measure = p.getEntriesByName('pageLoad')[0] + assert.isAtMost(measure.duration, 1000) }) }) it('check image load time', () => { - cy.visit('/index.html').its('performance').then(p => { - const img = p.getEntriesByType('resource').filter(x => x.name.indexOf('performance-example.png'))[0] + cy.visit('/index.html').its('performance').then((p) => { + const img = p.getEntriesByType('resource').filter((x) => x.name.indexOf('performance-example.png'))[0] + assert.isAtMost(img.duration, 400) }) }) it('ensure max load time for images', () => { - cy.visit('/index.html').its('performance').then(p => { - const imgs = p.getEntriesByType('resource').filter(x => x.initiatorType === 'img') + cy.visit('/index.html').its('performance').then((p) => { + const imgs = p.getEntriesByType('resource').filter((x) => x.initiatorType === 'img') const slowestImg = imgs.reduce((p, c) => c.duration > p.duration ? c : p, { duration: 0 }) + assert.isAtMost(slowestImg.duration, 400, `image '${slowestImg.name}' should be loaded in reasonable time`) }) }) it('ensure that no image failed to load', () => { - cy.visit('/index.html'); - cy.get('img').each(img => expect(img[0].naturalWidth).to.not.equal(0)) + cy.visit('/index.html') + cy.get('img').each((img) => expect(img[0].naturalWidth).to.not.equal(0)) }) -}) \ No newline at end of file +}) diff --git a/examples/testing-dom__performance-metrics/package.json b/examples/testing-dom__performance-metrics/package.json index 30d7e1aa7..2118c5ed6 100644 --- a/examples/testing-dom__performance-metrics/package.json +++ b/examples/testing-dom__performance-metrics/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "description": "Shows how to evaluate some performance metrics", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", - "cypress:open": "../../node_modules/.bin/cypress open" + "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run" } } diff --git a/examples/testing-dom__tab-handling-links/cypress/integration/tab_handling_anchor_links_spec.js b/examples/testing-dom__tab-handling-links/cypress/integration/tab_handling_anchor_links_spec.js index 3ad9a687b..e37f2b64b 100644 --- a/examples/testing-dom__tab-handling-links/cypress/integration/tab_handling_anchor_links_spec.js +++ b/examples/testing-dom__tab-handling-links/cypress/integration/tab_handling_anchor_links_spec.js @@ -7,12 +7,12 @@ // Another link is pointed to an external domain that // doesn't match our domain under test - https://www.google.com -describe('Tab Handling Anchor Links', function(){ - beforeEach(function(){ +describe('Tab Handling Anchor Links', function () { + beforeEach(function () { cy.visit('/index.html') }) - context('testing the target="_blank" link', function(){ + context('testing the target="_blank" link', function () { // The problem with the 'users' link is that by default when you click // on it, the browser will attempt to open the content in another // tab. You can open up your browser to the URL we visited above @@ -26,7 +26,7 @@ describe('Tab Handling Anchor Links', function(){ // Luckily there are lots of easy and safe workarounds that // enable you to test the behavior of your application - it('solution #1: verify the href, dont click through', function(){ + it('solution #1: verify the href, dont click through', function () { // The first question we should ask ourselves is... why do we want // to even click this link? // @@ -38,21 +38,21 @@ describe('Tab Handling Anchor Links', function(){ // // We verify that the has the right href and that's it! cy.get('#users') - // the href 'attribute' will only ever be what the - // literal value is on the element itself and will - // match what was served by the payload - .should('have.attr', 'href') - .and('include', 'users.html') + // the href 'attribute' will only ever be what the + // literal value is on the element itself and will + // match what was served by the payload + .should('have.attr', 'href') + .and('include', 'users.html') cy.get('#users') - // an also has an 'href' property which always resolves - // to the fully qualified URL. by asserting on this property - // we are testing this element more thoroughly - .should('have.prop', 'href') - .and('equal', 'http://localhost:7078/users.html') + // an also has an 'href' property which always resolves + // to the fully qualified URL. by asserting on this property + // we are testing this element more thoroughly + .should('have.prop', 'href') + .and('equal', 'http://localhost:7078/users.html') }) - it('solution #2: click through to the new page', function(){ + it('solution #2: click through to the new page', function () { // Okay so let's assume solution #1 isn't comprehensive enough // // Perhaps you have some event handling on the click event @@ -74,14 +74,14 @@ describe('Tab Handling Anchor Links', function(){ cy.url().should('include', 'users.html') }) - it('solution #3: visit without modifying the ', function(){ + it('solution #3: visit without modifying the ', function () { // Still not happy? Perhaps you don't like the idea of modifying your // application's HTML. // // We can still test this by visiting the href property that // would normally cause our browser to be navigated. - cy.get('#users').then(function($a){ + cy.get('#users').then(function ($a) { // extract the fully qualified href property const href = $a.prop('href') @@ -91,7 +91,7 @@ describe('Tab Handling Anchor Links', function(){ }) }) - it('solution #4: request without visiting', function(){ + it('solution #4: request without visiting', function () { // One thing you should always challenge yourself with is // trying to always reduce the time it takes to run a test // @@ -112,25 +112,25 @@ describe('Tab Handling Anchor Links', function(){ // your tests can 'act like the browser' and avoid all // of the side effects of loading resources. - cy.get('#users').then(function($a){ + cy.get('#users').then(function ($a) { // extract the fully qualified href property const href = $a.prop('href') // make an http request for this resource // outside of the browser cy.request(href) - // drill into the response body - .its('body') + // drill into the response body + .its('body') - // and assert that its contents have the response - .should('include', '') - .and('include', '<h1>Users</h1') - .and('include', '</html>') + // and assert that its contents have the <html> response + .should('include', '<title>') + .and('include', '<h1>Users</h1') + .and('include', '</html>') }) }) }) - context('testing the external domain link', function(){ + context('testing the external domain link', function () { // We have another <a> link that has an href that points to an // external domain that doesn't match our current domain under test. // @@ -146,7 +146,7 @@ describe('Tab Handling Anchor Links', function(){ // // Regardless, there are still many ways to test this behavior. - it('solution #1: verify the href property only', function(){ + it('solution #1: verify the href property only', function () { // The simpliest way to test an external link // involves not clicking on it. @@ -155,32 +155,32 @@ describe('Tab Handling Anchor Links', function(){ cy.get('#google').should('have.prop', 'href', 'https://www.google.com/') }) - it('solution #2: request its contents', function(){ + it('solution #2: request its contents', function () { // Okay but what if you need to see the content of the external // page being clicked on? // // We still have cy.request to our rescue. - cy.get('#google').then(function($a){ + cy.get('#google').then(function ($a) { const href = $a.prop('href') // request the contents of https://www.google.com/ cy.request(href) - // drill into the response body - .its('body') + // drill into the response body + .its('body') - // Because we don't control this site - we don't feel - // comfortable making any kind of assertions - // on the response body other than google having a closing <html> tag. - // - // You will notice that this test still goes much - // slower than the others and it requires internet access. - .should('include', '</html>') + // Because we don't control this site - we don't feel + // comfortable making any kind of assertions + // on the response body other than google having a closing <html> tag. + // + // You will notice that this test still goes much + // slower than the others and it requires internet access. + .should('include', '</html>') }) }) - it('solution #3: click through to the external domain', function(){ + it('solution #3: click through to the external domain', function () { // It is not preferred to do this, but it is actually possible // to click through the external domain with Cypress. There are // downsides though, for instance this is not cross browser diff --git a/examples/testing-dom__tab-handling-links/package.json b/examples/testing-dom__tab-handling-links/package.json index 031d3447c..eea3f8a99 100644 --- a/examples/testing-dom__tab-handling-links/package.json +++ b/examples/testing-dom__tab-handling-links/package.json @@ -3,10 +3,10 @@ "version": "1.0.0", "description": "", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "start": "node server.js --port 7078", + "cypress:run": "../../node_modules/.bin/cypress run", "dev": "../../node_modules/.bin/start-test 7078 cypress:open", + "start": "node server.js --port 7078", "test:ci": "../../node_modules/.bin/start-test 7078 cypress:run" } } diff --git a/examples/testing-dom__wait-for-resource/cypress/integration/spec.js b/examples/testing-dom__wait-for-resource/cypress/integration/spec.js index 32c9c4eb1..f4d568cc6 100644 --- a/examples/testing-dom__wait-for-resource/cypress/integration/spec.js +++ b/examples/testing-dom__wait-for-resource/cypress/integration/spec.js @@ -80,9 +80,11 @@ describe('loading style', () => { expect(resourceTiming) .property('entryType') .to.equal('resource') + expect(resourceTiming, 'the CSS file is very small (in bytes)') .property('transferSize') .to.be.lt(300) + expect(resourceTiming, 'loads in less than 150ms') .property('duration') .to.be.lt(150) @@ -103,15 +105,15 @@ describe('loading style', () => { // 3rd party module "cypress-wait-until" is really useful // for simple conditions like waiting for an item // @see https://github.com/NoriSte/cypress-wait-until - cy.waitUntil(() => - cy.window().then((win) => - win.performance + cy.waitUntil(() => { + return cy.window().then((win) => { + return win.performance .getEntriesByType('resource') // note: ".some(...)" method returns boolean value // which cypress-wait-until expects .some((item) => item.name.endsWith('app.css')) - ) - ) + }) + }) // red color means the style from "app.css" has been loaded and applied cy.get('h1', { timeout: 250 }).should('have.css', 'color', 'rgb(255, 0, 0)') diff --git a/examples/testing-dom__wait-for-resource/cypress/support/index.js b/examples/testing-dom__wait-for-resource/cypress/support/index.js index f12f57483..dc9d2a667 100644 --- a/examples/testing-dom__wait-for-resource/cypress/support/index.js +++ b/examples/testing-dom__wait-for-resource/cypress/support/index.js @@ -70,11 +70,12 @@ Cypress.Commands.add('waitForResources', (...args) => { }, timeout) const interval = setInterval(() => { - foundResources = names.every((name) => - win.performance + foundResources = names.every((name) => { + return win.performance .getEntriesByType('resource') .find((item) => item.name.endsWith(name)) - ) + }) + if (!foundResources) { // some resource not found, will try again return diff --git a/examples/testing-dom__wait-for-resource/package.json b/examples/testing-dom__wait-for-resource/package.json index 8eb1abc09..1b0604830 100644 --- a/examples/testing-dom__wait-for-resource/package.json +++ b/examples/testing-dom__wait-for-resource/package.json @@ -3,10 +3,10 @@ "version": "1.0.0", "description": "Shows how to wait for delayed CSS to load before continuing with the test", "scripts": { - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", - "start": "../../node_modules/.bin/http-server -c-1 -p 4500 public", + "cypress:run": "../../node_modules/.bin/cypress run", "dev": "../../node_modules/.bin/start-test 4500 cypress:open", + "start": "../../node_modules/.bin/http-server -c-1 -p 4500 public", "test:ci": "../../node_modules/.bin/start-test 4500 cypress:run" } } diff --git a/examples/unit-testing__application-code/async-methods.js b/examples/unit-testing__application-code/async-methods.js index 84e9cdecf..ccaa4badb 100644 --- a/examples/unit-testing__application-code/async-methods.js +++ b/examples/unit-testing__application-code/async-methods.js @@ -27,5 +27,6 @@ export const reverseString = (s) => { */ export const twice = async (s) => { await delay(500) + return s + s } diff --git a/examples/unit-testing__application-code/cypress/integration/async-tests.js b/examples/unit-testing__application-code/cypress/integration/async-tests.js index 08a517f6a..59564e78a 100644 --- a/examples/unit-testing__application-code/cypress/integration/async-tests.js +++ b/examples/unit-testing__application-code/cypress/integration/async-tests.js @@ -1,6 +1,6 @@ /// <reference types="cypress" /> -import {reverseString, twice} from '../../async-methods' +import { reverseString, twice } from '../../async-methods' describe('Async reverse', () => { it('reverses a string', () => { @@ -8,7 +8,7 @@ describe('Async reverse', () => { // to let the test runner know when the test has finished // otherwise the test will finish, but then the assertion will suddenly // run - and even if the assertion fails, the test has completed already - return reverseString('foo').then(result => { + return reverseString('foo').then((result) => { expect(result).to.equal('oof') }) }) @@ -17,6 +17,7 @@ describe('Async reverse', () => { // alternatively you can use "async / await" in these unit tests // to deal with promises const result = await reverseString('bar') + expect(result).to.equal('rab') }) @@ -26,18 +27,18 @@ describe('Async reverse', () => { // commands to finish, so you don't need to return a promise // from the test itself cy.fixture('string.txt', 'utf8') - .then(Cypress._.trim) - // if you call your Promise-returning functions - // cy.then automatically waits for the promise to resolve - // https://on.cypress.io/then - .then(reverseString) - .should('equal', 'xof nworb') + .then(Cypress._.trim) + // if you call your Promise-returning functions + // cy.then automatically waits for the promise to resolve + // https://on.cypress.io/then + .then(reverseString) + .should('equal', 'xof nworb') }) }) describe('Async twice', () => { it('doubles numbers', () => { - return twice(2).then(result => expect(result).to.equal(4)) + return twice(2).then((result) => expect(result).to.equal(4)) }) it('repeats a string', () => { @@ -45,7 +46,7 @@ describe('Async twice', () => { // and will wait for all commands in the chain to finish // before the test finishes cy.wrap('fox') - .then(twice).then(twice) - .should('equal', 'foxfoxfoxfox') + .then(twice).then(twice) + .should('equal', 'foxfoxfoxfox') }) }) diff --git a/examples/unit-testing__application-code/cypress/integration/unit_test_application_code_spec.js b/examples/unit-testing__application-code/cypress/integration/unit_test_application_code_spec.js index 5ee8ebcdf..f9b164b2a 100644 --- a/examples/unit-testing__application-code/cypress/integration/unit_test_application_code_spec.js +++ b/examples/unit-testing__application-code/cypress/integration/unit_test_application_code_spec.js @@ -26,7 +26,7 @@ describe('Unit Test Application Code', function () { function numsExpectedToEq (arr, expected) { // loop through the array of nums and make // sure they equal what is expected - arr.forEach(num => { + arr.forEach((num) => { expect(fizzbuzz(num)).to.eq(expected) }) } diff --git a/examples/unit-testing__application-code/cypress/integration/wait-for-object-property-spec.js b/examples/unit-testing__application-code/cypress/integration/wait-for-object-property-spec.js index fda523cb4..8d1a5b21f 100644 --- a/examples/unit-testing__application-code/cypress/integration/wait-for-object-property-spec.js +++ b/examples/unit-testing__application-code/cypress/integration/wait-for-object-property-spec.js @@ -34,6 +34,7 @@ context('waiting for a property of an object', () => { it('waits for added property value', () => { const o = {} + setTimeout(() => { o.foo = 42 }, 100) @@ -48,6 +49,7 @@ context('waiting for a property of an object', () => { it('waits for added property using .its', () => { const o = {} + setTimeout(() => { o.foo = 42 }, 100) @@ -62,6 +64,7 @@ context('waiting for a property of an object', () => { const o = { foo: 42, } + setTimeout(() => { delete o.foo }, 100) @@ -76,6 +79,7 @@ context('waiting for a property of an object', () => { it('waits for added property value using .its', () => { const o = {} + setTimeout(() => { o.foo = 42 }, 100) @@ -88,6 +92,7 @@ context('waiting for a property of an object', () => { it('waits for added nested property value', () => { const o = {} + setTimeout(() => { o.foo = { bar: { @@ -111,6 +116,7 @@ context('waiting for a property of an object', () => { }, }, } + setTimeout(() => { delete o.foo.bar.baz }, 100) diff --git a/examples/unit-testing__application-code/fizzbuzz.js b/examples/unit-testing__application-code/fizzbuzz.js index 8a1528d78..0d98e2163 100644 --- a/examples/unit-testing__application-code/fizzbuzz.js +++ b/examples/unit-testing__application-code/fizzbuzz.js @@ -1,13 +1,13 @@ module.exports = (num) => { if (num % 3 === 0 && num % 5 === 0) { - return "fizzbuzz" + return 'fizzbuzz' } if (num % 3 === 0) { - return "fizz" + return 'fizz' } if (num % 5 === 0) { - return "buzz" + return 'buzz' } -} \ No newline at end of file +} diff --git a/examples/unit-testing__application-code/math.js b/examples/unit-testing__application-code/math.js index 30d95fd79..a6e2dde44 100644 --- a/examples/unit-testing__application-code/math.js +++ b/examples/unit-testing__application-code/math.js @@ -13,5 +13,5 @@ export default { multiply: (a, b) => { return a * b - } -} \ No newline at end of file + }, +} diff --git a/examples/unit-testing__application-code/package.json b/examples/unit-testing__application-code/package.json index 1763adb6d..e091217c8 100644 --- a/examples/unit-testing__application-code/package.json +++ b/examples/unit-testing__application-code/package.json @@ -3,11 +3,11 @@ "version": "1.0.0", "description": "Load and unit test application code without loading a web page", "scripts": { - "start": "echo there is no web server to start in this project", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", + "start": "echo there is no web server to start in this project", "test:ci": "npm run cypress:run", - "test:ci:windows": "bin-up cypress run", - "test:ci:firefox": "npm run cypress:run -- --browser firefox" + "test:ci:firefox": "npm run cypress:run -- --browser firefox", + "test:ci:windows": "bin-up cypress run" } } diff --git a/examples/unit-testing__react/.eslintrc.json b/examples/unit-testing__react/.eslintrc.json index 0c9d055eb..9f23036f7 100644 --- a/examples/unit-testing__react/.eslintrc.json +++ b/examples/unit-testing__react/.eslintrc.json @@ -5,5 +5,10 @@ "extends": [ "plugin:@cypress/dev/general", "plugin:@cypress/dev/react" - ] + ], + "settings": { + "react": { + "version": "detect" + } + } } diff --git a/examples/unit-testing__react/package.json b/examples/unit-testing__react/package.json index c55939d26..63ede6e3b 100644 --- a/examples/unit-testing__react/package.json +++ b/examples/unit-testing__react/package.json @@ -3,11 +3,11 @@ "version": "1.0.0", "description": "Unit testing React code using Enzyme, react-testing-library and cypress-react-unit-test", "scripts": { - "start": "echo nothing to start, unit testing example", - "cypress:run": "../../node_modules/.bin/cypress run", "cypress:open": "../../node_modules/.bin/cypress open", + "cypress:run": "../../node_modules/.bin/cypress run", + "start": "echo nothing to start, unit testing example", "test:ci": "npm run cypress:run", - "test:ci:windows": "bin-up cypress run", - "test:ci:firefox": "npm run cypress:run -- --browser firefox" + "test:ci:firefox": "npm run cypress:run -- --browser firefox", + "test:ci:windows": "bin-up cypress run" } } diff --git a/package.json b/package.json index 02d969950..780525504 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,9 @@ "test:ci:windows": "node ./test-examples --windows", "test:ci:chrome": "node ./test-examples --chrome", "test:ci:brave": "node ./test-examples --brave", - "test:ci:firefox": "node ./test-examples --firefox" + "test:ci:firefox": "node ./test-examples --firefox", + "lint": "eslint examples", + "lint:json": "eslint --ext .json examples" }, "repository": { "type": "git",