diff --git a/.babelrc b/.babelrc index 083a98a9..dabbdc9b 100644 --- a/.babelrc +++ b/.babelrc @@ -5,5 +5,10 @@ "transform-object-rest-spread", "transform-class-properties", "transform-runtime" - ] + ], + "env": { + "test": { + "plugins": ["istanbul"] + } + } } diff --git a/.travis.yml b/.travis.yml index b30f5053..24da4b22 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,23 @@ +sudo: required +dist: trusty +addons: + apt: + sources: + - google-chrome + packages: + - google-chrome-stable language: node_js node_js: - - "node" - - "6" - "4" + - "6" cache: - yarn: true directories: - node_modules -install: - - curl -o- -L https://yarnpkg.com/install.sh | bash - - export PATH=$HOME/.yarn/bin:$PATH - - yarn --ignore-engines +before_install: + - rm yarn.lock + - export DISPLAY=:99.0 + - sh -e /etc/init.d/xvfb start + - sleep 3 +script: + - echo "No need to use npm test since it's done in the install section via 'npm prepublish'" after_script: npm run coveralls diff --git a/gulpfile.js b/gulpfile.js index f4acef00..9f699291 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -8,8 +8,9 @@ const sequence = require('run-sequence') const webpack = require('webpack') const webpackStream = require('webpack-stream') const del = require('del') -const jest = require('gulp-jest') +const childProcess = require('child_process') +const isWindows = /^win/.test(process.platform) const babelOptions = JSON.parse(fs.readFileSync('.babelrc', 'utf-8')) gulp.task('compile', [ @@ -123,21 +124,6 @@ gulp.task('build-prefetcher', ['compile-lib', 'compile-client'], () => { .pipe(notify('Built release prefetcher')) }) -gulp.task('test', ['compile'], () => { - return gulp.src('./test') - .pipe(jest.default({ - coverage: true, - verbose: true, - config: { - rootDir: './test', - testEnvironment: 'node', - coveragePathIgnorePatterns: [ - 'test/.*' - ] - } - })) -}) - gulp.task('bench', ['compile', 'copy', 'compile-bench', 'copy-bench-fixtures'], () => { return gulp.src('dist/bench/*.js', {read: false}) .pipe(benchmark({ @@ -193,7 +179,6 @@ gulp.task('default', [ 'compile', 'build', 'copy', - 'test', 'watch' ]) @@ -202,10 +187,36 @@ gulp.task('release', (cb) => { 'compile', 'build', 'copy', - 'test' ], cb) }) +// We run following task inside a NPM script chain and it runs chromedriver +// inside a child process tree. +// Even though we kill this task's process, chromedriver exists throughout +// the lifetime of the original npm script. + +gulp.task('start-chromedriver', ['stop-chromedriver'], (cb) => { + const processName = isWindows? 'chromedriver.cmd' : 'chromedriver' + const chromedriver = childProcess.spawn(processName, { stdio: 'inherit' }) + + const timeoutHandler = setTimeout(() => { + // We need to do this, otherwise this task's process will keep waiting. + process.exit(0) + }, 2000) +}) + +gulp.task('stop-chromedriver', () => { + try { + if (isWindows) { + childProcess.execSync('taskkill /im chromedriver* /t /f', { stdio: 'ignore' }) + } else { + childProcess.execSync('pkill chromedriver', { stdio: 'ignore' }) + } + } catch(ex) { + // Do nothing + } +}) + // avoid logging to the console // that we created a notification notify_.logLevel(0) diff --git a/package.json b/package.json index 99bd6cb9..f8ec4bc2 100644 --- a/package.json +++ b/package.json @@ -23,13 +23,15 @@ }, "scripts": { "build": "gulp", - "pretest": "npm run lint", - "test": "gulp test", - "html-report": "nyc report --temp-directory=./coverage --reporter=html", - "jest": "jest --coverage", - "coveralls": "nyc report --temp-directory=./coverage --reporter=text-lcov | coveralls", + "release": "gulp release", + "pretestonly": "gulp start-chromedriver", + "testonly": "cross-env NODE_PATH=test/lib jest \\.test.js", + "posttestonly": "gulp stop-chromedriver", + "pretest": "npm run lint && cross-env NODE_ENV=test npm run release", + "test": "npm run testonly -- --coverage --forceExit", + "coveralls": "nyc --instrument=false --source-map=false report --temp-directory=./coverage --reporter=text-lcov | coveralls", "lint": "standard 'bin/*' 'client/**/*.js' 'examples/**/*.js' 'lib/**/*.js' 'pages/**/*.js' 'server/**/*.js' 'test/**/*.js'", - "prepublish": "gulp release", + "prepublish": "npm run test && npm run release", "precommit": "npm run lint" }, "standard": { @@ -84,24 +86,34 @@ }, "devDependencies": { "babel-eslint": "7.1.1", + "babel-jest": "^18.0.0", + "babel-plugin-istanbul": "^3.0.0", "babel-plugin-transform-remove-strict-mode": "0.0.2", "babel-preset-env": "1.1.8", "benchmark": "2.1.3", + "cheerio": "^0.22.0", + "chromedriver": "^2.26.1", "coveralls": "2.11.15", "gulp": "3.9.1", "gulp-babel": "6.1.2", "gulp-benchmark": "1.1.1", "gulp-cached": "1.1.1", - "gulp-jest": "^1.0.0", "gulp-notify": "2.2.0", "husky": "0.12.0", - "jest": "^18.0.0", + "jest-cli": "^18.0.0", + "node-fetch": "^1.6.3", "nyc": "^10.0.0", + "portfinder": "^1.0.10", "run-sequence": "1.2.2", "standard": "8.6.0", - "webpack-stream": "3.2.0" + "wd": "^1.1.1", + "webpack-stream": "3.2.0", + "cross-env": "^3.1.4" }, "jest": { - "testEnvironment": "node" + "testEnvironment": "node", + "testPathDirs": [ + "test/" + ] } } diff --git a/server/index.js b/server/index.js index 7bc89595..1db0a7b2 100644 --- a/server/index.js +++ b/server/index.js @@ -55,6 +55,15 @@ export default class Server { if (this.hotReloader) { await this.hotReloader.stop() } + + if (this.http) { + await new Promise((resolve, reject) => { + this.http.close((err) => { + if (err) return reject(err) + return resolve() + }) + }) + } } defineRoutes () { diff --git a/server/render.js b/server/render.js index 5a11638f..7c59c5b3 100644 --- a/server/render.js +++ b/server/render.js @@ -161,6 +161,7 @@ export async function serveStaticWithGzip (req, res, path) { // we don't add gzipped files at runtime. await fs.stat(gzipPath) } catch (ex) { + // Handles the error thrown by fs.stat if (ex.code === 'ENOENT') { // Seems like there's no gzipped file. Let's serve the uncompressed file. return serveStatic(req, res, path) diff --git a/server/resolve.js b/server/resolve.js index ec1a57ee..2e6c2c89 100644 --- a/server/resolve.js +++ b/server/resolve.js @@ -31,8 +31,8 @@ function getPaths (id) { if (i[i.length - 1] === sep) { return [ - i + 'index.json', - i + 'index.js' + i + 'index.js', + i + 'index.json' ] } diff --git a/test/fixtures/basic/pages/async-props.js b/test/fixtures/basic/pages/async-props.js deleted file mode 100644 index 2401e133..00000000 --- a/test/fixtures/basic/pages/async-props.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react' - -export default class AsyncProps extends React.Component { - static async getInitialProps () { - return await AsyncProps.fetchData() - } - - static fetchData () { - const p = new Promise(resolve => { - setTimeout(() => resolve({ name: 'Diego Milito' }), 10) - }) - return p - } - - render () { - return

