From 31bace2977a6489580d45e16dd0fe5a3ffa3ec87 Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Sun, 29 Apr 2018 20:49:27 +0100 Subject: [PATCH] tests: add cypress for integration tests --- .gitignore | 5 + crossbow.yaml | 40 +- cypress.json | 3 + cypress/configs/css-console-notify.js | 12 + cypress/configs/css-overlay-notify.js | 9 + cypress/configs/file-reloading.js | 10 + cypress/configs/logPrefix.js | 10 + cypress/configs/no-notify.js | 9 + cypress/fixtures/example.json | 5 + cypress/fixtures/profile.json | 5 + cypress/fixtures/users.json | 232 +++ cypress/integration.backup/example_spec.js | 1497 ++++++++++++++++++++ cypress/integration/connection-notify.js | 12 + cypress/integration/css-console-notify.js | 26 + cypress/integration/css-overlay-notify.js | 13 + cypress/integration/file-reloading.js | 90 ++ cypress/integration/logPrefix.js | 22 + cypress/integration/no-notify.js | 14 + cypress/plugins/index.js | 17 + cypress/setup/bs.js | 20 + cypress/setup/run.js | 5 + cypress/support/commands.js | 25 + cypress/support/index.js | 20 + package.json | 6 +- yarn.lock | 611 +++++++- 25 files changed, 2690 insertions(+), 28 deletions(-) create mode 100644 cypress.json create mode 100644 cypress/configs/css-console-notify.js create mode 100644 cypress/configs/css-overlay-notify.js create mode 100644 cypress/configs/file-reloading.js create mode 100644 cypress/configs/logPrefix.js create mode 100644 cypress/configs/no-notify.js create mode 100644 cypress/fixtures/example.json create mode 100644 cypress/fixtures/profile.json create mode 100644 cypress/fixtures/users.json create mode 100644 cypress/integration.backup/example_spec.js create mode 100644 cypress/integration/connection-notify.js create mode 100644 cypress/integration/css-console-notify.js create mode 100644 cypress/integration/css-overlay-notify.js create mode 100644 cypress/integration/file-reloading.js create mode 100644 cypress/integration/logPrefix.js create mode 100644 cypress/integration/no-notify.js create mode 100644 cypress/plugins/index.js create mode 100644 cypress/setup/bs.js create mode 100644 cypress/setup/run.js create mode 100644 cypress/support/commands.js create mode 100644 cypress/support/index.js diff --git a/.gitignore b/.gitignore index 372f473cc..bafcc9f6a 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,8 @@ after.json bs-config.js /lodash.custom.min.js /dist +/cypress/videos +client/dist/index.js +client/dist/index.js.map +client/dist/index.min.js +client/dist/index.min.js.map \ No newline at end of file diff --git a/crossbow.yaml b/crossbow.yaml index ef5aba130..cebb309fd 100644 --- a/crossbow.yaml +++ b/crossbow.yaml @@ -1,5 +1,8 @@ tasks: + dev: + - '@npm cd client && ./node_modules/.bin/webpack --watch' + (example): bootstrap: '@sh node dist/bin test/fixtures/bootstrap -w --no-open' @@ -8,10 +11,41 @@ tasks: - build-server - build-client + test: + - build-all + - cypress:* + + (cypress): + file-reloading: > + @npm node cypress/setup/run.js + '../configs/file-reloading.js' + cypress/integration/file-reloading.js + no-notify: > + @npm node cypress/setup/run.js + '../configs/no-notify.js' + cypress/integration/no-notify.js + css-overlay: > + @npm node cypress/setup/run.js + '../configs/css-overlay-notify.js' + cypress/integration/css-overlay-notify.js + css-console-notify: > + @npm node cypress/setup/run.js + '../configs/css-console-notify.js' + cypress/integration/css-console-notify.js + connection-notify: > + @npm node cypress/setup/run.js + '../configs/file-reloading.js' + cypress/integration/connection-notify.js + log-prefix: > + @npm node cypress/setup/run.js + '../configs/logPrefix.js' + cypress/integration/logPrefix.js + build-server: - '@npm tsc' build-client: + - '@npm cd client && yarn' - '@npm cd client && ./node_modules/.bin/webpack' - '@npm cd client && ./node_modules/.bin/webpack -p --output-filename index.min.js' @@ -21,5 +55,9 @@ tasks: examples/* test/specs/**/* test/specs/*.js - client/lib/**/* + client/lib/* + client/lib/messages/* + client/lib/dom-effects/* + client/lib/effects/* + client/lib/listeners/* --write --tab-width 4 diff --git a/cypress.json b/cypress.json new file mode 100644 index 000000000..2594608b0 --- /dev/null +++ b/cypress.json @@ -0,0 +1,3 @@ +{ + "videoRecording": false +} diff --git a/cypress/configs/css-console-notify.js b/cypress/configs/css-console-notify.js new file mode 100644 index 000000000..a9272db5b --- /dev/null +++ b/cypress/configs/css-console-notify.js @@ -0,0 +1,12 @@ +module.exports = { + server: 'test/fixtures', + open: false, + watch: true, + online: false, + // logLevel: 'silent', + minify: false, + injectNotification: 'console', + ghostMode: { + clicks: false, + } +}; diff --git a/cypress/configs/css-overlay-notify.js b/cypress/configs/css-overlay-notify.js new file mode 100644 index 000000000..46815706c --- /dev/null +++ b/cypress/configs/css-overlay-notify.js @@ -0,0 +1,9 @@ +module.exports = { + server: 'test/fixtures', + open: false, + watch: true, + online: false, + logLevel: 'silent', + minify: false, + injectNotification: 'overlay' +}; diff --git a/cypress/configs/file-reloading.js b/cypress/configs/file-reloading.js new file mode 100644 index 000000000..85a59d5a2 --- /dev/null +++ b/cypress/configs/file-reloading.js @@ -0,0 +1,10 @@ +module.exports = { + server: 'test/fixtures', + open: false, + watch: true, + online: false, + // logLevel: 'silent', + minify: false, + // ghostMode: { scroll: true }, + // injectNotification: 'console' +}; diff --git a/cypress/configs/logPrefix.js b/cypress/configs/logPrefix.js new file mode 100644 index 000000000..3f1578017 --- /dev/null +++ b/cypress/configs/logPrefix.js @@ -0,0 +1,10 @@ +module.exports = { + server: 'test/fixtures', + open: false, + watch: true, + online: false, + logLevel: 'silent', + minify: false, + logPrefix: 'WSK', + injectNotification: 'console', +}; diff --git a/cypress/configs/no-notify.js b/cypress/configs/no-notify.js new file mode 100644 index 000000000..9c0d61015 --- /dev/null +++ b/cypress/configs/no-notify.js @@ -0,0 +1,9 @@ +module.exports = { + server: 'test/fixtures', + open: false, + watch: true, + online: false, + logLevel: 'silent', + minify: false, + notify: false, +}; diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json new file mode 100644 index 000000000..da18d9352 --- /dev/null +++ b/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} \ No newline at end of file diff --git a/cypress/fixtures/profile.json b/cypress/fixtures/profile.json new file mode 100644 index 000000000..b6c355ca5 --- /dev/null +++ b/cypress/fixtures/profile.json @@ -0,0 +1,5 @@ +{ + "id": 8739, + "name": "Jane", + "email": "jane@example.com" +} \ No newline at end of file diff --git a/cypress/fixtures/users.json b/cypress/fixtures/users.json new file mode 100644 index 000000000..79b699aa7 --- /dev/null +++ b/cypress/fixtures/users.json @@ -0,0 +1,232 @@ +[ + { + "id": 1, + "name": "Leanne Graham", + "username": "Bret", + "email": "Sincere@april.biz", + "address": { + "street": "Kulas Light", + "suite": "Apt. 556", + "city": "Gwenborough", + "zipcode": "92998-3874", + "geo": { + "lat": "-37.3159", + "lng": "81.1496" + } + }, + "phone": "1-770-736-8031 x56442", + "website": "hildegard.org", + "company": { + "name": "Romaguera-Crona", + "catchPhrase": "Multi-layered client-server neural-net", + "bs": "harness real-time e-markets" + } + }, + { + "id": 2, + "name": "Ervin Howell", + "username": "Antonette", + "email": "Shanna@melissa.tv", + "address": { + "street": "Victor Plains", + "suite": "Suite 879", + "city": "Wisokyburgh", + "zipcode": "90566-7771", + "geo": { + "lat": "-43.9509", + "lng": "-34.4618" + } + }, + "phone": "010-692-6593 x09125", + "website": "anastasia.net", + "company": { + "name": "Deckow-Crist", + "catchPhrase": "Proactive didactic contingency", + "bs": "synergize scalable supply-chains" + } + }, + { + "id": 3, + "name": "Clementine Bauch", + "username": "Samantha", + "email": "Nathan@yesenia.net", + "address": { + "street": "Douglas Extension", + "suite": "Suite 847", + "city": "McKenziehaven", + "zipcode": "59590-4157", + "geo": { + "lat": "-68.6102", + "lng": "-47.0653" + } + }, + "phone": "1-463-123-4447", + "website": "ramiro.info", + "company": { + "name": "Romaguera-Jacobson", + "catchPhrase": "Face to face bifurcated interface", + "bs": "e-enable strategic applications" + } + }, + { + "id": 4, + "name": "Patricia Lebsack", + "username": "Karianne", + "email": "Julianne.OConner@kory.org", + "address": { + "street": "Hoeger Mall", + "suite": "Apt. 692", + "city": "South Elvis", + "zipcode": "53919-4257", + "geo": { + "lat": "29.4572", + "lng": "-164.2990" + } + }, + "phone": "493-170-9623 x156", + "website": "kale.biz", + "company": { + "name": "Robel-Corkery", + "catchPhrase": "Multi-tiered zero tolerance productivity", + "bs": "transition cutting-edge web services" + } + }, + { + "id": 5, + "name": "Chelsey Dietrich", + "username": "Kamren", + "email": "Lucio_Hettinger@annie.ca", + "address": { + "street": "Skiles Walks", + "suite": "Suite 351", + "city": "Roscoeview", + "zipcode": "33263", + "geo": { + "lat": "-31.8129", + "lng": "62.5342" + } + }, + "phone": "(254)954-1289", + "website": "demarco.info", + "company": { + "name": "Keebler LLC", + "catchPhrase": "User-centric fault-tolerant solution", + "bs": "revolutionize end-to-end systems" + } + }, + { + "id": 6, + "name": "Mrs. Dennis Schulist", + "username": "Leopoldo_Corkery", + "email": "Karley_Dach@jasper.info", + "address": { + "street": "Norberto Crossing", + "suite": "Apt. 950", + "city": "South Christy", + "zipcode": "23505-1337", + "geo": { + "lat": "-71.4197", + "lng": "71.7478" + } + }, + "phone": "1-477-935-8478 x6430", + "website": "ola.org", + "company": { + "name": "Considine-Lockman", + "catchPhrase": "Synchronised bottom-line interface", + "bs": "e-enable innovative applications" + } + }, + { + "id": 7, + "name": "Kurtis Weissnat", + "username": "Elwyn.Skiles", + "email": "Telly.Hoeger@billy.biz", + "address": { + "street": "Rex Trail", + "suite": "Suite 280", + "city": "Howemouth", + "zipcode": "58804-1099", + "geo": { + "lat": "24.8918", + "lng": "21.8984" + } + }, + "phone": "210.067.6132", + "website": "elvis.io", + "company": { + "name": "Johns Group", + "catchPhrase": "Configurable multimedia task-force", + "bs": "generate enterprise e-tailers" + } + }, + { + "id": 8, + "name": "Nicholas Runolfsdottir V", + "username": "Maxime_Nienow", + "email": "Sherwood@rosamond.me", + "address": { + "street": "Ellsworth Summit", + "suite": "Suite 729", + "city": "Aliyaview", + "zipcode": "45169", + "geo": { + "lat": "-14.3990", + "lng": "-120.7677" + } + }, + "phone": "586.493.6943 x140", + "website": "jacynthe.com", + "company": { + "name": "Abernathy Group", + "catchPhrase": "Implemented secondary concept", + "bs": "e-enable extensible e-tailers" + } + }, + { + "id": 9, + "name": "Glenna Reichert", + "username": "Delphine", + "email": "Chaim_McDermott@dana.io", + "address": { + "street": "Dayna Park", + "suite": "Suite 449", + "city": "Bartholomebury", + "zipcode": "76495-3109", + "geo": { + "lat": "24.6463", + "lng": "-168.8889" + } + }, + "phone": "(775)976-6794 x41206", + "website": "conrad.com", + "company": { + "name": "Yost and Sons", + "catchPhrase": "Switchable contextually-based project", + "bs": "aggregate real-time technologies" + } + }, + { + "id": 10, + "name": "Clementina DuBuque", + "username": "Moriah.Stanton", + "email": "Rey.Padberg@karina.biz", + "address": { + "street": "Kattie Turnpike", + "suite": "Suite 198", + "city": "Lebsackbury", + "zipcode": "31428-2261", + "geo": { + "lat": "-38.2386", + "lng": "57.2232" + } + }, + "phone": "024-648-3804", + "website": "ambrose.net", + "company": { + "name": "Hoeger LLC", + "catchPhrase": "Centralized empowering task-force", + "bs": "target end-to-end models" + } + } +] \ No newline at end of file diff --git a/cypress/integration.backup/example_spec.js b/cypress/integration.backup/example_spec.js new file mode 100644 index 000000000..562d88dec --- /dev/null +++ b/cypress/integration.backup/example_spec.js @@ -0,0 +1,1497 @@ +// +// **** Kitchen Sink Tests **** +// +// This app was developed to demonstrate +// how to write tests in Cypress utilizing +// all of the available commands +// +// Feel free to modify this spec in your +// own application as a jumping off point + +// Please read our "Introduction to Cypress" +// https://on.cypress.io/introduction-to-cypress + +describe('Kitchen Sink', function () { + it('.should() - assert that is correct', function () { + // https://on.cypress.io/visit + cy.visit('https://example.cypress.io') + + // Here we've made our first assertion using a '.should()' command. + // An assertion is comprised of a chainer, subject, and optional value. + + // https://on.cypress.io/should + // https://on.cypress.io/and + + // https://on.cypress.io/title + cy.title().should('include', 'Kitchen Sink') + // ↲ ↲ ↲ + // subject chainer value + }) + + context('Querying', function () { + beforeEach(function () { + // Visiting our app before each test removes any state build up from + // previous tests. Visiting acts as if we closed a tab and opened a fresh one + cy.visit('https://example.cypress.io/commands/querying') + }) + + // Let's query for some DOM elements and make assertions + // The most commonly used query is 'cy.get()', you can + // think of this like the '$' in jQuery + + it('cy.get() - query DOM elements', function () { + // https://on.cypress.io/get + + // Get DOM elements by id + cy.get('#query-btn').should('contain', 'Button') + + // Get DOM elements by class + cy.get('.query-btn').should('contain', 'Button') + + cy.get('#querying .well>button:first').should('contain', 'Button') + // ↲ + // Use CSS selectors just like jQuery + }) + + it('cy.contains() - query DOM elements with matching content', function () { + // https://on.cypress.io/contains + cy.get('.query-list') + .contains('bananas').should('have.class', 'third') + + // we can pass a regexp to `.contains()` + cy.get('.query-list') + .contains(/^b\w+/).should('have.class', 'third') + + cy.get('.query-list') + .contains('apples').should('have.class', 'first') + + // passing a selector to contains will yield the selector containing the text + cy.get('#querying') + .contains('ul', 'oranges').should('have.class', 'query-list') + + // `.contains()` will favor input[type='submit'], + // button, a, and label over deeper elements inside them + // this will not yield the <span> inside the button, + // but the <button> itself + cy.get('.query-button') + .contains('Save Form').should('have.class', 'btn') + }) + + it('.within() - query DOM elements within a specific element', function () { + // https://on.cypress.io/within + cy.get('.query-form').within(function () { + cy.get('input:first').should('have.attr', 'placeholder', 'Email') + cy.get('input:last').should('have.attr', 'placeholder', 'Password') + }) + }) + + it('cy.root() - query the root DOM element', function () { + // https://on.cypress.io/root + // By default, root is the document + cy.root().should('match', 'html') + + cy.get('.query-ul').within(function () { + // In this within, the root is now the ul DOM element + cy.root().should('have.class', 'query-ul') + }) + }) + }) + + context('Traversal', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/traversal') + }) + + // Let's query for some DOM elements and make assertions + + it('.children() - get child DOM elements', function () { + // https://on.cypress.io/children + cy.get('.traversal-breadcrumb').children('.active') + .should('contain', 'Data') + }) + + it('.closest() - get closest ancestor DOM element', function () { + // https://on.cypress.io/closest + cy.get('.traversal-badge').closest('ul') + .should('have.class', 'list-group') + }) + + it('.eq() - get a DOM element at a specific index', function () { + // https://on.cypress.io/eq + cy.get('.traversal-list>li').eq(1).should('contain', 'siamese') + }) + + it('.filter() - get DOM elements that match the selector', function () { + // https://on.cypress.io/filter + cy.get('.traversal-nav>li').filter('.active').should('contain', 'About') + }) + + it('.find() - get descendant DOM elements of the selector', function () { + // https://on.cypress.io/find + cy.get('.traversal-pagination').find('li').find('a') + .should('have.length', 7) + }) + + it('.first() - get first DOM element', function () { + // https://on.cypress.io/first + cy.get('.traversal-table td').first().should('contain', '1') + }) + + it('.last() - get last DOM element', function () { + // https://on.cypress.io/last + cy.get('.traversal-buttons .btn').last().should('contain', 'Submit') + }) + + it('.next() - get next sibling DOM element', function () { + // https://on.cypress.io/next + cy.get('.traversal-ul').contains('apples').next().should('contain', 'oranges') + }) + + it('.nextAll() - get all next sibling DOM elements', function () { + // https://on.cypress.io/nextall + cy.get('.traversal-next-all').contains('oranges') + .nextAll().should('have.length', 3) + }) + + it('.nextUntil() - get next sibling DOM elements until next el', function () { + // https://on.cypress.io/nextuntil + cy.get('#veggies').nextUntil('#nuts').should('have.length', 3) + }) + + it('.not() - remove DOM elements from set of DOM elements', function () { + // https://on.cypress.io/not + cy.get('.traversal-disabled .btn').not('[disabled]').should('not.contain', 'Disabled') + }) + + it('.parent() - get parent DOM element from DOM elements', function () { + // https://on.cypress.io/parent + cy.get('.traversal-mark').parent().should('contain', 'Morbi leo risus') + }) + + it('.parents() - get parent DOM elements from DOM elements', function () { + // https://on.cypress.io/parents + cy.get('.traversal-cite').parents().should('match', 'blockquote') + }) + + it('.parentsUntil() - get parent DOM elements from DOM elements until el', function () { + // https://on.cypress.io/parentsuntil + cy.get('.clothes-nav').find('.active').parentsUntil('.clothes-nav') + .should('have.length', 2) + }) + + it('.prev() - get previous sibling DOM element', function () { + // https://on.cypress.io/prev + cy.get('.birds').find('.active').prev().should('contain', 'Lorikeets') + }) + + it('.prevAll() - get all previous sibling DOM elements', function () { + // https://on.cypress.io/prevAll + cy.get('.fruits-list').find('.third').prevAll().should('have.length', 2) + }) + + it('.prevUntil() - get all previous sibling DOM elements until el', function () { + // https://on.cypress.io/prevUntil + cy.get('.foods-list').find('#nuts').prevUntil('#veggies') + }) + + it('.siblings() - get all sibling DOM elements', function () { + // https://on.cypress.io/siblings + cy.get('.traversal-pills .active').siblings().should('have.length', 2) + }) + }) + + context('Actions', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/actions') + }) + + // Let's perform some actions on DOM elements + // https://on.cypress.io/interacting-with-elements + + it('.type() - type into a DOM element', function () { + // https://on.cypress.io/type + cy.get('.action-email') + .type('fake@email.com').should('have.value', 'fake@email.com') + + // .type() with special character sequences + .type('{leftarrow}{rightarrow}{uparrow}{downarrow}') + .type('{del}{selectall}{backspace}') + + // .type() with key modifiers + .type('{alt}{option}') //these are equivalent + .type('{ctrl}{control}') //these are equivalent + .type('{meta}{command}{cmd}') //these are equivalent + .type('{shift}') + + // Delay each keypress by 0.1 sec + .type('slow.typing@email.com', { delay: 100 }) + .should('have.value', 'slow.typing@email.com') + + cy.get('.action-disabled') + // Ignore error checking prior to type + // like whether the input is visible or disabled + .type('disabled error checking', { force: true }) + .should('have.value', 'disabled error checking') + }) + + it('.focus() - focus on a DOM element', function () { + // https://on.cypress.io/focus + cy.get('.action-focus').focus() + .should('have.class', 'focus') + .prev().should('have.attr', 'style', 'color: orange;') + }) + + it('.blur() - blur off a DOM element', function () { + // https://on.cypress.io/blur + cy.get('.action-blur').type('I\'m about to blur').blur() + .should('have.class', 'error') + .prev().should('have.attr', 'style', 'color: red;') + }) + + it('.clear() - clears an input or textarea element', function () { + // https://on.cypress.io/clear + cy.get('.action-clear').type('We are going to clear this text') + .should('have.value', 'We are going to clear this text') + .clear() + .should('have.value', '') + }) + + it('.submit() - submit a form', function () { + // https://on.cypress.io/submit + cy.get('.action-form') + .find('[type="text"]').type('HALFOFF') + cy.get('.action-form').submit() + .next().should('contain', 'Your form has been submitted!') + }) + + it('.click() - click on a DOM element', function () { + // https://on.cypress.io/click + cy.get('.action-btn').click() + + // You can click on 9 specific positions of an element: + // ----------------------------------- + // | topLeft top topRight | + // | | + // | | + // | | + // | left center right | + // | | + // | | + // | | + // | bottomLeft bottom bottomRight | + // ----------------------------------- + + // clicking in the center of the element is the default + cy.get('#action-canvas').click() + + cy.get('#action-canvas').click('topLeft') + cy.get('#action-canvas').click('top') + cy.get('#action-canvas').click('topRight') + cy.get('#action-canvas').click('left') + cy.get('#action-canvas').click('right') + cy.get('#action-canvas').click('bottomLeft') + cy.get('#action-canvas').click('bottom') + cy.get('#action-canvas').click('bottomRight') + + // .click() accepts an x and y coordinate + // that controls where the click occurs :) + + cy.get('#action-canvas') + .click(80, 75) // click 80px on x coord and 75px on y coord + .click(170, 75) + .click(80, 165) + .click(100, 185) + .click(125, 190) + .click(150, 185) + .click(170, 165) + + // click multiple elements by passing multiple: true + cy.get('.action-labels>.label').click({ multiple: true }) + + // Ignore error checking prior to clicking + // like whether the element is visible, clickable or disabled + // this button below is covered by another element. + cy.get('.action-opacity>.btn').click({ force: true }) + }) + + it('.dblclick() - double click on a DOM element', function () { + // Our app has a listener on 'dblclick' event in our 'scripts.js' + // that hides the div and shows an input on double click + + // https://on.cypress.io/dblclick + cy.get('.action-div').dblclick().should('not.be.visible') + cy.get('.action-input-hidden').should('be.visible') + }) + + it('cy.check() - check a checkbox or radio element', function () { + // By default, .check() will check all + // matching checkbox or radio elements in succession, one after another + + // https://on.cypress.io/check + cy.get('.action-checkboxes [type="checkbox"]').not('[disabled]') + .check().should('be.checked') + + cy.get('.action-radios [type="radio"]').not('[disabled]') + .check().should('be.checked') + + // .check() accepts a value argument + // that checks only checkboxes or radios + // with matching values + cy.get('.action-radios [type="radio"]').check('radio1').should('be.checked') + + // .check() accepts an array of values + // that checks only checkboxes or radios + // with matching values + cy.get('.action-multiple-checkboxes [type="checkbox"]') + .check(['checkbox1', 'checkbox2']).should('be.checked') + + // Ignore error checking prior to checking + // like whether the element is visible, clickable or disabled + // this checkbox below is disabled. + cy.get('.action-checkboxes [disabled]') + .check({ force: true }).should('be.checked') + + cy.get('.action-radios [type="radio"]') + .check('radio3', { force: true }).should('be.checked') + }) + + it('.uncheck() - uncheck a checkbox element', function () { + // By default, .uncheck() will uncheck all matching + // checkbox elements in succession, one after another + + // https://on.cypress.io/uncheck + cy.get('.action-check [type="checkbox"]') + .not('[disabled]') + .uncheck().should('not.be.checked') + + // .uncheck() accepts a value argument + // that unchecks only checkboxes + // with matching values + cy.get('.action-check [type="checkbox"]') + .check('checkbox1') + .uncheck('checkbox1').should('not.be.checked') + + // .uncheck() accepts an array of values + // that unchecks only checkboxes or radios + // with matching values + cy.get('.action-check [type="checkbox"]') + .check(['checkbox1', 'checkbox3']) + .uncheck(['checkbox1', 'checkbox3']).should('not.be.checked') + + // Ignore error checking prior to unchecking + // like whether the element is visible, clickable or disabled + // this checkbox below is disabled. + cy.get('.action-check [disabled]') + .uncheck({ force: true }).should('not.be.checked') + }) + + it('.select() - select an option in a <select> element', function () { + // https://on.cypress.io/select + + // Select option with matching text content + cy.get('.action-select').select('apples') + + // Select option with matching value + cy.get('.action-select').select('fr-bananas') + + // Select options with matching text content + cy.get('.action-select-multiple') + .select(['apples', 'oranges', 'bananas']) + + // Select options with matching values + cy.get('.action-select-multiple') + .select(['fr-apples', 'fr-oranges', 'fr-bananas']) + }) + + it('.scrollIntoView() - scroll an element into view', function () { + // https://on.cypress.io/scrollintoview + + // normally all of these buttons are hidden, because they're not within + // the viewable area of their parent (we need to scroll to see them) + cy.get('#scroll-horizontal button') + .should('not.be.visible') + + // scroll the button into view, as if the user had scrolled + cy.get('#scroll-horizontal button').scrollIntoView() + .should('be.visible') + + cy.get('#scroll-vertical button') + .should('not.be.visible') + + // Cypress handles the scroll direction needed + cy.get('#scroll-vertical button').scrollIntoView() + .should('be.visible') + + cy.get('#scroll-both button') + .should('not.be.visible') + + // Cypress knows to scroll to the right and down + cy.get('#scroll-both button').scrollIntoView() + .should('be.visible') + }) + + it('cy.scrollTo() - scroll the window or element to a position', function () { + + // https://on.cypress.io/scrollTo + + // You can scroll to 9 specific positions of an element: + // ----------------------------------- + // | topLeft top topRight | + // | | + // | | + // | | + // | left center right | + // | | + // | | + // | | + // | bottomLeft bottom bottomRight | + // ----------------------------------- + + // if you chain .scrollTo() off of cy, we will + // scroll the entire window + cy.scrollTo('bottom') + + cy.get('#scrollable-horizontal').scrollTo('right') + + // or you can scroll to a specific coordinate: + // (x axis, y axis) in pixels + cy.get('#scrollable-vertical').scrollTo(250, 250) + + // or you can scroll to a specific percentage + // of the (width, height) of the element + cy.get('#scrollable-both').scrollTo('75%', '25%') + + // control the easing of the scroll (default is 'swing') + cy.get('#scrollable-vertical').scrollTo('center', { easing: 'linear' }) + + // control the duration of the scroll (in ms) + cy.get('#scrollable-both').scrollTo('center', { duration: 2000 }) + }) + + it('.trigger() - trigger an event on a DOM element', 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 + + // Here, we invoke jQuery's val() method to set the value + // and trigger the 'change' event + + // Note that some implementations may rely on the 'input' event, + // which is fired as a user moves the slider, but is not supported + // by some browsers + + // https://on.cypress.io/trigger + cy.get('.trigger-input-range') + .invoke('val', 25) + .trigger('change') + .get('input[type=range]').siblings('p') + .should('have.text', '25') + + // See our example recipes for more examples of using trigger + // https://on.cypress.io/examples + }) + }) + + context('Window', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/window') + }) + + it('cy.window() - get the global window object', function () { + // https://on.cypress.io/window + cy.window().should('have.property', 'top') + }) + + it('cy.document() - get the document object', function () { + // https://on.cypress.io/document + cy.document().should('have.property', 'charset').and('eq', 'UTF-8') + }) + + it('cy.title() - get the title', function () { + // https://on.cypress.io/title + cy.title().should('include', 'Kitchen Sink') + }) + }) + + context('Viewport', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/viewport') + }) + + it('cy.viewport() - set the viewport size and dimension', function () { + + cy.get('#navbar').should('be.visible') + + // https://on.cypress.io/viewport + cy.viewport(320, 480) + + // the navbar should have collapse since our screen is smaller + cy.get('#navbar').should('not.be.visible') + cy.get('.navbar-toggle').should('be.visible').click() + cy.get('.nav').find('a').should('be.visible') + + // lets see what our app looks like on a super large screen + cy.viewport(2999, 2999) + + // cy.viewport() accepts a set of preset sizes + // to easily set the screen to a device's width and height + + // We added a cy.wait() between each viewport change so you can see + // the change otherwise it's a little too fast to see :) + + cy.viewport('macbook-15') + cy.wait(200) + cy.viewport('macbook-13') + cy.wait(200) + cy.viewport('macbook-11') + cy.wait(200) + cy.viewport('ipad-2') + cy.wait(200) + cy.viewport('ipad-mini') + cy.wait(200) + cy.viewport('iphone-6+') + cy.wait(200) + cy.viewport('iphone-6') + cy.wait(200) + cy.viewport('iphone-5') + cy.wait(200) + cy.viewport('iphone-4') + cy.wait(200) + cy.viewport('iphone-3') + cy.wait(200) + + // cy.viewport() accepts an orientation for all presets + // the default orientation is 'portrait' + cy.viewport('ipad-2', 'portrait') + cy.wait(200) + cy.viewport('iphone-4', 'landscape') + cy.wait(200) + + // The viewport will be reset back to the default dimensions + // in between tests (the default is set in cypress.json) + }) + }) + + context('Location', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/location') + }) + + // We look at the url to make assertions + // about the page's state + + it('cy.hash() - get the current URL hash', function () { + // https://on.cypress.io/hash + cy.hash().should('be.empty') + }) + + it('cy.location() - get window.location', function () { + // https://on.cypress.io/location + cy.location().should(function (location) { + expect(location.hash).to.be.empty + expect(location.href).to.eq('https://example.cypress.io/commands/location') + expect(location.host).to.eq('example.cypress.io') + expect(location.hostname).to.eq('example.cypress.io') + expect(location.origin).to.eq('https://example.cypress.io') + expect(location.pathname).to.eq('/commands/location') + expect(location.port).to.eq('') + expect(location.protocol).to.eq('https:') + expect(location.search).to.be.empty + }) + }) + + it('cy.url() - get the current URL', function () { + // https://on.cypress.io/url + cy.url().should('eq', 'https://example.cypress.io/commands/location') + }) + }) + + context('Navigation', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io') + cy.get('.navbar-nav').contains('Commands').click() + cy.get('.dropdown-menu').contains('Navigation').click() + }) + + it('cy.go() - go back or forward in the browser\'s history', function () { + cy.location('pathname').should('include', 'navigation') + + // https://on.cypress.io/go + cy.go('back') + cy.location('pathname').should('not.include', 'navigation') + + cy.go('forward') + cy.location('pathname').should('include', 'navigation') + + // equivalent to clicking back + cy.go(-1) + cy.location('pathname').should('not.include', 'navigation') + + // equivalent to clicking forward + cy.go(1) + cy.location('pathname').should('include', 'navigation') + }) + + it('cy.reload() - reload the page', function () { + // https://on.cypress.io/reload + cy.reload() + + // reload the page without using the cache + cy.reload(true) + }) + + it('cy.visit() - visit a remote url', function () { + // Visit any sub-domain of your current domain + // https://on.cypress.io/visit + + // Pass options to the visit + cy.visit('https://example.cypress.io/commands/navigation', { + timeout: 50000, // increase total time for the visit to resolve + onBeforeLoad (contentWindow) { + // contentWindow is the remote page's window object + }, + onLoad (contentWindow) { + // contentWindow is the remote page's window object + }, + }) + }) + }) + + context('Assertions', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/assertions') + }) + + describe('Implicit Assertions', function () { + + it('.should() - make an assertion about the current subject', function () { + // https://on.cypress.io/should + cy.get('.assertion-table') + .find('tbody tr:last').should('have.class', 'success') + }) + + it('.and() - chain multiple assertions together', function () { + // https://on.cypress.io/and + cy.get('.assertions-link') + .should('have.class', 'active') + .and('have.attr', 'href') + .and('include', 'cypress.io') + }) + }) + + describe('Explicit Assertions', function () { + // https://on.cypress.io/assertions + it('expect - assert shape of an object', function () { + const person = { + name: 'Joe', + age: 20, + } + expect(person).to.have.all.keys('name', 'age') + }) + + it('expect - make an assertion about a specified subject', function () { + // We can use Chai's BDD style assertions + expect(true).to.be.true + + // Pass a function to should that can have any number + // of explicit assertions within it. + cy.get('.assertions-p').find('p') + .should(function ($p) { + // return an array of texts from all of the p's + let texts = $p.map(function (i, el) { + // https://on.cypress.io/$ + return Cypress.$(el).text() + }) + + // jquery map returns jquery object + // and .get() convert this to simple array + texts = texts.get() + + // array should have length of 3 + expect(texts).to.have.length(3) + + // set this specific subject + expect(texts).to.deep.eq([ + 'Some text from first p', + 'More text from second p', + 'And even more text from third p', + ]) + }) + }) + }) + }) + + context('Misc', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/misc') + }) + + it('.end() - end the command chain', function () { + // cy.end is useful when you want to end a chain of commands + // and force Cypress to re-query from the root element + + // https://on.cypress.io/end + cy.get('.misc-table').within(function () { + // ends the current chain and yields null + cy.contains('Cheryl').click().end() + + // queries the entire table again + cy.contains('Charles').click() + }) + }) + + it('cy.exec() - execute a system command', function () { + // cy.exec allows you to execute a system command. + // so you can take actions necessary for your test, + // but outside the scope of Cypress. + + // https://on.cypress.io/exec + cy.exec('echo Jane Lane') + .its('stdout').should('contain', 'Jane Lane') + + // we can use Cypress.platform string to + // select appropriate command + // https://on.cypress/io/platform + cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`) + + if (Cypress.platform === 'win32') { + cy.exec('print cypress.json') + .its('stderr').should('be.empty') + } else { + cy.exec('cat cypress.json') + .its('stderr').should('be.empty') + + cy.exec('pwd') + .its('code').should('eq', 0) + } + }) + + it('cy.focused() - get the DOM element that has focus', function () { + // https://on.cypress.io/focused + cy.get('.misc-form').find('#name').click() + cy.focused().should('have.id', 'name') + + cy.get('.misc-form').find('#description').click() + cy.focused().should('have.id', 'description') + }) + + it('cy.screenshot() - take a screenshot', function () { + // https://on.cypress.io/screenshot + cy.screenshot('my-image') + }) + + it('cy.wrap() - wrap an object', function () { + // https://on.cypress.io/wrap + cy.wrap({ foo: 'bar' }) + .should('have.property', 'foo') + .and('include', 'bar') + }) + }) + + context('Connectors', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/connectors') + }) + + it('.each() - iterate over an array of elements', function () { + // https://on.cypress.io/each + cy.get('.connectors-each-ul>li') + .each(function ($el, index, $list) { + console.log($el, index, $list) + }) + }) + + it('.its() - get properties on the current subject', function () { + // https://on.cypress.io/its + cy.get('.connectors-its-ul>li') + // calls the 'length' property yielding that value + .its('length') + .should('be.gt', 2) + }) + + it('.invoke() - invoke a function on the current subject', function () { + // our div is hidden in our script.js + // $('.connectors-div').hide() + + // https://on.cypress.io/invoke + cy.get('.connectors-div').should('be.hidden') + + // call the jquery method 'show' on the 'div.container' + .invoke('show') + .should('be.visible') + }) + + it('.spread() - spread an array as individual args to callback function', function () { + // https://on.cypress.io/spread + let arr = ['foo', 'bar', 'baz'] + + cy.wrap(arr).spread(function (foo, bar, baz) { + expect(foo).to.eq('foo') + expect(bar).to.eq('bar') + expect(baz).to.eq('baz') + }) + }) + + it('.then() - invoke a callback function with the current subject', function () { + // https://on.cypress.io/then + cy.get('.connectors-list>li').then(function ($lis) { + expect($lis).to.have.length(3) + expect($lis.eq(0)).to.contain('Walk the dog') + expect($lis.eq(1)).to.contain('Feed the cat') + expect($lis.eq(2)).to.contain('Write JavaScript') + }) + }) + }) + + context('Aliasing', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/aliasing') + }) + + // We alias a DOM element for use later + // We don't have to traverse to the element + // later in our code, we just reference it with @ + + it('.as() - alias a route or DOM element for later use', function () { + // this is a good use case for an alias, + // we don't want to write this long traversal again + + // https://on.cypress.io/as + cy.get('.as-table').find('tbody>tr') + .first().find('td').first().find('button').as('firstBtn') + + // maybe do some more testing here... + + // when we reference the alias, we place an + // @ in front of it's name + cy.get('@firstBtn').click() + + cy.get('@firstBtn') + .should('have.class', 'btn-success') + .and('contain', 'Changed') + }) + }) + + context('Waiting', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/waiting') + }) + // BE CAREFUL of adding unnecessary wait times. + + // https://on.cypress.io/wait + it('cy.wait() - wait for a specific amount of time', function () { + cy.get('.wait-input1').type('Wait 1000ms after typing') + cy.wait(1000) + cy.get('.wait-input2').type('Wait 1000ms after typing') + cy.wait(1000) + cy.get('.wait-input3').type('Wait 1000ms after typing') + cy.wait(1000) + }) + + // Waiting for a specific resource to resolve + // is covered within the cy.route() test below + }) + + context('Network Requests', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/network-requests') + }) + + // Manage AJAX / XHR requests in your app + + it('cy.server() - control behavior of network requests and responses', function () { + // https://on.cypress.io/server + cy.server().should(function (server) { + // the default options on server + // you can override any of these options + expect(server.delay).to.eq(0) + expect(server.method).to.eq('GET') + expect(server.status).to.eq(200) + expect(server.headers).to.be.null + expect(server.response).to.be.null + expect(server.onRequest).to.be.undefined + expect(server.onResponse).to.be.undefined + expect(server.onAbort).to.be.undefined + + // These options control the server behavior + // affecting all requests + + // pass false to disable existing route stubs + expect(server.enable).to.be.true + // forces requests that don't match your routes to 404 + expect(server.force404).to.be.false + // whitelists requests from ever being logged or stubbed + expect(server.whitelist).to.be.a('function') + }) + + cy.server({ + method: 'POST', + delay: 1000, + status: 422, + response: {}, + }) + + // any route commands will now inherit the above options + // from the server. anything we pass specifically + // to route will override the defaults though. + }) + + it('cy.request() - make an XHR request', function () { + // https://on.cypress.io/request + cy.request('https://jsonplaceholder.typicode.com/comments') + .should(function (response) { + expect(response.status).to.eq(200) + expect(response.body).to.have.length(500) + expect(response).to.have.property('headers') + expect(response).to.have.property('duration') + }) + }) + + it('cy.route() - route responses to matching requests', function () { + let message = 'whoa, this comment doesn\'t exist' + cy.server() + + // **** GET comments route **** + + // https://on.cypress.io/route + cy.route(/comments\/1/).as('getComment') + + // we have code that fetches a comment when + // the button is clicked in scripts.js + cy.get('.network-btn').click() + + // **** Wait **** + + // Wait for a specific resource to resolve + // continuing to the next command + + // https://on.cypress.io/wait + cy.wait('@getComment').its('status').should('eq', 200) + + // **** POST comment route **** + + // Specify the route to listen to method 'POST' + cy.route('POST', '/comments').as('postComment') + + // we have code that posts a comment when + // the button is clicked in scripts.js + cy.get('.network-post').click() + cy.wait('@postComment') + + // get the route + cy.get('@postComment').then(function (xhr) { + expect(xhr.requestBody).to.include('email') + expect(xhr.requestHeaders).to.have.property('Content-Type') + expect(xhr.responseBody).to.have.property('name', 'Using POST in cy.route()') + }) + + // **** Stubbed PUT comment route **** + cy.route({ + method: 'PUT', + url: /comments\/\d+/, + status: 404, + response: { error: message }, + delay: 500, + }).as('putComment') + + // we have code that puts a comment when + // the button is clicked in scripts.js + cy.get('.network-put').click() + + cy.wait('@putComment') + + // our 404 statusCode logic in scripts.js executed + cy.get('.network-put-comment').should('contain', message) + }) + }) + + context('Files', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/files') + }) + it('cy.fixture() - load a fixture', function () { + // Instead of writing a response inline you can + // connect a response with a fixture file + // located in fixtures folder. + + cy.server() + + // https://on.cypress.io/fixture + cy.fixture('example.json').as('comment') + + cy.route(/comments/, '@comment').as('getComment') + + // we have code that gets a comment when + // the button is clicked in scripts.js + cy.get('.fixture-btn').click() + + cy.wait('@getComment').its('responseBody') + .should('have.property', 'name') + .and('include', 'Using fixtures to represent data') + + // you can also just write the fixture in the route + cy.route(/comments/, 'fixture:example.json').as('getComment') + + // we have code that gets a comment when + // the button is clicked in scripts.js + cy.get('.fixture-btn').click() + + cy.wait('@getComment').its('responseBody') + .should('have.property', 'name') + .and('include', 'Using fixtures to represent data') + + // or write fx to represent fixture + // by default it assumes it's .json + cy.route(/comments/, 'fx:example').as('getComment') + + // we have code that gets a comment when + // the button is clicked in scripts.js + cy.get('.fixture-btn').click() + + cy.wait('@getComment').its('responseBody') + .should('have.property', 'name') + .and('include', 'Using fixtures to represent data') + }) + + it('cy.readFile() - read a files contents', function () { + // You can read a file and yield its contents + // The filePath is relative to your project's root. + + // https://on.cypress.io/readfile + cy.readFile('cypress.json').then(function (json) { + expect(json).to.be.an('object') + }) + + }) + + it('cy.writeFile() - write to a file', function () { + // You can write to a file with the specified contents + + // Use a response from a request to automatically + // generate a fixture file for use later + cy.request('https://jsonplaceholder.typicode.com/users') + .then(function (response) { + // https://on.cypress.io/writefile + cy.writeFile('cypress/fixtures/users.json', response.body) + }) + cy.fixture('users').should(function (users) { + expect(users[0].name).to.exist + }) + + // JavaScript arrays and objects are stringified and formatted into text. + cy.writeFile('cypress/fixtures/profile.json', { + id: 8739, + name: 'Jane', + email: 'jane@example.com', + }) + + cy.fixture('profile').should(function (profile) { + expect(profile.name).to.eq('Jane') + }) + }) + }) + + context('Local Storage', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/commands/local-storage') + }) + // Although local storage is automatically cleared + // to maintain a clean state in between tests + // sometimes we need to clear the local storage manually + + it('cy.clearLocalStorage() - clear all data in local storage', function () { + // https://on.cypress.io/clearlocalstorage + cy.get('.ls-btn').click().should(function () { + expect(localStorage.getItem('prop1')).to.eq('red') + expect(localStorage.getItem('prop2')).to.eq('blue') + expect(localStorage.getItem('prop3')).to.eq('magenta') + }) + + // clearLocalStorage() yields the localStorage object + cy.clearLocalStorage().should(function (ls) { + expect(ls.getItem('prop1')).to.be.null + expect(ls.getItem('prop2')).to.be.null + expect(ls.getItem('prop3')).to.be.null + }) + + // **** Clear key matching string in Local Storage **** + cy.get('.ls-btn').click().should(function () { + expect(localStorage.getItem('prop1')).to.eq('red') + expect(localStorage.getItem('prop2')).to.eq('blue') + expect(localStorage.getItem('prop3')).to.eq('magenta') + }) + + cy.clearLocalStorage('prop1').should(function (ls) { + expect(ls.getItem('prop1')).to.be.null + expect(ls.getItem('prop2')).to.eq('blue') + expect(ls.getItem('prop3')).to.eq('magenta') + }) + + // **** Clear key's matching regex in Local Storage **** + cy.get('.ls-btn').click().should(function () { + expect(localStorage.getItem('prop1')).to.eq('red') + expect(localStorage.getItem('prop2')).to.eq('blue') + expect(localStorage.getItem('prop3')).to.eq('magenta') + }) + + cy.clearLocalStorage(/prop1|2/).should(function (ls) { + expect(ls.getItem('prop1')).to.be.null + expect(ls.getItem('prop2')).to.be.null + expect(ls.getItem('prop3')).to.eq('magenta') + }) + }) + }) + + context('Cookies', function () { + beforeEach(function () { + Cypress.Cookies.debug(true) + + cy.visit('https://example.cypress.io/commands/cookies') + + // clear cookies again after visiting to remove + // any 3rd party cookies picked up such as cloudflare + cy.clearCookies() + }) + + it('cy.getCookie() - get a browser cookie', function () { + // https://on.cypress.io/getcookie + cy.get('#getCookie .set-a-cookie').click() + + // cy.getCookie() yields a cookie object + cy.getCookie('token').should('have.property', 'value', '123ABC') + }) + + it('cy.getCookies() - get browser cookies', function () { + // https://on.cypress.io/getcookies + cy.getCookies().should('be.empty') + + cy.get('#getCookies .set-a-cookie').click() + + // cy.getCookies() yields an array of cookies + cy.getCookies().should('have.length', 1).should(function (cookies) { + + // each cookie has these properties + expect(cookies[0]).to.have.property('name', 'token') + expect(cookies[0]).to.have.property('value', '123ABC') + expect(cookies[0]).to.have.property('httpOnly', false) + expect(cookies[0]).to.have.property('secure', false) + expect(cookies[0]).to.have.property('domain') + expect(cookies[0]).to.have.property('path') + }) + }) + + it('cy.setCookie() - set a browser cookie', function () { + // https://on.cypress.io/setcookie + cy.getCookies().should('be.empty') + + cy.setCookie('foo', 'bar') + + // cy.getCookie() yields a cookie object + cy.getCookie('foo').should('have.property', 'value', 'bar') + }) + + it('cy.clearCookie() - clear a browser cookie', function () { + // https://on.cypress.io/clearcookie + cy.getCookie('token').should('be.null') + + cy.get('#clearCookie .set-a-cookie').click() + + cy.getCookie('token').should('have.property', 'value', '123ABC') + + // cy.clearCookies() yields null + cy.clearCookie('token').should('be.null') + + cy.getCookie('token').should('be.null') + }) + + it('cy.clearCookies() - clear browser cookies', function () { + // https://on.cypress.io/clearcookies + cy.getCookies().should('be.empty') + + cy.get('#clearCookies .set-a-cookie').click() + + cy.getCookies().should('have.length', 1) + + // cy.clearCookies() yields null + cy.clearCookies() + + cy.getCookies().should('be.empty') + }) + }) + + context('Spies, Stubs, and Clock', function () { + it('cy.spy() - wrap a method in a spy', function () { + // https://on.cypress.io/spy + cy.visit('https://example.cypress.io/commands/spies-stubs-clocks') + + let obj = { + foo () {}, + } + + let spy = cy.spy(obj, 'foo').as('anyArgs') + + obj.foo() + + expect(spy).to.be.called + + }) + + it('cy.stub() - create a stub and/or replace a function with a stub', function () { + // https://on.cypress.io/stub + cy.visit('https://example.cypress.io/commands/spies-stubs-clocks') + + let obj = { + foo () {}, + } + + let stub = cy.stub(obj, 'foo').as('foo') + + obj.foo('foo', 'bar') + + expect(stub).to.be.called + + }) + + it('cy.clock() - control time in the browser', function () { + // create the date in UTC so its always the same + // no matter what local timezone the browser is running in + let now = new Date(Date.UTC(2017, 2, 14)).getTime() + + // https://on.cypress.io/clock + cy.clock(now) + cy.visit('https://example.cypress.io/commands/spies-stubs-clocks') + cy.get('#clock-div').click() + .should('have.text', '1489449600') + }) + + it('cy.tick() - move time in the browser', function () { + // create the date in UTC so its always the same + // no matter what local timezone the browser is running in + let now = new Date(Date.UTC(2017, 2, 14)).getTime() + + // https://on.cypress.io/tick + cy.clock(now) + cy.visit('https://example.cypress.io/commands/spies-stubs-clocks') + cy.get('#tick-div').click() + .should('have.text', '1489449600') + cy.tick(10000) // 10 seconds passed + cy.get('#tick-div').click() + .should('have.text', '1489449610') + }) + }) + + context('Utilities', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/utilities') + }) + + it('Cypress._.method() - call a lodash method', function () { + // use the _.chain, _.map, _.take, and _.value functions + // https://on.cypress.io/_ + cy.request('https://jsonplaceholder.typicode.com/users') + .then(function (response) { + let ids = Cypress._.chain(response.body).map('id').take(3).value() + + expect(ids).to.deep.eq([1, 2, 3]) + }) + }) + + it('Cypress.$(selector) - call a jQuery method', function () { + // https://on.cypress.io/$ + let $li = Cypress.$('.utility-jquery li:first') + + cy.wrap($li) + .should('not.have.class', 'active') + .click() + .should('have.class', 'active') + }) + + it('Cypress.moment() - format or parse dates using a moment method', function () { + // use moment's format function + // https://on.cypress.io/cypress-moment + let time = Cypress.moment().utc('2014-04-25T19:38:53.196Z').format('h:mm A') + + cy.get('.utility-moment').contains('3:38 PM') + .should('have.class', 'badge') + }) + + it('Cypress.Blob.method() - blob utilities and base64 string conversion', function () { + cy.get('.utility-blob').then(function ($div) { + // https://on.cypress.io/blob + // https://github.com/nolanlawson/blob-util#imgSrcToDataURL + // get the dataUrl string for the javascript-logo + return Cypress.Blob.imgSrcToDataURL('https://example.cypress.io/assets/img/javascript-logo.png', undefined, 'anonymous') + .then(function (dataUrl) { + // create an <img> element and set its src to the dataUrl + let img = Cypress.$('<img />', { src: dataUrl }) + // need to explicitly return cy here since we are initially returning + // the Cypress.Blob.imgSrcToDataURL promise to our test + // append the image + $div.append(img) + + cy.get('.utility-blob img').click() + .should('have.attr', 'src', dataUrl) + }) + }) + }) + + it('new Cypress.Promise(function) - instantiate a bluebird promise', function () { + // https://on.cypress.io/promise + let waited = false + + function waitOneSecond () { + // return a promise that resolves after 1 second + return new Cypress.Promise(function (resolve, reject) { + setTimeout(function () { + // set waited to true + waited = true + + // resolve with 'foo' string + resolve('foo') + }, 1000) + }) + } + + cy.then(function () { + // return a promise to cy.then() that + // is awaited until it resolves + return waitOneSecond().then(function (str) { + expect(str).to.eq('foo') + expect(waited).to.be.true + }) + }) + }) + }) + + + context('Cypress.config()', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/cypress-api/config') + }) + + it('Cypress.config() - get and set configuration options', function () { + // https://on.cypress.io/config + let myConfig = Cypress.config() + + expect(myConfig).to.have.property('animationDistanceThreshold', 5) + expect(myConfig).to.have.property('baseUrl', null) + expect(myConfig).to.have.property('defaultCommandTimeout', 4000) + expect(myConfig).to.have.property('requestTimeout', 5000) + expect(myConfig).to.have.property('responseTimeout', 30000) + expect(myConfig).to.have.property('viewportHeight', 660) + expect(myConfig).to.have.property('viewportWidth', 1000) + expect(myConfig).to.have.property('pageLoadTimeout', 60000) + expect(myConfig).to.have.property('waitForAnimations', true) + + expect(Cypress.config('pageLoadTimeout')).to.eq(60000) + + // this will change the config for the rest of your tests! + Cypress.config('pageLoadTimeout', 20000) + + expect(Cypress.config('pageLoadTimeout')).to.eq(20000) + + Cypress.config('pageLoadTimeout', 60000) + }) + }) + + context('Cypress.env()', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/cypress-api/env') + }) + + // We can set environment variables for highly dynamic values + + // https://on.cypress.io/environment-variables + it('Cypress.env() - get environment variables', function () { + // https://on.cypress.io/env + // set multiple environment variables + Cypress.env({ + host: 'veronica.dev.local', + api_server: 'http://localhost:8888/v1/', + }) + + // get environment variable + expect(Cypress.env('host')).to.eq('veronica.dev.local') + + // set environment variable + Cypress.env('api_server', 'http://localhost:8888/v2/') + expect(Cypress.env('api_server')).to.eq('http://localhost:8888/v2/') + + // get all environment variable + expect(Cypress.env()).to.have.property('host', 'veronica.dev.local') + expect(Cypress.env()).to.have.property('api_server', 'http://localhost:8888/v2/') + }) + }) + + context('Cypress.Cookies', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/cypress-api/cookies') + }) + + // https://on.cypress.io/cookies + it('Cypress.Cookies.debug() - enable or disable debugging', function () { + Cypress.Cookies.debug(true) + + // Cypress will now log in the console when + // cookies are set or cleared + cy.setCookie('fakeCookie', '123ABC') + cy.clearCookie('fakeCookie') + cy.setCookie('fakeCookie', '123ABC') + cy.clearCookie('fakeCookie') + cy.setCookie('fakeCookie', '123ABC') + }) + + it('Cypress.Cookies.preserveOnce() - preserve cookies by key', function () { + // normally cookies are reset after each test + cy.getCookie('fakeCookie').should('not.be.ok') + + // preserving a cookie will not clear it when + // the next test starts + cy.setCookie('lastCookie', '789XYZ') + Cypress.Cookies.preserveOnce('lastCookie') + }) + + it('Cypress.Cookies.defaults() - set defaults for all cookies', function () { + // now any cookie with the name 'session_id' will + // not be cleared before each new test runs + Cypress.Cookies.defaults({ + whitelist: 'session_id', + }) + }) + }) + + context('Cypress.dom', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/cypress-api/dom') + }) + + // https://on.cypress.io/dom + it('Cypress.dom.isHidden() - determine if a DOM element is hidden', function () { + let hiddenP = Cypress.$('.dom-p p.hidden').get(0) + let visibleP = Cypress.$('.dom-p p.visible').get(0) + + // our first paragraph has css class 'hidden' + expect(Cypress.dom.isHidden(hiddenP)).to.be.true + expect(Cypress.dom.isHidden(visibleP)).to.be.false + }) + }) + + context('Cypress.Server', function () { + beforeEach(function () { + cy.visit('https://example.cypress.io/cypress-api/server') + }) + + // Permanently override server options for + // all instances of cy.server() + + // https://on.cypress.io/cypress-server + it('Cypress.Server.defaults() - change default config of server', function () { + Cypress.Server.defaults({ + delay: 0, + force404: false, + whitelist (xhr) { + // handle custom logic for whitelisting + }, + }) + }) + }) +}) diff --git a/cypress/integration/connection-notify.js b/cypress/integration/connection-notify.js new file mode 100644 index 000000000..ecae0788c --- /dev/null +++ b/cypress/integration/connection-notify.js @@ -0,0 +1,12 @@ +describe('Connection notification', function() { + beforeEach(function() { + cy.visit(Cypress.env('BS_URL')); + }); + it('should flash Connected message', function() { + cy.wait(500); + cy.get('#__bs_notify__').should(function($elems) { + expect($elems.length).to.equal(1); + expect($elems.text()).to.equal('Browsersync: connected'); + }); + }); +}); diff --git a/cypress/integration/css-console-notify.js b/cypress/integration/css-console-notify.js new file mode 100644 index 000000000..d5b497fbd --- /dev/null +++ b/cypress/integration/css-console-notify.js @@ -0,0 +1,26 @@ +describe('CSS console notification', function() { + beforeEach(function() { + cy.visit(Cypress.env('BS_URL')); + }); + it('should log message when css injected', function() { + cy.window().then((win) => { + const spy = cy.spy(win.console, "log"); + cy.exec('touch test/fixtures/**/style.css'); + cy.wait(1000).then(() => { + expect(spy.getCall(0).args.slice(-1)[0]).to.equal('[LinkReplace] style.css'); + }) + }); + }); + it('should log 2 messages when 2 css files injected', function() { + cy.window().then((win) => { + const spy = cy.spy(win.console, "log"); + cy.exec('touch test/fixtures/**/*.css'); + cy.wait(1000).then(() => { + expect(spy.callCount).to.equal(2); + const calls = new Set([spy.getCall(0).args.slice(-1)[0], spy.getCall(1).args.slice(-1)[0]]); + expect(calls.has('[LinkReplace] style.css')).to.be.true; + expect(calls.has('[LinkReplace] stylesheet.css')).to.be.true; + }) + }); + }); +}); diff --git a/cypress/integration/css-overlay-notify.js b/cypress/integration/css-overlay-notify.js new file mode 100644 index 000000000..0b7bb27d5 --- /dev/null +++ b/cypress/integration/css-overlay-notify.js @@ -0,0 +1,13 @@ +describe('CSS overlay notification', function() { + beforeEach(function() { + cy.visit(Cypress.env('BS_URL')); + }); + it('should flash messages when css injected', function() { + cy.exec('touch test/fixtures/**/style.css'); + cy.wait(500); + cy.get('#__bs_notify__').should(function($elems) { + expect($elems.length).to.equal(1); + expect($elems.text()).to.equal('[LinkReplace] style.css'); + }); + }); +}); diff --git a/cypress/integration/file-reloading.js b/cypress/integration/file-reloading.js new file mode 100644 index 000000000..38cdd6894 --- /dev/null +++ b/cypress/integration/file-reloading.js @@ -0,0 +1,90 @@ +describe('Reloading files', function() { + context('CSS', function() { + beforeEach(function() { + cy.visit(Cypress.env('BS_URL')); + }); + it('should reload single <link>', function() { + cy.exec('touch test/fixtures/**/style.css'); + cy.get('[id="css-style"]').should($link => { + const url = new URL($link.attr('href')); + expect(url.search).to.contain('?browsersync='); + }); + }); + it('should reload 2 css files', function() { + cy.exec('touch test/fixtures/**/*.css'); + cy.get('link').should($links => { + $links.each((i, elem) => { + const url = new URL(elem.href); + return expect(url.search).to.contain('?browsersync='); + }); + }); + }); + }); + context('CSS IMPORTS', function() { + it('can import 1 stylesheet from <style>@import</style>', () => { + cy.visit(Cypress.env('BS_URL') + '/import.html'); + cy.document().then((doc) => { + const firstStyle = doc.getElementsByTagName('style')[0]; + const href = firstStyle.sheet.cssRules[0].href; + expect(href).to.not.contain('?browsersync='); + }); + cy.exec('touch test/fixtures/assets/import.css'); + cy.get('style').eq(0).should((style) => { + const href = style[0].sheet.cssRules[0].href; + expect(href).to.contain('?browsersync='); + }); + }); + it('can import nested from nested @import rules', () => { + cy.visit(Cypress.env('BS_URL') + '/import-link.html'); + cy.document().then((doc) => { + const href = doc.styleSheets[0].cssRules[0].href; + expect(href).to.not.contain('?browsersync='); + }); + cy.exec('touch test/fixtures/assets/import2.css'); + cy.get('link').eq(0).should((link) => { + const href = link[0].sheet.cssRules[0].href; + expect(href).to.contain('?browsersync='); + }) + }); + }); + context('IMG', function() { + beforeEach(function() { + cy.visit(Cypress.env('BS_URL') + '/images.html'); + }); + it('should reload single <img src>', function() { + cy.exec('touch test/fixtures/**/cam-secure.png'); + cy.get('[id="img-src-attr"]').should($link => { + const url = new URL($link.attr('src')); + expect(url.search).to.contain('?browsersync='); + }); + cy.get('[id="img-style"]').should($link => { + const urlFromStyle = $link.css('backgroundImage').split('"').slice(1, -1); + const url = new URL(urlFromStyle); + expect(url.search).not.to.contain('?browsersync='); + }); + }); + it('should reload single style backgroundImage style property', function() { + cy.exec('touch test/fixtures/**/cam-secure-02.png'); + cy.get('[id="img-src-attr"]').should($link => { + expect($link.attr('src')).not.to.contain('?browsersync='); + }); + cy.get('[id="img-style"]').should($link => { + const urlFromStyle = $link.css('backgroundImage').split('"').slice(1, -1); + const url = new URL(urlFromStyle); + expect(url.search).to.contain('?browsersync='); + }); + }); + it('should reload both images', function() { + cy.exec('touch test/fixtures/**/*.png'); + cy.get('[id="img-src-attr"]').should($link => { + const url = new URL($link.attr('src')); + expect(url.search).to.contain('?browsersync='); + }); + cy.get('[id="img-style"]').should($link => { + const urlFromStyle = $link.css('backgroundImage').split('"').slice(1, -1); + const url = new URL(urlFromStyle); + expect(url.search).to.contain('?browsersync='); + }); + }); + }); +}); diff --git a/cypress/integration/logPrefix.js b/cypress/integration/logPrefix.js new file mode 100644 index 000000000..f22dc5b83 --- /dev/null +++ b/cypress/integration/logPrefix.js @@ -0,0 +1,22 @@ +describe('Connection notification (with logPrefix)', function() { + beforeEach(function() { + cy.visit(Cypress.env('BS_URL')); + }); + it('should flash correct Connected message', function() { + cy.wait(500); + cy.get('#__bs_notify__').should(function($elems) { + expect($elems.length).to.equal(1); + expect($elems.text()).to.equal('WSK: connected'); + }); + }); + it('should log prefixed message when css is injected', function() { + cy.window().then((win) => { + const spy = cy.spy(win.console, "log"); + cy.exec('touch test/fixtures/**/style.css'); + cy.wait(1000).then(() => { + expect(spy.getCall(0).args.slice(-1)[0]).to.equal('[LinkReplace] style.css'); + expect(spy.getCall(0).args.indexOf('WSK') > -1).to.be.true; + }) + }); + }); +}); diff --git a/cypress/integration/no-notify.js b/cypress/integration/no-notify.js new file mode 100644 index 000000000..c1ef72857 --- /dev/null +++ b/cypress/integration/no-notify.js @@ -0,0 +1,14 @@ +describe('disabled notification', function() { + beforeEach(function() { + cy.visit(Cypress.env('BS_URL')); + }); + it('should not flash Connected message', function() { + cy.wait(500); + cy.get('#__bs_notify__').should('have.length', 0); + }); + it('should not flash messages when css injected', function() { + cy.exec('touch test/fixtures/**/style.css'); + cy.wait(500); + cy.get('#__bs_notify__').should('have.length', 0); + }); +}); diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js new file mode 100644 index 000000000..fd170fba6 --- /dev/null +++ b/cypress/plugins/index.js @@ -0,0 +1,17 @@ +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +module.exports = (on, config) => { + // `on` is used to hook into various events Cypress emits + // `config` is the resolved Cypress config +} diff --git a/cypress/setup/bs.js b/cypress/setup/bs.js new file mode 100644 index 000000000..a6be36f94 --- /dev/null +++ b/cypress/setup/bs.js @@ -0,0 +1,20 @@ +module.exports = function(setup, specs) { + + const cypress = require('cypress'); + const bs = require('../../').create(); + + bs.init(setup, function(err, bs) { + return cypress.run({ + spec: specs, + env: `BS_URL=${bs.options.getIn(['urls', 'local'])}` + }) + .then((results) => { + // stop your server when it's complete + bs.cleanup(); + if (results.failures > 0) { + return process.exit(1); + } + process.exit(0); + }) + }); +}; diff --git a/cypress/setup/run.js b/cypress/setup/run.js new file mode 100644 index 000000000..d3e88676f --- /dev/null +++ b/cypress/setup/run.js @@ -0,0 +1,5 @@ +const run = require('./bs'); +const args = process.argv.slice(2); +const config = require(args[0]); +const specs = args.slice(1); +run(config, specs); \ No newline at end of file diff --git a/cypress/support/commands.js b/cypress/support/commands.js new file mode 100644 index 000000000..c1f5a772e --- /dev/null +++ b/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add("login", (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This is will overwrite an existing command -- +// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) diff --git a/cypress/support/index.js b/cypress/support/index.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/cypress/support/index.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/package.json b/package.json index 39a92e30e..62d89bd7a 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ }, "scripts": { "env": "node ./test/env.js", - "test": "npm run env && npm run unit", + "test": "cb build-all && npm run env && npm run unit", "lint": "prettier 'lib/**/*' 'examples/*' 'test/specs/**/*' 'test/specs/*.js' --write --tab-width 4", "pro": "protractor test/protractor/config.single.js", "pro-local": "node test/protractor/setup.js", @@ -32,7 +32,7 @@ "coveralls": "istanbul-coveralls", "pre-release": "npm test && npm run pro-local && npm run pro", "lodash": "lodash include=isUndefined,isFunction,toArray,includes,union,each,isString,merge,isObject,set exports=node", - "prepublish": "cb build-all" + "publishOnly": "cb build-all" }, "dependencies": { "browser-sync-ui": "v1.0.1", @@ -43,7 +43,6 @@ "dev-ip": "^1.0.1", "easy-extender": "2.3.2", "eazy-logger": "3.0.2", - "emitter-steward": "^1.0.0", "etag": "^1.8.1", "fresh": "^0.5.2", "fs-extra": "3.0.1", @@ -74,6 +73,7 @@ "chalk": "1.1.3", "compression": "1.6.2", "crossbow": "latest", + "cypress": "2.1.0", "generate-changelog": "^1.7.0", "graceful-fs": "4.1.9", "gulp": "3.9.1", diff --git a/yarn.lock b/yarn.lock index cc354a133..ed4e0d295 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,83 @@ # yarn lockfile v1 +"@cypress/listr-verbose-renderer@0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a" + dependencies: + chalk "^1.1.3" + cli-cursor "^1.0.2" + date-fns "^1.27.2" + figures "^1.7.0" + +"@cypress/xvfb@1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.1.3.tgz#6294a7d1feb751f12302248f2089fc534c4acb7f" + dependencies: + lodash.once "^4.1.1" + +"@types/blob-util@1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@types/blob-util/-/blob-util-1.3.3.tgz#adba644ae34f88e1dd9a5864c66ad651caaf628a" + +"@types/bluebird@3.5.18": + version "3.5.18" + resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.18.tgz#6a60435d4663e290f3709898a4f75014f279c4d6" + +"@types/chai-jquery@1.1.35": + version "1.1.35" + resolved "https://registry.yarnpkg.com/@types/chai-jquery/-/chai-jquery-1.1.35.tgz#9a8f0a39ec0851b2768a8f8c764158c2a2568d04" + dependencies: + "@types/chai" "*" + "@types/jquery" "*" + +"@types/chai@*": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.1.tgz#15f1257fab17b7acb9c413f9f88d3d87f834d11e" + +"@types/chai@4.0.8": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.8.tgz#d27600e9ba2f371e08695d90a0fe0408d89c7be7" + +"@types/jquery@*": + version "3.2.18" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.2.18.tgz#a1cd262034cd8c79fa4d9b2a409d8f747ac2f72f" + +"@types/jquery@3.2.16": + version "3.2.16" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.2.16.tgz#04419c404a3194350e7d3f339a90e72c88db3111" + +"@types/lodash@4.14.87": + version "4.14.87" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.87.tgz#55f92183b048c2c64402afe472f8333f4e319a6b" + +"@types/minimatch@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.1.tgz#b683eb60be358304ef146f5775db4c0e3696a550" + +"@types/mocha@2.2.44": + version "2.2.44" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.44.tgz#1d4a798e53f35212fd5ad4d04050620171cd5b5e" + "@types/node@^8.5.2": version "8.5.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.5.2.tgz#83b8103fa9a2c2e83d78f701a9aa7c9539739aa5" +"@types/sinon-chai@2.7.29": + version "2.7.29" + resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-2.7.29.tgz#4db01497e2dd1908b2bd30d1782f456353f5f723" + dependencies: + "@types/chai" "*" + "@types/sinon" "*" + +"@types/sinon@*": + version "4.1.3" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.1.3.tgz#2ee25e0e302f31e78a945650a60029e08878eaf8" + +"@types/sinon@4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.0.0.tgz#9a93ffa4ee1329e85166278a5ed99f81dc4c8362" + JSONStream@^1.0.4: version "1.3.2" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.2.tgz#c102371b6ec3a7cf3b847ca00c20bb0fce4c6dea" @@ -68,7 +141,7 @@ amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" -ansi-escapes@^1.1.0: +ansi-escapes@^1.0.0, ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" @@ -94,6 +167,18 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" +ansi-styles@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + dependencies: + color-convert "^1.9.0" + ansi-wrap@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" @@ -222,6 +307,12 @@ async@1.5.2, async@1.x, async@^1.4.0, async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" +async@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4" + dependencies: + lodash "^4.14.0" + async@~0.2.6: version "0.2.10" resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" @@ -249,6 +340,21 @@ axios@0.17.1: follow-redirects "^1.2.5" is-buffer "^1.1.5" +babel-code-frame@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-runtime@^6.18.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + backo2@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" @@ -311,6 +417,10 @@ block-stream@*: dependencies: inherits "~2.0.0" +bluebird@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" + bluebird@^3.0.6: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -407,7 +517,11 @@ bs-snippet-injector@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/bs-snippet-injector/-/bs-snippet-injector-2.0.1.tgz#61b5393f11f52559ed120693100343b6edb04dd5" -builtin-modules@^1.0.0: +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + +builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -415,6 +529,10 @@ bytes@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.3.0.tgz#d5b680a165b6201739acb611542aabc2d8ceb070" +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -475,7 +593,7 @@ chai@3.5.0: deep-eql "^0.1.3" type-detect "^1.0.0" -chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1: +chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -485,6 +603,14 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + chalk@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" @@ -495,6 +621,18 @@ chalk@^0.5.0: strip-ansi "^0.3.0" supports-color "^0.2.0" +chalk@^2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +check-more-types@2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" + chokidar@1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.4.3.tgz#5fe733a4d9acaea51b26454b7e59559163d0dbb2" @@ -525,6 +663,10 @@ chokidar@1.7.0: optionalDependencies: fsevents "^1.0.0" +ci-info@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.2.tgz#03561259db48d0474c8bdc90f5b47b068b6bbfb4" + class-utils@^0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.5.tgz#17e793103750f9627b2176ea34cfd1b565903c80" @@ -535,12 +677,23 @@ class-utils@^0.3.5: lazy-cache "^2.0.2" static-extend "^0.1.1" -cli-cursor@^1.0.1: +cli-cursor@^1.0.1, cli-cursor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" dependencies: restore-cursor "^1.0.1" +cli-spinners@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" + +cli-truncate@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" + dependencies: + slice-ansi "0.0.4" + string-width "^1.0.1" + cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" @@ -594,6 +747,16 @@ collection-visit@^1.0.0: map-visit "^1.0.0" object-visit "^1.0.0" +color-convert@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + color-support@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" @@ -608,12 +771,26 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + commander@2.9.0, commander@^2.2.0, commander@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" dependencies: graceful-readlink ">= 1.0.0" +commander@^2.12.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + +common-tags@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.4.0.tgz#1187be4f3d4cf0c0427d43f74eef1f73501614c0" + dependencies: + babel-runtime "^6.18.0" + compare-func@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.2.tgz#99dd0ba457e1f9bc722b12c08ec33eeab31fa648" @@ -654,7 +831,7 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.5.0: +concat-stream@1.6.0, concat-stream@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" dependencies: @@ -818,6 +995,10 @@ copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" +core-js@^2.4.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -875,6 +1056,47 @@ currently-unhandled@^0.4.1: dependencies: array-find-index "^1.0.1" +cypress@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-2.1.0.tgz#a8bd7d9b89c38a1e380db83b57d9bba0dbb95ba4" + dependencies: + "@cypress/listr-verbose-renderer" "0.4.1" + "@cypress/xvfb" "1.1.3" + "@types/blob-util" "1.3.3" + "@types/bluebird" "3.5.18" + "@types/chai" "4.0.8" + "@types/chai-jquery" "1.1.35" + "@types/jquery" "3.2.16" + "@types/lodash" "4.14.87" + "@types/minimatch" "3.0.1" + "@types/mocha" "2.2.44" + "@types/sinon" "4.0.0" + "@types/sinon-chai" "2.7.29" + bluebird "3.5.0" + chalk "2.1.0" + check-more-types "2.24.0" + commander "2.11.0" + common-tags "1.4.0" + debug "3.1.0" + extract-zip "1.6.6" + fs-extra "4.0.1" + getos "2.8.4" + glob "7.1.2" + is-ci "1.0.10" + is-installed-globally "0.1.0" + lazy-ass "1.6.0" + listr "0.12.0" + lodash "4.17.4" + minimist "1.2.0" + progress "1.1.8" + ramda "0.24.1" + request "2.81.0" + request-progress "0.3.1" + supports-color "5.1.0" + tmp "0.0.31" + url "0.11.0" + yauzl "2.8.0" + dargs@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17" @@ -887,6 +1109,10 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +date-fns@^1.27.2: + version "1.29.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" + dateformat@^1.0.11, dateformat@^1.0.12, dateformat@^1.0.7-1.2.3: version "1.0.12" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" @@ -922,13 +1148,13 @@ debug@2.6.8, debug@^2.1.3, debug@^2.2.0, debug@~2.6.4, debug@~2.6.6: dependencies: ms "2.0.0" -debug@^2.3.3, debug@~2.6.9: +debug@2.6.9, debug@^2.3.3, debug@~2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: ms "2.0.0" -debug@^3.1.0: +debug@3.1.0, debug@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" dependencies: @@ -1014,6 +1240,10 @@ diff@3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" +diff@^3.2.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + dom-compare-temp@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/dom-compare-temp/-/dom-compare-temp-0.1.0.tgz#d540969876741a83a447fe7dc8b28d8a5b95339a" @@ -1084,9 +1314,9 @@ ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" -emitter-steward@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/emitter-steward/-/emitter-steward-1.0.0.tgz#f3411ade9758a7565df848b2da0cbbd1b46cbd64" +elegant-spinner@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" encodeurl@~1.0.1: version "1.0.1" @@ -1170,6 +1400,10 @@ esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" +esprima@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" @@ -1255,6 +1489,15 @@ extglob@^2.0.2: snapdragon "^0.8.1" to-regex "^3.0.1" +extract-zip@1.6.6: + version "1.6.6" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.6.tgz#1290ede8d20d0872b429fd3f351ca128ec5ef85c" + dependencies: + concat-stream "1.6.0" + debug "2.6.9" + mkdirp "0.5.0" + yauzl "2.4.1" + extsprintf@1.3.0, extsprintf@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -1271,7 +1514,13 @@ fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" -figures@^1.3.5: +fd-slicer@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" + dependencies: + pend "~1.2.0" + +figures@^1.3.5, figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" dependencies: @@ -1423,6 +1672,14 @@ fs-extra@3.0.1: jsonfile "^3.0.0" universalify "^0.1.0" +fs-extra@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.1.tgz#7fc0c6c8957f983f57f306a24e5b9ddd8d0dd880" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^3.0.0" + universalify "^0.1.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1510,6 +1767,12 @@ get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" +getos@2.8.4: + version "2.8.4" + resolved "https://registry.yarnpkg.com/getos/-/getos-2.8.4.tgz#7b8603d3619c28e38cb0fe7a4f63c3acb80d5163" + dependencies: + async "2.1.4" + getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -1597,6 +1860,17 @@ glob@7.1.1, glob@^7.0.5: once "^1.3.0" path-is-absolute "^1.0.0" +glob@7.1.2, glob@^7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^4.3.1: version "4.5.3" resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" @@ -1624,6 +1898,12 @@ glob@~3.1.21: inherits "1" minimatch "~0.2.11" +global-dirs@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + dependencies: + ini "^1.3.4" + global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" @@ -1828,6 +2108,14 @@ has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + has-gulplog@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" @@ -1905,15 +2193,7 @@ hosted-git-info@^2.1.4: inherits "^2.0.1" readable-stream "^2.0.2" -http-errors@~1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750" - dependencies: - inherits "2.0.3" - setprototypeof "1.0.2" - statuses ">= 1.3.1 < 2" - -http-errors@~1.6.1: +http-errors@1.6.2, http-errors@~1.6.1: version "1.6.2" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" dependencies: @@ -1922,6 +2202,14 @@ http-errors@~1.6.1: setprototypeof "1.0.3" statuses ">= 1.3.1 < 2" +http-errors@~1.5.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750" + dependencies: + inherits "2.0.3" + setprototypeof "1.0.2" + statuses ">= 1.3.1 < 2" + http-proxy@1.15.2: version "1.15.2" resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.15.2.tgz#642fdcaffe52d3448d2bda3b0079e9409064da31" @@ -1941,6 +2229,10 @@ http2@^3.3.6: version "3.3.7" resolved "https://registry.yarnpkg.com/http2/-/http2-3.3.7.tgz#78396eb1e0bcd1db1f4b138d997c682e23414fbc" +iconv-lite@0.4.19: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + immutable@3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.0.tgz#5175514f70cb2a8218b58183d33747134a81c697" @@ -1959,6 +2251,10 @@ indent-string@^2.1.0: dependencies: repeating "^2.0.0" +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + indexof@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" @@ -2045,6 +2341,12 @@ is-builtin-module@^1.0.0: dependencies: builtin-modules "^1.0.0" +is-ci@1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e" + dependencies: + ci-info "^1.0.0" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -2119,6 +2421,13 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" +is-installed-globally@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + dependencies: + global-dirs "^0.1.0" + is-path-inside "^1.0.0" + is-my-json-valid@^2.12.4: version "2.17.1" resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz#3da98914a70a22f0a8563ef1511a246c6fc55471" @@ -2156,6 +2465,12 @@ is-odd@^1.0.0: dependencies: is-number "^3.0.0" +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + dependencies: + path-is-inside "^1.0.1" + is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -2184,6 +2499,10 @@ is-relative@^0.2.1: dependencies: is-unc-path "^0.1.1" +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + is-subset@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" @@ -2275,6 +2594,10 @@ istanbul@0.4.5: which "^1.1.1" wordwrap "^1.0.0" +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + js-yaml@3.6.0, js-yaml@3.x: version "3.6.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.0.tgz#3b7bf3256dd598f60f8b6f8ea75514a585a24dc6" @@ -2289,6 +2612,13 @@ js-yaml@3.6.1: argparse "^1.0.7" esprima "^2.6.0" +js-yaml@^3.7.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -2379,6 +2709,10 @@ kind-of@^6.0.0: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" +lazy-ass@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" + lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" @@ -2423,6 +2757,53 @@ limiter@^1.0.5: version "1.1.2" resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.2.tgz#229d8055891c8b11af9e0ee5200e8e09bb3dcbeb" +listr-silent-renderer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" + +listr-update-renderer@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz#ca80e1779b4e70266807e8eed1ad6abe398550f9" + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + elegant-spinner "^1.0.1" + figures "^1.7.0" + indent-string "^3.0.0" + log-symbols "^1.0.2" + log-update "^1.0.2" + strip-ansi "^3.0.1" + +listr-verbose-renderer@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35" + dependencies: + chalk "^1.1.3" + cli-cursor "^1.0.2" + date-fns "^1.27.2" + figures "^1.7.0" + +listr@0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.12.0.tgz#6bce2c0f5603fa49580ea17cd6a00cc0e5fa451a" + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + figures "^1.7.0" + indent-string "^2.1.0" + is-promise "^2.1.0" + is-stream "^1.1.0" + listr-silent-renderer "^1.1.1" + listr-update-renderer "^0.2.0" + listr-verbose-renderer "^0.4.0" + log-symbols "^1.0.2" + log-update "^1.0.2" + ora "^0.2.3" + p-map "^1.1.1" + rxjs "^5.0.0-beta.11" + stream-to-observable "^0.1.0" + strip-ansi "^3.0.1" + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -2601,6 +2982,10 @@ lodash.keys@~2.4.1: lodash._shimkeys "~2.4.1" lodash.isobject "~2.4.1" +lodash.once@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" @@ -2664,7 +3049,7 @@ lodash.values@~2.4.1: dependencies: lodash.keys "~2.4.1" -lodash@4.17.4, lodash@^4.0.0, lodash@^4.2.1, lodash@^4.3.0: +lodash@4.17.4, lodash@^4.0.0, lodash@^4.14.0, lodash@^4.2.1, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -2680,6 +3065,19 @@ log-driver@1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + dependencies: + chalk "^1.0.0" + +log-update@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1" + dependencies: + ansi-escapes "^1.0.0" + cli-cursor "^1.0.2" + lolex@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" @@ -2795,7 +3193,7 @@ mime@1.3.4, mime@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2: +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -2833,6 +3231,12 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mkdirp@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" + dependencies: + minimist "0.0.8" + mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" @@ -3114,6 +3518,15 @@ optionator@^0.8.1: type-check "~0.3.2" wordwrap "~1.0.0" +ora@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" + dependencies: + chalk "^1.1.1" + cli-cursor "^1.0.2" + cli-spinners "^0.1.2" + object-assign "^4.0.1" + orchestrator@^0.3.0: version "0.3.8" resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" @@ -3136,7 +3549,7 @@ os-locale@^1.4.0: dependencies: lcid "^1.0.0" -os-tmpdir@^1.0.0: +os-tmpdir@^1.0.0, os-tmpdir@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -3147,6 +3560,10 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +p-map@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" + parse-filepath@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.1.tgz#159d6155d43904d16c10ef698911da1e91969b73" @@ -3212,6 +3629,14 @@ path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" +path-is-inside@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + path-root-regex@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" @@ -3230,6 +3655,10 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" @@ -3279,6 +3708,14 @@ process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" +progress@1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" @@ -3303,6 +3740,14 @@ qs@~6.3.0: version "6.3.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + +ramda@0.24.1: + version "0.24.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857" + randomatic@^1.1.3: version "1.1.7" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" @@ -3314,6 +3759,15 @@ range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" +raw-body@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" + dependencies: + bytes "3.0.0" + http-errors "1.6.2" + iconv-lite "0.4.19" + unpipe "1.0.0" + rc@^1.1.7: version "1.2.2" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.2.tgz#d8ce9cb57e8d64d9c7badd9876c7c34cbe3c7077" @@ -3390,6 +3844,10 @@ redent@^1.0.0: indent-string "^2.1.0" strip-indent "^1.0.1" +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + regex-cache@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" @@ -3424,6 +3882,12 @@ replace-ext@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" +request-progress@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-0.3.1.tgz#0721c105d8a96ac6b2ce8b2c89ae2d5ecfcf6b3a" + dependencies: + throttleit "~0.0.2" + request@2.79.0: version "2.79.0" resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" @@ -3507,6 +3971,12 @@ resolve@1.1.x, resolve@^1.1.6, resolve@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" +resolve@^1.3.2: + version "1.7.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" + dependencies: + path-parse "^1.0.5" + resp-modifier@6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/resp-modifier/-/resp-modifier-6.0.2.tgz#b124de5c4fbafcba541f48ffa73970f4aa456b4f" @@ -3555,6 +4025,12 @@ rx@*, rx@4.1.0, rx@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" +rxjs@^5.0.0-beta.11: + version "5.5.6" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.6.tgz#e31fb96d6fd2ff1fd84bcea8ae9c02d007179c02" + dependencies: + symbol-observable "1.0.1" + safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -3675,6 +4151,10 @@ sinon@1.17.5: samsam "1.1.2" util ">=0.10.3 <1" +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -3865,6 +4345,10 @@ stream-throttle@^0.1.3: commander "^2.2.0" limiter "^1.0.5" +stream-to-observable@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe" + streamfilter@^1.0.5: version "1.0.7" resolved "https://registry.yarnpkg.com/streamfilter/-/streamfilter-1.0.7.tgz#ae3e64522aa5a35c061fd17f67620c7653c643c9" @@ -3962,6 +4446,12 @@ supports-color@3.1.2: dependencies: has-flag "^1.0.0" +supports-color@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5" + dependencies: + has-flag "^2.0.0" + supports-color@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a" @@ -3976,6 +4466,22 @@ supports-color@^3.1.0: dependencies: has-flag "^1.0.0" +supports-color@^4.0.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + dependencies: + has-flag "^2.0.0" + +supports-color@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" + dependencies: + has-flag "^3.0.0" + +symbol-observable@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" + "symbol-tree@>= 3.1.0 < 4.0.0": version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" @@ -4012,6 +4518,10 @@ tfunk@^3.0.1, tfunk@latest: chalk "^1.1.1" object-path "^0.9.0" +throttleit@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" + through2@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/through2/-/through2-0.5.1.tgz#dfdd012eb9c700e2323fd334f38ac622ab372da7" @@ -4054,6 +4564,12 @@ time-stamp@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" +tmp@0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + to-array@0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" @@ -4101,6 +4617,33 @@ trim-off-newlines@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" +tslib@^1.8.0, tslib@^1.8.1: + version "1.9.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" + +tslint@5.9.1: + version "5.9.1" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.9.1.tgz#1255f87a3ff57eb0b0e1f0e610a8b4748046c9ae" + dependencies: + babel-code-frame "^6.22.0" + builtin-modules "^1.1.1" + chalk "^2.3.0" + commander "^2.12.1" + diff "^3.2.0" + glob "^7.1.1" + js-yaml "^3.7.0" + minimatch "^3.0.4" + resolve "^1.3.2" + semver "^5.3.0" + tslib "^1.8.0" + tsutils "^2.12.1" + +tsutils@^2.12.1: + version "2.26.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.26.1.tgz#9e4a0cb9ff173863f34c22a961969081270d1878" + dependencies: + tslib "^1.8.1" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -4183,7 +4726,7 @@ universalify@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" -unpipe@~1.0.0: +unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -4198,6 +4741,13 @@ urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" +url@0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + dependencies: + punycode "1.3.2" + querystring "0.2.0" + use@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/use/-/use-2.0.2.tgz#ae28a0d72f93bf22422a18a2e379993112dec8e8" @@ -4446,6 +4996,19 @@ yargs@~3.10.0: decamelize "^1.0.0" window-size "0.1.0" +yauzl@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" + dependencies: + fd-slicer "~1.0.1" + +yauzl@2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.8.0.tgz#79450aff22b2a9c5a41ef54e02db907ccfbf9ee2" + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.0.1" + yeast@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"