{this.props.name}

- } -} diff --git a/test/fixtures/basic/pages/error.js b/test/fixtures/basic/pages/error.js deleted file mode 100644 index 2ef775f9..00000000 --- a/test/fixtures/basic/pages/error.js +++ /dev/null @@ -1 +0,0 @@ -throw new Error('This is an expected error') diff --git a/test/integration.test.js b/test/integration.test.js deleted file mode 100644 index cecbf383..00000000 --- a/test/integration.test.js +++ /dev/null @@ -1,122 +0,0 @@ -/* global expect, jasmine, describe, test, beforeAll, afterAll */ - -'use strict' - -import { join } from 'path' -import next from '../dist/server/next' -import pkg from '../package.json' - -const dir = join(__dirname, 'fixtures', 'basic') -const app = next({ - dir, - dev: true, - staticMarkup: true, - quiet: true -}) - -jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000 - -describe('integration tests', () => { - beforeAll(() => app.prepare()) - - afterAll(() => app.close()) - - test('renders a stateless component', async () => { - const html = await render('/stateless') - expect(html.includes('')).toBeTruthy() - expect(html.includes('

My component!

')).toBeTruthy() - }) - - test('renders a stateful component', async () => { - const html = await render('/stateful') - expect(html.includes('

The answer is 42

')).toBeTruthy() - }) - - test('header helper renders header information', async () => { - const html = await (render('/head')) - expect(html.includes('')).toBeTruthy() - expect(html.includes('')).toBeTruthy() - expect(html.includes('

I can haz meta tags

')).toBeTruthy() - }) - - test('css helper renders styles', async () => { - const html = await render('/css') - expect(/\.css-\w+/.test(html)).toBeTruthy() - expect(/
This is red<\/div>/.test(html)).toBeTruthy() - }) - - test('renders styled jsx', async () => { - const html = await render('/styled-jsx') - expect(html).toMatch(/
) diff --git a/test/integration/basic/test/client-navigation.js b/test/integration/basic/test/client-navigation.js new file mode 100644 index 00000000..cbbc13b8 --- /dev/null +++ b/test/integration/basic/test/client-navigation.js @@ -0,0 +1,48 @@ +/* global describe, it, expect */ + +import webdriver from 'next-webdriver' + +export default (context) => { + describe('Client Navigation', () => { + describe('with ', () => { + it('should navigate the page', async () => { + const browser = await webdriver(context.appPort, '/nav') + const text = await browser + .elementByCss('a').click() + .waitForElementByCss('.nav-about') + .elementByCss('p').text() + + expect(text).toBe('This is the about page.') + await browser.close() + }) + + it('should navigate via the client side', async () => { + const browser = await webdriver(context.appPort, '/nav') + + const counterText = await browser + .elementByCss('#increase').click() + .elementByCss('a').click() + .waitForElementByCss('.nav-about') + .elementByCss('a').click() + .waitForElementByCss('.nav-home') + .elementByCss('#counter').text() + + expect(counterText).toBe('Counter: 1') + await browser.close() + }) + }) + + describe('with tag inside the ', () => { + it('should navigate the page', async () => { + const browser = await webdriver(context.appPort, '/nav/about') + const text = await browser + .elementByCss('a').click() + .waitForElementByCss('.nav-home') + .elementByCss('p').text() + + expect(text).toBe('This is the home.') + await browser.close() + }) + }) + }) +} diff --git a/test/integration/basic/test/index.test.js b/test/integration/basic/test/index.test.js new file mode 100644 index 00000000..6a0de5e1 --- /dev/null +++ b/test/integration/basic/test/index.test.js @@ -0,0 +1,39 @@ +/* global jasmine, describe, beforeAll, afterAll */ + +import { join } from 'path' +import { + nextServer, + findPort, + renderViaAPI, + renderViaHTTP +} from 'next-test-utils' + +// test suits +import xPoweredBy from './xpowered-by' +import rendering from './rendering' +import misc from './misc' +import clientNavigation from './client-navigation' + +const context = {} +context.app = nextServer({ + dir: join(__dirname, '../'), + dev: true, + quiet: true +}) + +jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000 + +describe('Basic Features', () => { + beforeAll(async () => { + await context.app.prepare() + context.appPort = await findPort() + await context.app.start(context.appPort) + }) + afterAll(() => context.app.close()) + + rendering(context, 'Rendering via API', (p, q) => renderViaAPI(context.app, p, q)) + rendering(context, 'Rendering via HTTP', (p, q) => renderViaHTTP(context.appPort, p, q)) + xPoweredBy(context) + misc(context) + clientNavigation(context) +}) diff --git a/test/integration/basic/test/misc.js b/test/integration/basic/test/misc.js new file mode 100644 index 00000000..61c7f64e --- /dev/null +++ b/test/integration/basic/test/misc.js @@ -0,0 +1,16 @@ +/* global describe, test, expect */ + +export default function ({ app }) { + describe('Misc', () => { + test('finishes response', async () => { + const res = { + finished: false, + end () { + this.finished = true + } + } + const html = await app.renderToHTML({}, res, '/finish-response', {}) + expect(html).toBeFalsy() + }) + }) +} diff --git a/test/integration/basic/test/rendering.js b/test/integration/basic/test/rendering.js new file mode 100644 index 00000000..8152252d --- /dev/null +++ b/test/integration/basic/test/rendering.js @@ -0,0 +1,69 @@ +/* global describe, test, expect */ + +import cheerio from 'cheerio' + +export default function ({ app }, suiteName, render) { + async function get$ (path) { + const html = await render(path) + return cheerio.load(html) + } + + describe(suiteName, () => { + test('renders a stateless component', async () => { + const html = await render('/stateless') + expect(html.includes('')).toBeTruthy() + expect(html.includes('My component!')).toBeTruthy() + }) + + test('renders a stateful component', async () => { + const $ = await get$('/stateful') + const answer = $('#answer') + expect(answer.text()).toBe('The answer is 42') + }) + + test('header helper renders header information', async () => { + const html = await (render('/head')) + expect(html.includes('')).toBeTruthy() + expect(html.includes('')).toBeTruthy() + expect(html.includes('I can haz meta tags')).toBeTruthy() + }) + + test('css helper renders styles', async () => { + const $ = await get$('/css') + const redBox = $('#red-box') + + expect(redBox.text()).toBe('This is red') + expect(redBox.attr('class')).toMatch(/^css-/) + }) + + test('renders styled jsx', async () => { + const $ = await get$('/styled-jsx') + const styleId = $('#blue-box').attr('data-jsx') + const style = $(`#__jsx-style-${styleId}`) + + expect(style.text()).toMatch(/color: blue/) + }) + + test('renders properties populated asynchronously', async () => { + const html = await render('/async-props') + expect(html.includes('Diego Milito')).toBeTruthy() + }) + + test('renders a link component', async () => { + const $ = await get$('/link') + const link = $('a[href="/about"]') + expect(link.text()).toBe('About') + }) + + test('error', async () => { + const $ = await get$('/error') + expect($('pre').text()).toMatch(/This is an expected error/) + }) + + test('error 404', async () => { + const $ = await get$('/non-existent') + expect($('h1').text()).toBe('404') + expect($('h2').text()).toBe('This page could not be found.') + }) + }) +} diff --git a/test/integration/basic/test/xpowered-by.js b/test/integration/basic/test/xpowered-by.js new file mode 100644 index 00000000..d0108b0b --- /dev/null +++ b/test/integration/basic/test/xpowered-by.js @@ -0,0 +1,37 @@ +/* global describe, test, expect */ +import { pkg } from 'next-test-utils' + +export default function ({ app }) { + describe('X-Powered-By header', () => { + test('set it by default', async () => { + const req = { url: '/stateless' } + const headers = {} + const res = { + setHeader (key, value) { + headers[key] = value + }, + end () {} + } + + await app.render(req, res, req.url) + expect(headers['X-Powered-By']).toEqual(`Next.js ${pkg.version}`) + }) + + test('do not set it when poweredByHeader==false', async () => { + const req = { url: '/stateless' } + const originalConfigValue = app.config.poweredByHeader + app.config.poweredByHeader = false + const res = { + setHeader (key, value) { + if (key === 'X-Powered-By') { + throw new Error('Should not set the X-Powered-By header') + } + }, + end () {} + } + + await app.render(req, res, req.url) + app.config.poweredByHeader = originalConfigValue + }) + }) +} diff --git a/test/integration/production/pages/index.js b/test/integration/production/pages/index.js new file mode 100644 index 00000000..3d446a4e --- /dev/null +++ b/test/integration/production/pages/index.js @@ -0,0 +1,3 @@ +export default () => ( +
Hello World
+) diff --git a/test/integration/production/test/index.test.js b/test/integration/production/test/index.test.js new file mode 100644 index 00000000..161c1124 --- /dev/null +++ b/test/integration/production/test/index.test.js @@ -0,0 +1,78 @@ +/* global jasmine, describe, it, expect, beforeAll, afterAll */ + +import fetch from 'node-fetch' +import { join } from 'path' +import { + nextServer, + nextBuild, + findPort, + renderViaHTTP +} from 'next-test-utils' + +const appDir = join(__dirname, '../') +let app +let appPort +jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000 + +describe('Production Usage', () => { + beforeAll(async () => { + await nextBuild(appDir) + app = nextServer({ + dir: join(__dirname, '../'), + dev: false, + quiet: true + }) + + await app.prepare() + appPort = await findPort() + await app.start(appPort) + }) + afterAll(() => app.close()) + + describe('With basic usage', () => { + it('should render the page', async () => { + const html = await renderViaHTTP(appPort, '/') + expect(html).toMatch(/Hello World/) + }) + }) + + describe('JSON pages', () => { + describe('when asked for a gzipped page', () => { + it('should serve the gzipped page', async () => { + const url = `http://localhost:${appPort}/_next/${app.renderOpts.buildId}/pages` + const res = await fetch(url, { compress: true }) + expect(res.headers.get('Content-Encoding')).toBe('gzip') + + const page = await res.json() + expect(page.component).toBeDefined() + }) + }) + + describe('when asked for a normal page', () => { + it('should serve the normal page', async () => { + const url = `http://localhost:${appPort}/_next/${app.renderOpts.buildId}/pages` + const res = await fetch(url, { compress: false }) + expect(res.headers.get('Content-Encoding')).toBeNull() + + const page = await res.json() + expect(page.component).toBeDefined() + }) + }) + + describe('when asked for a page with an unknown encoding', () => { + it('should serve the normal page', async () => { + const url = `http://localhost:${appPort}/_next/${app.renderOpts.buildId}/pages` + const res = await fetch(url, { + compress: false, + headers: { + 'Accept-Encoding': 'br' + } + }) + expect(res.headers.get('Content-Encoding')).toBeNull() + + const page = await res.json() + expect(page.component).toBeDefined() + }) + }) + }) +}) diff --git a/test/isolated/_resolvedata/aa/index.js b/test/isolated/_resolvedata/aa/index.js new file mode 100644 index 00000000..e69de29b diff --git a/test/isolated/_resolvedata/bb/index.json b/test/isolated/_resolvedata/bb/index.json new file mode 100644 index 00000000..e69de29b diff --git a/test/isolated/_resolvedata/cc/index.js b/test/isolated/_resolvedata/cc/index.js new file mode 100644 index 00000000..e69de29b diff --git a/test/isolated/_resolvedata/cc/index.json b/test/isolated/_resolvedata/cc/index.json new file mode 100644 index 00000000..e69de29b diff --git a/test/isolated/_resolvedata/one.js b/test/isolated/_resolvedata/one.js new file mode 100644 index 00000000..e69de29b diff --git a/test/isolated/_resolvedata/one.json b/test/isolated/_resolvedata/one.json new file mode 100644 index 00000000..e69de29b diff --git a/test/isolated/_resolvedata/two.json b/test/isolated/_resolvedata/two.json new file mode 100644 index 00000000..e69de29b diff --git a/test/isolated/resolve.test.js b/test/isolated/resolve.test.js new file mode 100644 index 00000000..3506de7a --- /dev/null +++ b/test/isolated/resolve.test.js @@ -0,0 +1,52 @@ +/* global describe, it, expect */ + +import { join } from 'path' +import resolve from '../../dist/server/resolve' + +const dataPath = join(__dirname, '_resolvedata') + +describe('Resolve', () => { + it('should resolve a .js path', async () => { + const p = await resolve(join(dataPath, 'one.js')) + expect(p).toBe(join(dataPath, 'one.js')) + }) + + it('should resolve a .json path', async () => { + const p = await resolve(join(dataPath, 'two.json')) + expect(p).toBe(join(dataPath, 'two.json')) + }) + + it('should resolve a module without an extension', async () => { + const p = await resolve(join(dataPath, 'one')) + expect(p).toBe(join(dataPath, 'one.js')) + }) + + it('should resolve a .js module in a directory without /', async () => { + const p = await resolve(join(dataPath, 'aa')) + expect(p).toBe(join(dataPath, 'aa', 'index.js')) + }) + + it('should resolve a .js module in a directory with /', async () => { + const p = await resolve(join(dataPath, 'aa/')) + expect(p).toBe(join(dataPath, 'aa', 'index.js')) + }) + + it('should resolve a .json module in a directory', async () => { + const p = await resolve(join(dataPath, 'bb')) + expect(p).toBe(join(dataPath, 'bb', 'index.json')) + }) + + it('should resolve give priority to index.js over index.json', async () => { + const p = await resolve(join(dataPath, 'cc')) + expect(p).toBe(join(dataPath, 'cc', 'index.js')) + }) + + it('should throw an error for non existing paths', async () => { + try { + await resolve(join(dataPath, 'aaa.js')) + throw new Error('Should not run this line.') + } catch (ex) { + expect(ex.message).toMatch(/Cannot find module/) + } + }) +}) diff --git a/test/lib/next-test-utils.js b/test/lib/next-test-utils.js new file mode 100644 index 00000000..6546f2fa --- /dev/null +++ b/test/lib/next-test-utils.js @@ -0,0 +1,29 @@ +import portFinder from 'portfinder' +import fetch from 'node-fetch' +import qs from 'querystring' + +import server from '../../dist/server/next' +import build from '../../dist/server/build' +import _pkg from '../../package.json' + +export const nextServer = server +export const nextBuild = build +export const pkg = _pkg + +export function findPort () { + return new Promise((resolve, reject) => { + portFinder.getPort((err, port) => { + if (err) return reject(err) + return resolve(port) + }) + }) +} + +export function renderViaAPI (app, pathname, query = {}) { + return app.renderToHTML({}, {}, pathname, query) +} + +export function renderViaHTTP (appPort, pathname, query = {}) { + const url = `http://localhost:${appPort}${pathname}?${qs.stringify(query)}` + return fetch(url).then((res) => res.text()) +} diff --git a/test/lib/next-webdriver.js b/test/lib/next-webdriver.js new file mode 100644 index 00000000..a7967f8a --- /dev/null +++ b/test/lib/next-webdriver.js @@ -0,0 +1,10 @@ +import wd from 'wd' + +export default async function (appPort, pathname) { + const url = `http://localhost:${appPort}${pathname}` + + const browser = wd.promiseChainRemote('http://localhost:9515/') + await browser.init({browserName: 'chrome'}).get(url) + + return browser +} diff --git a/test/lib/shallow-equals.test.js b/test/lib/shallow-equals.test.js deleted file mode 100644 index 49ac220d..00000000 --- a/test/lib/shallow-equals.test.js +++ /dev/null @@ -1,44 +0,0 @@ -/* global expect, describe, test */ - -'use strict' - -import shallowEquals from '../../lib/shallow-equals' - -describe('shallow-equals', () => { - test('returns true if all key/value pairs match', () => { - expect(shallowEquals({ - a: 1, - b: 2, - c: 99 - }, { - a: 1, - b: 2, - c: 99 - })).toBeTruthy() - }) - - test('returns false if any key/value pair is different', () => { - expect(shallowEquals({ - a: 1, - b: 2, - c: 99 - }, { - a: 1, - b: 2, - c: 99, - d: 33 - })).toBeFalsy() - }) - - test('returns false if nested objects are contained', () => { - expect(shallowEquals({ - a: 1, - b: 2, - c: {} - }, { - a: 1, - b: 2, - c: {} - })).toBeFalsy() - }) -}) diff --git a/test/unit/shallow-equal.test.js b/test/unit/shallow-equal.test.js new file mode 100644 index 00000000..8ad4e744 --- /dev/null +++ b/test/unit/shallow-equal.test.js @@ -0,0 +1,34 @@ +/* global describe, it, expect */ + +import shallowEquals from '../../dist/lib/shallow-equals' + +describe('Shallow Equals', () => { + it('should be true if both objects are the same', () => { + const a = { aa: 10 } + expect(shallowEquals(a, a)).toBe(true) + }) + + it('should be true if both objects are similar', () => { + const a = { aa: 10, bb: 30 } + const b = { aa: 10, bb: 30 } + expect(shallowEquals(a, b)).toBe(true) + }) + + it('should be false if objects have different keys', () => { + const a = { aa: 10, bb: 30 } + const b = { aa: 10, cc: 50 } + expect(shallowEquals(a, b)).toBe(false) + }) + + it('should be false if objects have same keys but different values', () => { + const a = { aa: 10, bb: 30 } + const b = { aa: 10, bb: 50 } + expect(shallowEquals(a, b)).toBe(false) + }) + + it('should be false if objects if only they matched deeply', () => { + const a = { aa: 10, bb: { a: 10 } } + const b = { aa: 10, bb: { a: 10 } } + expect(shallowEquals(a, b)).toBe(false) + }) +}) diff --git a/yarn.lock b/yarn.lock index 932d774e..5fcf7fc9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -45,13 +45,17 @@ acorn@^4.0.1, acorn@^4.0.3: version "4.0.4" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.4.tgz#17a8d6a7a6c4ef538b814ec9abac2779293bf30a" +adm-zip@^0.4.7: + version "0.4.7" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1" + ajv-keywords@^1.0.0, ajv-keywords@^1.1.1: version "1.5.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.0.tgz#c11e6859eafff83e0dafc416929472eca946aa2c" ajv@^4.7.0: - version "4.10.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.10.3.tgz#3e4fea9675b157de7888b80dd0ed735b83f28e11" + version "4.10.4" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.10.4.tgz#c0974dd00b3464984892d6010aa9c2c945933254" dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" @@ -111,6 +115,30 @@ aproba@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.0.4.tgz#2713680775e7614c8ba186c065d4e2e52d1072c0" +archiver-utils@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-1.3.0.tgz#e50b4c09c70bf3d680e32ff1b7994e9f9d895174" + dependencies: + glob "^7.0.0" + graceful-fs "^4.1.0" + lazystream "^1.0.0" + lodash "^4.8.0" + normalize-path "^2.0.0" + readable-stream "^2.0.0" + +archiver@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/archiver/-/archiver-1.1.0.tgz#e1e8c4d356cf155308f351d60cc18cb6fb2344ee" + dependencies: + archiver-utils "^1.3.0" + async "^2.0.0" + buffer-crc32 "^0.2.1" + glob "^7.0.0" + lodash "^4.8.0" + readable-stream "^2.0.0" + tar-stream "^1.5.0" + zip-stream "^1.1.0" + archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" @@ -202,11 +230,11 @@ async@^0.9.0: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" -async@^1.3.0, async@^1.4.0, async@^1.4.2: +async@^1.3.0, async@^1.4.0, async@^1.4.2, async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^2.1.2, async@^2.1.4: +async@^2.0.0, async@^2.1.2, async@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4" dependencies: @@ -216,6 +244,12 @@ async@~0.2.6: version "0.2.10" resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" +async@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/async/-/async-2.0.1.tgz#b709cc0280a9c36f09f4536be823c838a9049e25" + dependencies: + lodash "^4.8.0" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -422,13 +456,13 @@ babel-plugin-check-es2015-constants@^6.3.13: babel-runtime "^6.0.0" babel-plugin-istanbul@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-3.0.0.tgz#da7324520ae0b8a44b6a078e72e883374a9fab76" + version "3.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-3.1.2.tgz#11d5abde18425ec24b5d648c7e0b5d25cd354a22" dependencies: find-up "^1.1.2" - istanbul-lib-instrument "^1.1.4" + istanbul-lib-instrument "^1.4.2" object-assign "^4.1.0" - test-exclude "^3.2.2" + test-exclude "^3.3.0" babel-plugin-jest-hoist@^18.0.0: version "18.0.0" @@ -906,7 +940,7 @@ binary-extensions@^1.0.0: version "1.8.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774" -bl@~1.1.2: +bl@^1.0.0, bl@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/bl/-/bl-1.1.2.tgz#fdca871a99713aa00d19e3bbba41c44787a65398" dependencies: @@ -922,6 +956,10 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" +boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + boom@2.x.x: version "2.10.1" resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" @@ -1011,10 +1049,10 @@ browserify-zlib@^0.1.4: pako "~0.2.0" browserslist@^1.4.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.5.1.tgz#67c3f2a1a6ad174cd01d25d2362e6e6083b26986" + version "1.5.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.5.2.tgz#1c82fde0ee8693e6d15c49b7bff209dc06298c56" dependencies: - caniuse-db "^1.0.30000601" + caniuse-db "^1.0.30000604" bser@^1.0.2: version "1.0.2" @@ -1022,6 +1060,10 @@ bser@^1.0.2: dependencies: node-int64 "^0.4.0" +buffer-crc32@^0.2.1: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + buffer-shims@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" @@ -1042,9 +1084,9 @@ builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" -builtin-status-codes@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-2.0.0.tgz#6f22003baacf003ccd287afe6872151fddc58579" +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" caching-transform@^1.0.0: version "1.0.1" @@ -1076,9 +1118,9 @@ camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" -caniuse-db@^1.0.30000601: - version "1.0.30000602" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000602.tgz#06b2cbfb6c3aeef7ddb18cd588043549ad1a2d4e" +caniuse-db@^1.0.30000604: + version "1.0.30000604" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000604.tgz#bc139270a777564d19c0aadcd832b491d093bda5" cardinal@^1.0.0: version "1.0.0" @@ -1087,7 +1129,7 @@ cardinal@^1.0.0: ansicolors "~0.2.1" redeyed "~1.0.0" -case-sensitive-paths-webpack-plugin: +case-sensitive-paths-webpack-plugin@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-1.1.4.tgz#8aaedd5699a86cac2b34cf40d9b4145758978472" @@ -1112,6 +1154,27 @@ chalk@*, chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +cheerio@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash.assignin "^4.0.9" + lodash.bind "^4.1.4" + lodash.defaults "^4.0.1" + lodash.filter "^4.4.0" + lodash.flatten "^4.2.0" + lodash.foreach "^4.3.0" + lodash.map "^4.4.0" + lodash.merge "^4.4.0" + lodash.pick "^4.2.1" + lodash.reduce "^4.4.0" + lodash.reject "^4.4.0" + lodash.some "^4.4.0" + chokidar@^1.0.0, chokidar@^1.4.3: version "1.6.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2" @@ -1127,6 +1190,15 @@ chokidar@^1.0.0, chokidar@^1.4.3: optionalDependencies: fsevents "^1.0.0" +chromedriver@^2.26.1: + version "2.27.1" + resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-2.27.1.tgz#b4f2fbace4309e7cf705e9c0af64c0c21c88fae9" + dependencies: + adm-zip "^0.4.7" + kew "^0.5.0" + mkdirp "^0.5.0" + rimraf "^2.0.3" + ci-info@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.0.0.tgz#dc5285f2b4e251821683681c381c3388f46ec534" @@ -1220,6 +1292,15 @@ commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" +compress-commons@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-1.1.0.tgz#9f4460bb1288564c7473916e0298aa3c320dcadb" + dependencies: + buffer-crc32 "^0.2.1" + crc32-stream "^1.0.0" + normalize-path "^2.0.0" + readable-stream "^2.0.0" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1276,6 +1357,13 @@ coveralls@2.11.15: minimist "1.2.0" request "2.75.0" +crc32-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-1.0.0.tgz#ea155e5e1d738ed3778438ffe92ffe2a141aeb3f" + dependencies: + buffer-crc32 "^0.2.1" + readable-stream "^2.0.0" + create-ecdh@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d" @@ -1299,6 +1387,19 @@ create-hmac@^1.1.0, create-hmac@^1.1.2: create-hash "^1.1.0" inherits "^2.0.1" +cross-env@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-3.1.4.tgz#56e8bca96f17908a6eb1bc2012ca126f92842130" + dependencies: + cross-spawn "^3.0.1" + +cross-spawn@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + cross-spawn@^4: version "4.0.2" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" @@ -1344,6 +1445,19 @@ crypto-browserify@3.3.0: ripemd160 "0.2.0" sha.js "2.2.6" +css-select@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" + dependencies: + boolbase "~1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "~1.0.1" + +css-what@2.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" + "cssom@>= 0.3.0 < 0.4.0", cssom@0.3.x: version "0.3.1" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.1.tgz#c9e37ef2490e64f6d1baa10fda852257082c25d3" @@ -1502,6 +1616,13 @@ doctrine@^1.2.2: esutils "^2.0.2" isarray "^1.0.0" +dom-serializer@~0.1.0, dom-serializer@0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + dom-walk@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" @@ -1510,6 +1631,27 @@ domain-browser@^1.1.1: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" +domelementtype@^1.3.0, domelementtype@1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" + dependencies: + domelementtype "1" + +domutils@^1.5.1, domutils@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + dependencies: + dom-serializer "0" + domelementtype "1" + duplexer2@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" @@ -1549,6 +1691,12 @@ encoding@^0.1.11: dependencies: iconv-lite "~0.4.13" +end-of-stream@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.1.0.tgz#e9353258baa9108965efc41cb0ef8ade2f3cfb07" + dependencies: + once "~1.3.0" + end-of-stream@~0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" @@ -1572,6 +1720,10 @@ enhanced-resolve@~0.9.0: memory-fs "^0.2.0" tapable "^0.1.8" +entities@^1.1.1, entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + errno@^0.1.3, "errno@>=0.1.1 <0.2.0-0": version "0.1.4" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" @@ -2051,8 +2203,8 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" fsevents@^1.0.0: - version "1.0.15" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.0.15.tgz#fa63f590f3c2ad91275e4972a6cea545fb0aae44" + version "1.0.17" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.0.17.tgz#8537f3f12272678765b4fd6528c0f1f66f8f4558" dependencies: nan "^2.3.0" node-pre-gyp "^0.6.29" @@ -2256,7 +2408,7 @@ graceful-fs@^3.0.0: dependencies: natives "^1.1.0" -graceful-fs@^4.1.2, graceful-fs@^4.1.6: +graceful-fs@^4.1.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -2301,13 +2453,6 @@ gulp-cached@1.1.1: lodash.defaults "^4.2.0" through2 "^2.0.1" -gulp-jest@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulp-jest/-/gulp-jest-1.0.0.tgz#cc8803a60503b00de02c825243d5d02ab1d05c39" - dependencies: - gulp-util "^3.0.0" - through2 "^2.0.1" - gulp-notify@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/gulp-notify/-/gulp-notify-2.2.0.tgz#046c8285c292e97eed4e15a009c26cbbe5cef135" @@ -2460,6 +2605,17 @@ htmlescape@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" +htmlparser2@^3.9.1: + version "3.9.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" + dependencies: + domelementtype "^1.3.0" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^2.0.2" + http-errors@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.4.0.tgz#6c0242dea6b3df7afda153c71089b31c6e82aabf" @@ -2807,9 +2963,9 @@ istanbul-lib-hook@^1.0.0-alpha.4: dependencies: append-transform "^0.3.0" -istanbul-lib-instrument@^1.1.1, istanbul-lib-instrument@^1.1.4, istanbul-lib-instrument@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.3.1.tgz#112c25a4f2f9bc361d13d14bbff992331b974e52" +istanbul-lib-instrument@^1.1.1, istanbul-lib-instrument@^1.3.0, istanbul-lib-instrument@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.4.2.tgz#0e2fdfac93c1dabf2e31578637dc78a19089f43e" dependencies: babel-generator "^6.18.0" babel-template "^6.16.0" @@ -2849,7 +3005,7 @@ jest-changed-files@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-17.0.2.tgz#f5657758736996f590a51b87e5c9369d904ba7b7" -jest-cli@^18.1.0: +jest-cli@^18.0.0: version "18.1.0" resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-18.1.0.tgz#5ead36ecad420817c2c9baa2aa7574f63257b3d6" dependencies: @@ -3021,12 +3177,6 @@ jest-util@^18.1.0: jest-mock "^18.0.0" mkdirp "^0.5.1" -jest@^18.0.0: - version "18.1.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-18.1.0.tgz#bcebf1e203dee5c2ad2091c805300a343d9e6c7d" - dependencies: - jest-cli "^18.1.0" - jodid25519@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" @@ -3037,16 +3187,16 @@ js-tokens@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-2.0.0.tgz#79903f5563ee778cc1162e6dcf1a0027c97f9cb5" -js-yaml@^3.5.1, js-yaml@3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30" +js-yaml@^3.5.1, js-yaml@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" dependencies: argparse "^1.0.7" esprima "^2.6.0" -js-yaml@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" +js-yaml@3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30" dependencies: argparse "^1.0.7" esprima "^2.6.0" @@ -3133,6 +3283,10 @@ jsx-ast-utils@^1.3.3: acorn-jsx "^3.0.1" object-assign "^4.1.0" +kew@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/kew/-/kew-0.5.0.tgz#ece11cb5d8d01a81f8ce804c8d0bba06e6b25ca2" + kind-of@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47" @@ -3143,6 +3297,12 @@ lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" +lazystream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" + dependencies: + readable-stream "^2.0.5" + lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" @@ -3271,10 +3431,18 @@ lodash.assign@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" +lodash.assignin@^4.0.9: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" + lodash.assignwith@^4.0.7: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz#127a97f02adc41751a954d24b0de17e100e038eb" +lodash.bind@^4.1.4: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" + lodash.clone@^4.3.2: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" @@ -3286,7 +3454,7 @@ lodash.clonedeep@^3.0.0: lodash._baseclone "^3.0.0" lodash._bindcallback "^3.0.0" -lodash.defaults@^4.2.0: +lodash.defaults@^4.0.1, lodash.defaults@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" @@ -3296,6 +3464,18 @@ lodash.escape@^3.0.0: dependencies: lodash._root "^3.0.0" +lodash.filter@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" + +lodash.flatten@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + +lodash.foreach@^4.3.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + lodash.isarguments@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" @@ -3324,10 +3504,18 @@ lodash.keys@^3.0.0: lodash.isarguments "^3.0.0" lodash.isarray "^3.0.0" +lodash.map@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" + lodash.mapvalues@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" +lodash.merge@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5" + lodash.pick@^4.2.1: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" @@ -3336,11 +3524,19 @@ lodash.pickby@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff" +lodash.reduce@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" + +lodash.reject@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" + lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" -lodash.some@^4.2.2: +lodash.some@^4.2.2, lodash.some@^4.4.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" @@ -3365,9 +3561,9 @@ lodash.templatesettings@^3.0.0: lodash._reinterpolate "^3.0.0" lodash.escape "^3.0.0" -lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.3, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1: - version "4.17.3" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.3.tgz#557ed7d2a9438cac5fd5a43043ca60cb455e01f7" +lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.3, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.1, lodash@^4.6.1, lodash@^4.8.0: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" lodash@~1.0.1: version "1.0.2" @@ -3377,6 +3573,10 @@ lodash@~2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-2.4.2.tgz#fadd834b9683073da179b3eae6d9c0d15053f73e" +lodash@4.16.2: + version "4.16.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.16.2.tgz#3e626db827048a699281a8a125226326cfc0e652" + log-driver@1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" @@ -3493,7 +3693,7 @@ mime-db@~1.25.0: version "1.25.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.25.0.tgz#c18dbd7c73a5dbf6f44a024dc0d165a1e7b1c392" -mime-types, mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.7: +mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.7, mime-types@2.1.13: version "2.1.13" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.13.tgz#e07aaa9c6c6b9a7ca3012c69003ad25a39e92a88" dependencies: @@ -3547,7 +3747,7 @@ mkdirp-then@1.2.0: any-promise "^1.1.0" mkdirp "^0.5.0" -mkdirp@^0.5.0, mkdirp@^0.5.1, "mkdirp@>=0.5 0", mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@^0.5.0, mkdirp@^0.5.1, "mkdirp@>=0.5 0", mkdirp@~0.5.0, mkdirp@~0.5.1, mkdirp@0.5.x: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: @@ -3600,12 +3800,12 @@ negotiator@0.6.1: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" node-emoji@^1.4.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.4.3.tgz#5272f70b823c4df6d7c39f84fd8203f35b3e5d36" + version "1.5.0" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.5.0.tgz#9a0d9fe03fd43afa357d6d8e439aa31e599959b7" dependencies: string.prototype.codepointat "^0.2.0" -node-fetch@^1.0.1: +node-fetch@^1.0.1, node-fetch@^1.6.3: version "1.6.3" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04" dependencies: @@ -3727,7 +3927,7 @@ normalize-path@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" -normalize-path@^2.0.1: +normalize-path@^2.0.0, normalize-path@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a" @@ -3740,6 +3940,12 @@ npmlog@^4.0.1: gauge "~2.7.1" set-blocking "~2.0.0" +nth-check@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" + dependencies: + boolbase "~1.0.0" + number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -4030,6 +4236,14 @@ pluralize@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" +portfinder@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.10.tgz#7a4de9d98553c315da6f1e1ed05138eeb2d16bb8" + dependencies: + async "^1.5.2" + debug "^2.2.0" + mkdirp "0.5.x" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -4100,7 +4314,7 @@ punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" -q@^1.1.2: +q@^1.1.2, q@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e" @@ -4196,7 +4410,7 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.0, readable-stream@^2.1.5, readable-stream@^2.2.2: +readable-stream@^2.0.0, "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.0, readable-stream@^2.1.5, readable-stream@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e" dependencies: @@ -4446,7 +4660,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@^2.2.8, rimraf@^2.3.3, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.5.4, rimraf@~2.5.1, rimraf@~2.5.4, rimraf@2: +rimraf@^2.0.3, rimraf@^2.2.8, rimraf@^2.3.3, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.5.4, rimraf@~2.5.1, rimraf@~2.5.4, rimraf@2: version "2.5.4" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04" dependencies: @@ -4563,8 +4777,8 @@ shebang-regex@^1.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" shelljs@^0.7.5: - version "0.7.5" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.5.tgz#2eef7a50a21e1ccf37da00df767ec69e30ad0675" + version "0.7.6" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad" dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -4659,7 +4873,7 @@ spdx-license-ids@^1.0.2: version "1.2.2" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" -sprintf-js@~1.0.2: +sprintf-js@^1.0.3, sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -4721,10 +4935,10 @@ stream-consume@~0.1.0: resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.0.tgz#a41ead1a6d6081ceb79f65b061901b6d8f3d1d0f" stream-http@^2.3.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.5.0.tgz#585eee513217ed98fe199817e7313b6f772a6802" + version "2.6.0" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.6.0.tgz#adf3309ced17624ebfb7ef13e6ac4cfe405a8b12" dependencies: - builtin-status-codes "^2.0.0" + builtin-status-codes "^3.0.0" inherits "^2.0.1" readable-stream "^2.1.0" to-arraybuffer "^1.0.0" @@ -4848,6 +5062,15 @@ tar-pack@~3.3.0: tar "~2.2.1" uid-number "~0.0.6" +tar-stream@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.2.tgz#fbc6c6e83c1a19d4cb48c7d96171fc248effc7bf" + dependencies: + bl "^1.0.0" + end-of-stream "^1.0.0" + readable-stream "^2.0.0" + xtend "^4.0.0" + tar@~2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" @@ -4856,7 +5079,7 @@ tar@~2.2.1: fstream "^1.0.2" inherits "2" -test-exclude@^3.2.2, test-exclude@^3.3.0: +test-exclude@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-3.3.0.tgz#7a17ca1239988c98367b0621456dbb7d4bc38977" dependencies: @@ -4993,6 +5216,13 @@ unc-path-regex@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" +underscore.string@3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-3.3.4.tgz#2c2a3f9f83e64762fdc45e6ceac65142864213db" + dependencies: + sprintf-js "^1.0.3" + util-deprecate "^1.0.2" + uniq@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" @@ -5018,7 +5248,7 @@ user-home@^2.0.0: dependencies: os-homedir "^1.0.0" -util-deprecate@~1.0.1: +util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -5045,6 +5275,10 @@ validate-npm-package-license@^3.0.1: spdx-correct "~1.0.0" spdx-expression-parse "~1.0.0" +vargs@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/vargs/-/vargs-0.1.0.tgz#6b6184da6520cc3204ce1b407cac26d92609ebff" + verror@1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" @@ -5125,6 +5359,18 @@ watchpack@^1.0.0: chokidar "^1.4.3" graceful-fs "^4.1.2" +wd@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/wd/-/wd-1.1.1.tgz#f2c6c41700f69e3009dcfc3574f42e9ae70fb5c1" + dependencies: + archiver "1.1.0" + async "2.0.1" + lodash "4.16.2" + q "1.4.1" + request "2.75.0" + underscore.string "3.3.4" + vargs "0.1.0" + webidl-conversions@^3.0.0, webidl-conversions@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -5230,8 +5476,8 @@ whatwg-fetch@>=0.10.0: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.1.tgz#078b9461bbe91cea73cbce8bb122a05f9e92b772" whatwg-url@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.1.1.tgz#567074923352de781e3500d64a86aa92a971b4a4" + version "4.2.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.2.0.tgz#abf1a3f5ff4bc2005b3f0c2119382631789d8e44" dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" @@ -5252,10 +5498,6 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.1" -window-size@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" @@ -5291,10 +5533,10 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" write-file-atomic@^1.1.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.2.0.tgz#14c66d4e4cb3ca0565c28cf3b7a6f3e4d5938fab" + version "1.3.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.1.tgz#7d45ba32316328dd1ec7d90f60ebc0d845bb759a" dependencies: - graceful-fs "^4.1.2" + graceful-fs "^4.1.11" imurmurhash "^0.1.4" slide "^1.1.5" @@ -5331,14 +5573,14 @@ yallist@^2.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.0.0.tgz#306c543835f09ee1a4cb23b7bce9ab341c91cdd4" yargs-parser@^4.0.2, yargs-parser@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.0.tgz#6ced869cd05a3dca6a1eaee38b68aeed4b0b4101" + version "4.2.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" dependencies: camelcase "^3.0.0" yargs@^6.0.0, yargs@^6.3.0, yargs@^6.4.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.5.0.tgz#a902e23a1f0fe912b2a03f6131b7ed740c9718ff" + version "6.6.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" dependencies: camelcase "^3.0.0" cliui "^3.2.0" @@ -5351,7 +5593,6 @@ yargs@^6.0.0, yargs@^6.3.0, yargs@^6.4.0: set-blocking "^2.0.0" string-width "^1.0.2" which-module "^1.0.0" - window-size "^0.2.0" y18n "^3.2.1" yargs-parser "^4.2.0" @@ -5364,3 +5605,12 @@ yargs@~3.10.0: decamelize "^1.0.0" window-size "0.1.0" +zip-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.1.0.tgz#2ad479fffc168e05a888e8c348ff6813b3f13733" + dependencies: + archiver-utils "^1.3.0" + compress-commons "^1.1.0" + lodash "^4.8.0" + readable-stream "^2.0.0" +