From 862bc8000f5a01613cd8f2279a4bd863e846573a Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Mon, 15 Jul 2019 06:27:13 -0400 Subject: [PATCH 01/32] fix add-to-studio modal height, gradient interference --- src/components/modal/addtostudio/modal.scss | 12 ++++++++++-- src/components/modal/addtostudio/presentation.jsx | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/modal/addtostudio/modal.scss b/src/components/modal/addtostudio/modal.scss index 9544e1e04..a497ce96a 100644 --- a/src/components/modal/addtostudio/modal.scss +++ b/src/components/modal/addtostudio/modal.scss @@ -3,15 +3,17 @@ .mod-addToStudio { min-height: 15rem; - max-height: calc(100% - 8rem); + max-height: calc(100% - 5rem); /* Some value for height must be set for scrolling to work */ - height: 100%; + height: 28rem; overflow: hidden; @media #{$small}, #{$small-height} { overflow: hidden; + height: 100%; + max-height: 100%; } } @@ -71,6 +73,12 @@ min-height: 30rem; */ +/* provides buffer at bottom of list, so that bottommost items +are not obscured by gradient overlay */ +.studio-list-footer-spacer { + height: 1.5rem; +} + .studio-list-bottom-gradient { position: absolute; right: 1rem; diff --git a/src/components/modal/addtostudio/presentation.jsx b/src/components/modal/addtostudio/presentation.jsx index 913ca1092..bf6725897 100644 --- a/src/components/modal/addtostudio/presentation.jsx +++ b/src/components/modal/addtostudio/presentation.jsx @@ -56,6 +56,7 @@ const AddToStudioModalPresentation = ({
{studioButtons}
+
From 911ecc85162764f825d6995784c346a77284396d Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Fri, 12 Jul 2019 11:39:04 -0400 Subject: [PATCH 02/32] Format validation; redo of PR 3116 --- src/components/formik-forms/formik-input.jsx | 11 ++++++++--- src/components/forms/row.scss | 5 +++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/components/formik-forms/formik-input.jsx b/src/components/formik-forms/formik-input.jsx index ab62130a0..b128d6b6b 100644 --- a/src/components/formik-forms/formik-input.jsx +++ b/src/components/formik-forms/formik-input.jsx @@ -11,9 +11,10 @@ require('../forms/row.scss'); const FormikInput = ({ className, error, + validationClassName, ...props }) => ( -
+
{error && ( - + )}
); @@ -31,7 +35,8 @@ const FormikInput = ({ FormikInput.propTypes = { className: PropTypes.string, error: PropTypes.string, - type: PropTypes.string + type: PropTypes.string, + validationClassName: PropTypes.string }; module.exports = FormikInput; diff --git a/src/components/forms/row.scss b/src/components/forms/row.scss index 17a8e3fa8..56f72fcc2 100644 --- a/src/components/forms/row.scss +++ b/src/components/forms/row.scss @@ -21,6 +21,11 @@ } } +/* allow elements such as validation errors to position relative to this row */ +.row-relative { + position: relative; +} + .row-label { margin-bottom: .75rem; line-height: 1.7rem; From faa37ae270bdd971930ed99760aac2caf4205a8d Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Mon, 15 Jul 2019 17:26:02 -0400 Subject: [PATCH 03/32] rename row-relative to row-with-tooltip --- src/components/formik-forms/formik-input.jsx | 2 +- src/components/forms/row.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/formik-forms/formik-input.jsx b/src/components/formik-forms/formik-input.jsx index b128d6b6b..0788d0b9c 100644 --- a/src/components/formik-forms/formik-input.jsx +++ b/src/components/formik-forms/formik-input.jsx @@ -14,7 +14,7 @@ const FormikInput = ({ validationClassName, ...props }) => ( -
+
Date: Wed, 17 Jul 2019 12:58:50 -0400 Subject: [PATCH 04/32] After rebasing on develop, reintroduce changes --- src/components/join-flow/join-flow-steps.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/join-flow/join-flow-steps.jsx b/src/components/join-flow/join-flow-steps.jsx index 1a03396dd..c612853cd 100644 --- a/src/components/join-flow/join-flow-steps.jsx +++ b/src/components/join-flow/join-flow-steps.jsx @@ -10,6 +10,8 @@ const validate = require('../../lib/validate'); const FormikInput = require('../../components/formik-forms/formik-input.jsx'); const JoinFlowStep = require('./join-flow-step.jsx'); +require('./join-flow-steps.scss'); + /* * Username step */ @@ -127,6 +129,7 @@ class UsernameStep extends React.Component { id="username" name="username" validate={this.validateUsernameIfPresent} + validationClassName="validation-full-width-input" onBlur={() => validateField('username')} // eslint-disable-line react/jsx-no-bind />
From dd6b7ba4e205215b60c2857279a28a918800153c Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Wed, 17 Jul 2019 14:56:48 -0400 Subject: [PATCH 05/32] Move tap tests into legacy folders --- package.json | 14 +- test/integration-legacy/README.md | 35 ++ test/integration-legacy/selenium-helpers.js | 168 ++++++++++ .../smoke-testing/test-join.js | 30 ++ .../smoke-testing/test-login-failures.js | 89 +++++ .../smoke-testing/test-my-stuff.js | 151 +++++++++ .../smoke-testing/test_footer_links.js | 305 ++++++++++++++++++ .../smoke-testing/test_navbar_links.js | 123 +++++++ .../smoke-testing/test_project_page.js | 61 ++++ .../smoke-testing/test_project_rows.js | 93 ++++++ .../smoke-testing/test_search.js | 58 ++++ .../test_signing_in_and_out_discuss.js | 62 ++++ .../test_signing_in_and_out_homepage.js | 59 ++++ .../smoke-testing/test_statistics_page.js | 68 ++++ .../teacher_registration_utils.js | 99 ++++++ .../test_teacher_registration_address_step.js | 60 ++++ ..._teacher_registration_demographics_step.js | 61 ++++ .../test_teacher_registration_name_step.js | 60 ++++ ..._teacher_registration_organization_step.js | 89 +++++ .../test_teacher_registration_phone_step.js | 45 +++ ...test_teacher_registration_username_step.js | 114 +++++++ ...st_teacher_registration_usescratch_step.js | 71 ++++ .../check_duplicate_strings.js | 52 +++ test/localization-legacy/check_string_ids.js | 72 +++++ test/localization-legacy/check_valid_json.js | 23 ++ test/unit-legacy/lib/validate.js | 66 ++++ test/unit-legacy/redux/preview-test.js | 176 ++++++++++ .../unit-legacy/test_fastly_config_methods.js | 79 +++++ 28 files changed, 2377 insertions(+), 6 deletions(-) create mode 100644 test/integration-legacy/README.md create mode 100644 test/integration-legacy/selenium-helpers.js create mode 100644 test/integration-legacy/smoke-testing/test-join.js create mode 100644 test/integration-legacy/smoke-testing/test-login-failures.js create mode 100644 test/integration-legacy/smoke-testing/test-my-stuff.js create mode 100644 test/integration-legacy/smoke-testing/test_footer_links.js create mode 100644 test/integration-legacy/smoke-testing/test_navbar_links.js create mode 100644 test/integration-legacy/smoke-testing/test_project_page.js create mode 100644 test/integration-legacy/smoke-testing/test_project_rows.js create mode 100644 test/integration-legacy/smoke-testing/test_search.js create mode 100644 test/integration-legacy/smoke-testing/test_signing_in_and_out_discuss.js create mode 100644 test/integration-legacy/smoke-testing/test_signing_in_and_out_homepage.js create mode 100644 test/integration-legacy/smoke-testing/test_statistics_page.js create mode 100644 test/integration-legacy/teacher-registration/teacher_registration_utils.js create mode 100644 test/integration-legacy/teacher-registration/test_teacher_registration_address_step.js create mode 100644 test/integration-legacy/teacher-registration/test_teacher_registration_demographics_step.js create mode 100644 test/integration-legacy/teacher-registration/test_teacher_registration_name_step.js create mode 100644 test/integration-legacy/teacher-registration/test_teacher_registration_organization_step.js create mode 100644 test/integration-legacy/teacher-registration/test_teacher_registration_phone_step.js create mode 100644 test/integration-legacy/teacher-registration/test_teacher_registration_username_step.js create mode 100644 test/integration-legacy/teacher-registration/test_teacher_registration_usescratch_step.js create mode 100644 test/localization-legacy/check_duplicate_strings.js create mode 100644 test/localization-legacy/check_string_ids.js create mode 100644 test/localization-legacy/check_valid_json.js create mode 100644 test/unit-legacy/lib/validate.js create mode 100644 test/unit-legacy/redux/preview-test.js create mode 100644 test/unit-legacy/test_fastly_config_methods.js diff --git a/package.json b/package.json index 970ed1fab..2681b4fa2 100644 --- a/package.json +++ b/package.json @@ -4,13 +4,13 @@ "description": "Standalone WWW client for Scratch", "scripts": { "start": "node ./dev-server/index.js", - "test": "npm run test:lint && npm run build && npm run test:tap", + "test": "npm run test:lint && npm run build && npm run test:unit:tap", "test:lint": "eslint . --ext .js,.jsx,.json", - "test:smoke": "tap ./test/integration/smoke-testing/*.js --timeout=3600 --no-coverage -R classic", - "test:smoke:verbose": "tap ./test/integration/smoke-testing/*.js --timeout=3600 --no-coverage -R spec", - "test:smoke:sauce": "SMOKE_REMOTE=true tap ./test/integration/smoke-testing/*.js --timeout=60000 --no-coverage -R classic", - "test:tap": "tap ./test/{unit,localization}/*.js --no-coverage -R classic", - "test:coverage": "tap ./test/{unit,localization}/*.js --coverage --coverage-report=lcov", + "test:smoke": "tap ./test/integration-legacy/smoke-testing/*.js --timeout=3600 --no-coverage -R classic", + "test:smoke:verbose": "tap ./test/integration-legacy/smoke-testing/*.js --timeout=3600 --no-coverage -R spec", + "test:smoke:sauce": "SMOKE_REMOTE=true tap ./test/integration-legacy/smoke-testing/*.js --timeout=60000 --no-coverage -R classic", + "test:unit:tap": "tap ./test/{unit-legacy,localization-legacy}/*.js --no-coverage -R classic", + "test:coverage": "tap ./test/{unit-legacy,localization-legacy}/*.js --coverage --coverage-report=lcov", "build": "npm run clean && npm run translate && webpack --bail", "clean": "rm -rf ./build && rm -rf ./intl && mkdir -p build && mkdir -p intl", "deploy": "npm run deploy:s3 && npm run deploy:fastly", @@ -60,6 +60,7 @@ "babel-preset-react": "6.22.0", "bowser": "1.9.4", "cheerio": "1.0.0-rc.2", + "chromedriver": "75.1.0", "classnames": "2.2.5", "cookie": "0.2.2", "copy-webpack-plugin": "0.2.0", @@ -115,6 +116,7 @@ "sass-loader": "6.0.6", "scratch-gui": "0.1.0-prerelease.20190711011201", "scratch-l10n": "latest", + "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0", "source-map-support": "0.3.2", "style-loader": "0.12.3", diff --git a/test/integration-legacy/README.md b/test/integration-legacy/README.md new file mode 100644 index 000000000..251e5d29a --- /dev/null +++ b/test/integration-legacy/README.md @@ -0,0 +1,35 @@ +# Requirements + +* Selenium + * See this directory's package.json +* TAP + * In the scratch-www repo's package.json +* [Chromedriver](https://sites.google.com/a/chromium.org/chromedriver/) + +# Running the tests + +* By default, tests run against our Staging instance, but you can pass in a different location if you want to run the tests against e.g. your local build +* Tests can be run using Saucelabs, an online service that can test browser/os combinations remotely. Currently all tests are written for use for chrome on mac. + +## Using tap +* Run all tests in the smoke-testing directory from the command-line: `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password ROOT_URL=https://scratch.mit.edu npm run smoke` +* To run a single file from the command-line: `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password ROOT_URL=https://scratch.mit.edu node_modules/.bin/tap ./test/integration/smoke-testing/filename.js --timeout=3600` + * The timeout var is for the length of the entire tap test-suite; if you are getting a timeout error, you may need to adjust this value (some of the Selenium tests take a while to run) +* To run tests using saucelabs run this command `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password SAUCE_USERNAME=saucelabsUsername SAUCE_ACCESS_KEY=saucelabsAccessKey ROOT_URL=https://scratch.mit.edu npm run smoke-sauce` + + +### Configuration + +| Variable | Default | Description | +| --------------------- | --------------------- | --------------------------------------------------------- | +| `ROOT_URL` | `scratch.ly` | Location you want to run the tests against | +| `SMOKE_USERNAME` | `None` | Username for Scratch user you're signing in with to test | +| `SMOKE_PASSWORD` | `None` | Password for Scratch user you're signing in with to test | +| `SMOKE_REMOTE` | `false` | Tests with Sauce Labs or not. True if running smoke-sauce | +| `SMOKE_HEADLESS` | `false` | Run browser in headless mode. Flaky at the moment | +| `SAUCE_USERNAME` | `None` | Username for your Sauce Labs account | +| `SAUCE_ACCESS_KEY` | `None` | Access Key for Sauce Labs found under User Settings | + + +## Using Saucelabs +* You will need a Saucelabs account in order to use it for testing. To find the Access Key, click your username and select User Settings from the dropdown menu. Near the bottom of the page is your access key that you can copy and use in the command line. diff --git a/test/integration-legacy/selenium-helpers.js b/test/integration-legacy/selenium-helpers.js new file mode 100644 index 000000000..710c00110 --- /dev/null +++ b/test/integration-legacy/selenium-helpers.js @@ -0,0 +1,168 @@ +const webdriver = require('selenium-webdriver'); +const bindAll = require('lodash.bindall'); +require('chromedriver'); + +const headless = process.env.SMOKE_HEADLESS || false; +const remote = process.env.SMOKE_REMOTE || false; +const ci = process.env.CI || false; +const buildID = process.env.TRAVIS_BUILD_NUMBER; +const {SAUCE_USERNAME, SAUCE_ACCESS_KEY} = process.env; +const {By, Key, until} = webdriver; + +const DEFAULT_TIMEOUT_MILLISECONDS = 20 * 1000; + +class SeleniumHelper { + constructor () { + bindAll(this, [ + 'buildDriver', + 'clickButton', + 'clickCss', + 'clickText', + 'clickXpath', + 'dragFromXpathToXpath', + 'findByCss', + 'findByXpath', + 'findText', + 'getKey', + 'getDriver', + 'getLogs', + 'getSauceDriver', + 'urlMatches', + 'waitUntilGone' + ]); + } + buildDriver (name) { + if (remote === 'true'){ + let nameToUse; + if (ci === 'true'){ + nameToUse = 'travis ' + buildID + ' : ' + name; + } else { + nameToUse = name; + } + this.driver = this.getSauceDriver(SAUCE_USERNAME, SAUCE_ACCESS_KEY, nameToUse); + } else { + this.driver = this.getDriver(); + } + return this.driver; + } + + getDriver () { + const chromeCapabilities = webdriver.Capabilities.chrome(); + let args = []; + if (headless) { + args.push('--headless'); + args.push('window-size=1024,1680'); + args.push('--no-sandbox'); + } + chromeCapabilities.set('chromeOptions', {args}); + let driver = new webdriver.Builder() + .forBrowser('chrome') + .withCapabilities(chromeCapabilities) + .build(); + return driver; + } + + getSauceDriver (username, accessKey, name) { + // Driver configs can be generated with the Sauce Platform Configurator + // https://wiki.saucelabs.com/display/DOCS/Platform+Configurator + let driverConfig = { + browserName: 'chrome', + platform: 'macOS 10.14', + version: '75.0' + }; + var driver = new webdriver.Builder() + .withCapabilities({ + browserName: driverConfig.browserName, + platform: driverConfig.platform, + version: driverConfig.version, + username: username, + accessKey: accessKey, + name: name + }) + .usingServer(`http://${username}:${accessKey + }@ondemand.saucelabs.com:80/wd/hub`) + .build(); + return driver; + } + + getKey (keyName) { + return Key[keyName]; + } + + findByXpath (xpath, timeoutMessage = `findByXpath timed out for path: ${xpath}`) { + return this.driver.wait(until.elementLocated(By.xpath(xpath)), DEFAULT_TIMEOUT_MILLISECONDS, timeoutMessage) + .then(el => ( + this.driver.wait(el.isDisplayed(), DEFAULT_TIMEOUT_MILLISECONDS, `${xpath} is not visible`) + .then(() => el) + )); + } + + waitUntilGone (element) { + return this.driver.wait(until.stalenessOf(element)); + } + + clickXpath (xpath) { + return this.findByXpath(xpath).then(el => el.click()); + } + + clickText (text) { + return this.clickXpath(`//*[contains(text(), '${text}')]`); + } + + findText (text) { + return this.driver.wait(until.elementLocated(By.xpath(`//*[contains(text(), '${text}')]`), 5 * 1000)); + } + + clickButton (text) { + return this.clickXpath(`//button[contains(text(), '${text}')]`); + } + + findByCss (css) { + return this.driver.wait(until.elementLocated(By.css(css), 1000 * 5)); + } + + clickCss (css) { + return this.findByCss(css).then(el => el.click()); + } + + dragFromXpathToXpath (startXpath, endXpath) { + return this.findByXpath(startXpath).then(startEl => { + return this.findByXpath(endXpath).then(endEl => { + return this.driver.actions() + .dragAndDrop(startEl, endEl) + .perform(); + }); + }); + } + + urlMatches (regex) { + return this.driver.wait(until.urlMatches(regex), 1000 * 5); + } + + getLogs (whitelist) { + return this.driver.manage() + .logs() + .get('browser') + .then((entries) => { + return entries.filter((entry) => { + const message = entry.message; + for (let i = 0; i < whitelist.length; i++) { + if (message.indexOf(whitelist[i]) !== -1) { + // eslint-disable-next-line no-console + // console.warn('Ignoring whitelisted error: ' + whitelist[i]); + return false; + } else if (entry.level !== 'SEVERE') { + // eslint-disable-next-line no-console + // console.warn('Ignoring non-SEVERE entry: ' + message); + return false; + } + return true; + } + return true; + }); + }); + } + +} + +module.exports = SeleniumHelper; diff --git a/test/integration-legacy/smoke-testing/test-join.js b/test/integration-legacy/smoke-testing/test-join.js new file mode 100644 index 000000000..ea524b061 --- /dev/null +++ b/test/integration-legacy/smoke-testing/test-join.js @@ -0,0 +1,30 @@ +const SeleniumHelper = require('../selenium-helpers.js'); +const helper = new SeleniumHelper(); + +var tap = require('tap'); +const test = tap.test; + +const driver = helper.buildDriver('www-smoke test-login-failures'); + +const { + clickText, + findByXpath +} = helper; + +var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; + +tap.plan(1); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + return driver.get(rootUrl); +}); + +test('Clicking Join Scratch opens scratchr2 iframe', t => { + clickText('Join Scratch') + .then(() => findByXpath('//iframe[contains(@class, "mod-registration")]')) + .then(() => t.end()); +}); diff --git a/test/integration-legacy/smoke-testing/test-login-failures.js b/test/integration-legacy/smoke-testing/test-login-failures.js new file mode 100644 index 000000000..a629bb5fd --- /dev/null +++ b/test/integration-legacy/smoke-testing/test-login-failures.js @@ -0,0 +1,89 @@ +const SeleniumHelper = require('../selenium-helpers.js'); +const helper = new SeleniumHelper(); + +var tap = require('tap'); +const test = tap.test; + +const webdriver = require('selenium-webdriver'); +const driver = helper.buildDriver('www-smoke test-login-failures'); + +const { + findByCss, + clickCss +} = helper; + +var until = webdriver.until; + +var username = process.env.SMOKE_USERNAME; +var password = process.env.SMOKE_PASSWORD; + +var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; +var url = rootUrl + '/users/' + username; + +tap.plan(3); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + return driver.get(url); +}); + +test('Trying to sign in with no password using scratchr2 navbar', t => { + var nonsenseusername = Math.random().toString(36) + .replace(/[^a-z]+/g, '') + .substr(0, 5); + clickCss('.dropdown-toggle') + .then(() => findByCss('form#login input#login_dropdown_username')) + .then((element) => element.sendKeys(nonsenseusername)) + .then(() => clickCss('form#login button')) + .then(() => findByCss('form#login .error')) + .then((element) => { + driver.wait(until.elementIsVisible(element)); + return element; + }) + .then((element) => element.getText()) + .then((text) => t.match(text, 'This field is required', + '"This field is required" error should be displayed')) + .then(() => t.end()); +}); + +test('Trying to sign in with the wrong username using scratchr2 navbar', t => { + var nonsenseusername = Math.random().toString(36) + .replace(/[^a-z]+/g, '') + .substr(0, 5); + clickCss('.dropdown-toggle') + .then(() => findByCss('form#login input#login_dropdown_username')) + .then((element) => element.sendKeys(nonsenseusername)) + .then(() => findByCss('form#login input.wide.password')) + .then((element) => element.sendKeys(password)) + .then(() => clickCss('form#login button')) + .then(() => findByCss('form#login .error')) + .then((element) => { + driver.wait(until.elementIsVisible(element)); + return element; + }) + .then((element) => element.getText()) + .then((text) => t.match(text, 'Incorrect username or password.', + '"Incorrect username or password" error should be displayed')) + .then(() => t.end()); +}); + +test('Trying to sign in with the wrong password using scratchr2 navbar', t => { + clickCss('.dropdown-toggle') + .then(() => findByCss('form#login input#login_dropdown_username')) + .then((element) => element.sendKeys(username)) + .then(() => findByCss('form#login input.wide.password')) + .then((element) => element.sendKeys('nonsensepassword')) + .then(() => clickCss('form#login button')) + .then(() => findByCss('form#login .error')) + .then((element) => { + driver.wait(until.elementIsVisible(element)); + return element; + }) + .then((element) => element.getText()) + .then((text) => t.match(text, 'Incorrect username or password.', + '"Incorrect username or password" error should be displayed')) + .then(() => t.end()); +}); diff --git a/test/integration-legacy/smoke-testing/test-my-stuff.js b/test/integration-legacy/smoke-testing/test-my-stuff.js new file mode 100644 index 000000000..32d06b5c5 --- /dev/null +++ b/test/integration-legacy/smoke-testing/test-my-stuff.js @@ -0,0 +1,151 @@ +/* + * Tests signing in & My Stuff according to smoke-tests at: + * + * https://github.com/LLK/scratchr2/wiki/Smoke-Testing-Test-Cases + * + */ + +const SeleniumHelper = require('../selenium-helpers.js'); +const helper = new SeleniumHelper(); + +var tap = require('tap'); +const test = tap.test; + +const driver = helper.buildDriver('www-smoke test-my-stuff'); + +const { + clickText, + findByXpath, + clickXpath, + clickButton +} = helper; + +var username = process.env.SMOKE_USERNAME; +var password = process.env.SMOKE_PASSWORD; + +var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; +var url = rootUrl + '/users/' + username; + +tap.plan(7); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + return driver.get(url) + .then(() => clickText('Sign in')) + .then(() => findByXpath('//input[@id="login_dropdown_username"]')) + .then((element) => element.sendKeys(username)) + .then(() => findByXpath('//input[@name="password"]')) + .then((element) => element.sendKeys(password)) + .then(() => clickButton('Sign in')); +}); + +tap.afterEach(function () { + return clickXpath('//span[@class="user-name dropdown-toggle"]') + .then(() => clickXpath('//li[@id="logout"] ')) + .then(() => findByXpath('//div[@class="title-banner intro-banner"]')); +}); + +test('Sign in to Scratch using scratchr2 navbar', t => { + findByXpath('//li[contains(@class, "logged-in-user")' + + 'and contains(@class, "dropdown")]/span') + .then((element) => element.getText('span')) + .then((text) => t.match(text.toLowerCase(), username.substring(0, 10).toLowerCase(), + 'first part of username should be displayed in navbar')) + .then(() => t.end()); +}); + +test('Sign in to Scratch & verify My Stuff structure (tabs, title)', t => { + clickXpath('//a[contains(@class, "mystuff-icon")]') + .then(() => findByXpath('//div[@class="box-head"]/h2')) + .then((element) => element.getText('h2')) + .then((text) => t.equal('My Stuff', text, 'title should be My Stuff')) + .then(() => findByXpath('//li[@data-tab="projects"]/a')) + .then((element) => element.getText('a')) + .then((text) => t.match(text, 'All Projects', 'All Projects tab should be present')) + .then(() => findByXpath('//li[@data-tab="shared"]/a')) + .then((element) => element.getText('a')) + .then((text) => t.match(text, 'Shared Projects', 'Shared Projects tab should be present')) + .then(() => findByXpath('//li[@data-tab="unshared"]/a')) + .then((element) => element.getText('a')) + .then((text) => t.match(text, 'Unshared Projects', 'Unshared Projects tab should be present')) + .then(() => findByXpath('//li[@data-tab="galleries"]/a')) + .then((element) => element.getText('a')) + .then((text) => t.match(text, 'My Studios', 'My Studios tab should be present')) + .then(() => findByXpath('//li[@data-tab="trash"]/a')) + .then((element) => element.getText('a')) + .then((text) => t.match(text, 'Trash', 'Trash tab should be present')) + .then(() => t.end()); +}); + +test('clicking See Inside should take you to the editor', t => { + clickXpath('//a[contains(@class, "mystuff-icon")]') + .then(() => findByXpath('//a[@data-control="edit"]')) + .then((element) => element.getText('span')) + .then((text) => t.equal(text, 'See inside', 'there should be a "See inside" button')) + .then(() => clickXpath('//a[@data-control="edit"]')) + .then(() => driver.getCurrentUrl()) + .then(function (u) { + var expectedUrl = '/editor'; + t.equal(u.substr(-expectedUrl.length), expectedUrl, 'after clicking, the URL should end in #editor'); + }) + .then(() => driver.get(url)) + .then(() => t.end()); +}); + +test('clicking a project title should take you to the project page', t => { + clickXpath('//a[contains(@class, "mystuff-icon")]') + .then(() => clickXpath('//a[@data-control="edit"]')) + .then(() => driver.getCurrentUrl()) + .then(function (u) { + var expectedUrlRegExp = new RegExp('/projects/.*[0-9].*/?'); + t.match(u, expectedUrlRegExp, 'after clicking, the URL should end in projects/PROJECT_ID/'); + }) + .then(() => driver.get(url)) + .then(() => t.end()); +}); + +test('Add To button should bring up a list of studios', t => { + clickXpath('//a[contains(@class, "mystuff-icon")]') + .then(() => clickXpath('//div[@id="sidebar"]/ul/li[@data-tab="shared"]')) + .then(() => findByXpath('//div[@data-control="add-to"]')) + .then((element) => element.getText('span')) + .then((text) => t.equal(text, 'Add to', 'there should be an "Add to" button')) + .then(() => clickXpath('//div[@data-control="add-to"]')) + .then(() => findByXpath('//div[@class="dropdown-menu"]/ul/li')) + .then((element) => element.getText('span')) + .then(function (text) { + var expectedRegExp = new RegExp('.+'); + t.match(text, expectedRegExp, 'the dropdown menu should have at least 1 text item in it'); + }) + .then(() => t.end()); +}); + +test('+ New Studio button should take you to the studio page', {skip: true}, t => { + clickXpath('//a[contains(@class, "mystuff-icon")]') + .then(() => clickXpath('//form[@id="new_studio"]/button[@type="submit"]')) + .then(() => findByXpath('//div[@id="show-add-project"]')) + .then((element) => element.getText('span')) + .then((text) => t.equal(text, 'Add projects', 'there should be an "Add projects" button')) + .then(() => driver.getCurrentUrl()) + .then(function (u) { + var expectedUrlRegExp = new RegExp('/studios/.*[0-9].*/?'); + t.match(u, expectedUrlRegExp, + 'after clicking the + New Studio, the URL should end in studios/STUDIO_ID'); + }) + .then(() => t.end()); +}); + +test('+ New Project button should open the editor', {skip: true}, t => { + clickXpath('//a[contains(@class, "mystuff-icon")]') + .then(() => clickText('+ New Project')) + .then(() => driver.getCurrentUrl()) + .then(function (u) { + var expectedUrlRegExp = new RegExp('/projects/editor'); + t.match(u, expectedUrlRegExp, + 'after clicking, the URL should end in projects/editor'); + }) + .then(() => t.end()); +}); diff --git a/test/integration-legacy/smoke-testing/test_footer_links.js b/test/integration-legacy/smoke-testing/test_footer_links.js new file mode 100644 index 000000000..0fa9ed80e --- /dev/null +++ b/test/integration-legacy/smoke-testing/test_footer_links.js @@ -0,0 +1,305 @@ +/* + * Checks that the links in the footer on the homepage have the right URLs to redirect to + * + * Test cases: https://github.com/LLK/scratch-www/wiki/Most-Important-Workflows + */ + +const SeleniumHelper = require('../selenium-helpers.js'); +const helper = new SeleniumHelper(); + +const tap = require('tap'); + +const webdriver = require('selenium-webdriver'); +const driver = helper.buildDriver('www-smoke test_footer_links'); + +const rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; + +// timeout for each test; timeout for suite set at command line level +const options = {timeout: 30000}; + +// number of tests in the plan +tap.plan(24); + +tap.tearDown(function () { + // quit the instance of the browser + driver.quit(); +}); + +tap.beforeEach(function () { + // load the page with the driver + return driver.get(rootUrl); +}); + +// Function clicks the link and returns the url of the resulting page + +const clickFooterLinks = function (linkText) { + return driver.wait(webdriver.until.elementLocated(webdriver.By.id('footer'))) + .then(function (element) { + return element.findElement(webdriver.By.linkText(linkText)); + }) + .then(function (element) { + return element.click(); + }) + .then(function () { + return driver.getCurrentUrl(); + }); +}; + +// ==== ABOUT SCRATCH column ==== + +// ABOUT SCRATCH +tap.test('clickAboutScratchLink', options, t => { + const linkText = 'About Scratch'; + const expectedHref = '/about'; + clickFooterLinks(linkText).then(url => { + // the href should be at the end of the URL + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// FOR PARENTS +tap.test('clickForParentsLink', options, t => { + const linkText = 'For Parents'; + const expectedHref = '/parents/'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// FOR EDUCATORS +tap.test('clickForEducatorsLink', options, t => { + const linkText = 'For Educators'; + const expectedHref = '/educators'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// FOR DEVELOPERS +tap.test('clickForDevelopersScratchLink', options, t => { + const linkText = 'For Developers'; + const expectedHref = '/developers'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// CREDITS +tap.test('clickCreditsLink', options, t => { + const linkText = 'Credits'; + const expectedHref = '/credits'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// JOBS +tap.test('clickJobsLink', options, t => { + const linkText = 'Jobs'; + const expectedHref = '/jobs'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// PRESS +tap.test('clickPressLink', options, t => { + const linkText = 'Press'; + const expectedUrl = 'https://www.scratchfoundation.org/media-kit/'; + clickFooterLinks(linkText).then(url => { + t.equal(url, expectedUrl); + t.end(); + }); +}); + +// ==== COMMUNITY column ==== + +// COMMUNITY GUIDELINES +tap.test('clickCommunityGuidelinesLink', options, t => { + const linkText = 'Community Guidelines'; + const expectedHref = '/community_guidelines'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// DISCUSSION FORUMS +tap.test('clickDiscussionForumsLink', options, t => { + const linkText = 'Discussion Forums'; + const expectedHref = '/discuss/'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// SCRATCH WIKI test has been removed. + +// STATISTICS +tap.test('clickStatisticsLink', options, t => { + const linkText = 'Statistics'; + const expectedHref = '/statistics/'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// ==== SUPPORT column ==== + +// IDEAS PAGE +tap.test('clickIdeasPageLink', options, t => { + const linkText = 'Ideas'; + const expectedHref = '/ideas'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// FAQ +tap.test('clickFAQLink', options, t => { + const linkText = 'FAQ'; + const expectedHref = '/info/faq'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// OFFLINE EDITOR +tap.test('clickOfflineEditorLink', options, t => { + const linkText = 'Offline Editor'; + const expectedHref = '/download'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// CONTACT US +tap.test('clickContactUsLink', options, t => { + const linkText = 'Contact Us'; + const expectedHref = '/contact-us/'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// skip this test since it points to an external site +// SCRATCH STORE +tap.test('clickScratchStoreLink', {skip: true}, t => { + const linkText = 'Scratch Store'; + const expectedUrl = 'https://scratch-foundation.myshopify.com/'; + clickFooterLinks(linkText).then(url => { + t.equal(url, expectedUrl); + t.end(); + }); +}); + +// skip this test since it points to an external site +// DONATE +tap.test('clickDonateLink', {skip: true}, t => { + const linkText = 'Donate'; + const expectedUrl = 'https://secure.donationpay.org/scratchfoundation/'; + clickFooterLinks(linkText).then(url => { + t.equal(url, expectedUrl); + t.end(); + }); +}); + +// ==== LEGAL column ==== + +// TERMS OF USE +tap.test('clickTermsOfUseLink', options, t => { + const linkText = 'Terms of Use'; + const expectedHref = '/terms_of_use'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// PRIVACY POLICY +tap.test('clickPrivacyPolicyLink', options, t => { + const linkText = 'Privacy Policy'; + const expectedHref = '/privacy_policy'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// DMCA +tap.test('clickDMCALink', options, t => { + const linkText = 'DMCA'; + const expectedHref = '/DMCA'; + clickFooterLinks(linkText).then(url => { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// ==== SCRATCH FAMILY column ==== + +// skip this test since it points to an external site +// SCRATCH ED (SCRATCHED) +tap.test('clickScratchEdLink', {skip: true}, t => { + const linkText = 'ScratchEd'; + const expectedUrl = 'http://scratched.gse.harvard.edu/'; + clickFooterLinks(linkText).then(url => { + t.equal(url, expectedUrl); + t.end(); + }); +}); + +// skip this test since it points to an external site +// SCRATCH JR (SCRATCHJR) +tap.test('clickScratchJrLink', {skip: true}, t => { + const linkText = 'ScratchJr'; + const expectedUrl = 'https://www.scratchjr.org/'; + clickFooterLinks(linkText).then(url => { + t.equal(url, expectedUrl); + t.end(); + }); +}); + +// skip this test since it points to an external site +// SCRATCH DAY +tap.test('clickScratchDayLink', {skip: true}, t => { + const linkText = 'Scratch Day'; + const expectedUrl = 'https://day.scratch.mit.edu/'; + clickFooterLinks(linkText).then(url => { + t.equal(url, expectedUrl); + t.end(); + }); +}); + +// SCRATCH CONFERENCE +tap.test('clickScratchConferenceLink', options, t => { + const linkText = 'Scratch Conference'; + const expectedHref = '/conference/20'; + clickFooterLinks(linkText).then(url => { + t.match(url.substr(-(expectedHref.length + 2)), expectedHref); + t.end(); + }); +}); + +// skip this test since it points to an external site +// SCRATCH FOUNDATION +tap.test('clickScratchFoundationLink', {skip: true}, t => { + const linkText = 'Scratch Foundation'; + const expectedUrl = 'https://www.scratchfoundation.org/'; + clickFooterLinks(linkText).then(url => { + t.equal(url, expectedUrl); + t.end(); + }); +}); diff --git a/test/integration-legacy/smoke-testing/test_navbar_links.js b/test/integration-legacy/smoke-testing/test_navbar_links.js new file mode 100644 index 000000000..632c6d9e9 --- /dev/null +++ b/test/integration-legacy/smoke-testing/test_navbar_links.js @@ -0,0 +1,123 @@ +/* + * Checks that the links in the navbar on the homepage have the right URLs to redirect to + * + * Test cases: https://github.com/LLK/scratch-www/wiki/Most-Important-Workflows + */ + +const SeleniumHelper = require('../selenium-helpers.js'); +const helper = new SeleniumHelper(); + +var tap = require('tap'); + +const webdriver = require('selenium-webdriver'); +const driver = helper.buildDriver('www-smoke test_navbar_links'); + +// Set test url through environment variable +var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; + +// number of tests in the plan +tap.plan(7); + +tap.tearDown(function () { + // quit the instance of the browser + driver.quit(); +}); + +tap.beforeEach(function () { + // load the page with the driver + return driver.get(rootUrl); +}); + +// ==== Links in navbar ==== + +// the create link changes depending on whether the user is signed in or not (tips window opens) +tap.test('checkCreateLinkWhenSignedOut', function (t) { + var xPathLink = '//li[contains(@class, "link") and contains(@class, "create")]/a'; + var expectedHref = '/projects/editor/?tutorial=getStarted'; + driver.findElement(webdriver.By.xpath(xPathLink)) + .then(function (element) { + return element.getAttribute('href'); + }) + .then(function (url) { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +tap.test('checkExploreLinkWhenSignedOut', function (t) { + var xPathLink = '//li[contains(@class, "link") and contains(@class, "explore")]/a'; + var expectedHref = '/explore/projects/all'; + driver.findElement(webdriver.By.xpath(xPathLink)) + .then(function (element) { + return element.getAttribute('href'); + }) + .then(function (url) { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +tap.test('checkIdeasLinkWhenSignedOut', function (t) { + var xPathLink = '//li[contains(@class, "link") and contains(@class, "ideas")]/a'; + var expectedHref = '/ideas'; + driver.findElement(webdriver.By.xpath(xPathLink)) + .then(function (element) { + return element.getAttribute('href'); + }) + .then(function (url) { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +tap.test('checkAboutLinkWhenSignedOut', function (t) { + var xPathLink = '//li[contains(@class, "link") and contains(@class, "about")]/a'; + var expectedHref = '/about'; + driver.findElement(webdriver.By.xpath(xPathLink)) + .then(function (element) { + return element.getAttribute('href'); + }) + .then(function (url) { + t.equal(url.substr(-expectedHref.length), expectedHref); + t.end(); + }); +}); + +// ==== Search bar ==== + +tap.test('checkSearchBar', function (t) { + var xPathLink = '//input[@id="frc-q-1088"]'; + // search bar should exist + driver.findElement(webdriver.By.xpath(xPathLink)).then(function (element) { + t.ok(element); + t.end(); + }); +}); + +// ==== Join Scratch & Sign In ==== + +tap.test('checkJoinScratchLinkWhenSignedOut', function (t) { + var xPathLink = '//li[contains(@class, "link") and contains(@class, "right") and contains(@class, "join")]/a'; + var expectedText = 'Join Scratch'; + driver.findElement(webdriver.By.xpath(xPathLink)) + .then(function (element) { + return element.getText('a'); + }) + .then(function (text) { + t.equal(text, expectedText); + t.end(); + }); +}); + +tap.test('checkSignInLinkWhenSignedOut', function (t) { + var xPathLink = '//li[contains(@class, "link") and contains(@class, "right") and contains(@class, "login-item")]/a'; + var expectedText = 'Sign in'; + driver.findElement(webdriver.By.xpath(xPathLink)) + .then(function (element) { + return element.getText('a'); + }) + .then(function (text) { + t.equal(text, expectedText); + t.end(); + }); +}); diff --git a/test/integration-legacy/smoke-testing/test_project_page.js b/test/integration-legacy/smoke-testing/test_project_page.js new file mode 100644 index 000000000..df9c031e4 --- /dev/null +++ b/test/integration-legacy/smoke-testing/test_project_page.js @@ -0,0 +1,61 @@ +const SeleniumHelper = require('../selenium-helpers.js'); +const helper = new SeleniumHelper(); + +var tap = require('tap'); +const test = tap.test; + +const driver = helper.buildDriver('www-smoke test_sign_in_out_homepage'); + +const { + clickText, + clickXpath, + dragFromXpathToXpath, + findByXpath, + waitUntilGone +} = helper; + +const rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; +const projectId = 1; +const projectUrl = `${rootUrl}/projects/${projectId}`; + +tap.plan(3); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + return driver.get(projectUrl); +}); + +test('Find fullscreen button', {skip: true}, t => { + findByXpath('//div[starts-with(@class, "loader_background")]') + .then(el => waitUntilGone(el)) + .then(() => clickXpath('//div[starts-with(@class, "stage_green-flag-overlay")]')) + .then(() => clickXpath('//img[contains(@alt, "Enter full screen mode")]')) + .then(() => t.end()); +}); + +test('Open and close Copy Link modal', {skip: true}, t => { + findByXpath('//div[starts-with(@class, "loader_background")]') + .then(el => waitUntilGone(el)) + .then(() => clickText('Copy Link')) + .then(() => clickXpath('//div[contains(@class, "social-label-title")]')) + .then(() => clickXpath('//img[contains(@alt, "close-icon")]')) + .then(() => clickXpath('//img[contains(@alt, "Enter full screen mode")]')) + .then(() => t.end()); +}); + +test('Dragging out of modal should not close modal', {skip: true}, t => { + findByXpath('//div[starts-with(@class, "loader_background")]') + .then(el => waitUntilGone(el)) + .then(() => clickXpath('//div[starts-with(@class, "stage_green-flag-overlay")]')) + .then(() => clickText('Copy Link')) + .then(() => clickXpath('//div[contains(@class, "social-label-title")]')) + .then(() => dragFromXpathToXpath( + '//div[contains(@class, "social-label-title")]', + '//li[contains(@class, "logo")]' + )) + .then(() => clickXpath('//div[contains(@class, "social-label-title")]')) + .then(() => t.end()); +}); diff --git a/test/integration-legacy/smoke-testing/test_project_rows.js b/test/integration-legacy/smoke-testing/test_project_rows.js new file mode 100644 index 000000000..029125b3a --- /dev/null +++ b/test/integration-legacy/smoke-testing/test_project_rows.js @@ -0,0 +1,93 @@ +/* + * Checks that the some of the homepage rows on the homepage are displayed and + * contents have the right URLs to redirect to + * + * Test cases: https://github.com/LLK/scratch-www/wiki/Most-Important-Workflows + */ + +const SeleniumHelper = require('../selenium-helpers.js'); +const helper = new SeleniumHelper(); + +var tap = require('tap'); + +const webdriver = require('selenium-webdriver'); +const driver = helper.buildDriver('www-smoke test_project_rows'); + +var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; + +// number of tests in the plan +tap.plan(4); + +tap.tearDown(function () { + // quit the instance of the browser + driver.quit(); +}); + +tap.beforeEach(function () { + // load the page with the driver + return driver.get(rootUrl); +}); + +// checks that the title of the first row is Featured Projects +tap.test('checkFeaturedProjectsRowTitleWhenSignedOut', function (t) { + var xPathLink = '//div[@class="box"]/div[@class="box-header"]/h4'; + driver.findElement(webdriver.By.xpath(xPathLink)) + .then(function (element) { + element.getText('h4') + .then(function (text) { + // expected value of the title text + var expectedText = 'Featured Projects'; + t.equal(text, expectedText); + t.end(); + }); + }); +}); + +// checks that the link for a project makes sense +tap.test('checkFeaturedProjectsRowLinkWhenSignedOut', function (t) { + var xPathLink = '//div[contains(@class, "thumbnail") ' + + 'and contains(@class, "project") and contains(@class, "slick-slide") ' + + 'and contains(@class, "slick-active")]/a[@class="thumbnail-image"]'; + driver.wait(webdriver.until + .elementLocated(webdriver.By.xpath(xPathLink))) + .then(function (element) { + element.getAttribute('href') + .then(function (url) { + // expected pattern for the project URL + // since I don't know the length of the project ID number + var expectedUrlRegExp = new RegExp('/projects/.*[0-9].*/?'); + t.match(url, expectedUrlRegExp); + t.end(); + }); + }); +}); + +// checks that the title of the 2nd row is Featured Studios +tap.test('checkFeaturedStudiosRowWhenSignedOut', function (t) { + var xPathLink = '//div[@class="box"][2]/div[@class="box-header"]/h4'; + driver.findElement(webdriver.By.xpath(xPathLink)) + .then(function (element) { + element.getText('h4') + .then(function (text) { + var expectedText = 'Featured Studios'; + t.equal(text, expectedText); + t.end(); + }); + }); +}); + +// checks that the link for a studio makes sense +tap.test('checkFeaturedStudiosRowLinkWhenSignedOut', function (t) { + var xPathLink = '//div[contains(@class, "thumbnail") and contains(@class, "gallery") ' + + 'and contains(@class, "slick-slide") ' + + 'and contains(@class, "slick-active")]/a[@class="thumbnail-image"]'; + driver.findElement(webdriver.By.xpath(xPathLink)) + .then(function (element) { + element.getAttribute('href') + .then(function (url) { + var expectedUrlRegExp = new RegExp('/studios/.*[0-9].*/?'); + t.match(url, expectedUrlRegExp); + t.end(); + }); + }); +}); diff --git a/test/integration-legacy/smoke-testing/test_search.js b/test/integration-legacy/smoke-testing/test_search.js new file mode 100644 index 000000000..22a85e651 --- /dev/null +++ b/test/integration-legacy/smoke-testing/test_search.js @@ -0,0 +1,58 @@ +/* + * Checks the behavior of the search interface + */ +require('chromedriver'); +const seleniumWebdriver = require('selenium-webdriver'); +const SeleniumHelper = require('../selenium-helpers.js'); +const helper = new SeleniumHelper(); +const { + urlMatches +} = helper; + +const tap = require('tap'); +const test = tap.test; + +// Set test url through environment variable +const rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; +const searchBaseUrl = `${rootUrl}/search/`; + +// chrome driver +const driver = helper.buildDriver('www-search test_search'); + +tap.plan(3); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + return driver.get(searchBaseUrl); +}); + +test('Search escapes spaces', function (t) { + const searchInput = driver.findElement(seleniumWebdriver.By.name('q')); + searchInput.sendKeys('Test search string', helper.getKey('ENTER')).then(function () { + urlMatches(/^.*\?q=Test%20search%20string$/) + .then(() => t.end()); + }); +}); + +test('Search escapes symbols', function (t) { + const searchInput = driver.findElement(seleniumWebdriver.By.name('q')); + searchInput.sendKeys('100% pen', helper.getKey('ENTER')).then(function () { + urlMatches(/^.*\?q=100%25%20pen$/) + .then(() => t.end()); + }); +}); + +test('Switching to studios maintains search string', function (t) { + const searchInput = driver.findElement(seleniumWebdriver.By.name('q')); + searchInput.sendKeys('100% pen', helper.getKey('ENTER')).then(function () { + const studiosTab = driver.findElement(seleniumWebdriver.By.xpath( + '//a/li/span[contains(text(),"Studios")]')); + studiosTab.click().then(function () { + urlMatches(/^.*\?q=100%25%20pen$/) + .then(() => t.end()); + }); + }); +}); diff --git a/test/integration-legacy/smoke-testing/test_signing_in_and_out_discuss.js b/test/integration-legacy/smoke-testing/test_signing_in_and_out_discuss.js new file mode 100644 index 000000000..e95426548 --- /dev/null +++ b/test/integration-legacy/smoke-testing/test_signing_in_and_out_discuss.js @@ -0,0 +1,62 @@ +/* + * Tests from: + * + * https://github.com/LLK/scratchr2/wiki/Smoke-Testing-Test-Cases + * + */ + +const SeleniumHelper = require('../selenium-helpers.js'); +const helper = new SeleniumHelper(); + +var tap = require('tap'); +const test = tap.test; + +const driver = helper.buildDriver('www-smoke test_sign_in_out_discuss'); + +const { + clickText, + findByXpath, + findText, + clickXpath, + clickButton +} = helper; + +var username = process.env.SMOKE_USERNAME; +var password = process.env.SMOKE_PASSWORD; + +var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; +var url = rootUrl + '/discuss'; + +tap.plan(2); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + return driver.get(url); +}); + +test('Sign in to Scratch using scratchr2 navbar', t => { + clickText('Sign in') + .then(() => findByXpath('//input[@id="login_dropdown_username"]')) + .then((element) => element.sendKeys(username)) + .then(() => findByXpath('//input[@name="password"]')) + .then((element) => element.sendKeys(password)) + .then(() => clickButton('Sign in')) + .then(() => findByXpath('//li[contains(@class, "logged-in-user")' + + 'and contains(@class, "dropdown")]/span')) + .then((element) => element.getText('span')) + .then((text) => t.match(text.toLowerCase(), username.substring(0, 10).toLowerCase(), + 'first part of username should be displayed in navbar')) + .then(() => t.end()); +}); + +test('Sign out of Scratch using scratchr2 navbar', t => { + clickXpath('//span[contains(@class, "user-name")' + + ' and contains(@class, "dropdown-toggle")]/img[contains(@class, "user-icon")]') + .then(() => clickXpath('//input[@value="Sign out"]')) + .then(() => findText('Sign in')) + .then((element) => t.ok(element, 'Sign in reappeared on the page after signing out')) + .then(() => t.end()); +}); diff --git a/test/integration-legacy/smoke-testing/test_signing_in_and_out_homepage.js b/test/integration-legacy/smoke-testing/test_signing_in_and_out_homepage.js new file mode 100644 index 000000000..15687b0cf --- /dev/null +++ b/test/integration-legacy/smoke-testing/test_signing_in_and_out_homepage.js @@ -0,0 +1,59 @@ +/* + * Tests from: + * + * https://github.com/LLK/scratchr2/wiki/Smoke-Testing-Test-Cases + * + */ + +const SeleniumHelper = require('../selenium-helpers.js'); +const helper = new SeleniumHelper(); + +var tap = require('tap'); +const test = tap.test; + +const driver = helper.buildDriver('www-smoke test_sign_in_out_homepage'); + +const { + clickText, + findText, + findByXpath, + clickXpath +} = helper; + +var username = process.env.SMOKE_USERNAME; +var password = process.env.SMOKE_PASSWORD; + +var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; + +tap.plan(2); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + return driver.get(rootUrl); +}); + +test('Sign in to Scratch using scratch-www navbar', {skip: true}, t => { + clickText('Sign in') + .then(() => findByXpath('//input[@id="frc-username-1088"]')) + .then((element) => element.sendKeys(username)) + .then(() => findByXpath('//input[@id="frc-password-1088"]')) + .then((element) => element.sendKeys(password)) + .then(() => clickXpath('//button[contains(@class, "button") and ' + + 'contains(@class, "submit-button") and contains(@class, "white")]')) + .then(() => findByXpath('//span[contains(@class, "profile-name")]')) + .then((element) => element.getText()) + .then((text) => t.match(text.toLowerCase(), username.substring(0, 10).toLowerCase(), + 'first part of username should be displayed in navbar')) + .then(() => t.end()); +}); + +test('Sign out of Scratch using scratch-www navbar', {skip: true}, t => { + clickXpath('//a[contains(@class, "user-info")]') + .then(() => clickText('Sign out')) + .then(() => findText('Sign in')) + .then((element) => t.ok(element, 'Sign in reappeared on the page after signing out')) + .then(() => t.end()); +}); diff --git a/test/integration-legacy/smoke-testing/test_statistics_page.js b/test/integration-legacy/smoke-testing/test_statistics_page.js new file mode 100644 index 000000000..9a8f9596c --- /dev/null +++ b/test/integration-legacy/smoke-testing/test_statistics_page.js @@ -0,0 +1,68 @@ +/* + * Tests stats page according to smoke-tests at: + * + * https://github.com/LLK/scratchr2/wiki/Smoke-Testing-Test-Cases + * + */ + +const SeleniumHelper = require('../selenium-helpers.js'); +const helper = new SeleniumHelper(); + +var tap = require('tap'); +const test = tap.test; + +const driver = helper.buildDriver('www-smoke test_statistics_page'); + +const { + clickText, + findByXpath, + findByCss +} = helper; + +tap.plan(2); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + /* + * load the page with the driver + * note that for now this is not testable on Staging, + * so I left it pointing to Production - + * we can at least use it post-deploy. + * + * var stagingURL = 'https://scratch.ly/statistics'; + */ + var productionURL = 'https://scratch.mit.edu/statistics'; + return driver.get(productionURL); +}); + +test('check that Monthly Activity Trends title is present & correct', t => { + var chartTitle = 'Monthly Activity Trends'; + findByCss('div.box-head h3') + .then((element) => element.getText('h3')) + .then((text) => t.equal(text, chartTitle, 'chart title should be Monthly Activity Trends')) + .then(() => t.end()); +}); + +test('check that Monthly Activity Trends chart > New Projects label is toggleable', t => { + var classXpath = `(//div[@id="activity_chart"]/*[name()='svg']/*[name()='g']/*[name()='g']/*` + + `[name()='g'])[4]/*[name()='g']/*[name()='g']/*[name()='g']`; + findByXpath(classXpath) + .then((element) => element.getAttribute('class')) + .then((classtext) => t.equal(classtext, 'nv-series', 'by default, New Projects should be enabled')) + .then(() => clickText('New Projects')) + .then(() => findByXpath(classXpath)) + .then((element) => element.getAttribute('class')) + .then((classtext) => t.equal( + classtext, + 'nv-series nv-disabled', + 'when clicked, New Projects should be disabled' + )) + .then(() => clickText('New Projects')) + .then(() => findByXpath(classXpath)) + .then((element) => element.getAttribute('class')) + .then((classtext) => t.equal(classtext, 'nv-series', 'when clicked again, New Projects should be enabled')) + .then(() => t.end()); +}); diff --git a/test/integration-legacy/teacher-registration/teacher_registration_utils.js b/test/integration-legacy/teacher-registration/teacher_registration_utils.js new file mode 100644 index 000000000..dfc828f68 --- /dev/null +++ b/test/integration-legacy/teacher-registration/teacher_registration_utils.js @@ -0,0 +1,99 @@ +module.exports.constants = { + nextStepXpath: '//button[span[contains(text(), "Next Step")]]', + generalErrorMessageXpath: '//span[@class="help-block validation-message"]/span[contains(text(),' + + '"This field is required")]', + loremIpsumTextLong: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur viverra' + + 'nec mauris efficitur tincidunt. Vestibulum ut diam odio. Cum sociis natoque penatibus et magnis dis' + + 'parturient montes, nascetur ridiculus mus. Morbi non enim dolor. Vestibulum at enim vestibulum, ullamcorper' + + 'Duis eget quam pharetra, ultricies est eu, pharetra nisi. In tempor cursus nisi, non sagittis quam gravida.' +}; + +module.exports.fillUsernameSlide = function (driver, seleniumWebdriver) { + var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password')); + var usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username')); + var usernamePromise = usernameInput.sendKeys('clipspringer'); + var passwordPromise = passwordInput.sendKeys('educators'); + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath)); + return Promise.all([usernamePromise, passwordPromise]).then(function () { // eslint-disable-line no-undef + nextStepButton.click().then(function () { + driver.wait(seleniumWebdriver.until + .elementLocated(seleniumWebdriver.By.className('demographics-step'))); + }); + }); +}; + +module.exports.fillDemographicsSlide = function (driver, seleniumWebdriver) { + var clickMaleInput = driver.findElement(seleniumWebdriver.By.xpath('//input[@value="male"' + + 'and @type="radio"]')).click(); + var selectCountry = driver.findElement(seleniumWebdriver.By.xpath('//select[@name="user.country"]' + + '/option[@value="us"]')).click(); + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath)); + return Promise.all([clickMaleInput, selectCountry]).then(function () { // eslint-disable-line no-undef + nextStepButton.click().then(function () { + driver.wait(seleniumWebdriver.until + .elementLocated(seleniumWebdriver.By.className('name-step'))); + }); + }); +}; + +module.exports.fillNameSlide = function (driver, seleniumWebdriver) { + var firstNamePromise = driver.findElement(seleniumWebdriver.By.name('user.name.first')).sendKeys('first'); + var lastNamePromise = driver.findElement(seleniumWebdriver.By.name('user.name.last')).sendKeys('surname'); + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath)); + return Promise.all([firstNamePromise, lastNamePromise]).then(function () { // eslint-disable-line no-undef + nextStepButton.click().then(function () { + driver.wait(seleniumWebdriver.until + .elementLocated(seleniumWebdriver.By.className('phone-step'))); + }); + }); +}; + +module.exports.fillPhoneSlide = function (driver, seleniumWebdriver) { + var phoneInput = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="tel"]')); + var consentCheckbox = driver.findElement(seleniumWebdriver.By.name('phoneConsent')); + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath)); + var phoneNumberPromise = phoneInput.sendKeys('6172535960'); + var consentPromise = consentCheckbox.click(); + return Promise.all([phoneNumberPromise, consentPromise]).then(function () { // eslint-disable-line no-undef + nextStepButton.click().then(function () { + driver.wait(seleniumWebdriver.until + .elementLocated(seleniumWebdriver.By.className('organization-step'))); + }); + }); +}; + +module.exports.fillOrganizationSlide = function (driver, seleniumWebdriver) { + var organizationInput = driver.findElement(seleniumWebdriver.By.name('organization.name')); + var titleInput = driver.findElement(seleniumWebdriver.By.name('organization.title')); + var typeCheckbox = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="checkbox" and @value="3"]')); + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath)); + var organizationPromise = organizationInput.sendKeys('MIT Media Lab'); + var titlePromise = titleInput.sendKeys('Software Developer'); + var typePromise = typeCheckbox.click(); + return Promise.all([organizationPromise, titlePromise, typePromise]) // eslint-disable-line no-undef + .then(function () { + nextStepButton.click().then(function () { + driver.wait(seleniumWebdriver.until + .elementLocated(seleniumWebdriver.By.className('address-step'))); + }); + }); +}; + +module.exports.fillAddressSlide = function (driver, seleniumWebdriver) { + var addressInput = driver.findElement(seleniumWebdriver.By.name('address.line1')); + var cityInput = driver.findElement(seleniumWebdriver.By.name('address.city')); + var zipCodeInput = driver.findElement(seleniumWebdriver.By.name('address.zip')); + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath)); + var addressPromise = addressInput.sendKeys('77 Massachusetts Avenue, E14/E15'); + var cityPromise = cityInput.sendKeys('Cambridge'); + var statePromise = driver.findElement(seleniumWebdriver.By.xpath('//select[@name="address.state"]' + + '/option[@value="us-ma"]')).click(); + var zipPromise = zipCodeInput.sendKeys('02139'); + return Promise.all([addressPromise, cityPromise, statePromise, zipPromise]) // eslint-disable-line no-undef + .then(function () { + nextStepButton.click().then(function () { + driver.wait(seleniumWebdriver.until + .elementLocated(seleniumWebdriver.By.className('usescratch-step'))); + }); + }); +}; diff --git a/test/integration-legacy/teacher-registration/test_teacher_registration_address_step.js b/test/integration-legacy/teacher-registration/test_teacher_registration_address_step.js new file mode 100644 index 000000000..557f5155f --- /dev/null +++ b/test/integration-legacy/teacher-registration/test_teacher_registration_address_step.js @@ -0,0 +1,60 @@ +/* + * Checks the behavior of the address step in the educators registration process + * + * Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow + */ +require('chromedriver'); +var seleniumWebdriver = require('selenium-webdriver'); +var tap = require('tap'); + +var utils = require('./teacher_registration_utils.js'); +var constants = utils.constants; + +// Set test url through environment variable +var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; + +// chrome driver +var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) + .build(); + +tap.plan(2); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + driver.get(rootUrl + '/educators/register'); + return utils.fillUsernameSlide(driver, seleniumWebdriver) + .then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this + .then(utils.fillNameSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this + .then(utils.fillPhoneSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this + .then(utils.fillOrganizationSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this +}); + +// Selects Vatican City as the country, and checks that the state dropdown disappears +tap.test('checkStateDropdownOnlyPresentWhenNeeded', function (t) { + driver.findElement(seleniumWebdriver.By.xpath('//select[@name="address.country"]' + + '/option[@value="va"]')).click() // select Vatican City as the country + .then(function () { + driver.findElements(seleniumWebdriver.By.name('address.state')) + .then(function (stateDropdown) { + t.equal(stateDropdown.length, 0); + t.end(); + }); + }); +}); + +tap.test('checkZipCodeRequired', function (t) { + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); + var errorMessageXPath = '//input[@name="address.zip"]/following-sibling::' + + 'span[@class="help-block validation-message"]/span[contains(text(),' + + '"This field is required")]'; + nextStepButton.click().then(function () { + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) + .then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); diff --git a/test/integration-legacy/teacher-registration/test_teacher_registration_demographics_step.js b/test/integration-legacy/teacher-registration/test_teacher_registration_demographics_step.js new file mode 100644 index 000000000..cb589d137 --- /dev/null +++ b/test/integration-legacy/teacher-registration/test_teacher_registration_demographics_step.js @@ -0,0 +1,61 @@ +/* + * Checks the behavior of demographics step in the educators registration process + * + * Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow + */ +require('chromedriver'); +var seleniumWebdriver = require('selenium-webdriver'); +var tap = require('tap'); + +var utils = require('./teacher_registration_utils.js'); +var constants = utils.constants; + +// Set test url through environment variable +var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; + +// chrome driver +var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) + .build(); + +tap.plan(2); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + driver.get(rootUrl + '/educators/register'); + return utils.fillUsernameSlide(driver, seleniumWebdriver); +}); + +// if the user selects the other gender option, they must input a gender +// selects the other gender option and attempt to advance the slide +tap.test('checkOtherGenderInput', function (t) { + var otherGenderRadio = driver.findElement(seleniumWebdriver.By.xpath('//input[@value="other"' + + 'and @type="radio"]')); + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); + driver.findElement(seleniumWebdriver.By.xpath('//select[@name="user.country"]/option[2]')).click(); + otherGenderRadio.click().then(function () { + nextStepButton.click().then(function () { + driver.findElements(seleniumWebdriver.By.xpath(constants.generalErrorMessageXpath)) + .then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); + }); +}); + +// the user must select a gender +// tries to advance the slide without selecting a gender +tap.test('checkNoGenderInput', function (t) { + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); + driver.findElement(seleniumWebdriver.By.xpath('//select[@name="user.country"]/option[2]')).click(); + nextStepButton.click().then(function () { + driver.findElements(seleniumWebdriver.By.xpath(constants.generalErrorMessageXpath)) + .then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); diff --git a/test/integration-legacy/teacher-registration/test_teacher_registration_name_step.js b/test/integration-legacy/teacher-registration/test_teacher_registration_name_step.js new file mode 100644 index 000000000..dee76448d --- /dev/null +++ b/test/integration-legacy/teacher-registration/test_teacher_registration_name_step.js @@ -0,0 +1,60 @@ +/* + * Checks the behavior of the name step in the educators registration process + * + * Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow + */ +require('chromedriver'); +var seleniumWebdriver = require('selenium-webdriver'); +var tap = require('tap'); + +var utils = require('./teacher_registration_utils.js'); +var constants = utils.constants; + +// Set test url through environment variable +var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; + +// chrome driver +var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) + .build(); + +tap.plan(2); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + driver.get(rootUrl + '/educators/register'); + return utils.fillUsernameSlide(driver, seleniumWebdriver) + .then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this +}); + +// attempts to advance the slide without inputting either name, checks that both give the correct error +tap.test('checkFirstNameRequired', function (t) { + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); + var errorMessageXPath = '//input[@name="user.name.first"]/following-sibling::' + + 'span[@class="help-block validation-message"]/span[contains(text(),' + + '"This field is required")]'; + nextStepButton.click().then(function () { + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) + .then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); + +// attempts to advance the slide without inputting either name, checks that both give the correct error +tap.test('checkLastNameRequired', function (t) { + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); + var errorMessageXPath = '//input[@name="user.name.last"]/following-sibling::' + + 'span[@class="help-block validation-message"]/span[contains(text(),' + + '"This field is required")]'; + nextStepButton.click().then(function () { + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) + .then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); diff --git a/test/integration-legacy/teacher-registration/test_teacher_registration_organization_step.js b/test/integration-legacy/teacher-registration/test_teacher_registration_organization_step.js new file mode 100644 index 000000000..6a136ecea --- /dev/null +++ b/test/integration-legacy/teacher-registration/test_teacher_registration_organization_step.js @@ -0,0 +1,89 @@ +/* + * Checks the behavior of the organization step in the educators registration process + * + * Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow + */ +require('chromedriver'); +var seleniumWebdriver = require('selenium-webdriver'); +var tap = require('tap'); + +var utils = require('./teacher_registration_utils.js'); +var constants = utils.constants; + +// Set test url through environment variable +var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; + +// chrome driver +var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) + .build(); + +tap.plan(4); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + driver.get(rootUrl + '/educators/register'); + return utils.fillUsernameSlide(driver, seleniumWebdriver) + .then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this + .then(utils.fillNameSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this + .then(utils.fillPhoneSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this +}); + +tap.test('otherFieldRequiredIfChecked', function (t) { + var otherCheckbox = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="checkbox" and @value="8"]')); + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); + var errorMessageXPath = '//div[@class="other-input"]' + constants.generalErrorMessageXpath; + otherCheckbox.click().then(function () { + nextStepButton.click().then(function () { + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) + .then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); + }); +}); + +tap.test('checkOrganizationFieldRequired', function (t) { + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); + var errorMessageXPath = '//input[@name="organization.name"]/following-sibling::' + + 'span[@class="help-block validation-message"]/span[contains(text(),' + + '"This field is required")]'; + nextStepButton.click().then(function () { + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) + .then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); + +tap.test('checkRoleFieldRequired', function (t) { + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); + var errorMessageXPath = '//input[@name="organization.title"]/following-sibling::' + + 'span[@class="help-block validation-message"]/span[contains(text(),' + + '"This field is required")]'; + nextStepButton.click().then(function () { + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) + .then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); + +tap.test('checkOrganizationTypeRequired', function (t) { + var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); + var errorMessageXPath = '//div[@class="checkbox"]/following-sibling::' + + 'span[@class="help-block validation-message" and contains(text(),' + + '"This field is required")]'; + nextStepButton.click().then(function () { + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) + .then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); diff --git a/test/integration-legacy/teacher-registration/test_teacher_registration_phone_step.js b/test/integration-legacy/teacher-registration/test_teacher_registration_phone_step.js new file mode 100644 index 000000000..ec3feaac9 --- /dev/null +++ b/test/integration-legacy/teacher-registration/test_teacher_registration_phone_step.js @@ -0,0 +1,45 @@ +/* + * Checks the behavior of the phone number step in the educators registration process + * + * Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow + */ +require('chromedriver'); +var seleniumWebdriver = require('selenium-webdriver'); +var tap = require('tap'); + +var utils = require('./teacher_registration_utils.js'); + +// Set test url through environment variable +var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; + +// chrome driver +var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) + .build(); + +tap.plan(1); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + driver.get(rootUrl + '/educators/register'); + return utils.fillUsernameSlide(driver, seleniumWebdriver) + .then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this + .then(utils.fillNameSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this +}); + +// inputs an invalid phone number and checks that the correct error message appears +tap.test('validatePhoneNumber', function (t) { + var phoneInput = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="tel"]')); + var errorMessage = 'Please enter a valid phone number'; + var errorMessageXPath = '//span[@class="help-block validation-message"]/span[contains(text(),"' + + errorMessage + '")]'; + phoneInput.sendKeys(1234567890).then(function () { + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) + .then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); diff --git a/test/integration-legacy/teacher-registration/test_teacher_registration_username_step.js b/test/integration-legacy/teacher-registration/test_teacher_registration_username_step.js new file mode 100644 index 000000000..96c8d46ea --- /dev/null +++ b/test/integration-legacy/teacher-registration/test_teacher_registration_username_step.js @@ -0,0 +1,114 @@ +/* +* Checks the behavior of first step in the educators registration process +* +* Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow +*/ + +require('chromedriver'); +var seleniumWebdriver = require('selenium-webdriver'); +var tap = require('tap'); + +// Set test url through environment variable +var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; + +// chrome driver +var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) + .build(); + +tap.plan(5); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + return driver.get(rootUrl + '/educators/register'); +}); + +// an error message should appear for a username less than 3 characters long +// input a username less than 3 characters and look for the validation message +tap.test('checkAtLeastThreeCharacters', function (t) { + // open scratch in a new instance of the browser + driver.get('https://scratch.mit.edu/educators/register'); + var usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username')); + var errorMessage = 'Usernames must be at least 3 characters'; + var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' + + errorMessage + '")]'; + usernameInput.sendKeys('hi').then(function () { + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); + +// usernames have to be unique +// input a username that exists and check that an error message appears +tap.test('checkUsernameExistsError', function (t) { + var usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username')); + var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password')); + var inputUsername = usernameInput.sendKeys('mres'); + var passwordClick = passwordInput.click(); + var errorMessage = 'Sorry, that username already exists'; + var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' + + errorMessage + '")]'; + Promise.all([inputUsername, passwordClick]).then(function () { // eslint-disable-line no-undef + var errorBubble = driver.wait(seleniumWebdriver.until + .elementLocated(seleniumWebdriver.By.xpath(errorMessageXPath)), 10000); + t.notEqual(errorBubble, undefined); // eslint-disable-line no-undefined + t.end(); + }); +}); + +// passwords must be at least 6 characters +// find the validation message if the input password is less than 6 characters +tap.test('checkPasswordAtLeastSixCharacters', function (t) { + var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password')); + var errorMessage = 'Passwords must be at least six characters'; + var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' + + errorMessage + '")]'; + passwordInput.sendKeys('hello').then(function () { + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); + +// password cannot be "password" +// find the validation message if the user inputs "password" +tap.test('checkPasswordNotPassword', function (t) { + driver.get('https://scratch.mit.edu/educators/register'); + var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password')); + // keeping "password" in messed with the xPath, may need to find a better way + var errorMessage = 'Your password may not be'; + var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' + + errorMessage + '")]'; + passwordInput.sendKeys('password').then(function () { + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); + +// the username and password cannot be the same +// find the validation message if the username and password match +tap.test('checkPasswordNotUsername', function (t) { + driver.get('https://scratch.mit.edu/educators/register'); + var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password')); + var usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username')); + var errorMessage = 'Your password may not be your username'; + var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' + + errorMessage + '")]'; + var usernamePromise = usernameInput.sendKeys('educator'); + var passwordPromise = passwordInput.sendKeys('educator'); + // wait for both inputs to have the same text, and check for validation message + Promise.all([usernamePromise, passwordPromise]).then(function () { // eslint-disable-line no-undef + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) { + // there should be only one validation message + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); diff --git a/test/integration-legacy/teacher-registration/test_teacher_registration_usescratch_step.js b/test/integration-legacy/teacher-registration/test_teacher_registration_usescratch_step.js new file mode 100644 index 000000000..f91baf590 --- /dev/null +++ b/test/integration-legacy/teacher-registration/test_teacher_registration_usescratch_step.js @@ -0,0 +1,71 @@ +/* + * Checks the behavior of the 'use scratch' step in the educators registration process + * + * Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow + */ +require('chromedriver'); +var seleniumWebdriver = require('selenium-webdriver'); +var tap = require('tap'); + +var utils = require('./teacher_registration_utils.js'); +var constants = utils.constants; + +// Set test url through environment variable +var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; + +// chrome driver +var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) + .build(); + +tap.plan(3); + +tap.tearDown(function () { + driver.quit(); +}); + +tap.beforeEach(function () { + driver.get(rootUrl + '/educators/register'); + return utils.fillUsernameSlide(driver, seleniumWebdriver) + .then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this + .then(utils.fillNameSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this + .then(utils.fillPhoneSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this + .then(utils.fillOrganizationSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this + .then(utils.fillAddressSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this +}); + +tap.test('checkCharacterCountIsCorrect', function (t) { + var textarea = driver.findElement(seleniumWebdriver.By.name('useScratch')); + var charCount = driver.findElement(seleniumWebdriver.By.xpath('//p[@class="char-count"]')); + textarea.sendKeys('hello').then(function () { + charCount.getText().then(function (charCountText) { + t.equal(charCountText, '5/300'); + t.end(); + }); + }); +}); + +// Inputs more than 300 characters and checks that the char count gets the class 'overmax' +// which turns the text orange +tap.test('checkCharacterCountTurnsOrangeWhenTooLong', function (t) { + var textarea = driver.findElement(seleniumWebdriver.By.name('useScratch')); + var charCount = driver.findElement(seleniumWebdriver.By.xpath('//p[@class="char-count"]')); + textarea.sendKeys(constants.loremIpsumTextLong).then(function () { + charCount.getAttribute('class').then(function (charCountClasses) { + t.ok(charCountClasses.includes('overmax')); + t.end(); + }); + }); +}); + +tap.test('checkCharacterCountErrorAppersWhenTooLong', function (t) { + var textarea = driver.findElement(seleniumWebdriver.By.name('useScratch')); + var errorMessage = 'Description must be at most 300 characters'; + var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' + + errorMessage + '")]'; + textarea.sendKeys(constants.loremIpsumTextLong).then(function () { + driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) { + t.equal(validationMessages.length, 1); + t.end(); + }); + }); +}); diff --git a/test/localization-legacy/check_duplicate_strings.js b/test/localization-legacy/check_duplicate_strings.js new file mode 100644 index 000000000..16f7ab71c --- /dev/null +++ b/test/localization-legacy/check_duplicate_strings.js @@ -0,0 +1,52 @@ +/* +* Check that there are no duplicate strings in any individual l10n json file. + */ +var path = require('path'); +var fs = require('fs'); +var tap = require('tap'); + +var routes = require('../../src/routes.json'); + +const noDuplicateValues = (idsToCheck, name) => { + let values = {}; + for (const key in idsToCheck) { + if (values.hasOwnProperty(idsToCheck[key])) { + // duplicate values + // return false; + tap.fail(`${name}.${idsToCheck[key]} has duplicates`); + } else { + values[idsToCheck[key]] = key; + } + } + tap.pass(); + // return true; +}; + +tap.test('generalCheckForDuplicates', function (t) { + const ids = require(path.resolve(__dirname, '../../src/l10n.json')); // eslint-disable-line global-require + noDuplicateValues(ids, 'general'); + t.end(); +}); + +for (var v in routes) { + if (typeof routes[v].redirect !== 'undefined') { + continue; + } + var subdir = routes[v].view.split('/'); + subdir.pop(); + var name = routes[v].name; + var uri = path.resolve(__dirname, '../../src/views/' + subdir.join('/') + '/l10n.json'); + try { + var file = fs.readFileSync(uri, 'utf8'); + var ids = JSON.parse(file); + tap.test(name + 'CheckForDuplicates', function (t) { // eslint-disable-line no-loop-func + noDuplicateValues(ids, name); + t.end(); + }); + } catch (err) { + if (err.code !== 'ENOENT') { + // ignore if ENOENT for routes with no l10n file, throw error for anything else + throw err; + } + } +} diff --git a/test/localization-legacy/check_string_ids.js b/test/localization-legacy/check_string_ids.js new file mode 100644 index 000000000..8fc019228 --- /dev/null +++ b/test/localization-legacy/check_string_ids.js @@ -0,0 +1,72 @@ +/** + * Tests whether any page in www has any languages which are missing string IDs + * - checks every language against the list of english IDs for that page + * - test fails if the length of the list of languages missing any IDs is not 0 + * - if the test fails, you can see which pages/ languages/ IDs are causing the failure: + * - Object.keys(pagesWithLanguagesMissingIds) gives you a list + * of the pages which had languages with missing IDs + * - pagesWithLanguagesMissingIds['pageName.intl.js'] gives you an object + * with languages as keys and the missing IDs as values + */ + +var path = require('path'); +var fs = require('fs'); +var tap = require('tap'); + +/** + * To get the files (containing message IDs and localized strings for each page in www) + * from the intl directory + */ +var intlDirPath = path.resolve(__dirname, '../../intl/'); +var intlFiles = fs.readdirSync(intlDirPath); + +/* + * Tells tap whether the test should pass or fail for a given file. + * @param {string} fileName + * @param {Object} missingMessageId + * @param {Object} pagesMissingIds + */ +const noMissingStrings = (fileName, missingMessageId, pagesMissingIds) => { + if (Object.keys(missingMessageId).length === 0) { + tap.pass(); + } else { + tap.fail(fileName + ' is missing string IDs'); + pagesMissingIds[fileName] = []; + pagesMissingIds[fileName].push(missingMessageId); + } +}; + +var pagesWithLanguagesMissingIds = {}; + +for (var i in intlFiles) { + var file = intlFiles[i]; + var filePath = path.resolve(__dirname, '../../intl/' + file); + var pageMessagesString = fs.readFileSync(filePath, 'utf8'); + + /** + * To make the string of the file of the page.intl.js back into useable objects + */ + var window = {}; + var pageMessages = eval(pageMessagesString); // eslint-disable-line no-eval + + /** + * The goal is to compare the IDs for each language to the IDs for English, + * so we need the list of IDs for the given page in English + */ + var englishIdList = window._messages.en; + + var messageIdNotInLanguage = {}; + + for (var languageKey in pageMessages) { + var currentLanguageObject = pageMessages[languageKey]; + for (var messageId in englishIdList) { + if (!(messageId in currentLanguageObject)) { + if (typeof messageIdNotInLanguage[languageKey] === 'undefined') { + messageIdNotInLanguage[languageKey] = []; + } + messageIdNotInLanguage[languageKey].push(messageId); + } + } + } + noMissingStrings(file, messageIdNotInLanguage, pagesWithLanguagesMissingIds); +} diff --git a/test/localization-legacy/check_valid_json.js b/test/localization-legacy/check_valid_json.js new file mode 100644 index 000000000..20ab2a890 --- /dev/null +++ b/test/localization-legacy/check_valid_json.js @@ -0,0 +1,23 @@ +var fs = require('fs'); +var glob = require('glob'); +var tap = require('tap'); + +var TRANSLATIONS_PATTERN = './node_modules/scratch-l10n/www/**/*.json'; +var files = glob.sync(TRANSLATIONS_PATTERN); + +const checkJson = (data, name) => { + try { + JSON.parse(data); + } catch (e) { + tap.fail(name + ' has invalid Json.\n'); + } +}; + +tap.test('check valid json', function (t) { + files.forEach(function (f) { + const data = fs.readFileSync(f); + checkJson(data, f); + }); + t.pass(); + t.end(); +}); diff --git a/test/unit-legacy/lib/validate.js b/test/unit-legacy/lib/validate.js new file mode 100644 index 000000000..3209a4307 --- /dev/null +++ b/test/unit-legacy/lib/validate.js @@ -0,0 +1,66 @@ +const tap = require('tap'); +const validate = require('../../../src/lib/validate'); + +tap.tearDown(() => process.nextTick(process.exit)); + +tap.test('validate username locally', t => { + let response; + t.type(validate.validateUsernameLocally, 'function'); + response = validate.validateUsernameLocally('abc'); + t.deepEqual(response, {valid: true}); + response = validate.validateUsernameLocally('abcdefghijklmnopqrst'); + t.deepEqual(response, {valid: true}); + response = validate.validateUsernameLocally('abc-def-ghi'); + t.deepEqual(response, {valid: true}); + response = validate.validateUsernameLocally(''); + t.deepEqual(response, {valid: false, errMsgId: 'form.validationRequired'}); + response = validate.validateUsernameLocally('ab'); + t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameMinLength'}); + response = validate.validateUsernameLocally('abcdefghijklmnopqrstu'); + t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameMaxLength'}); + response = validate.validateUsernameLocally('abc def'); + t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameRegexp'}); + response = validate.validateUsernameLocally('abc!def'); + t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameRegexp'}); + response = validate.validateUsernameLocally('abc😄def'); + t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameRegexp'}); + t.end(); +}); + +tap.test('validate password', t => { + let response; + t.type(validate.validatePassword, 'function'); + response = validate.validatePassword('abcdef'); + t.deepEqual(response, {valid: true}); + response = validate.validatePassword('abcdefghijklmnopqrst'); + t.deepEqual(response, {valid: true}); + response = validate.validatePassword('passwo'); + t.deepEqual(response, {valid: true}); + response = validate.validatePassword(''); + t.deepEqual(response, {valid: false, errMsgId: 'form.validationRequired'}); + response = validate.validatePassword('abcde'); + t.deepEqual(response, {valid: false, errMsgId: 'registration.validationPasswordLength'}); + response = validate.validatePassword('password'); + t.deepEqual(response, {valid: false, errMsgId: 'registration.validationPasswordNotEquals'}); + t.end(); +}); + +tap.test('validate password confirm', t => { + let response; + t.type(validate.validatePasswordConfirm, 'function'); + response = validate.validatePasswordConfirm('abcdef', 'abcdef'); + t.deepEqual(response, {valid: true}); + response = validate.validatePasswordConfirm('abcdefghijklmnopqrst', 'abcdefghijklmnopqrst'); + t.deepEqual(response, {valid: true}); + response = validate.validatePasswordConfirm('passwo', 'passwo'); + t.deepEqual(response, {valid: true}); + response = validate.validatePasswordConfirm('', ''); + t.deepEqual(response, {valid: false, errMsgId: 'form.validationRequired'}); + response = validate.validatePasswordConfirm('abcdef', 'abcdefg'); + t.deepEqual(response, {valid: false, errMsgId: 'general.error'}); + response = validate.validatePasswordConfirm('abcdef', '123456'); + t.deepEqual(response, {valid: false, errMsgId: 'general.error'}); + response = validate.validatePasswordConfirm('', 'abcdefg'); + t.deepEqual(response, {valid: false, errMsgId: 'general.error'}); + t.end(); +}); diff --git a/test/unit-legacy/redux/preview-test.js b/test/unit-legacy/redux/preview-test.js new file mode 100644 index 000000000..24a91ce84 --- /dev/null +++ b/test/unit-legacy/redux/preview-test.js @@ -0,0 +1,176 @@ +const tap = require('tap'); +const Preview = require('../../../src/redux/preview'); +const initialState = Preview.getInitialState(); +const reducer = Preview.previewReducer; + +let state; + +tap.tearDown(() => process.nextTick(process.exit)); + +tap.test('Reducer', t => { + t.type(reducer, 'function'); + t.type(initialState, 'object'); + + // Reducers should return their default state when called without state + let undefinedState; + t.deepEqual(initialState, reducer(undefinedState, {type: 'fake action'})); + t.end(); +}); + +tap.test('resetProject', t => { + state = reducer({some: 'garbage'}, Preview.resetProject()); + t.deepEqual(state, initialState); + t.end(); +}); + +tap.test('setProjectInfo', t => { + // Initial values + t.equal(initialState.projectNotAvailable, false); + t.deepEqual(initialState.projectInfo, {}); + + // setProjectInfo action with an `info` value sets the projectInfo + state = reducer(initialState, Preview.setProjectInfo('a value')); + t.equal(state.projectInfo, 'a value'); + t.equal(state.projectNotAvailable, false); + + // setProjectInfo action with null info sets projectNotAvailable to true + // and resets the project info back to default state + state = reducer(initialState, Preview.setProjectInfo(null)); + t.deepEqual(state.projectInfo, initialState.projectInfo); + t.equal(state.projectNotAvailable, true); + t.end(); +}); + +tap.test('updateProjectInfo', t => { + const info = {a: 'value a', b: 'value b'}; + state = reducer({projectInfo: info}, Preview.updateProjectInfo({ + b: 'new value b', + c: 'new value c' + })); + t.deepEqual(state.projectInfo, { + a: 'value a', + b: 'new value b', + c: 'new value c' + }); + t.end(); +}); + +tap.test('setComments', t => { + // Initial value + t.deepEqual(initialState.comments, []); + + state = reducer(initialState, Preview.setComments([{id: 1}, {id: 2}])); + state = reducer(state, Preview.setComments([{id: 3}, {id: 4}])); + t.deepEqual(state.comments, [{id: 1}, {id: 2}, {id: 3}, {id: 4}]); + + t.end(); +}); + +const commentState = { + comments: [ + {id: 'id1', visibility: 'visible'}, + {id: 'id2', visibility: 'visible'}, + {id: 'id3', visibility: 'visible'} + ], + replies: { + id1: [ + {id: 'id4', visibility: 'visible'}, + {id: 'id5', visibility: 'visible'} + ] + } +}; + +tap.test('setComments, discards duplicates', t => { + state = reducer(commentState, Preview.setComments([{id: 'id1'}])); + // Does not increase the number of comments, still 3 + t.equal(state.comments.length, 3); + t.end(); +}); + +tap.test('setCommentDeleted, top level comment', t => { + state = reducer(commentState, Preview.setCommentDeleted('id2')); + t.equal(state.comments[1].visibility, 'deleted'); + t.end(); +}); + +tap.test('setCommentDeleted, reply comment', t => { + state = reducer(commentState, Preview.setCommentDeleted('id4', 'id1')); + t.equal(state.replies.id1[0].visibility, 'deleted'); + t.end(); +}); + +tap.test('setRepliesDeleted/Restored', t => { + state = reducer(commentState, Preview.setRepliesDeleted('id1')); + t.equal(state.replies.id1[0].visibility, 'deleted'); + t.equal(state.replies.id1[1].visibility, 'deleted'); + + state = reducer(state, Preview.setRepliesRestored('id1')); + t.equal(state.replies.id1[0].visibility, 'visible'); + t.equal(state.replies.id1[1].visibility, 'visible'); + t.end(); +}); + +tap.test('setCommentReported, top level comment', t => { + state = reducer(commentState, Preview.setCommentReported('id2')); + t.equal(state.comments[1].visibility, 'reported'); + t.end(); +}); + +tap.test('setCommentReported, reply comment', t => { + state = reducer(commentState, Preview.setCommentReported('id4', 'id1')); + t.equal(state.replies.id1[0].visibility, 'reported'); + t.end(); +}); + +tap.test('addNewComment, top level comment', t => { + state = reducer(commentState, Preview.addNewComment({id: 'new comment'})); + // Adds comment to beginning of list + t.equal(state.comments[0].id, 'new comment'); + t.end(); +}); + +tap.test('addNewComment, reply comment', t => { + state = reducer(commentState, Preview.addNewComment({id: 'new comment'}, 'id1')); + // Adds replies to the end of the replies list + t.equal(state.replies.id1[2].id, 'new comment'); + t.end(); +}); + +tap.test('setReplies', t => { + // setReplies should append new replies + state = reducer(commentState, Preview.setReplies({ + id1: {id: 'id6'} + })); + t.equal(state.replies.id1[2].id, 'id6'); + t.equal(state.comments[0].moreRepliesToLoad, false); + + // setReplies should ignore duplicates, do the same as above again + t.equal(state.replies.id1.length, 3); + state = reducer(state, Preview.setReplies({id1: {id: 'id6'}})); + t.equal(state.replies.id1.length, 3); + + // setReplies can add replies to a comment that didn't have any + state = reducer(state, Preview.setReplies({ + id2: {id: 'id7'} + })); + t.equal(state.replies.id1.length, 3); + t.equal(state.replies.id2.length, 1); + t.equal(state.replies.id2[0].id, 'id7'); + t.equal(state.comments[0].moreRepliesToLoad, false); + t.equal(state.comments[1].moreRepliesToLoad, false); + + // Getting 20 (COMMENT_LIMIT) replies sets moreRepliesToLoad to true + state = reducer(state, Preview.setReplies({ + id3: (new Array(20)).map((_, i) => ({id: `id${i + 1}`})) + })); + t.equal(state.comments[0].moreRepliesToLoad, false); + t.equal(state.comments[1].moreRepliesToLoad, false); + t.equal(state.comments[2].moreRepliesToLoad, true); + + // Getting one more reply sets moreRepliesToLoad back to false + state = reducer(state, Preview.setReplies({ + id3: {id: 'id21'} + })); + t.equal(state.comments[2].moreRepliesToLoad, false); + t.end(); +}); diff --git a/test/unit-legacy/test_fastly_config_methods.js b/test/unit-legacy/test_fastly_config_methods.js new file mode 100644 index 000000000..81d96d11a --- /dev/null +++ b/test/unit-legacy/test_fastly_config_methods.js @@ -0,0 +1,79 @@ +var defaults = require('lodash.defaults'); +var fastlyConfig = require('../../bin/lib/fastly-config-methods'); +var routeJson = require('../../src/routes.json'); +var tap = require('tap'); + +var testRoutes = [ + { + name: 'less-traveled', + pattern: '^/?$', + routeAlias: '/?$', + view: 'less-traveled/less-traveled', + title: 'Robert Frost Goes Here' + }, + { + name: 'more-traveled', + pattern: '^/more?$', + routeAlias: '/more?$', + view: 'more-traveled/more-traveled', + title: 'Robert Frost Does Not Go Here' + } +]; + +var routes = routeJson.map(function (route) { + return defaults({}, {pattern: fastlyConfig.expressPatternToRegex(route.pattern)}, route); +}); +var extraAppRoutes = [ + // Homepage with querystring. + // TODO: Should this be added for every route? + '/\\?', + // View html + '/[^/]*.html$' +]; + + +tap.test('getStaticPaths', function (t) { + var staticPaths = fastlyConfig.getStaticPaths(__dirname, '../../build/*'); + t.type(staticPaths, 'object'); + t.end(); +}); + +tap.test('getViewPaths', function (t) { + var viewPaths = fastlyConfig.getViewPaths(testRoutes); + t.type(viewPaths, 'object'); + t.equal(viewPaths[0], '/?$'); + t.equal(viewPaths[1], '/more?$'); + t.end(); +}); + +tap.test('pathsToCondition', function (t) { + var condition = fastlyConfig.pathsToCondition(['/?$', '/more?$']); + t.type(condition, 'string'); + t.equal(condition, 'req.url~"^(/?$|/more?$)"'); + t.end(); +}); + +tap.test('getAppRouteCondition', function (t) { + var condition = fastlyConfig.getAppRouteCondition('../../build/*', routes, extraAppRoutes, __dirname); + t.type(condition, 'string'); + t.end(); +}); + +tap.test('testSetTTL', function (t) { + var ttl = fastlyConfig.setResponseTTL('itsactuallyttyl'); + t.equal(ttl, '' + + 'if (itsactuallyttyl) {\n' + + ' if (req.url ~ "^(/projects/|/fragment/account-nav.json|/session/)" && ' + + '!req.http.Cookie:scratchsessionsid) {\n' + + ' set beresp.http.Vary = "Accept-Encoding, Accept-Language";\n' + + ' unset beresp.http.set-cookie;\n' + + ' return(deliver);\n' + + ' } else {\n' + + ' set beresp.ttl = 0s;\n' + + ' set beresp.grace = 0s;\n' + + ' return(pass);\n' + + ' }\n' + + '}\n' + ); + t.end(); +}); From 4a963dbfaa1811d7a201f858762f636e606d91b3 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Wed, 17 Jul 2019 15:12:55 -0400 Subject: [PATCH 06/32] remove tap tests from non-legacy folders --- test/integration/package.json | 6 - test/integration/smoke-testing/test-join.js | 30 -- .../smoke-testing/test-login-failures.js | 89 ----- .../smoke-testing/test-my-stuff.js | 143 -------- .../smoke-testing/test_footer_links.js | 305 ------------------ .../smoke-testing/test_navbar_links.js | 123 ------- .../smoke-testing/test_project_page.js | 61 ---- .../smoke-testing/test_project_rows.js | 93 ------ test/integration/smoke-testing/test_search.js | 58 ---- .../test_signing_in_and_out_discuss.js | 62 ---- .../test_signing_in_and_out_homepage.js | 59 ---- .../smoke-testing/test_statistics_page.js | 68 ---- .../teacher_registration_utils.js | 99 ------ .../test_teacher_registration_address_step.js | 60 ---- ..._teacher_registration_demographics_step.js | 61 ---- .../test_teacher_registration_name_step.js | 60 ---- ..._teacher_registration_organization_step.js | 89 ----- .../test_teacher_registration_phone_step.js | 45 --- ...test_teacher_registration_username_step.js | 114 ------- ...st_teacher_registration_usescratch_step.js | 71 ---- test/localization/check_duplicate_strings.js | 52 --- test/localization/check_string_ids.js | 72 ----- test/localization/check_valid_json.js | 23 -- test/unit/lib/validate.js | 66 ---- test/unit/redux/preview-test.js | 176 ---------- test/unit/test_fastly_config_methods.js | 79 ----- 26 files changed, 2164 deletions(-) delete mode 100644 test/integration/package.json delete mode 100644 test/integration/smoke-testing/test-join.js delete mode 100644 test/integration/smoke-testing/test-login-failures.js delete mode 100644 test/integration/smoke-testing/test-my-stuff.js delete mode 100644 test/integration/smoke-testing/test_footer_links.js delete mode 100644 test/integration/smoke-testing/test_navbar_links.js delete mode 100644 test/integration/smoke-testing/test_project_page.js delete mode 100644 test/integration/smoke-testing/test_project_rows.js delete mode 100644 test/integration/smoke-testing/test_search.js delete mode 100644 test/integration/smoke-testing/test_signing_in_and_out_discuss.js delete mode 100644 test/integration/smoke-testing/test_signing_in_and_out_homepage.js delete mode 100644 test/integration/smoke-testing/test_statistics_page.js delete mode 100644 test/integration/teacher-registration/teacher_registration_utils.js delete mode 100644 test/integration/teacher-registration/test_teacher_registration_address_step.js delete mode 100644 test/integration/teacher-registration/test_teacher_registration_demographics_step.js delete mode 100644 test/integration/teacher-registration/test_teacher_registration_name_step.js delete mode 100644 test/integration/teacher-registration/test_teacher_registration_organization_step.js delete mode 100644 test/integration/teacher-registration/test_teacher_registration_phone_step.js delete mode 100644 test/integration/teacher-registration/test_teacher_registration_username_step.js delete mode 100644 test/integration/teacher-registration/test_teacher_registration_usescratch_step.js delete mode 100644 test/localization/check_duplicate_strings.js delete mode 100644 test/localization/check_string_ids.js delete mode 100644 test/localization/check_valid_json.js delete mode 100644 test/unit/lib/validate.js delete mode 100644 test/unit/redux/preview-test.js delete mode 100644 test/unit/test_fastly_config_methods.js diff --git a/test/integration/package.json b/test/integration/package.json deleted file mode 100644 index 811acf4df..000000000 --- a/test/integration/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "dependencies": { - "selenium-webdriver": "3.6.0", - "chromedriver": "2.43.1" - } -} diff --git a/test/integration/smoke-testing/test-join.js b/test/integration/smoke-testing/test-join.js deleted file mode 100644 index ea524b061..000000000 --- a/test/integration/smoke-testing/test-join.js +++ /dev/null @@ -1,30 +0,0 @@ -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); - -var tap = require('tap'); -const test = tap.test; - -const driver = helper.buildDriver('www-smoke test-login-failures'); - -const { - clickText, - findByXpath -} = helper; - -var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; - -tap.plan(1); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - return driver.get(rootUrl); -}); - -test('Clicking Join Scratch opens scratchr2 iframe', t => { - clickText('Join Scratch') - .then(() => findByXpath('//iframe[contains(@class, "mod-registration")]')) - .then(() => t.end()); -}); diff --git a/test/integration/smoke-testing/test-login-failures.js b/test/integration/smoke-testing/test-login-failures.js deleted file mode 100644 index a629bb5fd..000000000 --- a/test/integration/smoke-testing/test-login-failures.js +++ /dev/null @@ -1,89 +0,0 @@ -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); - -var tap = require('tap'); -const test = tap.test; - -const webdriver = require('selenium-webdriver'); -const driver = helper.buildDriver('www-smoke test-login-failures'); - -const { - findByCss, - clickCss -} = helper; - -var until = webdriver.until; - -var username = process.env.SMOKE_USERNAME; -var password = process.env.SMOKE_PASSWORD; - -var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; -var url = rootUrl + '/users/' + username; - -tap.plan(3); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - return driver.get(url); -}); - -test('Trying to sign in with no password using scratchr2 navbar', t => { - var nonsenseusername = Math.random().toString(36) - .replace(/[^a-z]+/g, '') - .substr(0, 5); - clickCss('.dropdown-toggle') - .then(() => findByCss('form#login input#login_dropdown_username')) - .then((element) => element.sendKeys(nonsenseusername)) - .then(() => clickCss('form#login button')) - .then(() => findByCss('form#login .error')) - .then((element) => { - driver.wait(until.elementIsVisible(element)); - return element; - }) - .then((element) => element.getText()) - .then((text) => t.match(text, 'This field is required', - '"This field is required" error should be displayed')) - .then(() => t.end()); -}); - -test('Trying to sign in with the wrong username using scratchr2 navbar', t => { - var nonsenseusername = Math.random().toString(36) - .replace(/[^a-z]+/g, '') - .substr(0, 5); - clickCss('.dropdown-toggle') - .then(() => findByCss('form#login input#login_dropdown_username')) - .then((element) => element.sendKeys(nonsenseusername)) - .then(() => findByCss('form#login input.wide.password')) - .then((element) => element.sendKeys(password)) - .then(() => clickCss('form#login button')) - .then(() => findByCss('form#login .error')) - .then((element) => { - driver.wait(until.elementIsVisible(element)); - return element; - }) - .then((element) => element.getText()) - .then((text) => t.match(text, 'Incorrect username or password.', - '"Incorrect username or password" error should be displayed')) - .then(() => t.end()); -}); - -test('Trying to sign in with the wrong password using scratchr2 navbar', t => { - clickCss('.dropdown-toggle') - .then(() => findByCss('form#login input#login_dropdown_username')) - .then((element) => element.sendKeys(username)) - .then(() => findByCss('form#login input.wide.password')) - .then((element) => element.sendKeys('nonsensepassword')) - .then(() => clickCss('form#login button')) - .then(() => findByCss('form#login .error')) - .then((element) => { - driver.wait(until.elementIsVisible(element)); - return element; - }) - .then((element) => element.getText()) - .then((text) => t.match(text, 'Incorrect username or password.', - '"Incorrect username or password" error should be displayed')) - .then(() => t.end()); -}); diff --git a/test/integration/smoke-testing/test-my-stuff.js b/test/integration/smoke-testing/test-my-stuff.js deleted file mode 100644 index 14ea7d227..000000000 --- a/test/integration/smoke-testing/test-my-stuff.js +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Tests signing in & My Stuff according to smoke-tests at: - * - * https://github.com/LLK/scratchr2/wiki/Smoke-Testing-Test-Cases - * - */ - -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); - -var tap = require('tap'); -const test = tap.test; - -const driver = helper.buildDriver('www-smoke test-my-stuff'); - -const { - clickText, - findByXpath, - clickXpath, - clickButton -} = helper; - -var username = process.env.SMOKE_USERNAME; -var password = process.env.SMOKE_PASSWORD; - -var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; -var url = rootUrl + '/users/' + username; - -tap.plan(7); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - return driver.get(url); -}); - -test('Sign in to Scratch using scratchr2 navbar', t => { - clickText('Sign in') - .then(() => findByXpath('//input[@id="login_dropdown_username"]')) - .then((element) => element.sendKeys(username)) - .then(() => findByXpath('//input[@name="password"]')) - .then((element) => element.sendKeys(password)) - .then(() => clickButton('Sign in')) - .then(() => findByXpath('//li[contains(@class, "logged-in-user")' + - 'and contains(@class, "dropdown")]/span')) - .then((element) => element.getText('span')) - .then((text) => t.match(text.toLowerCase(), username.substring(0, 10).toLowerCase(), - 'first part of username should be displayed in navbar')) - .then(() => t.end()); -}); - -test('Sign in to Scratch & verify My Stuff structure (tabs, title)', t => { - clickXpath('//a[contains(@class, "mystuff-icon")]') - .then(() => findByXpath('//div[@class="box-head"]/h2')) - .then((element) => element.getText('h2')) - .then((text) => t.equal('My Stuff', text, 'title should be My Stuff')) - .then(() => findByXpath('//li[@data-tab="projects"]/a')) - .then((element) => element.getText('a')) - .then((text) => t.match(text, 'All Projects', 'All Projects tab should be present')) - .then(() => findByXpath('//li[@data-tab="shared"]/a')) - .then((element) => element.getText('a')) - .then((text) => t.match(text, 'Shared Projects', 'Shared Projects tab should be present')) - .then(() => findByXpath('//li[@data-tab="unshared"]/a')) - .then((element) => element.getText('a')) - .then((text) => t.match(text, 'Unshared Projects', 'Unshared Projects tab should be present')) - .then(() => findByXpath('//li[@data-tab="galleries"]/a')) - .then((element) => element.getText('a')) - .then((text) => t.match(text, 'My Studios', 'My Studios tab should be present')) - .then(() => findByXpath('//li[@data-tab="trash"]/a')) - .then((element) => element.getText('a')) - .then((text) => t.match(text, 'Trash', 'Trash tab should be present')) - .then(() => t.end()); -}); - -test('clicking See Inside should take you to the editor', t => { - clickXpath('//a[contains(@class, "mystuff-icon")]') - .then(() => findByXpath('//a[@data-control="edit"]')) - .then((element) => element.getText('span')) - .then((text) => t.equal(text, 'See inside', 'there should be a "See inside" button')) - .then(() => clickXpath('//a[@data-control="edit"]')) - .then(() => driver.getCurrentUrl()) - .then(function (u) { - var expectedUrl = '/editor'; - t.equal(u.substr(-expectedUrl.length), expectedUrl, 'after clicking, the URL should end in #editor'); - }) - .then(() => t.end()); -}); - -test('clicking a project title should take you to the project page', t => { - clickXpath('//a[contains(@class, "mystuff-icon")]') - .then(() => clickXpath('//a[@data-control="edit"]')) - .then(() => driver.getCurrentUrl()) - .then(function (u) { - var expectedUrlRegExp = new RegExp('/projects/.*[0-9].*/?'); - t.match(u, expectedUrlRegExp, 'after clicking, the URL should end in projects/PROJECT_ID/'); - }) - .then(() => t.end()); -}); - -test('Add To button should bring up a list of studios', t => { - clickXpath('//a[contains(@class, "mystuff-icon")]') - .then(() => clickXpath('//div[@id="sidebar"]/ul/li[@data-tab="shared"]')) - .then(() => findByXpath('//div[@data-control="add-to"]')) - .then((element) => element.getText('span')) - .then((text) => t.equal(text, 'Add to', 'there should be an "Add to" button')) - .then(() => clickXpath('//div[@data-control="add-to"]')) - .then(() => findByXpath('//div[@class="dropdown-menu"]/ul/li')) - .then((element) => element.getText('span')) - .then(function (text) { - var expectedRegExp = new RegExp('.+'); - t.match(text, expectedRegExp, 'the dropdown menu should have at least 1 text item in it'); - }) - .then(() => t.end()); -}); - -test('+ New Studio button should take you to the studio page', {skip: true}, t => { - clickXpath('//a[contains(@class, "mystuff-icon")]') - .then(() => clickXpath('//form[@id="new_studio"]/button[@type="submit"]')) - .then(() => findByXpath('//div[@id="show-add-project"]')) - .then((element) => element.getText('span')) - .then((text) => t.equal(text, 'Add projects', 'there should be an "Add projects" button')) - .then(() => driver.getCurrentUrl()) - .then(function (u) { - var expectedUrlRegExp = new RegExp('/studios/.*[0-9].*/?'); - t.match(u, expectedUrlRegExp, - 'after clicking the + New Studio, the URL should end in studios/STUDIO_ID'); - }) - .then(() => t.end()); -}); - -test('+ New Project button should open the editor', {skip: true}, t => { - clickXpath('//a[contains(@class, "mystuff-icon")]') - .then(() => clickText('+ New Project')) - .then(() => driver.getCurrentUrl()) - .then(function (u) { - var expectedUrlRegExp = new RegExp('/projects/editor'); - t.match(u, expectedUrlRegExp, - 'after clicking, the URL should end in projects/editor'); - }) - .then(() => t.end()); -}); diff --git a/test/integration/smoke-testing/test_footer_links.js b/test/integration/smoke-testing/test_footer_links.js deleted file mode 100644 index 0fa9ed80e..000000000 --- a/test/integration/smoke-testing/test_footer_links.js +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Checks that the links in the footer on the homepage have the right URLs to redirect to - * - * Test cases: https://github.com/LLK/scratch-www/wiki/Most-Important-Workflows - */ - -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); - -const tap = require('tap'); - -const webdriver = require('selenium-webdriver'); -const driver = helper.buildDriver('www-smoke test_footer_links'); - -const rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; - -// timeout for each test; timeout for suite set at command line level -const options = {timeout: 30000}; - -// number of tests in the plan -tap.plan(24); - -tap.tearDown(function () { - // quit the instance of the browser - driver.quit(); -}); - -tap.beforeEach(function () { - // load the page with the driver - return driver.get(rootUrl); -}); - -// Function clicks the link and returns the url of the resulting page - -const clickFooterLinks = function (linkText) { - return driver.wait(webdriver.until.elementLocated(webdriver.By.id('footer'))) - .then(function (element) { - return element.findElement(webdriver.By.linkText(linkText)); - }) - .then(function (element) { - return element.click(); - }) - .then(function () { - return driver.getCurrentUrl(); - }); -}; - -// ==== ABOUT SCRATCH column ==== - -// ABOUT SCRATCH -tap.test('clickAboutScratchLink', options, t => { - const linkText = 'About Scratch'; - const expectedHref = '/about'; - clickFooterLinks(linkText).then(url => { - // the href should be at the end of the URL - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// FOR PARENTS -tap.test('clickForParentsLink', options, t => { - const linkText = 'For Parents'; - const expectedHref = '/parents/'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// FOR EDUCATORS -tap.test('clickForEducatorsLink', options, t => { - const linkText = 'For Educators'; - const expectedHref = '/educators'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// FOR DEVELOPERS -tap.test('clickForDevelopersScratchLink', options, t => { - const linkText = 'For Developers'; - const expectedHref = '/developers'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// CREDITS -tap.test('clickCreditsLink', options, t => { - const linkText = 'Credits'; - const expectedHref = '/credits'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// JOBS -tap.test('clickJobsLink', options, t => { - const linkText = 'Jobs'; - const expectedHref = '/jobs'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// PRESS -tap.test('clickPressLink', options, t => { - const linkText = 'Press'; - const expectedUrl = 'https://www.scratchfoundation.org/media-kit/'; - clickFooterLinks(linkText).then(url => { - t.equal(url, expectedUrl); - t.end(); - }); -}); - -// ==== COMMUNITY column ==== - -// COMMUNITY GUIDELINES -tap.test('clickCommunityGuidelinesLink', options, t => { - const linkText = 'Community Guidelines'; - const expectedHref = '/community_guidelines'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// DISCUSSION FORUMS -tap.test('clickDiscussionForumsLink', options, t => { - const linkText = 'Discussion Forums'; - const expectedHref = '/discuss/'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// SCRATCH WIKI test has been removed. - -// STATISTICS -tap.test('clickStatisticsLink', options, t => { - const linkText = 'Statistics'; - const expectedHref = '/statistics/'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// ==== SUPPORT column ==== - -// IDEAS PAGE -tap.test('clickIdeasPageLink', options, t => { - const linkText = 'Ideas'; - const expectedHref = '/ideas'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// FAQ -tap.test('clickFAQLink', options, t => { - const linkText = 'FAQ'; - const expectedHref = '/info/faq'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// OFFLINE EDITOR -tap.test('clickOfflineEditorLink', options, t => { - const linkText = 'Offline Editor'; - const expectedHref = '/download'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// CONTACT US -tap.test('clickContactUsLink', options, t => { - const linkText = 'Contact Us'; - const expectedHref = '/contact-us/'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// skip this test since it points to an external site -// SCRATCH STORE -tap.test('clickScratchStoreLink', {skip: true}, t => { - const linkText = 'Scratch Store'; - const expectedUrl = 'https://scratch-foundation.myshopify.com/'; - clickFooterLinks(linkText).then(url => { - t.equal(url, expectedUrl); - t.end(); - }); -}); - -// skip this test since it points to an external site -// DONATE -tap.test('clickDonateLink', {skip: true}, t => { - const linkText = 'Donate'; - const expectedUrl = 'https://secure.donationpay.org/scratchfoundation/'; - clickFooterLinks(linkText).then(url => { - t.equal(url, expectedUrl); - t.end(); - }); -}); - -// ==== LEGAL column ==== - -// TERMS OF USE -tap.test('clickTermsOfUseLink', options, t => { - const linkText = 'Terms of Use'; - const expectedHref = '/terms_of_use'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// PRIVACY POLICY -tap.test('clickPrivacyPolicyLink', options, t => { - const linkText = 'Privacy Policy'; - const expectedHref = '/privacy_policy'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// DMCA -tap.test('clickDMCALink', options, t => { - const linkText = 'DMCA'; - const expectedHref = '/DMCA'; - clickFooterLinks(linkText).then(url => { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// ==== SCRATCH FAMILY column ==== - -// skip this test since it points to an external site -// SCRATCH ED (SCRATCHED) -tap.test('clickScratchEdLink', {skip: true}, t => { - const linkText = 'ScratchEd'; - const expectedUrl = 'http://scratched.gse.harvard.edu/'; - clickFooterLinks(linkText).then(url => { - t.equal(url, expectedUrl); - t.end(); - }); -}); - -// skip this test since it points to an external site -// SCRATCH JR (SCRATCHJR) -tap.test('clickScratchJrLink', {skip: true}, t => { - const linkText = 'ScratchJr'; - const expectedUrl = 'https://www.scratchjr.org/'; - clickFooterLinks(linkText).then(url => { - t.equal(url, expectedUrl); - t.end(); - }); -}); - -// skip this test since it points to an external site -// SCRATCH DAY -tap.test('clickScratchDayLink', {skip: true}, t => { - const linkText = 'Scratch Day'; - const expectedUrl = 'https://day.scratch.mit.edu/'; - clickFooterLinks(linkText).then(url => { - t.equal(url, expectedUrl); - t.end(); - }); -}); - -// SCRATCH CONFERENCE -tap.test('clickScratchConferenceLink', options, t => { - const linkText = 'Scratch Conference'; - const expectedHref = '/conference/20'; - clickFooterLinks(linkText).then(url => { - t.match(url.substr(-(expectedHref.length + 2)), expectedHref); - t.end(); - }); -}); - -// skip this test since it points to an external site -// SCRATCH FOUNDATION -tap.test('clickScratchFoundationLink', {skip: true}, t => { - const linkText = 'Scratch Foundation'; - const expectedUrl = 'https://www.scratchfoundation.org/'; - clickFooterLinks(linkText).then(url => { - t.equal(url, expectedUrl); - t.end(); - }); -}); diff --git a/test/integration/smoke-testing/test_navbar_links.js b/test/integration/smoke-testing/test_navbar_links.js deleted file mode 100644 index 632c6d9e9..000000000 --- a/test/integration/smoke-testing/test_navbar_links.js +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Checks that the links in the navbar on the homepage have the right URLs to redirect to - * - * Test cases: https://github.com/LLK/scratch-www/wiki/Most-Important-Workflows - */ - -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); - -var tap = require('tap'); - -const webdriver = require('selenium-webdriver'); -const driver = helper.buildDriver('www-smoke test_navbar_links'); - -// Set test url through environment variable -var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; - -// number of tests in the plan -tap.plan(7); - -tap.tearDown(function () { - // quit the instance of the browser - driver.quit(); -}); - -tap.beforeEach(function () { - // load the page with the driver - return driver.get(rootUrl); -}); - -// ==== Links in navbar ==== - -// the create link changes depending on whether the user is signed in or not (tips window opens) -tap.test('checkCreateLinkWhenSignedOut', function (t) { - var xPathLink = '//li[contains(@class, "link") and contains(@class, "create")]/a'; - var expectedHref = '/projects/editor/?tutorial=getStarted'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - return element.getAttribute('href'); - }) - .then(function (url) { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -tap.test('checkExploreLinkWhenSignedOut', function (t) { - var xPathLink = '//li[contains(@class, "link") and contains(@class, "explore")]/a'; - var expectedHref = '/explore/projects/all'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - return element.getAttribute('href'); - }) - .then(function (url) { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -tap.test('checkIdeasLinkWhenSignedOut', function (t) { - var xPathLink = '//li[contains(@class, "link") and contains(@class, "ideas")]/a'; - var expectedHref = '/ideas'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - return element.getAttribute('href'); - }) - .then(function (url) { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -tap.test('checkAboutLinkWhenSignedOut', function (t) { - var xPathLink = '//li[contains(@class, "link") and contains(@class, "about")]/a'; - var expectedHref = '/about'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - return element.getAttribute('href'); - }) - .then(function (url) { - t.equal(url.substr(-expectedHref.length), expectedHref); - t.end(); - }); -}); - -// ==== Search bar ==== - -tap.test('checkSearchBar', function (t) { - var xPathLink = '//input[@id="frc-q-1088"]'; - // search bar should exist - driver.findElement(webdriver.By.xpath(xPathLink)).then(function (element) { - t.ok(element); - t.end(); - }); -}); - -// ==== Join Scratch & Sign In ==== - -tap.test('checkJoinScratchLinkWhenSignedOut', function (t) { - var xPathLink = '//li[contains(@class, "link") and contains(@class, "right") and contains(@class, "join")]/a'; - var expectedText = 'Join Scratch'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - return element.getText('a'); - }) - .then(function (text) { - t.equal(text, expectedText); - t.end(); - }); -}); - -tap.test('checkSignInLinkWhenSignedOut', function (t) { - var xPathLink = '//li[contains(@class, "link") and contains(@class, "right") and contains(@class, "login-item")]/a'; - var expectedText = 'Sign in'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - return element.getText('a'); - }) - .then(function (text) { - t.equal(text, expectedText); - t.end(); - }); -}); diff --git a/test/integration/smoke-testing/test_project_page.js b/test/integration/smoke-testing/test_project_page.js deleted file mode 100644 index df9c031e4..000000000 --- a/test/integration/smoke-testing/test_project_page.js +++ /dev/null @@ -1,61 +0,0 @@ -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); - -var tap = require('tap'); -const test = tap.test; - -const driver = helper.buildDriver('www-smoke test_sign_in_out_homepage'); - -const { - clickText, - clickXpath, - dragFromXpathToXpath, - findByXpath, - waitUntilGone -} = helper; - -const rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; -const projectId = 1; -const projectUrl = `${rootUrl}/projects/${projectId}`; - -tap.plan(3); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - return driver.get(projectUrl); -}); - -test('Find fullscreen button', {skip: true}, t => { - findByXpath('//div[starts-with(@class, "loader_background")]') - .then(el => waitUntilGone(el)) - .then(() => clickXpath('//div[starts-with(@class, "stage_green-flag-overlay")]')) - .then(() => clickXpath('//img[contains(@alt, "Enter full screen mode")]')) - .then(() => t.end()); -}); - -test('Open and close Copy Link modal', {skip: true}, t => { - findByXpath('//div[starts-with(@class, "loader_background")]') - .then(el => waitUntilGone(el)) - .then(() => clickText('Copy Link')) - .then(() => clickXpath('//div[contains(@class, "social-label-title")]')) - .then(() => clickXpath('//img[contains(@alt, "close-icon")]')) - .then(() => clickXpath('//img[contains(@alt, "Enter full screen mode")]')) - .then(() => t.end()); -}); - -test('Dragging out of modal should not close modal', {skip: true}, t => { - findByXpath('//div[starts-with(@class, "loader_background")]') - .then(el => waitUntilGone(el)) - .then(() => clickXpath('//div[starts-with(@class, "stage_green-flag-overlay")]')) - .then(() => clickText('Copy Link')) - .then(() => clickXpath('//div[contains(@class, "social-label-title")]')) - .then(() => dragFromXpathToXpath( - '//div[contains(@class, "social-label-title")]', - '//li[contains(@class, "logo")]' - )) - .then(() => clickXpath('//div[contains(@class, "social-label-title")]')) - .then(() => t.end()); -}); diff --git a/test/integration/smoke-testing/test_project_rows.js b/test/integration/smoke-testing/test_project_rows.js deleted file mode 100644 index 029125b3a..000000000 --- a/test/integration/smoke-testing/test_project_rows.js +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Checks that the some of the homepage rows on the homepage are displayed and - * contents have the right URLs to redirect to - * - * Test cases: https://github.com/LLK/scratch-www/wiki/Most-Important-Workflows - */ - -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); - -var tap = require('tap'); - -const webdriver = require('selenium-webdriver'); -const driver = helper.buildDriver('www-smoke test_project_rows'); - -var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; - -// number of tests in the plan -tap.plan(4); - -tap.tearDown(function () { - // quit the instance of the browser - driver.quit(); -}); - -tap.beforeEach(function () { - // load the page with the driver - return driver.get(rootUrl); -}); - -// checks that the title of the first row is Featured Projects -tap.test('checkFeaturedProjectsRowTitleWhenSignedOut', function (t) { - var xPathLink = '//div[@class="box"]/div[@class="box-header"]/h4'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - element.getText('h4') - .then(function (text) { - // expected value of the title text - var expectedText = 'Featured Projects'; - t.equal(text, expectedText); - t.end(); - }); - }); -}); - -// checks that the link for a project makes sense -tap.test('checkFeaturedProjectsRowLinkWhenSignedOut', function (t) { - var xPathLink = '//div[contains(@class, "thumbnail") ' + - 'and contains(@class, "project") and contains(@class, "slick-slide") ' + - 'and contains(@class, "slick-active")]/a[@class="thumbnail-image"]'; - driver.wait(webdriver.until - .elementLocated(webdriver.By.xpath(xPathLink))) - .then(function (element) { - element.getAttribute('href') - .then(function (url) { - // expected pattern for the project URL - // since I don't know the length of the project ID number - var expectedUrlRegExp = new RegExp('/projects/.*[0-9].*/?'); - t.match(url, expectedUrlRegExp); - t.end(); - }); - }); -}); - -// checks that the title of the 2nd row is Featured Studios -tap.test('checkFeaturedStudiosRowWhenSignedOut', function (t) { - var xPathLink = '//div[@class="box"][2]/div[@class="box-header"]/h4'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - element.getText('h4') - .then(function (text) { - var expectedText = 'Featured Studios'; - t.equal(text, expectedText); - t.end(); - }); - }); -}); - -// checks that the link for a studio makes sense -tap.test('checkFeaturedStudiosRowLinkWhenSignedOut', function (t) { - var xPathLink = '//div[contains(@class, "thumbnail") and contains(@class, "gallery") ' + - 'and contains(@class, "slick-slide") ' + - 'and contains(@class, "slick-active")]/a[@class="thumbnail-image"]'; - driver.findElement(webdriver.By.xpath(xPathLink)) - .then(function (element) { - element.getAttribute('href') - .then(function (url) { - var expectedUrlRegExp = new RegExp('/studios/.*[0-9].*/?'); - t.match(url, expectedUrlRegExp); - t.end(); - }); - }); -}); diff --git a/test/integration/smoke-testing/test_search.js b/test/integration/smoke-testing/test_search.js deleted file mode 100644 index 22a85e651..000000000 --- a/test/integration/smoke-testing/test_search.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Checks the behavior of the search interface - */ -require('chromedriver'); -const seleniumWebdriver = require('selenium-webdriver'); -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); -const { - urlMatches -} = helper; - -const tap = require('tap'); -const test = tap.test; - -// Set test url through environment variable -const rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; -const searchBaseUrl = `${rootUrl}/search/`; - -// chrome driver -const driver = helper.buildDriver('www-search test_search'); - -tap.plan(3); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - return driver.get(searchBaseUrl); -}); - -test('Search escapes spaces', function (t) { - const searchInput = driver.findElement(seleniumWebdriver.By.name('q')); - searchInput.sendKeys('Test search string', helper.getKey('ENTER')).then(function () { - urlMatches(/^.*\?q=Test%20search%20string$/) - .then(() => t.end()); - }); -}); - -test('Search escapes symbols', function (t) { - const searchInput = driver.findElement(seleniumWebdriver.By.name('q')); - searchInput.sendKeys('100% pen', helper.getKey('ENTER')).then(function () { - urlMatches(/^.*\?q=100%25%20pen$/) - .then(() => t.end()); - }); -}); - -test('Switching to studios maintains search string', function (t) { - const searchInput = driver.findElement(seleniumWebdriver.By.name('q')); - searchInput.sendKeys('100% pen', helper.getKey('ENTER')).then(function () { - const studiosTab = driver.findElement(seleniumWebdriver.By.xpath( - '//a/li/span[contains(text(),"Studios")]')); - studiosTab.click().then(function () { - urlMatches(/^.*\?q=100%25%20pen$/) - .then(() => t.end()); - }); - }); -}); diff --git a/test/integration/smoke-testing/test_signing_in_and_out_discuss.js b/test/integration/smoke-testing/test_signing_in_and_out_discuss.js deleted file mode 100644 index e95426548..000000000 --- a/test/integration/smoke-testing/test_signing_in_and_out_discuss.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Tests from: - * - * https://github.com/LLK/scratchr2/wiki/Smoke-Testing-Test-Cases - * - */ - -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); - -var tap = require('tap'); -const test = tap.test; - -const driver = helper.buildDriver('www-smoke test_sign_in_out_discuss'); - -const { - clickText, - findByXpath, - findText, - clickXpath, - clickButton -} = helper; - -var username = process.env.SMOKE_USERNAME; -var password = process.env.SMOKE_PASSWORD; - -var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; -var url = rootUrl + '/discuss'; - -tap.plan(2); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - return driver.get(url); -}); - -test('Sign in to Scratch using scratchr2 navbar', t => { - clickText('Sign in') - .then(() => findByXpath('//input[@id="login_dropdown_username"]')) - .then((element) => element.sendKeys(username)) - .then(() => findByXpath('//input[@name="password"]')) - .then((element) => element.sendKeys(password)) - .then(() => clickButton('Sign in')) - .then(() => findByXpath('//li[contains(@class, "logged-in-user")' + - 'and contains(@class, "dropdown")]/span')) - .then((element) => element.getText('span')) - .then((text) => t.match(text.toLowerCase(), username.substring(0, 10).toLowerCase(), - 'first part of username should be displayed in navbar')) - .then(() => t.end()); -}); - -test('Sign out of Scratch using scratchr2 navbar', t => { - clickXpath('//span[contains(@class, "user-name")' + - ' and contains(@class, "dropdown-toggle")]/img[contains(@class, "user-icon")]') - .then(() => clickXpath('//input[@value="Sign out"]')) - .then(() => findText('Sign in')) - .then((element) => t.ok(element, 'Sign in reappeared on the page after signing out')) - .then(() => t.end()); -}); diff --git a/test/integration/smoke-testing/test_signing_in_and_out_homepage.js b/test/integration/smoke-testing/test_signing_in_and_out_homepage.js deleted file mode 100644 index 15687b0cf..000000000 --- a/test/integration/smoke-testing/test_signing_in_and_out_homepage.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Tests from: - * - * https://github.com/LLK/scratchr2/wiki/Smoke-Testing-Test-Cases - * - */ - -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); - -var tap = require('tap'); -const test = tap.test; - -const driver = helper.buildDriver('www-smoke test_sign_in_out_homepage'); - -const { - clickText, - findText, - findByXpath, - clickXpath -} = helper; - -var username = process.env.SMOKE_USERNAME; -var password = process.env.SMOKE_PASSWORD; - -var rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; - -tap.plan(2); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - return driver.get(rootUrl); -}); - -test('Sign in to Scratch using scratch-www navbar', {skip: true}, t => { - clickText('Sign in') - .then(() => findByXpath('//input[@id="frc-username-1088"]')) - .then((element) => element.sendKeys(username)) - .then(() => findByXpath('//input[@id="frc-password-1088"]')) - .then((element) => element.sendKeys(password)) - .then(() => clickXpath('//button[contains(@class, "button") and ' + - 'contains(@class, "submit-button") and contains(@class, "white")]')) - .then(() => findByXpath('//span[contains(@class, "profile-name")]')) - .then((element) => element.getText()) - .then((text) => t.match(text.toLowerCase(), username.substring(0, 10).toLowerCase(), - 'first part of username should be displayed in navbar')) - .then(() => t.end()); -}); - -test('Sign out of Scratch using scratch-www navbar', {skip: true}, t => { - clickXpath('//a[contains(@class, "user-info")]') - .then(() => clickText('Sign out')) - .then(() => findText('Sign in')) - .then((element) => t.ok(element, 'Sign in reappeared on the page after signing out')) - .then(() => t.end()); -}); diff --git a/test/integration/smoke-testing/test_statistics_page.js b/test/integration/smoke-testing/test_statistics_page.js deleted file mode 100644 index 9a8f9596c..000000000 --- a/test/integration/smoke-testing/test_statistics_page.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Tests stats page according to smoke-tests at: - * - * https://github.com/LLK/scratchr2/wiki/Smoke-Testing-Test-Cases - * - */ - -const SeleniumHelper = require('../selenium-helpers.js'); -const helper = new SeleniumHelper(); - -var tap = require('tap'); -const test = tap.test; - -const driver = helper.buildDriver('www-smoke test_statistics_page'); - -const { - clickText, - findByXpath, - findByCss -} = helper; - -tap.plan(2); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - /* - * load the page with the driver - * note that for now this is not testable on Staging, - * so I left it pointing to Production - - * we can at least use it post-deploy. - * - * var stagingURL = 'https://scratch.ly/statistics'; - */ - var productionURL = 'https://scratch.mit.edu/statistics'; - return driver.get(productionURL); -}); - -test('check that Monthly Activity Trends title is present & correct', t => { - var chartTitle = 'Monthly Activity Trends'; - findByCss('div.box-head h3') - .then((element) => element.getText('h3')) - .then((text) => t.equal(text, chartTitle, 'chart title should be Monthly Activity Trends')) - .then(() => t.end()); -}); - -test('check that Monthly Activity Trends chart > New Projects label is toggleable', t => { - var classXpath = `(//div[@id="activity_chart"]/*[name()='svg']/*[name()='g']/*[name()='g']/*` + - `[name()='g'])[4]/*[name()='g']/*[name()='g']/*[name()='g']`; - findByXpath(classXpath) - .then((element) => element.getAttribute('class')) - .then((classtext) => t.equal(classtext, 'nv-series', 'by default, New Projects should be enabled')) - .then(() => clickText('New Projects')) - .then(() => findByXpath(classXpath)) - .then((element) => element.getAttribute('class')) - .then((classtext) => t.equal( - classtext, - 'nv-series nv-disabled', - 'when clicked, New Projects should be disabled' - )) - .then(() => clickText('New Projects')) - .then(() => findByXpath(classXpath)) - .then((element) => element.getAttribute('class')) - .then((classtext) => t.equal(classtext, 'nv-series', 'when clicked again, New Projects should be enabled')) - .then(() => t.end()); -}); diff --git a/test/integration/teacher-registration/teacher_registration_utils.js b/test/integration/teacher-registration/teacher_registration_utils.js deleted file mode 100644 index dfc828f68..000000000 --- a/test/integration/teacher-registration/teacher_registration_utils.js +++ /dev/null @@ -1,99 +0,0 @@ -module.exports.constants = { - nextStepXpath: '//button[span[contains(text(), "Next Step")]]', - generalErrorMessageXpath: '//span[@class="help-block validation-message"]/span[contains(text(),' + - '"This field is required")]', - loremIpsumTextLong: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur viverra' + - 'nec mauris efficitur tincidunt. Vestibulum ut diam odio. Cum sociis natoque penatibus et magnis dis' + - 'parturient montes, nascetur ridiculus mus. Morbi non enim dolor. Vestibulum at enim vestibulum, ullamcorper' + - 'Duis eget quam pharetra, ultricies est eu, pharetra nisi. In tempor cursus nisi, non sagittis quam gravida.' -}; - -module.exports.fillUsernameSlide = function (driver, seleniumWebdriver) { - var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password')); - var usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username')); - var usernamePromise = usernameInput.sendKeys('clipspringer'); - var passwordPromise = passwordInput.sendKeys('educators'); - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath)); - return Promise.all([usernamePromise, passwordPromise]).then(function () { // eslint-disable-line no-undef - nextStepButton.click().then(function () { - driver.wait(seleniumWebdriver.until - .elementLocated(seleniumWebdriver.By.className('demographics-step'))); - }); - }); -}; - -module.exports.fillDemographicsSlide = function (driver, seleniumWebdriver) { - var clickMaleInput = driver.findElement(seleniumWebdriver.By.xpath('//input[@value="male"' + - 'and @type="radio"]')).click(); - var selectCountry = driver.findElement(seleniumWebdriver.By.xpath('//select[@name="user.country"]' + - '/option[@value="us"]')).click(); - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath)); - return Promise.all([clickMaleInput, selectCountry]).then(function () { // eslint-disable-line no-undef - nextStepButton.click().then(function () { - driver.wait(seleniumWebdriver.until - .elementLocated(seleniumWebdriver.By.className('name-step'))); - }); - }); -}; - -module.exports.fillNameSlide = function (driver, seleniumWebdriver) { - var firstNamePromise = driver.findElement(seleniumWebdriver.By.name('user.name.first')).sendKeys('first'); - var lastNamePromise = driver.findElement(seleniumWebdriver.By.name('user.name.last')).sendKeys('surname'); - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath)); - return Promise.all([firstNamePromise, lastNamePromise]).then(function () { // eslint-disable-line no-undef - nextStepButton.click().then(function () { - driver.wait(seleniumWebdriver.until - .elementLocated(seleniumWebdriver.By.className('phone-step'))); - }); - }); -}; - -module.exports.fillPhoneSlide = function (driver, seleniumWebdriver) { - var phoneInput = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="tel"]')); - var consentCheckbox = driver.findElement(seleniumWebdriver.By.name('phoneConsent')); - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath)); - var phoneNumberPromise = phoneInput.sendKeys('6172535960'); - var consentPromise = consentCheckbox.click(); - return Promise.all([phoneNumberPromise, consentPromise]).then(function () { // eslint-disable-line no-undef - nextStepButton.click().then(function () { - driver.wait(seleniumWebdriver.until - .elementLocated(seleniumWebdriver.By.className('organization-step'))); - }); - }); -}; - -module.exports.fillOrganizationSlide = function (driver, seleniumWebdriver) { - var organizationInput = driver.findElement(seleniumWebdriver.By.name('organization.name')); - var titleInput = driver.findElement(seleniumWebdriver.By.name('organization.title')); - var typeCheckbox = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="checkbox" and @value="3"]')); - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath)); - var organizationPromise = organizationInput.sendKeys('MIT Media Lab'); - var titlePromise = titleInput.sendKeys('Software Developer'); - var typePromise = typeCheckbox.click(); - return Promise.all([organizationPromise, titlePromise, typePromise]) // eslint-disable-line no-undef - .then(function () { - nextStepButton.click().then(function () { - driver.wait(seleniumWebdriver.until - .elementLocated(seleniumWebdriver.By.className('address-step'))); - }); - }); -}; - -module.exports.fillAddressSlide = function (driver, seleniumWebdriver) { - var addressInput = driver.findElement(seleniumWebdriver.By.name('address.line1')); - var cityInput = driver.findElement(seleniumWebdriver.By.name('address.city')); - var zipCodeInput = driver.findElement(seleniumWebdriver.By.name('address.zip')); - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath)); - var addressPromise = addressInput.sendKeys('77 Massachusetts Avenue, E14/E15'); - var cityPromise = cityInput.sendKeys('Cambridge'); - var statePromise = driver.findElement(seleniumWebdriver.By.xpath('//select[@name="address.state"]' + - '/option[@value="us-ma"]')).click(); - var zipPromise = zipCodeInput.sendKeys('02139'); - return Promise.all([addressPromise, cityPromise, statePromise, zipPromise]) // eslint-disable-line no-undef - .then(function () { - nextStepButton.click().then(function () { - driver.wait(seleniumWebdriver.until - .elementLocated(seleniumWebdriver.By.className('usescratch-step'))); - }); - }); -}; diff --git a/test/integration/teacher-registration/test_teacher_registration_address_step.js b/test/integration/teacher-registration/test_teacher_registration_address_step.js deleted file mode 100644 index 557f5155f..000000000 --- a/test/integration/teacher-registration/test_teacher_registration_address_step.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Checks the behavior of the address step in the educators registration process - * - * Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow - */ -require('chromedriver'); -var seleniumWebdriver = require('selenium-webdriver'); -var tap = require('tap'); - -var utils = require('./teacher_registration_utils.js'); -var constants = utils.constants; - -// Set test url through environment variable -var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; - -// chrome driver -var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) - .build(); - -tap.plan(2); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - driver.get(rootUrl + '/educators/register'); - return utils.fillUsernameSlide(driver, seleniumWebdriver) - .then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this - .then(utils.fillNameSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this - .then(utils.fillPhoneSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this - .then(utils.fillOrganizationSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this -}); - -// Selects Vatican City as the country, and checks that the state dropdown disappears -tap.test('checkStateDropdownOnlyPresentWhenNeeded', function (t) { - driver.findElement(seleniumWebdriver.By.xpath('//select[@name="address.country"]' + - '/option[@value="va"]')).click() // select Vatican City as the country - .then(function () { - driver.findElements(seleniumWebdriver.By.name('address.state')) - .then(function (stateDropdown) { - t.equal(stateDropdown.length, 0); - t.end(); - }); - }); -}); - -tap.test('checkZipCodeRequired', function (t) { - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); - var errorMessageXPath = '//input[@name="address.zip"]/following-sibling::' + - 'span[@class="help-block validation-message"]/span[contains(text(),' + - '"This field is required")]'; - nextStepButton.click().then(function () { - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) - .then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); diff --git a/test/integration/teacher-registration/test_teacher_registration_demographics_step.js b/test/integration/teacher-registration/test_teacher_registration_demographics_step.js deleted file mode 100644 index cb589d137..000000000 --- a/test/integration/teacher-registration/test_teacher_registration_demographics_step.js +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Checks the behavior of demographics step in the educators registration process - * - * Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow - */ -require('chromedriver'); -var seleniumWebdriver = require('selenium-webdriver'); -var tap = require('tap'); - -var utils = require('./teacher_registration_utils.js'); -var constants = utils.constants; - -// Set test url through environment variable -var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; - -// chrome driver -var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) - .build(); - -tap.plan(2); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - driver.get(rootUrl + '/educators/register'); - return utils.fillUsernameSlide(driver, seleniumWebdriver); -}); - -// if the user selects the other gender option, they must input a gender -// selects the other gender option and attempt to advance the slide -tap.test('checkOtherGenderInput', function (t) { - var otherGenderRadio = driver.findElement(seleniumWebdriver.By.xpath('//input[@value="other"' + - 'and @type="radio"]')); - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); - driver.findElement(seleniumWebdriver.By.xpath('//select[@name="user.country"]/option[2]')).click(); - otherGenderRadio.click().then(function () { - nextStepButton.click().then(function () { - driver.findElements(seleniumWebdriver.By.xpath(constants.generalErrorMessageXpath)) - .then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); - }); -}); - -// the user must select a gender -// tries to advance the slide without selecting a gender -tap.test('checkNoGenderInput', function (t) { - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); - driver.findElement(seleniumWebdriver.By.xpath('//select[@name="user.country"]/option[2]')).click(); - nextStepButton.click().then(function () { - driver.findElements(seleniumWebdriver.By.xpath(constants.generalErrorMessageXpath)) - .then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); diff --git a/test/integration/teacher-registration/test_teacher_registration_name_step.js b/test/integration/teacher-registration/test_teacher_registration_name_step.js deleted file mode 100644 index dee76448d..000000000 --- a/test/integration/teacher-registration/test_teacher_registration_name_step.js +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Checks the behavior of the name step in the educators registration process - * - * Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow - */ -require('chromedriver'); -var seleniumWebdriver = require('selenium-webdriver'); -var tap = require('tap'); - -var utils = require('./teacher_registration_utils.js'); -var constants = utils.constants; - -// Set test url through environment variable -var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; - -// chrome driver -var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) - .build(); - -tap.plan(2); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - driver.get(rootUrl + '/educators/register'); - return utils.fillUsernameSlide(driver, seleniumWebdriver) - .then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this -}); - -// attempts to advance the slide without inputting either name, checks that both give the correct error -tap.test('checkFirstNameRequired', function (t) { - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); - var errorMessageXPath = '//input[@name="user.name.first"]/following-sibling::' + - 'span[@class="help-block validation-message"]/span[contains(text(),' + - '"This field is required")]'; - nextStepButton.click().then(function () { - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) - .then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); - -// attempts to advance the slide without inputting either name, checks that both give the correct error -tap.test('checkLastNameRequired', function (t) { - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); - var errorMessageXPath = '//input[@name="user.name.last"]/following-sibling::' + - 'span[@class="help-block validation-message"]/span[contains(text(),' + - '"This field is required")]'; - nextStepButton.click().then(function () { - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) - .then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); diff --git a/test/integration/teacher-registration/test_teacher_registration_organization_step.js b/test/integration/teacher-registration/test_teacher_registration_organization_step.js deleted file mode 100644 index 6a136ecea..000000000 --- a/test/integration/teacher-registration/test_teacher_registration_organization_step.js +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Checks the behavior of the organization step in the educators registration process - * - * Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow - */ -require('chromedriver'); -var seleniumWebdriver = require('selenium-webdriver'); -var tap = require('tap'); - -var utils = require('./teacher_registration_utils.js'); -var constants = utils.constants; - -// Set test url through environment variable -var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; - -// chrome driver -var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) - .build(); - -tap.plan(4); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - driver.get(rootUrl + '/educators/register'); - return utils.fillUsernameSlide(driver, seleniumWebdriver) - .then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this - .then(utils.fillNameSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this - .then(utils.fillPhoneSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this -}); - -tap.test('otherFieldRequiredIfChecked', function (t) { - var otherCheckbox = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="checkbox" and @value="8"]')); - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); - var errorMessageXPath = '//div[@class="other-input"]' + constants.generalErrorMessageXpath; - otherCheckbox.click().then(function () { - nextStepButton.click().then(function () { - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) - .then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); - }); -}); - -tap.test('checkOrganizationFieldRequired', function (t) { - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); - var errorMessageXPath = '//input[@name="organization.name"]/following-sibling::' + - 'span[@class="help-block validation-message"]/span[contains(text(),' + - '"This field is required")]'; - nextStepButton.click().then(function () { - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) - .then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); - -tap.test('checkRoleFieldRequired', function (t) { - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); - var errorMessageXPath = '//input[@name="organization.title"]/following-sibling::' + - 'span[@class="help-block validation-message"]/span[contains(text(),' + - '"This field is required")]'; - nextStepButton.click().then(function () { - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) - .then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); - -tap.test('checkOrganizationTypeRequired', function (t) { - var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath)); - var errorMessageXPath = '//div[@class="checkbox"]/following-sibling::' + - 'span[@class="help-block validation-message" and contains(text(),' + - '"This field is required")]'; - nextStepButton.click().then(function () { - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) - .then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); diff --git a/test/integration/teacher-registration/test_teacher_registration_phone_step.js b/test/integration/teacher-registration/test_teacher_registration_phone_step.js deleted file mode 100644 index ec3feaac9..000000000 --- a/test/integration/teacher-registration/test_teacher_registration_phone_step.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Checks the behavior of the phone number step in the educators registration process - * - * Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow - */ -require('chromedriver'); -var seleniumWebdriver = require('selenium-webdriver'); -var tap = require('tap'); - -var utils = require('./teacher_registration_utils.js'); - -// Set test url through environment variable -var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; - -// chrome driver -var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) - .build(); - -tap.plan(1); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - driver.get(rootUrl + '/educators/register'); - return utils.fillUsernameSlide(driver, seleniumWebdriver) - .then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this - .then(utils.fillNameSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this -}); - -// inputs an invalid phone number and checks that the correct error message appears -tap.test('validatePhoneNumber', function (t) { - var phoneInput = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="tel"]')); - var errorMessage = 'Please enter a valid phone number'; - var errorMessageXPath = '//span[@class="help-block validation-message"]/span[contains(text(),"' + - errorMessage + '")]'; - phoneInput.sendKeys(1234567890).then(function () { - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)) - .then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); diff --git a/test/integration/teacher-registration/test_teacher_registration_username_step.js b/test/integration/teacher-registration/test_teacher_registration_username_step.js deleted file mode 100644 index 96c8d46ea..000000000 --- a/test/integration/teacher-registration/test_teacher_registration_username_step.js +++ /dev/null @@ -1,114 +0,0 @@ -/* -* Checks the behavior of first step in the educators registration process -* -* Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow -*/ - -require('chromedriver'); -var seleniumWebdriver = require('selenium-webdriver'); -var tap = require('tap'); - -// Set test url through environment variable -var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; - -// chrome driver -var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) - .build(); - -tap.plan(5); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - return driver.get(rootUrl + '/educators/register'); -}); - -// an error message should appear for a username less than 3 characters long -// input a username less than 3 characters and look for the validation message -tap.test('checkAtLeastThreeCharacters', function (t) { - // open scratch in a new instance of the browser - driver.get('https://scratch.mit.edu/educators/register'); - var usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username')); - var errorMessage = 'Usernames must be at least 3 characters'; - var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' + - errorMessage + '")]'; - usernameInput.sendKeys('hi').then(function () { - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); - -// usernames have to be unique -// input a username that exists and check that an error message appears -tap.test('checkUsernameExistsError', function (t) { - var usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username')); - var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password')); - var inputUsername = usernameInput.sendKeys('mres'); - var passwordClick = passwordInput.click(); - var errorMessage = 'Sorry, that username already exists'; - var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' + - errorMessage + '")]'; - Promise.all([inputUsername, passwordClick]).then(function () { // eslint-disable-line no-undef - var errorBubble = driver.wait(seleniumWebdriver.until - .elementLocated(seleniumWebdriver.By.xpath(errorMessageXPath)), 10000); - t.notEqual(errorBubble, undefined); // eslint-disable-line no-undefined - t.end(); - }); -}); - -// passwords must be at least 6 characters -// find the validation message if the input password is less than 6 characters -tap.test('checkPasswordAtLeastSixCharacters', function (t) { - var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password')); - var errorMessage = 'Passwords must be at least six characters'; - var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' + - errorMessage + '")]'; - passwordInput.sendKeys('hello').then(function () { - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); - -// password cannot be "password" -// find the validation message if the user inputs "password" -tap.test('checkPasswordNotPassword', function (t) { - driver.get('https://scratch.mit.edu/educators/register'); - var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password')); - // keeping "password" in messed with the xPath, may need to find a better way - var errorMessage = 'Your password may not be'; - var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' + - errorMessage + '")]'; - passwordInput.sendKeys('password').then(function () { - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); - -// the username and password cannot be the same -// find the validation message if the username and password match -tap.test('checkPasswordNotUsername', function (t) { - driver.get('https://scratch.mit.edu/educators/register'); - var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password')); - var usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username')); - var errorMessage = 'Your password may not be your username'; - var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' + - errorMessage + '")]'; - var usernamePromise = usernameInput.sendKeys('educator'); - var passwordPromise = passwordInput.sendKeys('educator'); - // wait for both inputs to have the same text, and check for validation message - Promise.all([usernamePromise, passwordPromise]).then(function () { // eslint-disable-line no-undef - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) { - // there should be only one validation message - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); diff --git a/test/integration/teacher-registration/test_teacher_registration_usescratch_step.js b/test/integration/teacher-registration/test_teacher_registration_usescratch_step.js deleted file mode 100644 index f91baf590..000000000 --- a/test/integration/teacher-registration/test_teacher_registration_usescratch_step.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Checks the behavior of the 'use scratch' step in the educators registration process - * - * Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow - */ -require('chromedriver'); -var seleniumWebdriver = require('selenium-webdriver'); -var tap = require('tap'); - -var utils = require('./teacher_registration_utils.js'); -var constants = utils.constants; - -// Set test url through environment variable -var rootUrl = process.env.ROOT_URL || 'http://localhost:8333'; - -// chrome driver -var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome()) - .build(); - -tap.plan(3); - -tap.tearDown(function () { - driver.quit(); -}); - -tap.beforeEach(function () { - driver.get(rootUrl + '/educators/register'); - return utils.fillUsernameSlide(driver, seleniumWebdriver) - .then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this - .then(utils.fillNameSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this - .then(utils.fillPhoneSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this - .then(utils.fillOrganizationSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this - .then(utils.fillAddressSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this -}); - -tap.test('checkCharacterCountIsCorrect', function (t) { - var textarea = driver.findElement(seleniumWebdriver.By.name('useScratch')); - var charCount = driver.findElement(seleniumWebdriver.By.xpath('//p[@class="char-count"]')); - textarea.sendKeys('hello').then(function () { - charCount.getText().then(function (charCountText) { - t.equal(charCountText, '5/300'); - t.end(); - }); - }); -}); - -// Inputs more than 300 characters and checks that the char count gets the class 'overmax' -// which turns the text orange -tap.test('checkCharacterCountTurnsOrangeWhenTooLong', function (t) { - var textarea = driver.findElement(seleniumWebdriver.By.name('useScratch')); - var charCount = driver.findElement(seleniumWebdriver.By.xpath('//p[@class="char-count"]')); - textarea.sendKeys(constants.loremIpsumTextLong).then(function () { - charCount.getAttribute('class').then(function (charCountClasses) { - t.ok(charCountClasses.includes('overmax')); - t.end(); - }); - }); -}); - -tap.test('checkCharacterCountErrorAppersWhenTooLong', function (t) { - var textarea = driver.findElement(seleniumWebdriver.By.name('useScratch')); - var errorMessage = 'Description must be at most 300 characters'; - var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' + - errorMessage + '")]'; - textarea.sendKeys(constants.loremIpsumTextLong).then(function () { - driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) { - t.equal(validationMessages.length, 1); - t.end(); - }); - }); -}); diff --git a/test/localization/check_duplicate_strings.js b/test/localization/check_duplicate_strings.js deleted file mode 100644 index 16f7ab71c..000000000 --- a/test/localization/check_duplicate_strings.js +++ /dev/null @@ -1,52 +0,0 @@ -/* -* Check that there are no duplicate strings in any individual l10n json file. - */ -var path = require('path'); -var fs = require('fs'); -var tap = require('tap'); - -var routes = require('../../src/routes.json'); - -const noDuplicateValues = (idsToCheck, name) => { - let values = {}; - for (const key in idsToCheck) { - if (values.hasOwnProperty(idsToCheck[key])) { - // duplicate values - // return false; - tap.fail(`${name}.${idsToCheck[key]} has duplicates`); - } else { - values[idsToCheck[key]] = key; - } - } - tap.pass(); - // return true; -}; - -tap.test('generalCheckForDuplicates', function (t) { - const ids = require(path.resolve(__dirname, '../../src/l10n.json')); // eslint-disable-line global-require - noDuplicateValues(ids, 'general'); - t.end(); -}); - -for (var v in routes) { - if (typeof routes[v].redirect !== 'undefined') { - continue; - } - var subdir = routes[v].view.split('/'); - subdir.pop(); - var name = routes[v].name; - var uri = path.resolve(__dirname, '../../src/views/' + subdir.join('/') + '/l10n.json'); - try { - var file = fs.readFileSync(uri, 'utf8'); - var ids = JSON.parse(file); - tap.test(name + 'CheckForDuplicates', function (t) { // eslint-disable-line no-loop-func - noDuplicateValues(ids, name); - t.end(); - }); - } catch (err) { - if (err.code !== 'ENOENT') { - // ignore if ENOENT for routes with no l10n file, throw error for anything else - throw err; - } - } -} diff --git a/test/localization/check_string_ids.js b/test/localization/check_string_ids.js deleted file mode 100644 index 8fc019228..000000000 --- a/test/localization/check_string_ids.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Tests whether any page in www has any languages which are missing string IDs - * - checks every language against the list of english IDs for that page - * - test fails if the length of the list of languages missing any IDs is not 0 - * - if the test fails, you can see which pages/ languages/ IDs are causing the failure: - * - Object.keys(pagesWithLanguagesMissingIds) gives you a list - * of the pages which had languages with missing IDs - * - pagesWithLanguagesMissingIds['pageName.intl.js'] gives you an object - * with languages as keys and the missing IDs as values - */ - -var path = require('path'); -var fs = require('fs'); -var tap = require('tap'); - -/** - * To get the files (containing message IDs and localized strings for each page in www) - * from the intl directory - */ -var intlDirPath = path.resolve(__dirname, '../../intl/'); -var intlFiles = fs.readdirSync(intlDirPath); - -/* - * Tells tap whether the test should pass or fail for a given file. - * @param {string} fileName - * @param {Object} missingMessageId - * @param {Object} pagesMissingIds - */ -const noMissingStrings = (fileName, missingMessageId, pagesMissingIds) => { - if (Object.keys(missingMessageId).length === 0) { - tap.pass(); - } else { - tap.fail(fileName + ' is missing string IDs'); - pagesMissingIds[fileName] = []; - pagesMissingIds[fileName].push(missingMessageId); - } -}; - -var pagesWithLanguagesMissingIds = {}; - -for (var i in intlFiles) { - var file = intlFiles[i]; - var filePath = path.resolve(__dirname, '../../intl/' + file); - var pageMessagesString = fs.readFileSync(filePath, 'utf8'); - - /** - * To make the string of the file of the page.intl.js back into useable objects - */ - var window = {}; - var pageMessages = eval(pageMessagesString); // eslint-disable-line no-eval - - /** - * The goal is to compare the IDs for each language to the IDs for English, - * so we need the list of IDs for the given page in English - */ - var englishIdList = window._messages.en; - - var messageIdNotInLanguage = {}; - - for (var languageKey in pageMessages) { - var currentLanguageObject = pageMessages[languageKey]; - for (var messageId in englishIdList) { - if (!(messageId in currentLanguageObject)) { - if (typeof messageIdNotInLanguage[languageKey] === 'undefined') { - messageIdNotInLanguage[languageKey] = []; - } - messageIdNotInLanguage[languageKey].push(messageId); - } - } - } - noMissingStrings(file, messageIdNotInLanguage, pagesWithLanguagesMissingIds); -} diff --git a/test/localization/check_valid_json.js b/test/localization/check_valid_json.js deleted file mode 100644 index 20ab2a890..000000000 --- a/test/localization/check_valid_json.js +++ /dev/null @@ -1,23 +0,0 @@ -var fs = require('fs'); -var glob = require('glob'); -var tap = require('tap'); - -var TRANSLATIONS_PATTERN = './node_modules/scratch-l10n/www/**/*.json'; -var files = glob.sync(TRANSLATIONS_PATTERN); - -const checkJson = (data, name) => { - try { - JSON.parse(data); - } catch (e) { - tap.fail(name + ' has invalid Json.\n'); - } -}; - -tap.test('check valid json', function (t) { - files.forEach(function (f) { - const data = fs.readFileSync(f); - checkJson(data, f); - }); - t.pass(); - t.end(); -}); diff --git a/test/unit/lib/validate.js b/test/unit/lib/validate.js deleted file mode 100644 index 3209a4307..000000000 --- a/test/unit/lib/validate.js +++ /dev/null @@ -1,66 +0,0 @@ -const tap = require('tap'); -const validate = require('../../../src/lib/validate'); - -tap.tearDown(() => process.nextTick(process.exit)); - -tap.test('validate username locally', t => { - let response; - t.type(validate.validateUsernameLocally, 'function'); - response = validate.validateUsernameLocally('abc'); - t.deepEqual(response, {valid: true}); - response = validate.validateUsernameLocally('abcdefghijklmnopqrst'); - t.deepEqual(response, {valid: true}); - response = validate.validateUsernameLocally('abc-def-ghi'); - t.deepEqual(response, {valid: true}); - response = validate.validateUsernameLocally(''); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationRequired'}); - response = validate.validateUsernameLocally('ab'); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameMinLength'}); - response = validate.validateUsernameLocally('abcdefghijklmnopqrstu'); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameMaxLength'}); - response = validate.validateUsernameLocally('abc def'); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameRegexp'}); - response = validate.validateUsernameLocally('abc!def'); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameRegexp'}); - response = validate.validateUsernameLocally('abc😄def'); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameRegexp'}); - t.end(); -}); - -tap.test('validate password', t => { - let response; - t.type(validate.validatePassword, 'function'); - response = validate.validatePassword('abcdef'); - t.deepEqual(response, {valid: true}); - response = validate.validatePassword('abcdefghijklmnopqrst'); - t.deepEqual(response, {valid: true}); - response = validate.validatePassword('passwo'); - t.deepEqual(response, {valid: true}); - response = validate.validatePassword(''); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationRequired'}); - response = validate.validatePassword('abcde'); - t.deepEqual(response, {valid: false, errMsgId: 'registration.validationPasswordLength'}); - response = validate.validatePassword('password'); - t.deepEqual(response, {valid: false, errMsgId: 'registration.validationPasswordNotEquals'}); - t.end(); -}); - -tap.test('validate password confirm', t => { - let response; - t.type(validate.validatePasswordConfirm, 'function'); - response = validate.validatePasswordConfirm('abcdef', 'abcdef'); - t.deepEqual(response, {valid: true}); - response = validate.validatePasswordConfirm('abcdefghijklmnopqrst', 'abcdefghijklmnopqrst'); - t.deepEqual(response, {valid: true}); - response = validate.validatePasswordConfirm('passwo', 'passwo'); - t.deepEqual(response, {valid: true}); - response = validate.validatePasswordConfirm('', ''); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationRequired'}); - response = validate.validatePasswordConfirm('abcdef', 'abcdefg'); - t.deepEqual(response, {valid: false, errMsgId: 'general.error'}); - response = validate.validatePasswordConfirm('abcdef', '123456'); - t.deepEqual(response, {valid: false, errMsgId: 'general.error'}); - response = validate.validatePasswordConfirm('', 'abcdefg'); - t.deepEqual(response, {valid: false, errMsgId: 'general.error'}); - t.end(); -}); diff --git a/test/unit/redux/preview-test.js b/test/unit/redux/preview-test.js deleted file mode 100644 index 24a91ce84..000000000 --- a/test/unit/redux/preview-test.js +++ /dev/null @@ -1,176 +0,0 @@ -const tap = require('tap'); -const Preview = require('../../../src/redux/preview'); -const initialState = Preview.getInitialState(); -const reducer = Preview.previewReducer; - -let state; - -tap.tearDown(() => process.nextTick(process.exit)); - -tap.test('Reducer', t => { - t.type(reducer, 'function'); - t.type(initialState, 'object'); - - // Reducers should return their default state when called without state - let undefinedState; - t.deepEqual(initialState, reducer(undefinedState, {type: 'fake action'})); - t.end(); -}); - -tap.test('resetProject', t => { - state = reducer({some: 'garbage'}, Preview.resetProject()); - t.deepEqual(state, initialState); - t.end(); -}); - -tap.test('setProjectInfo', t => { - // Initial values - t.equal(initialState.projectNotAvailable, false); - t.deepEqual(initialState.projectInfo, {}); - - // setProjectInfo action with an `info` value sets the projectInfo - state = reducer(initialState, Preview.setProjectInfo('a value')); - t.equal(state.projectInfo, 'a value'); - t.equal(state.projectNotAvailable, false); - - // setProjectInfo action with null info sets projectNotAvailable to true - // and resets the project info back to default state - state = reducer(initialState, Preview.setProjectInfo(null)); - t.deepEqual(state.projectInfo, initialState.projectInfo); - t.equal(state.projectNotAvailable, true); - t.end(); -}); - -tap.test('updateProjectInfo', t => { - const info = {a: 'value a', b: 'value b'}; - state = reducer({projectInfo: info}, Preview.updateProjectInfo({ - b: 'new value b', - c: 'new value c' - })); - t.deepEqual(state.projectInfo, { - a: 'value a', - b: 'new value b', - c: 'new value c' - }); - t.end(); -}); - -tap.test('setComments', t => { - // Initial value - t.deepEqual(initialState.comments, []); - - state = reducer(initialState, Preview.setComments([{id: 1}, {id: 2}])); - state = reducer(state, Preview.setComments([{id: 3}, {id: 4}])); - t.deepEqual(state.comments, [{id: 1}, {id: 2}, {id: 3}, {id: 4}]); - - t.end(); -}); - -const commentState = { - comments: [ - {id: 'id1', visibility: 'visible'}, - {id: 'id2', visibility: 'visible'}, - {id: 'id3', visibility: 'visible'} - ], - replies: { - id1: [ - {id: 'id4', visibility: 'visible'}, - {id: 'id5', visibility: 'visible'} - ] - } -}; - -tap.test('setComments, discards duplicates', t => { - state = reducer(commentState, Preview.setComments([{id: 'id1'}])); - // Does not increase the number of comments, still 3 - t.equal(state.comments.length, 3); - t.end(); -}); - -tap.test('setCommentDeleted, top level comment', t => { - state = reducer(commentState, Preview.setCommentDeleted('id2')); - t.equal(state.comments[1].visibility, 'deleted'); - t.end(); -}); - -tap.test('setCommentDeleted, reply comment', t => { - state = reducer(commentState, Preview.setCommentDeleted('id4', 'id1')); - t.equal(state.replies.id1[0].visibility, 'deleted'); - t.end(); -}); - -tap.test('setRepliesDeleted/Restored', t => { - state = reducer(commentState, Preview.setRepliesDeleted('id1')); - t.equal(state.replies.id1[0].visibility, 'deleted'); - t.equal(state.replies.id1[1].visibility, 'deleted'); - - state = reducer(state, Preview.setRepliesRestored('id1')); - t.equal(state.replies.id1[0].visibility, 'visible'); - t.equal(state.replies.id1[1].visibility, 'visible'); - t.end(); -}); - -tap.test('setCommentReported, top level comment', t => { - state = reducer(commentState, Preview.setCommentReported('id2')); - t.equal(state.comments[1].visibility, 'reported'); - t.end(); -}); - -tap.test('setCommentReported, reply comment', t => { - state = reducer(commentState, Preview.setCommentReported('id4', 'id1')); - t.equal(state.replies.id1[0].visibility, 'reported'); - t.end(); -}); - -tap.test('addNewComment, top level comment', t => { - state = reducer(commentState, Preview.addNewComment({id: 'new comment'})); - // Adds comment to beginning of list - t.equal(state.comments[0].id, 'new comment'); - t.end(); -}); - -tap.test('addNewComment, reply comment', t => { - state = reducer(commentState, Preview.addNewComment({id: 'new comment'}, 'id1')); - // Adds replies to the end of the replies list - t.equal(state.replies.id1[2].id, 'new comment'); - t.end(); -}); - -tap.test('setReplies', t => { - // setReplies should append new replies - state = reducer(commentState, Preview.setReplies({ - id1: {id: 'id6'} - })); - t.equal(state.replies.id1[2].id, 'id6'); - t.equal(state.comments[0].moreRepliesToLoad, false); - - // setReplies should ignore duplicates, do the same as above again - t.equal(state.replies.id1.length, 3); - state = reducer(state, Preview.setReplies({id1: {id: 'id6'}})); - t.equal(state.replies.id1.length, 3); - - // setReplies can add replies to a comment that didn't have any - state = reducer(state, Preview.setReplies({ - id2: {id: 'id7'} - })); - t.equal(state.replies.id1.length, 3); - t.equal(state.replies.id2.length, 1); - t.equal(state.replies.id2[0].id, 'id7'); - t.equal(state.comments[0].moreRepliesToLoad, false); - t.equal(state.comments[1].moreRepliesToLoad, false); - - // Getting 20 (COMMENT_LIMIT) replies sets moreRepliesToLoad to true - state = reducer(state, Preview.setReplies({ - id3: (new Array(20)).map((_, i) => ({id: `id${i + 1}`})) - })); - t.equal(state.comments[0].moreRepliesToLoad, false); - t.equal(state.comments[1].moreRepliesToLoad, false); - t.equal(state.comments[2].moreRepliesToLoad, true); - - // Getting one more reply sets moreRepliesToLoad back to false - state = reducer(state, Preview.setReplies({ - id3: {id: 'id21'} - })); - t.equal(state.comments[2].moreRepliesToLoad, false); - t.end(); -}); diff --git a/test/unit/test_fastly_config_methods.js b/test/unit/test_fastly_config_methods.js deleted file mode 100644 index 81d96d11a..000000000 --- a/test/unit/test_fastly_config_methods.js +++ /dev/null @@ -1,79 +0,0 @@ -var defaults = require('lodash.defaults'); -var fastlyConfig = require('../../bin/lib/fastly-config-methods'); -var routeJson = require('../../src/routes.json'); -var tap = require('tap'); - -var testRoutes = [ - { - name: 'less-traveled', - pattern: '^/?$', - routeAlias: '/?$', - view: 'less-traveled/less-traveled', - title: 'Robert Frost Goes Here' - }, - { - name: 'more-traveled', - pattern: '^/more?$', - routeAlias: '/more?$', - view: 'more-traveled/more-traveled', - title: 'Robert Frost Does Not Go Here' - } -]; - -var routes = routeJson.map(function (route) { - return defaults({}, {pattern: fastlyConfig.expressPatternToRegex(route.pattern)}, route); -}); -var extraAppRoutes = [ - // Homepage with querystring. - // TODO: Should this be added for every route? - '/\\?', - // View html - '/[^/]*.html$' -]; - - -tap.test('getStaticPaths', function (t) { - var staticPaths = fastlyConfig.getStaticPaths(__dirname, '../../build/*'); - t.type(staticPaths, 'object'); - t.end(); -}); - -tap.test('getViewPaths', function (t) { - var viewPaths = fastlyConfig.getViewPaths(testRoutes); - t.type(viewPaths, 'object'); - t.equal(viewPaths[0], '/?$'); - t.equal(viewPaths[1], '/more?$'); - t.end(); -}); - -tap.test('pathsToCondition', function (t) { - var condition = fastlyConfig.pathsToCondition(['/?$', '/more?$']); - t.type(condition, 'string'); - t.equal(condition, 'req.url~"^(/?$|/more?$)"'); - t.end(); -}); - -tap.test('getAppRouteCondition', function (t) { - var condition = fastlyConfig.getAppRouteCondition('../../build/*', routes, extraAppRoutes, __dirname); - t.type(condition, 'string'); - t.end(); -}); - -tap.test('testSetTTL', function (t) { - var ttl = fastlyConfig.setResponseTTL('itsactuallyttyl'); - t.equal(ttl, '' + - 'if (itsactuallyttyl) {\n' + - ' if (req.url ~ "^(/projects/|/fragment/account-nav.json|/session/)" && ' + - '!req.http.Cookie:scratchsessionsid) {\n' + - ' set beresp.http.Vary = "Accept-Encoding, Accept-Language";\n' + - ' unset beresp.http.set-cookie;\n' + - ' return(deliver);\n' + - ' } else {\n' + - ' set beresp.ttl = 0s;\n' + - ' set beresp.grace = 0s;\n' + - ' return(pass);\n' + - ' }\n' + - '}\n' - ); - t.end(); -}); From c56f488b33cf84219828b994b49fa06643950f78 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Wed, 17 Jul 2019 15:27:13 -0400 Subject: [PATCH 07/32] Add Jest, Enzyme, and sample tests --- package.json | 5 +++++ test/.eslintrc.js | 5 +++++ test/integration/test-integration.test.js | 5 +++++ test/localization/test-localization.test.js | 5 +++++ test/unit/test-unit.test.js | 5 +++++ 5 files changed, 25 insertions(+) create mode 100644 test/.eslintrc.js create mode 100644 test/integration/test-integration.test.js create mode 100644 test/localization/test-localization.test.js create mode 100644 test/unit/test-unit.test.js diff --git a/package.json b/package.json index 2681b4fa2..b6571d0ef 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,11 @@ "start": "node ./dev-server/index.js", "test": "npm run test:lint && npm run build && npm run test:unit:tap", "test:lint": "eslint . --ext .js,.jsx,.json", + "test:integration:jest": "jest ./test/integration/*.test.js", "test:smoke": "tap ./test/integration-legacy/smoke-testing/*.js --timeout=3600 --no-coverage -R classic", "test:smoke:verbose": "tap ./test/integration-legacy/smoke-testing/*.js --timeout=3600 --no-coverage -R spec", "test:smoke:sauce": "SMOKE_REMOTE=true tap ./test/integration-legacy/smoke-testing/*.js --timeout=60000 --no-coverage -R classic", + "test:unit:jest": "jest ./test/unit/*.test.js && jest ./test/localization/*.test.js", "test:unit:tap": "tap ./test/{unit-legacy,localization-legacy}/*.js --no-coverage -R classic", "test:coverage": "tap ./test/{unit-legacy,localization-legacy}/*.js --coverage --coverage-report=lcov", "build": "npm run clean && npm run translate && webpack --bail", @@ -66,6 +68,8 @@ "copy-webpack-plugin": "0.2.0", "create-react-class": "15.6.2", "css-loader": "0.23.1", + "enzyme": "3.10.0", + "enzyme-adapter-react-16": "1.14.0", "eslint": "4.7.1", "eslint-config-scratch": "5.0.0", "eslint-plugin-cypress": "^2.0.1", @@ -82,6 +86,7 @@ "google-libphonenumber": "3.2.3", "html-webpack-plugin": "2.22.0", "iso-3166-2": "0.4.0", + "jest": "^23.6.0", "json-loader": "0.5.2", "json2po-stream": "1.0.3", "keymirror": "0.1.1", diff --git a/test/.eslintrc.js b/test/.eslintrc.js new file mode 100644 index 000000000..26ef5d954 --- /dev/null +++ b/test/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + env: { + jest: true + } +}; diff --git a/test/integration/test-integration.test.js b/test/integration/test-integration.test.js new file mode 100644 index 000000000..44c96735d --- /dev/null +++ b/test/integration/test-integration.test.js @@ -0,0 +1,5 @@ +describe('test jest integration', () => { + test('testing test', () => { + expect('integration').toEqual('integration'); + }); +}); diff --git a/test/localization/test-localization.test.js b/test/localization/test-localization.test.js new file mode 100644 index 000000000..012e67810 --- /dev/null +++ b/test/localization/test-localization.test.js @@ -0,0 +1,5 @@ +describe('test jest localization', () => { + test('testing localization test', () => { + expect('localization').toEqual('localization'); + }); +}); diff --git a/test/unit/test-unit.test.js b/test/unit/test-unit.test.js new file mode 100644 index 000000000..d29619cfd --- /dev/null +++ b/test/unit/test-unit.test.js @@ -0,0 +1,5 @@ +describe('test jest unit', () => { + test('testing test', () => { + expect('unit').toEqual('unit'); + }); +}); From b63d64d03e512b956d9999ecfcff80948cc339e0 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Wed, 17 Jul 2019 15:33:01 -0400 Subject: [PATCH 08/32] Run Jest tests alongside Tap tests --- .travis.yml | 6 +----- package.json | 3 +++ test/README.md | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 test/README.md diff --git a/.travis.yml b/.travis.yml index 5a53d2652..aaf414d4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -129,11 +129,7 @@ jobs: branch: - master - stage: smoke - install: - - cd test/integration - - npm install - - cd - - script: npm run test:smoke:sauce + script: npm run test:integration:remote stages: - test - name: smoke diff --git a/package.json b/package.json index b6571d0ef..7e352b769 100644 --- a/package.json +++ b/package.json @@ -6,10 +6,13 @@ "start": "node ./dev-server/index.js", "test": "npm run test:lint && npm run build && npm run test:unit:tap", "test:lint": "eslint . --ext .js,.jsx,.json", + "test:integration": "npm run test:integration:jest && npm run test:smoke", "test:integration:jest": "jest ./test/integration/*.test.js", + "test:integration:remote": "npm run test:integration:jest && npm run test:smoke:sauce", "test:smoke": "tap ./test/integration-legacy/smoke-testing/*.js --timeout=3600 --no-coverage -R classic", "test:smoke:verbose": "tap ./test/integration-legacy/smoke-testing/*.js --timeout=3600 --no-coverage -R spec", "test:smoke:sauce": "SMOKE_REMOTE=true tap ./test/integration-legacy/smoke-testing/*.js --timeout=60000 --no-coverage -R classic", + "test:unit": "npm run test:unit:jest && npm run test:unit:tap", "test:unit:jest": "jest ./test/unit/*.test.js && jest ./test/localization/*.test.js", "test:unit:tap": "tap ./test/{unit-legacy,localization-legacy}/*.js --no-coverage -R classic", "test:coverage": "tap ./test/{unit-legacy,localization-legacy}/*.js --coverage --coverage-report=lcov", diff --git a/test/README.md b/test/README.md new file mode 100644 index 000000000..251e5d29a --- /dev/null +++ b/test/README.md @@ -0,0 +1,35 @@ +# Requirements + +* Selenium + * See this directory's package.json +* TAP + * In the scratch-www repo's package.json +* [Chromedriver](https://sites.google.com/a/chromium.org/chromedriver/) + +# Running the tests + +* By default, tests run against our Staging instance, but you can pass in a different location if you want to run the tests against e.g. your local build +* Tests can be run using Saucelabs, an online service that can test browser/os combinations remotely. Currently all tests are written for use for chrome on mac. + +## Using tap +* Run all tests in the smoke-testing directory from the command-line: `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password ROOT_URL=https://scratch.mit.edu npm run smoke` +* To run a single file from the command-line: `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password ROOT_URL=https://scratch.mit.edu node_modules/.bin/tap ./test/integration/smoke-testing/filename.js --timeout=3600` + * The timeout var is for the length of the entire tap test-suite; if you are getting a timeout error, you may need to adjust this value (some of the Selenium tests take a while to run) +* To run tests using saucelabs run this command `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password SAUCE_USERNAME=saucelabsUsername SAUCE_ACCESS_KEY=saucelabsAccessKey ROOT_URL=https://scratch.mit.edu npm run smoke-sauce` + + +### Configuration + +| Variable | Default | Description | +| --------------------- | --------------------- | --------------------------------------------------------- | +| `ROOT_URL` | `scratch.ly` | Location you want to run the tests against | +| `SMOKE_USERNAME` | `None` | Username for Scratch user you're signing in with to test | +| `SMOKE_PASSWORD` | `None` | Password for Scratch user you're signing in with to test | +| `SMOKE_REMOTE` | `false` | Tests with Sauce Labs or not. True if running smoke-sauce | +| `SMOKE_HEADLESS` | `false` | Run browser in headless mode. Flaky at the moment | +| `SAUCE_USERNAME` | `None` | Username for your Sauce Labs account | +| `SAUCE_ACCESS_KEY` | `None` | Access Key for Sauce Labs found under User Settings | + + +## Using Saucelabs +* You will need a Saucelabs account in order to use it for testing. To find the Access Key, click your username and select User Settings from the dropdown menu. Near the bottom of the page is your access key that you can copy and use in the command line. From 126f3a34b24330d765c1a96361b94acf43cd2635 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Wed, 17 Jul 2019 15:59:34 -0400 Subject: [PATCH 09/32] Updeate integration test README --- test/integration/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/integration/README.md b/test/integration/README.md index 4af0db93a..ee606d9ca 100644 --- a/test/integration/README.md +++ b/test/integration/README.md @@ -1,8 +1,6 @@ # Requirements -* Selenium - * See this directory's package.json -* TAP +* TAP and Selenium * In the scratch-www repo's package.json * [Chromedriver](https://sites.google.com/a/chromium.org/chromedriver/) From 7f6a316224de7ee5ba1fc909a76bbfea9e59ad0f Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Wed, 17 Jul 2019 16:20:11 -0400 Subject: [PATCH 10/32] remove enzyme since we don't use it yet --- package.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/package.json b/package.json index 7e352b769..0dc14df03 100644 --- a/package.json +++ b/package.json @@ -71,8 +71,6 @@ "copy-webpack-plugin": "0.2.0", "create-react-class": "15.6.2", "css-loader": "0.23.1", - "enzyme": "3.10.0", - "enzyme-adapter-react-16": "1.14.0", "eslint": "4.7.1", "eslint-config-scratch": "5.0.0", "eslint-plugin-cypress": "^2.0.1", From d8738c9a6798e0f8053c8d18fbd7f7324f45e96f Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Wed, 17 Jul 2019 16:21:53 -0400 Subject: [PATCH 11/32] Update package-lock --- package-lock.json | 3739 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 3223 insertions(+), 516 deletions(-) diff --git a/package-lock.json b/package-lock.json index 13856618a..b711b5605 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,471 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/cli": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.5.0.tgz", + "integrity": "sha512-qNH55fWbKrEsCwID+Qc/3JDPnsSGpIIiMDbppnR8Z6PxLAqMQCFNqBctkIkBrMH49Nx+qqVTrHRWUR+ho2k+qQ==", + "dev": true, + "requires": { + "chokidar": "^2.0.4", + "commander": "^2.8.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.11", + "mkdirp": "^0.5.1", + "output-file-sync": "^2.0.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "optional": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "optional": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", + "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "optional": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "optional": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "optional": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "optional": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "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-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "optional": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "optional": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true, + "optional": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "optional": true + }, + "output-file-sync": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz", + "integrity": "sha512-mDho4qm7WgIXIGf4eYU1RHN2UU5tPfVYVSRwDJw0uTmj35DQUt/eNp19N7v6T3SrR0ESTEf2up2CGO73qI35zQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "is-plain-obj": "^1.1.0", + "mkdirp": "^0.5.1" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, "@babel/code-frame": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", @@ -385,6 +850,29 @@ "@babel/types": "^7.3.0" } }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, "@types/node": { "version": "12.6.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.2.tgz", @@ -407,6 +895,12 @@ "csstype": "^2.2.0" } }, + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", + "dev": true + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -444,6 +938,24 @@ } } }, + "acorn-globals": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.2.tgz", + "integrity": "sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz", + "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==", + "dev": true + } + } + }, "acorn-jsx": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", @@ -461,6 +973,12 @@ } } }, + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "dev": true + }, "ajv": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.4.0.tgz", @@ -604,7 +1122,6 @@ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, - "optional": true, "requires": { "arr-flatten": "^1.0.1" } @@ -621,6 +1138,12 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -642,12 +1165,26 @@ "es-abstract": "^1.7.0" } }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true, - "optional": true + "dev": true }, "arraybuffer-loader": { "version": "1.0.7", @@ -782,6 +1319,12 @@ } } }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1136,6 +1679,16 @@ "babel-template": "^6.24.1" } }, + "babel-jest": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-23.6.0.tgz", + "integrity": "sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==", + "dev": true, + "requires": { + "babel-plugin-istanbul": "^4.1.6", + "babel-preset-jest": "^23.2.0" + } + }, "babel-loader": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.0.tgz", @@ -1165,6 +1718,60 @@ "babel-runtime": "^6.22.0" } }, + "babel-plugin-istanbul": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", + "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.13.0", + "find-up": "^2.1.0", + "istanbul-lib-instrument": "^1.10.1", + "test-exclude": "^4.2.1" + }, + "dependencies": { + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } + }, + "test-exclude": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.3.tgz", + "integrity": "sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "micromatch": "^2.3.11", + "object-assign": "^4.1.0", + "read-pkg-up": "^1.0.1", + "require-main-filename": "^1.0.1" + } + } + } + }, + "babel-plugin-jest-hoist": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz", + "integrity": "sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=", + "dev": true + }, "babel-plugin-react-intl": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/babel-plugin-react-intl/-/babel-plugin-react-intl-3.5.1.tgz", @@ -1574,6 +2181,16 @@ "babel-plugin-transform-regenerator": "^6.22.0" } }, + "babel-preset-jest": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz", + "integrity": "sha1-jsegOhOPABoaj7HoETZSvxpV2kY=", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^23.2.0", + "babel-plugin-syntax-object-rest-spread": "^6.13.0" + } + }, "babel-preset-react": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.22.0.tgz", @@ -1949,7 +2566,6 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, - "optional": true, "requires": { "expand-range": "^1.8.1", "preserve": "^0.2.0", @@ -1968,6 +2584,23 @@ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, "browser-stdout": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", @@ -2070,6 +2703,15 @@ "caniuse-db": "^1.0.30000525" } }, + "bser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.0.tgz", + "integrity": "sha512-8zsjWrQkkBoLK6uxASk1nJ2SKv97ltiGDo6A3wA0/yRPz+CwmEyDo0hUrhIuukG2JHpAl3bvFIixw2/3Hi0DOg==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", @@ -2265,6 +2907,15 @@ "integrity": "sha512-LS3aD+ti+fezwo8oN01l5vfZF9/CIN/4pxV5SeakHo5leudiHjE66rVHl+XqoCGw4GpO2u5ab6LOpftTfCN9cw==", "dev": true }, + "capture-exit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-1.2.0.tgz", + "integrity": "sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=", + "dev": true, + "requires": { + "rsvp": "^3.3.3" + } + }, "capture-stack-trace": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", @@ -2381,6 +3032,19 @@ "readdirp": "^2.0.0" } }, + "chromedriver": { + "version": "75.1.0", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-75.1.0.tgz", + "integrity": "sha512-N2P0fg6FS4c+tTG0R7cCOD5qiVo+E6uAz6xVjmbZesYv1xs1iGdcCUo0IqOY+ppD/4OOObG+XWV1CFWXT6UIgA==", + "dev": true, + "requires": { + "del": "^4.1.1", + "extract-zip": "^1.6.7", + "mkdirp": "^0.5.1", + "request": "^2.88.0", + "tcp-port-used": "^1.0.1" + } + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -3191,6 +3855,21 @@ } } }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, "csstype": { "version": "2.6.6", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.6.tgz", @@ -3224,6 +3903,30 @@ "assert-plus": "^1.0.0" } }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -3351,6 +4054,46 @@ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "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" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3391,10 +4134,16 @@ "repeating": "^2.0.0" } }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, "diffie-hellman": { @@ -3453,6 +4202,15 @@ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, "domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", @@ -3717,6 +4475,28 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "escodegen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, "eslint": { "version": "4.7.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.7.1.tgz", @@ -3957,6 +4737,12 @@ } } }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, "esprima-fb": { "version": "3001.1.0-dev-harmony-fb", "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz", @@ -4075,7 +4861,6 @@ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, - "optional": true, "requires": { "is-posix-bracket": "^0.1.0" } @@ -4085,11 +4870,35 @@ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, - "optional": true, "requires": { "fill-range": "^2.1.0" } }, + "expect": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-23.6.0.tgz", + "integrity": "sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "jest-diff": "^23.6.0", + "jest-get-type": "^22.1.0", + "jest-matcher-utils": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-regex-util": "^23.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + } + } + }, "express": { "version": "4.16.1", "resolved": "https://registry.npmjs.org/express/-/express-4.16.1.tgz", @@ -4214,11 +5023,39 @@ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, - "optional": true, "requires": { "is-extglob": "^1.0.0" } }, + "extract-zip": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", + "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", + "dev": true, + "requires": { + "concat-stream": "1.6.2", + "debug": "2.6.9", + "mkdirp": "0.5.1", + "yauzl": "2.4.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -4324,6 +5161,15 @@ "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", "dev": true }, + "fb-watchman": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", + "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", + "dev": true, + "requires": { + "bser": "^2.0.0" + } + }, "fbjs": { "version": "0.8.17", "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", @@ -4347,6 +5193,15 @@ } } }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -4380,15 +5235,39 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", "dev": true, - "optional": true + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + }, + "dependencies": { + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "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" + } + } + } }, "fill-range": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dev": true, - "optional": true, "requires": { "is-number": "^2.1.0", "isobject": "^2.0.0", @@ -4531,7 +5410,6 @@ "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, - "optional": true, "requires": { "for-in": "^1.0.1" } @@ -5379,7 +6257,6 @@ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, - "optional": true, "requires": { "glob-parent": "^2.0.0", "is-glob": "^2.0.0" @@ -5390,7 +6267,6 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, - "optional": true, "requires": { "is-glob": "^2.0.0" } @@ -5410,6 +6286,41 @@ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", "dev": true }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "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" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, "globule": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", @@ -5461,6 +6372,12 @@ "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", "dev": true }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, "gud": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", @@ -5719,6 +6636,15 @@ "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", "dev": true }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, "html-minifier": { "version": "2.1.7", "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-2.1.7.tgz", @@ -5998,6 +6924,16 @@ } } }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "dev": true, + "requires": { + "pkg-dir": "^2.0.0", + "resolve-cwd": "^2.0.0" + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -6301,6 +7237,12 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, "ipaddr.js": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", @@ -6399,15 +7341,13 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true, - "optional": true + "dev": true }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, - "optional": true, "requires": { "is-primitive": "^2.0.0" } @@ -6422,8 +7362,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true, - "optional": true + "dev": true }, "is-finite": { "version": "1.0.2", @@ -6445,12 +7384,17 @@ "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" }, + "is-generator-fn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-1.0.0.tgz", + "integrity": "sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=", + "dev": true + }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, - "optional": true, "requires": { "is-extglob": "^1.0.0" } @@ -6469,11 +7413,34 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, - "optional": true, "requires": { "kind-of": "^3.0.2" } }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -6501,15 +7468,13 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true, - "optional": true + "dev": true }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true, - "optional": true + "dev": true }, "is-promise": { "version": "2.1.0", @@ -6568,6 +7533,12 @@ "upper-case": "^1.1.0" } }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -6580,6 +7551,23 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "is2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.1.tgz", + "integrity": "sha512-+WaJvnaA7aJySz2q/8sLjMb2Mw14KTplHmSwcSpZ/fWJPkUmqw3YTzSWbPJ7OAwRvdYTWF2Wg+yYJ1AdP5Z8CA==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "ip-regex": "^2.1.0", + "is-url": "^1.2.2" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -6608,7 +7596,6 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, - "optional": true, "requires": { "isarray": "1.0.0" } @@ -6628,6 +7615,162 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "istanbul-api": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", + "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", + "dev": true, + "requires": { + "async": "^2.1.4", + "fileset": "^2.0.2", + "istanbul-lib-coverage": "^1.2.1", + "istanbul-lib-hook": "^1.2.2", + "istanbul-lib-instrument": "^1.10.2", + "istanbul-lib-report": "^1.1.5", + "istanbul-lib-source-maps": "^1.2.6", + "istanbul-reports": "^1.5.1", + "js-yaml": "^3.7.0", + "mkdirp": "^0.5.1", + "once": "^1.4.0" + }, + "dependencies": { + "append-transform": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", + "dev": true, + "requires": { + "default-require-extensions": "^1.0.0" + } + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "default-require-extensions": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", + "dev": true, + "requires": { + "strip-bom": "^2.0.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "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" + } + }, + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", + "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", + "dev": true, + "requires": { + "append-transform": "^0.4.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } + }, + "istanbul-lib-report": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", + "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", + "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + } + }, + "istanbul-reports": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", + "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", + "dev": true, + "requires": { + "handlebars": "^4.0.3" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, "istanbul-lib-coverage": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", @@ -6870,6 +8013,1239 @@ } } }, + "jest": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-23.6.0.tgz", + "integrity": "sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==", + "dev": true, + "requires": { + "import-local": "^1.0.0", + "jest-cli": "^23.6.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "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" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "^1.5.0" + } + }, + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", + "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + } + }, + "jest-cli": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-23.6.0.tgz", + "integrity": "sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.1.11", + "import-local": "^1.0.0", + "is-ci": "^1.0.10", + "istanbul-api": "^1.3.1", + "istanbul-lib-coverage": "^1.2.0", + "istanbul-lib-instrument": "^1.10.1", + "istanbul-lib-source-maps": "^1.2.4", + "jest-changed-files": "^23.4.2", + "jest-config": "^23.6.0", + "jest-environment-jsdom": "^23.4.0", + "jest-get-type": "^22.1.0", + "jest-haste-map": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-regex-util": "^23.3.0", + "jest-resolve-dependencies": "^23.6.0", + "jest-runner": "^23.6.0", + "jest-runtime": "^23.6.0", + "jest-snapshot": "^23.6.0", + "jest-util": "^23.4.0", + "jest-validate": "^23.6.0", + "jest-watcher": "^23.4.0", + "jest-worker": "^23.2.0", + "micromatch": "^2.3.11", + "node-notifier": "^5.2.1", + "prompts": "^0.1.9", + "realpath-native": "^1.0.0", + "rimraf": "^2.5.4", + "slash": "^1.0.0", + "string-length": "^2.0.0", + "strip-ansi": "^4.0.0", + "which": "^1.2.12", + "yargs": "^11.0.0" + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "yargs": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "jest-changed-files": { + "version": "23.4.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-23.4.2.tgz", + "integrity": "sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==", + "dev": true, + "requires": { + "throat": "^4.0.0" + } + }, + "jest-config": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-23.6.0.tgz", + "integrity": "sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==", + "dev": true, + "requires": { + "babel-core": "^6.0.0", + "babel-jest": "^23.6.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^23.4.0", + "jest-environment-node": "^23.4.0", + "jest-get-type": "^22.1.0", + "jest-jasmine2": "^23.6.0", + "jest-regex-util": "^23.3.0", + "jest-resolve": "^23.6.0", + "jest-util": "^23.4.0", + "jest-validate": "^23.6.0", + "micromatch": "^2.3.11", + "pretty-format": "^23.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "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" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-diff": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-23.6.0.tgz", + "integrity": "sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff": "^3.2.0", + "jest-get-type": "^22.1.0", + "pretty-format": "^23.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-docblock": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-23.2.0.tgz", + "integrity": "sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-23.6.0.tgz", + "integrity": "sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "pretty-format": "^23.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-environment-jsdom": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz", + "integrity": "sha1-BWp5UrP+pROsYqFAosNox52eYCM=", + "dev": true, + "requires": { + "jest-mock": "^23.2.0", + "jest-util": "^23.4.0", + "jsdom": "^11.5.1" + } + }, + "jest-environment-node": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-23.4.0.tgz", + "integrity": "sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=", + "dev": true, + "requires": { + "jest-mock": "^23.2.0", + "jest-util": "^23.4.0" + } + }, + "jest-get-type": { + "version": "22.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", + "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", + "dev": true + }, + "jest-haste-map": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-23.6.0.tgz", + "integrity": "sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==", + "dev": true, + "requires": { + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.1.11", + "invariant": "^2.2.4", + "jest-docblock": "^23.2.0", + "jest-serializer": "^23.0.1", + "jest-worker": "^23.2.0", + "micromatch": "^2.3.11", + "sane": "^2.0.0" + } + }, + "jest-jasmine2": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz", + "integrity": "sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==", + "dev": true, + "requires": { + "babel-traverse": "^6.0.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^23.6.0", + "is-generator-fn": "^1.0.0", + "jest-diff": "^23.6.0", + "jest-each": "^23.6.0", + "jest-matcher-utils": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-snapshot": "^23.6.0", + "jest-util": "^23.4.0", + "pretty-format": "^23.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-leak-detector": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz", + "integrity": "sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==", + "dev": true, + "requires": { + "pretty-format": "^23.6.0" + } + }, + "jest-matcher-utils": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz", + "integrity": "sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-get-type": "^22.1.0", + "pretty-format": "^23.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-message-util": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-23.4.0.tgz", + "integrity": "sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0-beta.35", + "chalk": "^2.0.1", + "micromatch": "^2.3.11", + "slash": "^1.0.0", + "stack-utils": "^1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-mock": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-23.2.0.tgz", + "integrity": "sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=", + "dev": true + }, + "jest-regex-util": { + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-23.3.0.tgz", + "integrity": "sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=", + "dev": true + }, + "jest-resolve": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-23.6.0.tgz", + "integrity": "sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==", + "dev": true, + "requires": { + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "realpath-native": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-resolve-dependencies": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz", + "integrity": "sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==", + "dev": true, + "requires": { + "jest-regex-util": "^23.3.0", + "jest-snapshot": "^23.6.0" + } + }, + "jest-runner": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-23.6.0.tgz", + "integrity": "sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==", + "dev": true, + "requires": { + "exit": "^0.1.2", + "graceful-fs": "^4.1.11", + "jest-config": "^23.6.0", + "jest-docblock": "^23.2.0", + "jest-haste-map": "^23.6.0", + "jest-jasmine2": "^23.6.0", + "jest-leak-detector": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-runtime": "^23.6.0", + "jest-util": "^23.4.0", + "jest-worker": "^23.2.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "jest-runtime": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-23.6.0.tgz", + "integrity": "sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==", + "dev": true, + "requires": { + "babel-core": "^6.0.0", + "babel-plugin-istanbul": "^4.1.6", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "exit": "^0.1.2", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.11", + "jest-config": "^23.6.0", + "jest-haste-map": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-regex-util": "^23.3.0", + "jest-resolve": "^23.6.0", + "jest-snapshot": "^23.6.0", + "jest-util": "^23.4.0", + "jest-validate": "^23.6.0", + "micromatch": "^2.3.11", + "realpath-native": "^1.0.0", + "slash": "^1.0.0", + "strip-bom": "3.0.0", + "write-file-atomic": "^2.1.0", + "yargs": "^11.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "yargs": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "jest-serializer": { + "version": "23.0.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-23.0.1.tgz", + "integrity": "sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=", + "dev": true + }, + "jest-snapshot": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-23.6.0.tgz", + "integrity": "sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==", + "dev": true, + "requires": { + "babel-types": "^6.0.0", + "chalk": "^2.0.1", + "jest-diff": "^23.6.0", + "jest-matcher-utils": "^23.6.0", + "jest-message-util": "^23.4.0", + "jest-resolve": "^23.6.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^23.6.0", + "semver": "^5.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-util": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-23.4.0.tgz", + "integrity": "sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=", + "dev": true, + "requires": { + "callsites": "^2.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.11", + "is-ci": "^1.0.10", + "jest-message-util": "^23.4.0", + "mkdirp": "^0.5.1", + "slash": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "^1.5.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-validate": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz", + "integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-get-type": "^22.1.0", + "leven": "^2.1.0", + "pretty-format": "^23.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-watcher": { + "version": "23.4.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-23.4.0.tgz", + "integrity": "sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "string-length": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jest-worker": { + "version": "23.2.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-23.2.0.tgz", + "integrity": "sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=", + "dev": true, + "requires": { + "merge-stream": "^1.0.1" + } + }, "joi": { "version": "6.10.1", "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", @@ -6927,6 +9303,54 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + } + } + }, "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", @@ -7202,6 +9626,12 @@ "is-buffer": "^1.1.5" } }, + "kleur": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-2.0.2.tgz", + "integrity": "sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==", + "dev": true + }, "lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -7223,6 +9653,18 @@ "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", "dev": true }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "dev": true + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -7659,13 +10101,10 @@ } }, "lodash.range": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash.range/-/lodash.range-3.0.1.tgz", - "integrity": "sha1-Au9YGtvbxITLYj7I5MjSSVGaKQM=", - "dev": true, - "requires": { - "lodash._isiterateecall": "^3.0.0" - } + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.range/-/lodash.range-3.2.0.tgz", + "integrity": "sha1-9GHliPZmg/fq3q3lE+OKaaVloV0=", + "dev": true }, "lodash.rest": { "version": "4.0.5", @@ -7678,6 +10117,12 @@ "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", "dev": true }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, "lodash.tail": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", @@ -7914,6 +10359,15 @@ "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", "dev": true }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "dev": true, + "requires": { + "tmpl": "1.0.x" + } + }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -7963,8 +10417,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", - "dev": true, - "optional": true + "dev": true }, "md5.js": { "version": "1.3.5", @@ -8073,6 +10526,15 @@ } } }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -8089,7 +10551,6 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, - "optional": true, "requires": { "arr-diff": "^2.0.0", "array-unique": "^0.2.1", @@ -8292,6 +10753,12 @@ "ms": "2.0.0" } }, + "diff": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", + "dev": true + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -8751,6 +11218,12 @@ } } }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -8843,6 +11316,19 @@ "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", "dev": true }, + "node-notifier": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.0.tgz", + "integrity": "sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + } + }, "node-sass": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.6.1.tgz", @@ -8921,7 +11407,6 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, - "optional": true, "requires": { "remove-trailing-separator": "^1.0.1" } @@ -8986,6 +11471,12 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "nwsapi": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", + "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==", + "dev": true + }, "nyc": { "version": "14.1.1", "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", @@ -9347,12 +11838,21 @@ "object-keys": "^1.0.11" } }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" + } + }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, - "optional": true, "requires": { "for-own": "^0.1.4", "is-extendable": "^0.1.1" @@ -9542,6 +12042,12 @@ "p-limit": "^1.1.0" } }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", @@ -9594,7 +12100,6 @@ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, - "optional": true, "requires": { "glob-base": "^0.3.0", "is-dotfile": "^1.0.0", @@ -9737,6 +12242,12 @@ "sha.js": "^2.4.8" } }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -9792,6 +12303,12 @@ "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, "po2icu": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/po2icu/-/po2icu-0.0.2.tgz", @@ -10558,8 +13075,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true, - "optional": true + "dev": true }, "pretty-error": { "version": "2.1.1", @@ -10571,6 +13087,33 @@ "utila": "~0.4" } }, + "pretty-format": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", + "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + } + } + }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -10601,6 +13144,16 @@ "asap": "~2.0.3" } }, + "prompts": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-0.1.14.tgz", + "integrity": "sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==", + "dev": true, + "requires": { + "kleur": "^2.0.1", + "sisteransi": "^0.1.1" + } + }, "prop-types": { "version": "15.6.0", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz", @@ -10713,7 +13266,6 @@ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", "dev": true, - "optional": true, "requires": { "is-number": "^4.0.0", "kind-of": "^6.0.0", @@ -10724,15 +13276,13 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true, - "optional": true + "dev": true }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true, - "optional": true + "dev": true } } }, @@ -11385,6 +13935,15 @@ } } }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, "recast": { "version": "0.10.43", "resolved": "https://registry.npmjs.org/recast/-/recast-0.10.43.tgz", @@ -11517,7 +14076,6 @@ "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", "dev": true, - "optional": true, "requires": { "is-equal-shallow": "^0.1.3" } @@ -11660,6 +14218,26 @@ } } }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "request-promise-native": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", + "dev": true, + "requires": { + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -11697,6 +14275,23 @@ "path-parse": "^1.0.6" } }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, "resolve-from": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", @@ -11766,6 +14361,12 @@ "inherits": "^2.0.1" } }, + "rsvp": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", + "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", + "dev": true + }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -11815,6 +14416,340 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "sane": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/sane/-/sane-2.5.2.tgz", + "integrity": "sha1-tNwYYcIbQn6SlQej51HiosuKs/o=", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "capture-exit": "^1.2.0", + "exec-sh": "^0.2.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.3", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5", + "watch": "~0.18.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "watch": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz", + "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=", + "dev": true, + "requires": { + "exec-sh": "^0.2.0", + "minimist": "^1.2.0" + } + } + } + }, "sass-graph": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", @@ -11965,480 +14900,15 @@ "dev": true }, "scratch-l10n": { - "version": "3.3.20190711005050", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.3.20190711005050.tgz", - "integrity": "sha512-6PYceYvmkE8weaLG1rtCsoN7HgLL8C2xiaHciD2Y0/KmWvm8HyXHO2XO4+zsRCa2pCPpKvenvkKSy08z0952vw==", + "version": "3.3.20190717144934", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.3.20190717144934.tgz", + "integrity": "sha512-EJJWUsPRkUjAnB/UVwSl+ub1KAJln8ssYOVIUf/OWQxho/CsXfpaND4UbhmsS/0TpH1tR/WgEtU4Eb+DGwCsfw==", "dev": true, "requires": { "@babel/cli": "^7.1.2", "@babel/core": "^7.1.2", "babel-plugin-react-intl": "^3.0.1", "transifex": "1.6.6" - }, - "dependencies": { - "@babel/cli": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.5.0.tgz", - "integrity": "sha512-qNH55fWbKrEsCwID+Qc/3JDPnsSGpIIiMDbppnR8Z6PxLAqMQCFNqBctkIkBrMH49Nx+qqVTrHRWUR+ho2k+qQ==", - "dev": true, - "requires": { - "chokidar": "^2.0.4", - "commander": "^2.8.1", - "convert-source-map": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.0.0", - "lodash": "^4.17.11", - "mkdirp": "^0.5.1", - "output-file-sync": "^2.0.0", - "slash": "^2.0.0", - "source-map": "^0.5.0" - } - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "optional": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "optional": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "optional": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "optional": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "optional": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", - "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "optional": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "optional": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "optional": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "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-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "optional": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "optional": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "optional": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "optional": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "optional": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true, - "optional": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "optional": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true, - "optional": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "optional": true - }, - "output-file-sync": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-2.0.1.tgz", - "integrity": "sha512-mDho4qm7WgIXIGf4eYU1RHN2UU5tPfVYVSRwDJw0uTmj35DQUt/eNp19N7v6T3SrR0ESTEf2up2CGO73qI35zQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "is-plain-obj": "^1.1.0", - "mkdirp": "^0.5.1" - } - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } } }, "scratch-parser": { @@ -12497,6 +14967,52 @@ } } }, + "selenium-webdriver": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", + "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", + "dev": true, + "requires": { + "jszip": "^3.1.3", + "rimraf": "^2.5.4", + "tmp": "0.0.30", + "xml2js": "^0.4.17" + }, + "dependencies": { + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "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" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "tmp": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", + "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.1" + } + } + } + }, "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", @@ -12664,6 +15180,12 @@ "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", "dev": true }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, "should": { "version": "13.2.3", "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", @@ -12724,6 +15246,12 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, + "sisteransi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-0.1.1.tgz", + "integrity": "sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==", + "dev": true + }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -13127,6 +15655,12 @@ "readable-stream": "^2.0.1" } }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -13377,6 +15911,12 @@ "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=", "dev": true }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, "table": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", @@ -13771,6 +16311,33 @@ "integrity": "sha512-fAfA73uFtFGybWGt4+IYT6UPLYVZQ4NfsP+IXEZGY0vh8e2IF7LVKafcQNMRBLqP0wzEA65LM9Tqj+FSmO8GLw==", "dev": true }, + "tcp-port-used": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.1.tgz", + "integrity": "sha512-rwi5xJeU6utXoEIiMvVBMc9eJ2/ofzB+7nLOdnZuFTmNCLqRiQh2sMG9MqCxHU/69VC/Fwp5dV9306Qd54ll1Q==", + "dev": true, + "requires": { + "debug": "4.1.0", + "is2": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "test-exclude": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", @@ -13923,6 +16490,12 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -13989,6 +16562,12 @@ "os-tmpdir": "~1.0.2" } }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "dev": true + }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", @@ -14074,6 +16653,15 @@ } } }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "transifex": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/transifex/-/transifex-1.6.6.tgz", @@ -14564,6 +17152,16 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, "utila": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", @@ -14632,6 +17230,32 @@ "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", "dev": true }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + }, + "dependencies": { + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + } + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "dev": true, + "requires": { + "makeerror": "1.0.x" + } + }, "warning": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", @@ -15044,6 +17668,12 @@ } } }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, "webpack": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-2.7.0.tgz", @@ -15340,12 +17970,49 @@ } } }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, "whatwg-fetch": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==", "dev": true }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "whet.extend": { "version": "0.9.9", "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", @@ -15455,6 +18122,15 @@ "typedarray-to-buffer": "^3.1.5" } }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, "xhr": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.2.0.tgz", @@ -15482,6 +18158,28 @@ "integrity": "sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0=", "dev": true }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dev": true, + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "dev": true + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -15543,6 +18241,15 @@ } } }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "~1.0.1" + } + }, "yn": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.0.tgz", From 755b26a578f5fdfa6144d3e45b378bca63fe3990 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Thu, 18 Jul 2019 16:17:39 -0400 Subject: [PATCH 12/32] Move testing README into the main README --- README.md | 35 ++++++++++++++++++++++++++++++- test/integration-legacy/README.md | 35 ------------------------------- test/integration/README.md | 33 ----------------------------- 3 files changed, 34 insertions(+), 69 deletions(-) delete mode 100644 test/integration-legacy/README.md delete mode 100644 test/integration/README.md diff --git a/README.md b/README.md index 127adf469..6b69db03c 100644 --- a/README.md +++ b/README.md @@ -95,10 +95,43 @@ To stop the process that is making the site available to your web browser (creat **NOTE:** Because by default `API_HOST=https://api.scratch.mit.edu`, please be aware that, by default, you will be seeing and interacting with real data on the Scratch website. -### To Test +### Unit Tests +To run: ```bash npm test ``` +This will build the application and run the unit and localization tests. Some of the tests are run using the TAP framework and others run using Jest. + +### Integration tests +We are transitioning from using TAP to using Jest as our testing framework so for the time being our tests run using both. + +#### Running the tests + +* By default, tests run against our Staging instance, but you can pass in a different location with the ROOT_URL environment variable (see below) if you want to run the tests against e.g. your local build + +#### Running the tests +* Run all tests from the command-line: `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password ROOT_URL=https://scratch.mit.edu npm run test:integration` +* To run a single file from the command-line using TAP: `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password ROOT_URL=https://scratch.mit.edu node_modules/.bin/tap ./test/integration-legacy/smoke-testing/filename.js --timeout=3600` + * The timeout var is for the length of the entire tap test-suite; if you are getting a timeout error, you may need to adjust this value (some of the Selenium tests take a while to run) +* To run a single file from the command-line using Jest: `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password ROOT_URL=https://scratch.mit.edu node_modules/.bin/jest ./test/integration/filename.test.js` + +#### Running Remote tests +* TAP tests can be run using Saucelabs, an online service that can test browser/os combinations remotely. Currently all tests are written for use for chrome on mac. +* You will need a Saucelabs account in order to use it for testing. To find the Access Key, click your username and select User Settings from the dropdown menu. Near the bottom of the page is your access key that you can copy and use in the command line. +* Currently Jest tests will not run with Saucelabs. +* To run tests using saucelabs run this command `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password SAUCE_USERNAME=saucelabsUsername SAUCE_ACCESS_KEY=saucelabsAccessKey ROOT_URL=https://scratch.mit.edu npm run test:integration:remote` + +#### Configuration + +| Variable | Default | Description | +| --------------------- | --------------------- | --------------------------------------------------------- | +| `ROOT_URL` | `scratch.ly` | Location you want to run the tests against | +| `SMOKE_USERNAME` | `None` | Username for Scratch user you're signing in with to test | +| `SMOKE_PASSWORD` | `None` | Password for Scratch user you're signing in with to test | +| `SMOKE_REMOTE` | `false` | Tests with Sauce Labs or not. True if running test:smoke:sauce | +| `SMOKE_HEADLESS` | `false` | Run browser in headless mode. Flaky at the moment | +| `SAUCE_USERNAME` | `None` | Username for your Sauce Labs account | +| `SAUCE_ACCESS_KEY` | `None` | Access Key for Sauce Labs found under User Settings | ### To Deploy diff --git a/test/integration-legacy/README.md b/test/integration-legacy/README.md deleted file mode 100644 index 251e5d29a..000000000 --- a/test/integration-legacy/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Requirements - -* Selenium - * See this directory's package.json -* TAP - * In the scratch-www repo's package.json -* [Chromedriver](https://sites.google.com/a/chromium.org/chromedriver/) - -# Running the tests - -* By default, tests run against our Staging instance, but you can pass in a different location if you want to run the tests against e.g. your local build -* Tests can be run using Saucelabs, an online service that can test browser/os combinations remotely. Currently all tests are written for use for chrome on mac. - -## Using tap -* Run all tests in the smoke-testing directory from the command-line: `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password ROOT_URL=https://scratch.mit.edu npm run smoke` -* To run a single file from the command-line: `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password ROOT_URL=https://scratch.mit.edu node_modules/.bin/tap ./test/integration/smoke-testing/filename.js --timeout=3600` - * The timeout var is for the length of the entire tap test-suite; if you are getting a timeout error, you may need to adjust this value (some of the Selenium tests take a while to run) -* To run tests using saucelabs run this command `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password SAUCE_USERNAME=saucelabsUsername SAUCE_ACCESS_KEY=saucelabsAccessKey ROOT_URL=https://scratch.mit.edu npm run smoke-sauce` - - -### Configuration - -| Variable | Default | Description | -| --------------------- | --------------------- | --------------------------------------------------------- | -| `ROOT_URL` | `scratch.ly` | Location you want to run the tests against | -| `SMOKE_USERNAME` | `None` | Username for Scratch user you're signing in with to test | -| `SMOKE_PASSWORD` | `None` | Password for Scratch user you're signing in with to test | -| `SMOKE_REMOTE` | `false` | Tests with Sauce Labs or not. True if running smoke-sauce | -| `SMOKE_HEADLESS` | `false` | Run browser in headless mode. Flaky at the moment | -| `SAUCE_USERNAME` | `None` | Username for your Sauce Labs account | -| `SAUCE_ACCESS_KEY` | `None` | Access Key for Sauce Labs found under User Settings | - - -## Using Saucelabs -* You will need a Saucelabs account in order to use it for testing. To find the Access Key, click your username and select User Settings from the dropdown menu. Near the bottom of the page is your access key that you can copy and use in the command line. diff --git a/test/integration/README.md b/test/integration/README.md deleted file mode 100644 index ee606d9ca..000000000 --- a/test/integration/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# Requirements - -* TAP and Selenium - * In the scratch-www repo's package.json -* [Chromedriver](https://sites.google.com/a/chromium.org/chromedriver/) - -# Running the tests - -* By default, tests run against our Staging instance, but you can pass in a different location if you want to run the tests against e.g. your local build -* Tests can be run using Saucelabs, an online service that can test browser/os combinations remotely. Currently all tests are written for use for chrome on mac. - -## Using tap -* Run all tests in the smoke-testing directory from the command-line: `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password ROOT_URL=https://scratch.mit.edu npm run test:smoke` -* To run a single file from the command-line: `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password ROOT_URL=https://scratch.mit.edu node_modules/.bin/tap ./test/integration/smoke-testing/filename.js --timeout=3600` - * The timeout var is for the length of the entire tap test-suite; if you are getting a timeout error, you may need to adjust this value (some of the Selenium tests take a while to run) -* To run tests using saucelabs run this command `$ SMOKE_USERNAME=username SMOKE_PASSWORD=password SAUCE_USERNAME=saucelabsUsername SAUCE_ACCESS_KEY=saucelabsAccessKey ROOT_URL=https://scratch.mit.edu npm run test:smoke:sauce` - - -### Configuration - -| Variable | Default | Description | -| --------------------- | --------------------- | --------------------------------------------------------- | -| `ROOT_URL` | `scratch.ly` | Location you want to run the tests against | -| `SMOKE_USERNAME` | `None` | Username for Scratch user you're signing in with to test | -| `SMOKE_PASSWORD` | `None` | Password for Scratch user you're signing in with to test | -| `SMOKE_REMOTE` | `false` | Tests with Sauce Labs or not. True if running test:smoke:sauce | -| `SMOKE_HEADLESS` | `false` | Run browser in headless mode. Flaky at the moment | -| `SAUCE_USERNAME` | `None` | Username for your Sauce Labs account | -| `SAUCE_ACCESS_KEY` | `None` | Access Key for Sauce Labs found under User Settings | - - -## Using Saucelabs -* You will need a Saucelabs account in order to use it for testing. To find the Access Key, click your username and select User Settings from the dropdown menu. Near the bottom of the page is your access key that you can copy and use in the command line. From 53fc6e57fd3ff4178c7e62b43167055dbb0ed2d9 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Thu, 18 Jul 2019 16:18:27 -0400 Subject: [PATCH 13/32] Make npm run test run all unit tests --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0dc14df03..31a54a858 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Standalone WWW client for Scratch", "scripts": { "start": "node ./dev-server/index.js", - "test": "npm run test:lint && npm run build && npm run test:unit:tap", + "test": "npm run test:lint && npm run build && npm run test:unit", "test:lint": "eslint . --ext .js,.jsx,.json", "test:integration": "npm run test:integration:jest && npm run test:smoke", "test:integration:jest": "jest ./test/integration/*.test.js", From 39fd6b07eaba53460c09c36f77f22c9f925a2506 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 26 Jun 2019 19:46:26 -0400 Subject: [PATCH 14/32] added draft of birth date step; localize birth month string --- src/components/join-flow/join-flow-steps.jsx | 120 ++++++++++++++++++- src/components/join-flow/join-flow.jsx | 3 + 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/src/components/join-flow/join-flow-steps.jsx b/src/components/join-flow/join-flow-steps.jsx index c612853cd..5e1b2cf04 100644 --- a/src/components/join-flow/join-flow-steps.jsx +++ b/src/components/join-flow/join-flow-steps.jsx @@ -8,6 +8,7 @@ const {injectIntl, intlShape} = require('react-intl'); const validate = require('../../lib/validate'); const FormikInput = require('../../components/formik-forms/formik-input.jsx'); +const FormikSelect = require('../../components/formik-forms/formik-select.jsx'); const JoinFlowStep = require('./join-flow-step.jsx'); require('./join-flow-steps.scss'); @@ -190,11 +191,126 @@ class UsernameStep extends React.Component { ); } } -/* eslint-enable */ UsernameStep.propTypes = { intl: intlShape, onNextStep: PropTypes.func }; -module.exports.UsernameStep = injectIntl(UsernameStep); +const IntlUsernameStep = injectIntl(UsernameStep); + +module.exports.UsernameStep = IntlUsernameStep; + +/* + * BirthDateStep + */ + +const birthMonthIds = [ + {value: 'null', id: 'general.monthJanuary'}, + {value: 1, id: 'general.monthJanuary'}, + {value: 2, id: 'general.monthFebruary'}, + {value: 3, id: 'general.monthMarch'}, + {value: 4, id: 'general.monthApril'}, + {value: 5, id: 'general.monthMay'}, + {value: 6, id: 'general.monthJune'}, + {value: 7, id: 'general.monthJuly'}, + {value: 8, id: 'general.monthAugust'}, + {value: 9, id: 'general.monthSeptember'}, + {value: 10, id: 'general.monthOctober'}, + {value: 11, id: 'general.monthNovember'}, + {value: 12, id: 'general.monthDecember'} +]; +const curYear = (new Date()).getYear() + 1900; +const birthYearOptions = Array(120).fill() + .map((_, i) => ( + {value: curYear - i, label: curYear - i} + )); + +class BirthDateStep extends React.Component { + constructor (props) { + super(props); + bindAll(this, [ + 'handleValidSubmit', + 'validateForm', + 'validateSelect' + ]); + } + validateSelect (selection) { + console.log(selection); + } + validateForm (values) { + console.log(values); + } + handleValidSubmit (formData, formikBag) { + formikBag.setSubmitting(false); + this.props.onNextStep(formData); + } + render () { + const birthMonthOptions = birthMonthIds.map(item => ( + {value: item.value, label: this.props.intl.formatMessage({id: item.id})} + )); + return ( + + {props => { + const { + errors, + handleSubmit, + isSubmitting + } = props; + return ( + +
+
+ {this.props.intl.formatMessage({id: 'general.birthMonth'})} +
+ + +
+
+ ); + }} +
+ ); + } +} + +BirthDateStep.propTypes = { + intl: intlShape, + onNextStep: PropTypes.func +}; + +const IntlBirthDateStep = injectIntl(BirthDateStep); + +module.exports.BirthDateStep = IntlBirthDateStep; + +/* eslint-enable */ diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index ba80726a7..b848ef52c 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -38,6 +38,9 @@ class JoinFlow extends React.Component { + ); From 71baf3e8028535859481b4ade9c0f1f7c402b9bb Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 17 Jul 2019 11:47:32 -0400 Subject: [PATCH 15/32] birthdate month and year layout --- src/components/formik-forms/formik-select.jsx | 3 +-- src/components/join-flow/join-flow-steps.jsx | 22 ++++++++++++++----- src/components/join-flow/join-flow-steps.scss | 13 +++++++++++ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/components/formik-forms/formik-select.jsx b/src/components/formik-forms/formik-select.jsx index dcd631012..5ec1bcdf5 100644 --- a/src/components/formik-forms/formik-select.jsx +++ b/src/components/formik-forms/formik-select.jsx @@ -24,10 +24,9 @@ const FormikSelect = ({ )); return ( -
+
-
-
- {this.props.intl.formatMessage({id: 'general.birthMonth'})} -
+
Date: Wed, 17 Jul 2019 11:55:27 -0400 Subject: [PATCH 16/32] add birthdate month and year header labels, initial vals --- src/components/join-flow/join-flow-steps.jsx | 41 +++++++++++--------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/components/join-flow/join-flow-steps.jsx b/src/components/join-flow/join-flow-steps.jsx index 605197b86..bf28f3e79 100644 --- a/src/components/join-flow/join-flow-steps.jsx +++ b/src/components/join-flow/join-flow-steps.jsx @@ -206,24 +206,25 @@ module.exports.UsernameStep = IntlUsernameStep; */ const birthMonthIds = [ - {value: 'null', id: 'general.monthJanuary'}, - {value: 1, id: 'general.monthJanuary'}, - {value: 2, id: 'general.monthFebruary'}, - {value: 3, id: 'general.monthMarch'}, - {value: 4, id: 'general.monthApril'}, - {value: 5, id: 'general.monthMay'}, - {value: 6, id: 'general.monthJune'}, - {value: 7, id: 'general.monthJuly'}, - {value: 8, id: 'general.monthAugust'}, - {value: 9, id: 'general.monthSeptember'}, - {value: 10, id: 'general.monthOctober'}, - {value: 11, id: 'general.monthNovember'}, - {value: 12, id: 'general.monthDecember'} + {value: 'null', id: 'general.month'}, + {value: '1', id: 'general.monthJanuary'}, + {value: '2', id: 'general.monthFebruary'}, + {value: '3', id: 'general.monthMarch'}, + {value: '4', id: 'general.monthApril'}, + {value: '5', id: 'general.monthMay'}, + {value: '6', id: 'general.monthJune'}, + {value: '7', id: 'general.monthJuly'}, + {value: '8', id: 'general.monthAugust'}, + {value: '9', id: 'general.monthSeptember'}, + {value: '10', id: 'general.monthOctober'}, + {value: '11', id: 'general.monthNovember'}, + {value: '12', id: 'general.monthDecember'} ]; -const curYear = (new Date()).getYear() + 1900; -const birthYearOptions = Array(120).fill() +const curYearRaw = (new Date()).getYear(); +const curYear = curYearRaw + 1900; +const birthYearOptions = Array(curYearRaw + 2).fill() .map((_, i) => ( - {value: curYear - i, label: curYear - i} + {value: String(curYear - i), label: String(curYear - i)} )); class BirthDateStep extends React.Component { @@ -249,11 +250,15 @@ class BirthDateStep extends React.Component { const birthMonthOptions = birthMonthIds.map(item => ( {value: item.value, label: this.props.intl.formatMessage({id: item.id})} )); + birthYearOptions[0] = { + value: 'null', + label: this.props.intl.formatMessage({id: 'general.year'}) + }; return ( Date: Wed, 17 Jul 2019 12:40:21 -0400 Subject: [PATCH 17/32] add birthdate header image --- src/components/join-flow/join-flow-step.jsx | 7 +++++++ src/components/join-flow/join-flow-step.scss | 10 ++++++++++ src/components/join-flow/join-flow-steps.jsx | 1 + 3 files changed, 18 insertions(+) diff --git a/src/components/join-flow/join-flow-step.jsx b/src/components/join-flow/join-flow-step.jsx index 6ce43ac83..6b1b91fe1 100644 --- a/src/components/join-flow/join-flow-step.jsx +++ b/src/components/join-flow/join-flow-step.jsx @@ -10,11 +10,17 @@ require('./join-flow-step.scss'); const JoinFlowStep = ({ children, description, + headerImgSrc, onSubmit, title, waiting }) => (
+ {headerImgSrc && ( +
+ +
+ )}
{title && ( @@ -38,6 +44,7 @@ const JoinFlowStep = ({ JoinFlowStep.propTypes = { children: PropTypes.node, description: PropTypes.string, + headerImgSrc: PropTypes.string, onSubmit: PropTypes.func, title: PropTypes.string, waiting: PropTypes.bool diff --git a/src/components/join-flow/join-flow-step.scss b/src/components/join-flow/join-flow-step.scss index eeddbf87c..499646956 100644 --- a/src/components/join-flow/join-flow-step.scss +++ b/src/components/join-flow/join-flow-step.scss @@ -21,3 +21,13 @@ padding: 2.3125rem 0 2.5rem; font-size: .875rem; } + +/* overflow will only work if this class is set on parent of img, not img itself */ +.join-flow-header-image { + width: 100%; + height: 7.5rem; + overflow: hidden; + margin: 0; + border-top-left-radius: 1rem; + border-top-right-radius: 1rem; +} diff --git a/src/components/join-flow/join-flow-steps.jsx b/src/components/join-flow/join-flow-steps.jsx index bf28f3e79..92489074e 100644 --- a/src/components/join-flow/join-flow-steps.jsx +++ b/src/components/join-flow/join-flow-steps.jsx @@ -274,6 +274,7 @@ class BirthDateStep extends React.Component { return ( Date: Wed, 17 Jul 2019 12:40:59 -0400 Subject: [PATCH 18/32] validate birthdate --- src/components/join-flow/join-flow-steps.jsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/join-flow/join-flow-steps.jsx b/src/components/join-flow/join-flow-steps.jsx index 92489074e..5b9f2edfc 100644 --- a/src/components/join-flow/join-flow-steps.jsx +++ b/src/components/join-flow/join-flow-steps.jsx @@ -237,10 +237,13 @@ class BirthDateStep extends React.Component { ]); } validateSelect (selection) { - console.log(selection); + if (selection === 'null') { + return this.props.intl.formatMessage({id: 'form.validationRequired'}); + } + return null; } - validateForm (values) { - console.log(values); + validateForm () { + return {}; } handleValidSubmit (formData, formikBag) { formikBag.setSubmitting(false); From e33d7dd0eefdb3002186e035200cda2e2094421c Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 17 Jul 2019 17:12:39 -0400 Subject: [PATCH 19/32] Simplify birth month option generation --- src/components/join-flow/join-flow-steps.jsx | 36 +++++++++----------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/components/join-flow/join-flow-steps.jsx b/src/components/join-flow/join-flow-steps.jsx index 5b9f2edfc..ebd1ad6f7 100644 --- a/src/components/join-flow/join-flow-steps.jsx +++ b/src/components/join-flow/join-flow-steps.jsx @@ -205,26 +205,26 @@ module.exports.UsernameStep = IntlUsernameStep; * BirthDateStep */ -const birthMonthIds = [ - {value: 'null', id: 'general.month'}, - {value: '1', id: 'general.monthJanuary'}, - {value: '2', id: 'general.monthFebruary'}, - {value: '3', id: 'general.monthMarch'}, - {value: '4', id: 'general.monthApril'}, - {value: '5', id: 'general.monthMay'}, - {value: '6', id: 'general.monthJune'}, - {value: '7', id: 'general.monthJuly'}, - {value: '8', id: 'general.monthAugust'}, - {value: '9', id: 'general.monthSeptember'}, - {value: '10', id: 'general.monthOctober'}, - {value: '11', id: 'general.monthNovember'}, - {value: '12', id: 'general.monthDecember'} -]; +const getBirthMonthOptions = intl => ([ + {value: 'null', label: intl.formatMessage({id: 'general.month'})}, + {value: '1', label: intl.formatMessage({id: 'general.monthJanuary'})}, + {value: '2', label: intl.formatMessage({id: 'general.monthFebruary'})}, + {value: '3', label: intl.formatMessage({id: 'general.monthMarch'})}, + {value: '4', label: intl.formatMessage({id: 'general.monthApril'})}, + {value: '5', label: intl.formatMessage({id: 'general.monthMay'})}, + {value: '6', label: intl.formatMessage({id: 'general.monthJune'})}, + {value: '7', label: intl.formatMessage({id: 'general.monthJuly'})}, + {value: '8', label: intl.formatMessage({id: 'general.monthAugust'})}, + {value: '9', label: intl.formatMessage({id: 'general.monthSeptember'})}, + {value: '10', label: intl.formatMessage({id: 'general.monthOctober'})}, + {value: '11', label: intl.formatMessage({id: 'general.monthNovember'})}, + {value: '12', label: intl.formatMessage({id: 'general.monthDecember'})} +]); const curYearRaw = (new Date()).getYear(); const curYear = curYearRaw + 1900; const birthYearOptions = Array(curYearRaw + 2).fill() .map((_, i) => ( - {value: String(curYear - i), label: String(curYear - i)} + {value: String(curYear + 1 - i), label: String(curYear + 1 - i)} )); class BirthDateStep extends React.Component { @@ -250,9 +250,7 @@ class BirthDateStep extends React.Component { this.props.onNextStep(formData); } render () { - const birthMonthOptions = birthMonthIds.map(item => ( - {value: item.value, label: this.props.intl.formatMessage({id: item.id})} - )); + const birthMonthOptions = getBirthMonthOptions(this.props.intl); birthYearOptions[0] = { value: 'null', label: this.props.intl.formatMessage({id: 'general.year'}) From 740f1fb46683d9f2f4936d4576f8e5d714f66fa8 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Thu, 18 Jul 2019 20:39:16 -0400 Subject: [PATCH 20/32] split join-flow-steps into separate files; simplify birth year options --- src/components/join-flow/birthdate-step.jsx | 143 ++++++++++++++++++ src/components/join-flow/join-flow.jsx | 11 +- ...{join-flow-steps.jsx => username-step.jsx} | 135 +---------------- 3 files changed, 148 insertions(+), 141 deletions(-) create mode 100644 src/components/join-flow/birthdate-step.jsx rename src/components/join-flow/{join-flow-steps.jsx => username-step.jsx} (64%) diff --git a/src/components/join-flow/birthdate-step.jsx b/src/components/join-flow/birthdate-step.jsx new file mode 100644 index 000000000..708be8c16 --- /dev/null +++ b/src/components/join-flow/birthdate-step.jsx @@ -0,0 +1,143 @@ +const bindAll = require('lodash.bindall'); +const classNames = require('classnames'); +const React = require('react'); +const PropTypes = require('prop-types'); +import {Formik} from 'formik'; +const {injectIntl, intlShape} = require('react-intl'); + +const FormikSelect = require('../../components/formik-forms/formik-select.jsx'); +const JoinFlowStep = require('./join-flow-step.jsx'); + +require('./join-flow-steps.scss'); + +const getBirthMonthOptions = intl => ([ + {value: 'null', label: intl.formatMessage({id: 'general.month'})}, + {value: '1', label: intl.formatMessage({id: 'general.monthJanuary'})}, + {value: '2', label: intl.formatMessage({id: 'general.monthFebruary'})}, + {value: '3', label: intl.formatMessage({id: 'general.monthMarch'})}, + {value: '4', label: intl.formatMessage({id: 'general.monthApril'})}, + {value: '5', label: intl.formatMessage({id: 'general.monthMay'})}, + {value: '6', label: intl.formatMessage({id: 'general.monthJune'})}, + {value: '7', label: intl.formatMessage({id: 'general.monthJuly'})}, + {value: '8', label: intl.formatMessage({id: 'general.monthAugust'})}, + {value: '9', label: intl.formatMessage({id: 'general.monthSeptember'})}, + {value: '10', label: intl.formatMessage({id: 'general.monthOctober'})}, + {value: '11', label: intl.formatMessage({id: 'general.monthNovember'})}, + {value: '12', label: intl.formatMessage({id: 'general.monthDecember'})} +]); + +const getBirthYearOptions = intl => { + const curYearRaw = (new Date()).getYear(); + const curYear = curYearRaw + 1900; + // including both 1900 and current year, there are (curYearRaw + 1) options. + const numYearOptions = curYearRaw + 1; + const birthYearOptions = Array(numYearOptions).fill() + .map((defaultVal, i) => ( + {value: String(curYear - i), label: String(curYear - i)} + )); + birthYearOptions.unshift({ + value: 'null', + label: intl.formatMessage({id: 'general.year'}) + }); + return birthYearOptions; +}; + +class BirthDateStep extends React.Component { + constructor (props) { + super(props); + bindAll(this, [ + 'handleValidSubmit', + 'validateForm', + 'validateSelect' + ]); + } + validateSelect (selection) { + if (selection === 'null') { + return this.props.intl.formatMessage({id: 'form.validationRequired'}); + } + return null; + } + validateForm () { + return {}; + } + handleValidSubmit (formData, formikBag) { + formikBag.setSubmitting(false); + this.props.onNextStep(formData); + } + render () { + const birthMonthOptions = getBirthMonthOptions(this.props.intl); + const birthYearOptions = getBirthYearOptions(this.props.intl); + return ( + + {props => { + const { + errors, + handleSubmit, + isSubmitting + } = props; + return ( + +
+ + +
+
+ ); + }} +
+ ); + } +} + +BirthDateStep.propTypes = { + intl: intlShape, + onNextStep: PropTypes.func +}; + +const IntlBirthDateStep = injectIntl(BirthDateStep); + +module.exports = IntlBirthDateStep; diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index b848ef52c..efa663abd 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -7,7 +7,8 @@ const injectIntl = require('../../lib/intl.jsx').injectIntl; const intlShape = require('../../lib/intl.jsx').intlShape; const Progression = require('../progression/progression.jsx'); -const JoinFlowSteps = require('./join-flow-steps.jsx'); +const UsernameStep = require('./username-step.jsx'); +const BirthDateStep = require('./birthdate-step.jsx'); /* eslint-disable react/prefer-stateless-function, react/no-unused-prop-types, no-useless-constructor @@ -35,12 +36,8 @@ class JoinFlow extends React.Component { return ( - - + + ); diff --git a/src/components/join-flow/join-flow-steps.jsx b/src/components/join-flow/username-step.jsx similarity index 64% rename from src/components/join-flow/join-flow-steps.jsx rename to src/components/join-flow/username-step.jsx index ebd1ad6f7..2d0a8bb49 100644 --- a/src/components/join-flow/join-flow-steps.jsx +++ b/src/components/join-flow/username-step.jsx @@ -1,4 +1,3 @@ -/* eslint-disable react/no-multi-comp */ const bindAll = require('lodash.bindall'); const classNames = require('classnames'); const React = require('react'); @@ -8,7 +7,6 @@ const {injectIntl, intlShape} = require('react-intl'); const validate = require('../../lib/validate'); const FormikInput = require('../../components/formik-forms/formik-input.jsx'); -const FormikSelect = require('../../components/formik-forms/formik-select.jsx'); const JoinFlowStep = require('./join-flow-step.jsx'); require('./join-flow-steps.scss'); @@ -199,135 +197,4 @@ UsernameStep.propTypes = { const IntlUsernameStep = injectIntl(UsernameStep); -module.exports.UsernameStep = IntlUsernameStep; - -/* - * BirthDateStep - */ - -const getBirthMonthOptions = intl => ([ - {value: 'null', label: intl.formatMessage({id: 'general.month'})}, - {value: '1', label: intl.formatMessage({id: 'general.monthJanuary'})}, - {value: '2', label: intl.formatMessage({id: 'general.monthFebruary'})}, - {value: '3', label: intl.formatMessage({id: 'general.monthMarch'})}, - {value: '4', label: intl.formatMessage({id: 'general.monthApril'})}, - {value: '5', label: intl.formatMessage({id: 'general.monthMay'})}, - {value: '6', label: intl.formatMessage({id: 'general.monthJune'})}, - {value: '7', label: intl.formatMessage({id: 'general.monthJuly'})}, - {value: '8', label: intl.formatMessage({id: 'general.monthAugust'})}, - {value: '9', label: intl.formatMessage({id: 'general.monthSeptember'})}, - {value: '10', label: intl.formatMessage({id: 'general.monthOctober'})}, - {value: '11', label: intl.formatMessage({id: 'general.monthNovember'})}, - {value: '12', label: intl.formatMessage({id: 'general.monthDecember'})} -]); -const curYearRaw = (new Date()).getYear(); -const curYear = curYearRaw + 1900; -const birthYearOptions = Array(curYearRaw + 2).fill() - .map((_, i) => ( - {value: String(curYear + 1 - i), label: String(curYear + 1 - i)} - )); - -class BirthDateStep extends React.Component { - constructor (props) { - super(props); - bindAll(this, [ - 'handleValidSubmit', - 'validateForm', - 'validateSelect' - ]); - } - validateSelect (selection) { - if (selection === 'null') { - return this.props.intl.formatMessage({id: 'form.validationRequired'}); - } - return null; - } - validateForm () { - return {}; - } - handleValidSubmit (formData, formikBag) { - formikBag.setSubmitting(false); - this.props.onNextStep(formData); - } - render () { - const birthMonthOptions = getBirthMonthOptions(this.props.intl); - birthYearOptions[0] = { - value: 'null', - label: this.props.intl.formatMessage({id: 'general.year'}) - }; - return ( - - {props => { - const { - errors, - handleSubmit, - isSubmitting - } = props; - return ( - -
- - -
-
- ); - }} -
- ); - } -} - -BirthDateStep.propTypes = { - intl: intlShape, - onNextStep: PropTypes.func -}; - -const IntlBirthDateStep = injectIntl(BirthDateStep); - -module.exports.BirthDateStep = IntlBirthDateStep; - -/* eslint-enable */ +module.exports = IntlUsernameStep; From a6dc573f3009161a848bcc7f98af3c19a17a176f Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Mon, 22 Jul 2019 14:54:25 -0400 Subject: [PATCH 21/32] rewrote validate legacy unit test from using tap, to using jest --- package.json | 2 +- test/unit-legacy/lib/validate.js | 66 -------------------------------- test/unit/lib/validate.test.js | 62 ++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 67 deletions(-) delete mode 100644 test/unit-legacy/lib/validate.js create mode 100644 test/unit/lib/validate.test.js diff --git a/package.json b/package.json index a9df0e1df..a040a0b03 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test:smoke:verbose": "tap ./test/integration-legacy/smoke-testing/*.js --timeout=3600 --no-coverage -R spec", "test:smoke:sauce": "SMOKE_REMOTE=true tap ./test/integration-legacy/smoke-testing/*.js --timeout=60000 --no-coverage -R classic", "test:unit": "npm run test:unit:jest && npm run test:unit:tap", - "test:unit:jest": "jest ./test/unit/*.test.js && jest ./test/localization/*.test.js", + "test:unit:jest": "jest ./test/unit/ && jest ./test/localization/*.test.js", "test:unit:tap": "tap ./test/{unit-legacy,localization-legacy}/*.js --no-coverage -R classic", "test:coverage": "tap ./test/{unit-legacy,localization-legacy}/*.js --coverage --coverage-report=lcov", "build": "npm run clean && npm run translate && webpack --bail", diff --git a/test/unit-legacy/lib/validate.js b/test/unit-legacy/lib/validate.js deleted file mode 100644 index 3209a4307..000000000 --- a/test/unit-legacy/lib/validate.js +++ /dev/null @@ -1,66 +0,0 @@ -const tap = require('tap'); -const validate = require('../../../src/lib/validate'); - -tap.tearDown(() => process.nextTick(process.exit)); - -tap.test('validate username locally', t => { - let response; - t.type(validate.validateUsernameLocally, 'function'); - response = validate.validateUsernameLocally('abc'); - t.deepEqual(response, {valid: true}); - response = validate.validateUsernameLocally('abcdefghijklmnopqrst'); - t.deepEqual(response, {valid: true}); - response = validate.validateUsernameLocally('abc-def-ghi'); - t.deepEqual(response, {valid: true}); - response = validate.validateUsernameLocally(''); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationRequired'}); - response = validate.validateUsernameLocally('ab'); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameMinLength'}); - response = validate.validateUsernameLocally('abcdefghijklmnopqrstu'); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameMaxLength'}); - response = validate.validateUsernameLocally('abc def'); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameRegexp'}); - response = validate.validateUsernameLocally('abc!def'); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameRegexp'}); - response = validate.validateUsernameLocally('abc😄def'); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationUsernameRegexp'}); - t.end(); -}); - -tap.test('validate password', t => { - let response; - t.type(validate.validatePassword, 'function'); - response = validate.validatePassword('abcdef'); - t.deepEqual(response, {valid: true}); - response = validate.validatePassword('abcdefghijklmnopqrst'); - t.deepEqual(response, {valid: true}); - response = validate.validatePassword('passwo'); - t.deepEqual(response, {valid: true}); - response = validate.validatePassword(''); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationRequired'}); - response = validate.validatePassword('abcde'); - t.deepEqual(response, {valid: false, errMsgId: 'registration.validationPasswordLength'}); - response = validate.validatePassword('password'); - t.deepEqual(response, {valid: false, errMsgId: 'registration.validationPasswordNotEquals'}); - t.end(); -}); - -tap.test('validate password confirm', t => { - let response; - t.type(validate.validatePasswordConfirm, 'function'); - response = validate.validatePasswordConfirm('abcdef', 'abcdef'); - t.deepEqual(response, {valid: true}); - response = validate.validatePasswordConfirm('abcdefghijklmnopqrst', 'abcdefghijklmnopqrst'); - t.deepEqual(response, {valid: true}); - response = validate.validatePasswordConfirm('passwo', 'passwo'); - t.deepEqual(response, {valid: true}); - response = validate.validatePasswordConfirm('', ''); - t.deepEqual(response, {valid: false, errMsgId: 'form.validationRequired'}); - response = validate.validatePasswordConfirm('abcdef', 'abcdefg'); - t.deepEqual(response, {valid: false, errMsgId: 'general.error'}); - response = validate.validatePasswordConfirm('abcdef', '123456'); - t.deepEqual(response, {valid: false, errMsgId: 'general.error'}); - response = validate.validatePasswordConfirm('', 'abcdefg'); - t.deepEqual(response, {valid: false, errMsgId: 'general.error'}); - t.end(); -}); diff --git a/test/unit/lib/validate.test.js b/test/unit/lib/validate.test.js new file mode 100644 index 000000000..31eca3e36 --- /dev/null +++ b/test/unit/lib/validate.test.js @@ -0,0 +1,62 @@ +const validate = require('../../../src/lib/validate'); + +describe('unit test lib/validate.js', () => { + test('validate username locally', () => { + let response; + expect(typeof validate.validateUsernameLocally).toBe('function'); + response = validate.validateUsernameLocally('abc'); + expect(response).toEqual({valid: true}); + response = validate.validateUsernameLocally('abcdefghijklmnopqrst'); + expect(response).toEqual({valid: true}); + response = validate.validateUsernameLocally('abc-def-ghi'); + expect(response).toEqual({valid: true}); + response = validate.validateUsernameLocally(''); + expect(response).toEqual({valid: false, errMsgId: 'form.validationRequired'}); + response = validate.validateUsernameLocally('ab'); + expect(response).toEqual({valid: false, errMsgId: 'form.validationUsernameMinLength'}); + response = validate.validateUsernameLocally('abcdefghijklmnopqrstu'); + expect(response).toEqual({valid: false, errMsgId: 'form.validationUsernameMaxLength'}); + response = validate.validateUsernameLocally('abc def'); + expect(response).toEqual({valid: false, errMsgId: 'form.validationUsernameRegexp'}); + response = validate.validateUsernameLocally('abc!def'); + expect(response).toEqual({valid: false, errMsgId: 'form.validationUsernameRegexp'}); + response = validate.validateUsernameLocally('abc😄def'); + expect(response).toEqual({valid: false, errMsgId: 'form.validationUsernameRegexp'}); + }); + + test('validate password', () => { + let response; + expect(typeof validate.validatePassword).toBe('function'); + response = validate.validatePassword('abcdef'); + expect(response).toEqual({valid: true}); + response = validate.validatePassword('abcdefghijklmnopqrst'); + expect(response).toEqual({valid: true}); + response = validate.validatePassword('passwo'); + expect(response).toEqual({valid: true}); + response = validate.validatePassword(''); + expect(response).toEqual({valid: false, errMsgId: 'form.validationRequired'}); + response = validate.validatePassword('abcde'); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationPasswordLength'}); + response = validate.validatePassword('password'); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationPasswordNotEquals'}); + }); + + test('validate password confirm', () => { + let response; + expect(typeof validate.validatePasswordConfirm).toBe('function'); + response = validate.validatePasswordConfirm('abcdef', 'abcdef'); + expect(response).toEqual({valid: true}); + response = validate.validatePasswordConfirm('abcdefghijklmnopqrst', 'abcdefghijklmnopqrst'); + expect(response).toEqual({valid: true}); + response = validate.validatePasswordConfirm('passwo', 'passwo'); + expect(response).toEqual({valid: true}); + response = validate.validatePasswordConfirm('', ''); + expect(response).toEqual({valid: false, errMsgId: 'form.validationRequired'}); + response = validate.validatePasswordConfirm('abcdef', 'abcdefg'); + expect(response).toEqual({valid: false, errMsgId: 'general.error'}); + response = validate.validatePasswordConfirm('abcdef', '123456'); + expect(response).toEqual({valid: false, errMsgId: 'general.error'}); + response = validate.validatePasswordConfirm('', 'abcdefg'); + expect(response).toEqual({valid: false, errMsgId: 'general.error'}); + }); +}); From 748e07d1723d569e7aed692638664b217c6fc10c Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Mon, 22 Jul 2019 15:14:28 -0400 Subject: [PATCH 22/32] deleted template example of unit test --- test/unit/test-unit.test.js | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 test/unit/test-unit.test.js diff --git a/test/unit/test-unit.test.js b/test/unit/test-unit.test.js deleted file mode 100644 index d29619cfd..000000000 --- a/test/unit/test-unit.test.js +++ /dev/null @@ -1,5 +0,0 @@ -describe('test jest unit', () => { - test('testing test', () => { - expect('unit').toEqual('unit'); - }); -}); From f180d4f3950a5fbf1f0113f7fe4a04ff72574bfc Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Sun, 21 Jul 2019 21:08:55 -0400 Subject: [PATCH 23/32] update eslint-related package versions --- package-lock.json | 4019 ++++++++------------------------------------- package.json | 8 +- 2 files changed, 713 insertions(+), 3314 deletions(-) diff --git a/package-lock.json b/package-lock.json index d3b06a460..2f6c619d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@babel/cli": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.5.0.tgz", - "integrity": "sha512-qNH55fWbKrEsCwID+Qc/3JDPnsSGpIIiMDbppnR8Z6PxLAqMQCFNqBctkIkBrMH49Nx+qqVTrHRWUR+ho2k+qQ==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.5.5.tgz", + "integrity": "sha512-UHI+7pHv/tk9g6WXQKYz+kmXTI77YtuY3vqC59KIqcoWEjsJJSG6rAxKaLsgj3LDyadsPrCB929gVOKM6Hui0w==", "dev": true, "requires": { "chokidar": "^2.0.4", @@ -15,7 +15,7 @@ "convert-source-map": "^1.1.0", "fs-readdir-recursive": "^1.1.0", "glob": "^7.0.0", - "lodash": "^4.17.11", + "lodash": "^4.17.13", "mkdirp": "^0.5.1", "output-file-sync": "^2.0.0", "slash": "^2.0.0", @@ -56,13 +56,15 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true + "dev": true, + "optional": true }, "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, + "optional": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -81,6 +83,7 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, + "optional": true, "requires": { "is-extendable": "^0.1.0" } @@ -263,6 +266,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, + "optional": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -275,6 +279,7 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, + "optional": true, "requires": { "is-extendable": "^0.1.0" } @@ -354,7 +359,8 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "dev": true, + "optional": true }, "is-glob": { "version": "4.0.1", @@ -371,6 +377,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, + "optional": true, "requires": { "kind-of": "^3.0.2" }, @@ -380,6 +387,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, + "optional": true, "requires": { "is-buffer": "^1.1.5" } @@ -390,13 +398,15 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "dev": true, + "optional": true }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "dev": true, + "optional": true }, "micromatch": { "version": "3.1.10", @@ -469,27 +479,83 @@ } }, "@babel/core": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.4.tgz", - "integrity": "sha512-+DaeBEpYq6b2+ZmHx3tHspC+ZRflrvLqwfv8E3hNr5LVQoyBnL8RPKSBCg+rK2W2My9PWlujBiqd0ZPsR9Q6zQ==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", + "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.5.0", - "@babel/helpers": "^7.5.4", - "@babel/parser": "^7.5.0", + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helpers": "^7.5.5", + "@babel/parser": "^7.5.5", "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.0", - "@babel/types": "^7.5.0", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", - "lodash": "^4.17.11", + "lodash": "^4.17.13", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" }, "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", + "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "dev": true, + "requires": { + "@babel/types": "^7.5.5", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/parser": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "dev": true + }, + "@babel/traverse": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", + "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.5.5", + "@babel/types": "^7.5.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", + "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -499,6 +565,18 @@ "ms": "^2.1.1" } }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, "json5": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", @@ -525,6 +603,12 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true } } }, @@ -591,14 +675,111 @@ } }, "@babel/helpers": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.4.tgz", - "integrity": "sha512-6LJ6xwUEJP51w0sIgKyfvFMJvIb9mWAfohJp0+m6eHJigkFdcH8duZ1sfhn0ltJRzwUIT/yqqhdSfRpCpL7oow==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", + "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", "dev": true, "requires": { "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.0", - "@babel/types": "^7.5.0" + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", + "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "dev": true, + "requires": { + "@babel/types": "^7.5.5", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/parser": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "dev": true + }, + "@babel/traverse": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", + "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.5.5", + "@babel/types": "^7.5.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + } + }, + "@babel/types": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", + "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } } }, "@babel/highlight": { @@ -840,29 +1021,6 @@ "@babel/types": "^7.3.0" } }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true - }, - "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", - "dev": true, - "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, "@types/node": { "version": "12.6.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.2.tgz", @@ -885,12 +1043,6 @@ "csstype": "^2.2.0" } }, - "abab": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", - "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", - "dev": true - }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -928,45 +1080,10 @@ } } }, - "acorn-globals": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.2.tgz", - "integrity": "sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ==", - "dev": true, - "requires": { - "acorn": "^6.0.1", - "acorn-walk": "^6.0.1" - }, - "dependencies": { - "acorn": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz", - "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==", - "dev": true - } - } - }, "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "acorn-walk": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", "dev": true }, "ajv": { @@ -1112,6 +1229,7 @@ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, + "optional": true, "requires": { "arr-flatten": "^1.0.1" } @@ -1128,12 +1246,6 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, - "array-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", - "dev": true - }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -1155,26 +1267,12 @@ "es-abstract": "^1.7.0" } }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true + "dev": true, + "optional": true }, "arraybuffer-loader": { "version": "1.0.7", @@ -1182,52 +1280,6 @@ "integrity": "sha512-8FPjFP26OF723Oiaj5E208WW2tAgE0noCsrtQZ20TwdHt6qs5iuAaKqX5WY/C3wYdF/2cRUiuIXj98qy/2NB7g==", "requires": { "loader-utils": "^1.1.0" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } } }, "arrify": { @@ -1239,7 +1291,8 @@ "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true }, "asn1": { "version": "0.2.4", @@ -1354,12 +1407,6 @@ } } }, - "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", - "dev": true - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1558,23 +1605,17 @@ } }, "babel-eslint": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-8.0.2.tgz", - "integrity": "sha512-yyl5U088oE+419+BNLJDKVWkUokuPLQeQt9ZTy9uM9kAzbtQgyYL3JkG425B8jxXA7MwTxnDAtRLMKJNH36qjA==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.2.tgz", + "integrity": "sha512-UdsurWPtgiPgpJ06ryUnuaSXC2s0WoSZnQmEpbAH65XZSdwowgN5MvyP7e88nW07FYXv72erVtpBkxyDVKhH1Q==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0-beta.31", - "@babel/traverse": "^7.0.0-beta.31", - "@babel/types": "^7.0.0-beta.31", - "babylon": "^7.0.0-beta.31" - }, - "dependencies": { - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - } + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "^1.0.0" } }, "babel-generator": { @@ -1714,16 +1755,6 @@ "babel-template": "^6.24.1" } }, - "babel-jest": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-23.6.0.tgz", - "integrity": "sha512-lqKGG6LYXYu+DQh/slrQ8nxXQkEkhugdXsU6St7GmhVS7Ilc/22ArwqXNJrf0QaOBjZB0360qZMwXqDYQHXaew==", - "dev": true, - "requires": { - "babel-plugin-istanbul": "^4.1.6", - "babel-preset-jest": "^23.2.0" - } - }, "babel-loader": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.0.tgz", @@ -1753,60 +1784,6 @@ "babel-runtime": "^6.22.0" } }, - "babel-plugin-istanbul": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz", - "integrity": "sha512-PWP9FQ1AhZhS01T/4qLSKoHGY/xvkZdVBGlKM/HuxxS3+sC66HhTNR7+MpbO/so/cz/wY94MeSWJuP1hXIPfwQ==", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "^6.13.0", - "find-up": "^2.1.0", - "istanbul-lib-instrument": "^1.10.1", - "test-exclude": "^4.2.1" - }, - "dependencies": { - "istanbul-lib-coverage": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", - "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true, - "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.1", - "semver": "^5.3.0" - } - }, - "test-exclude": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.3.tgz", - "integrity": "sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "micromatch": "^2.3.11", - "object-assign": "^4.1.0", - "read-pkg-up": "^1.0.1", - "require-main-filename": "^1.0.1" - } - } - } - }, - "babel-plugin-jest-hoist": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-23.2.0.tgz", - "integrity": "sha1-5h+uBaHKiAGq3uV6bWa4zvr0QWc=", - "dev": true - }, "babel-plugin-react-intl": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/babel-plugin-react-intl/-/babel-plugin-react-intl-3.5.1.tgz", @@ -2216,16 +2193,6 @@ "babel-plugin-transform-regenerator": "^6.22.0" } }, - "babel-preset-jest": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-23.2.0.tgz", - "integrity": "sha1-jsegOhOPABoaj7HoETZSvxpV2kY=", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^23.2.0", - "babel-plugin-syntax-object-rest-spread": "^6.13.0" - } - }, "babel-preset-react": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.22.0.tgz", @@ -2601,6 +2568,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, + "optional": true, "requires": { "expand-range": "^1.8.1", "preserve": "^0.2.0", @@ -2619,23 +2587,6 @@ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, - "browser-resolve": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", - "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", - "dev": true, - "requires": { - "resolve": "1.1.7" - }, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } - } - }, "browser-stdout": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", @@ -2738,15 +2689,6 @@ "caniuse-db": "^1.0.30000525" } }, - "bser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.0.tgz", - "integrity": "sha512-8zsjWrQkkBoLK6uxASk1nJ2SKv97ltiGDo6A3wA0/yRPz+CwmEyDo0hUrhIuukG2JHpAl3bvFIixw2/3Hi0DOg==", - "dev": true, - "requires": { - "node-int64": "^0.4.0" - } - }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", @@ -2869,19 +2811,10 @@ } } }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } - }, "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "camel-case": { @@ -2942,15 +2875,6 @@ "integrity": "sha512-LS3aD+ti+fezwo8oN01l5vfZF9/CIN/4pxV5SeakHo5leudiHjE66rVHl+XqoCGw4GpO2u5ab6LOpftTfCN9cw==", "dev": true }, - "capture-exit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-1.2.0.tgz", - "integrity": "sha1-HF/MSJ/QqwDU8ax64QcuMXP7q28=", - "dev": true, - "requires": { - "rsvp": "^3.3.3" - } - }, "capture-stack-trace": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", @@ -3030,9 +2954,9 @@ } }, "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, "cheerio": { @@ -3067,19 +2991,6 @@ "readdirp": "^2.0.0" } }, - "chromedriver": { - "version": "75.1.0", - "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-75.1.0.tgz", - "integrity": "sha512-N2P0fg6FS4c+tTG0R7cCOD5qiVo+E6uAz6xVjmbZesYv1xs1iGdcCUo0IqOY+ppD/4OOObG+XWV1CFWXT6UIgA==", - "dev": true, - "requires": { - "del": "^4.1.1", - "extract-zip": "^1.6.7", - "mkdirp": "^0.5.1", - "request": "^2.88.0", - "tcp-port-used": "^1.0.1" - } - }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", @@ -3096,12 +3007,6 @@ "safe-buffer": "^5.0.1" } }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, "clap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", @@ -3176,32 +3081,6 @@ } } }, - "cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", - "dev": true, - "requires": { - "exit": "0.1.2", - "glob": "^7.1.1" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "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" - } - } - } - }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -3421,50 +3300,6 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", @@ -3712,12 +3547,14 @@ } }, "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "lru-cache": "^4.0.1", + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } @@ -3890,21 +3727,6 @@ } } }, - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "cssstyle": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", - "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", - "dev": true, - "requires": { - "cssom": "0.3.x" - } - }, "csstype": { "version": "2.6.6", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.6.tgz", @@ -3938,30 +3760,6 @@ "assert-plus": "^1.0.0" } }, - "data-urls": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", - "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "whatwg-mimetype": "^2.2.0", - "whatwg-url": "^7.0.0" - }, - "dependencies": { - "whatwg-url": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", - "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - } - } - }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -4089,46 +3887,6 @@ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, - "del": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", - "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "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" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -4169,16 +3927,10 @@ "repeating": "^2.0.0" } }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true - }, "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", + "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", "dev": true }, "diffie-hellman": { @@ -4193,9 +3945,9 @@ } }, "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "requires": { "esutils": "^2.0.2" @@ -4237,15 +3989,6 @@ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, - "domexception": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", - "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", - "dev": true, - "requires": { - "webidl-conversions": "^4.0.2" - } - }, "domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", @@ -4367,6 +4110,7 @@ "version": "0.1.12", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "dev": true, "requires": { "iconv-lite": "~0.4.13" } @@ -4509,83 +4253,60 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "escodegen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", - "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", - "dev": true, - "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - } - } - }, "eslint": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.7.1.tgz", - "integrity": "sha1-hJgEE2lT6+NmeC+fhhHiy9G1RoE=", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", "dev": true, "requires": { - "ajv": "^5.2.0", - "babel-code-frame": "^6.22.0", + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.0.1", - "doctrine": "^2.0.0", - "eslint-scope": "^3.7.1", - "espree": "^3.5.1", - "esquery": "^1.0.0", - "estraverse": "^4.2.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", + "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", "glob": "^7.1.2", - "globals": "^9.17.0", - "ignore": "^3.3.3", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", - "json-stable-stringify": "^1.0.1", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", "optionator": "^0.8.2", "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", "progress": "^2.0.0", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "^4.0.1", - "text-table": "~0.2.0" + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" }, "dependencies": { "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "dev": true, "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", + "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, "ansi-regex": { @@ -4615,20 +4336,36 @@ } }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" } }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, "glob": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", @@ -4643,6 +4380,12 @@ "path-is-absolute": "^1.0.0" } }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -4659,6 +4402,12 @@ "esprima": "^4.0.0" } }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -4712,36 +4461,78 @@ } }, "eslint-plugin-json": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-json/-/eslint-plugin-json-1.2.0.tgz", - "integrity": "sha1-m6c7sL6Z1QCT6In1uWhGPSow764=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-json/-/eslint-plugin-json-1.4.0.tgz", + "integrity": "sha512-CECvgRAWtUzuepdlPWd+VA7fhyF9HT183pZnl8wQw5x699Mk/MbME/q8xtULBfooi3LUbj6fToieNmsvUcDxWA==", "dev": true, "requires": { - "jshint": "^2.8.0" + "vscode-json-languageservice": "^3.2.1" } }, "eslint-plugin-react": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.4.0.tgz", - "integrity": "sha512-tvjU9u3VqmW2vVuYnE8Qptq+6ji4JltjOjJ9u7VAOxVYkUkyBZWRvNYKbDv5fN+L6wiA+4we9+qQahZ0m63XEA==", + "version": "7.14.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.14.2.tgz", + "integrity": "sha512-jZdnKe3ip7FQOdjxks9XPN0pjUKZYq48OggNMd16Sk+8VXx6JOvXmlElxROCgp7tiUsTsze3jd78s/9AFJP2mA==", "dev": true, "requires": { - "doctrine": "^2.0.0", - "has": "^1.0.1", - "jsx-ast-utils": "^2.0.0", - "prop-types": "^15.5.10" + "array-includes": "^3.0.3", + "doctrine": "^2.1.0", + "has": "^1.0.3", + "jsx-ast-utils": "^2.1.0", + "object.entries": "^1.1.0", + "object.fromentries": "^2.0.0", + "object.values": "^1.1.0", + "prop-types": "^15.7.2", + "resolve": "^1.10.1" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } } }, "eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" } }, + "eslint-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.0.tgz", + "integrity": "sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.0.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, "esm": { "version": "3.2.25", "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", @@ -4754,29 +4545,24 @@ "integrity": "sha1-Yg2GbvSGGzMR91dm1SqFcrs8YzY=" }, "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", "dev": true, "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" }, "dependencies": { "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz", + "integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==", "dev": true } } }, - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - }, "esprima-fb": { "version": "3001.1.0-dev-harmony-fb", "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz", @@ -4884,17 +4670,12 @@ "integrity": "sha1-ODXxJ6vwdb/ggtCu1EhAV8eOPIk=", "dev": true }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true - }, "expand-brackets": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, + "optional": true, "requires": { "is-posix-bracket": "^0.1.0" } @@ -4904,35 +4685,11 @@ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, + "optional": true, "requires": { "fill-range": "^2.1.0" } }, - "expect": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-23.6.0.tgz", - "integrity": "sha512-dgSoOHgmtn/aDGRVFWclQyPDKl2CQRq0hmIEoUAuQs/2rn2NcvCWcSCovm6BLeuB/7EZuLGu2QfnR+qRt5OM4w==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "jest-diff": "^23.6.0", - "jest-get-type": "^22.1.0", - "jest-matcher-utils": "^23.6.0", - "jest-message-util": "^23.4.0", - "jest-regex-util": "^23.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - } - } - }, "express": { "version": "4.16.1", "resolved": "https://registry.npmjs.org/express/-/express-4.16.1.tgz", @@ -5042,14 +4799,25 @@ } }, "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", "tmp": "^0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } } }, "extglob": { @@ -5057,39 +4825,11 @@ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, + "optional": true, "requires": { "is-extglob": "^1.0.0" } }, - "extract-zip": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", - "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", - "dev": true, - "requires": { - "concat-stream": "1.6.2", - "debug": "2.6.9", - "mkdirp": "0.5.1", - "yauzl": "2.4.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -5195,19 +4935,11 @@ "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", "dev": true }, - "fb-watchman": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", - "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", - "dev": true, - "requires": { - "bser": "^2.0.0" - } - }, "fbjs": { "version": "0.8.17", "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", "integrity": "sha1-xNWY6taUkRJlPWWIsBpc3Nn5D90=", + "dev": true, "requires": { "core-js": "^1.0.0", "isomorphic-fetch": "^2.1.1", @@ -5221,19 +4953,11 @@ "core-js": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true } } }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -5244,13 +4968,12 @@ } }, "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", "dev": true, "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" + "flat-cache": "^2.0.1" } }, "file-loader": { @@ -5267,39 +4990,15 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fileset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", - "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", "dev": true, - "requires": { - "glob": "^7.0.3", - "minimatch": "^3.0.3" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "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" - } - } - } + "optional": true }, "fill-range": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", "dev": true, + "optional": true, "requires": { "is-number": "^2.1.0", "isobject": "^2.0.0", @@ -5364,15 +5063,14 @@ "dev": true }, "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", "dev": true, "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" }, "dependencies": { "glob": { @@ -5400,6 +5098,12 @@ } } }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, "flatten": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", @@ -5442,6 +5146,7 @@ "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, + "optional": true, "requires": { "for-in": "^1.0.1" } @@ -5590,7 +5295,8 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "fsevents": { "version": "1.2.9", @@ -5612,7 +5318,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -5633,12 +5340,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5653,17 +5362,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -5780,7 +5492,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -5792,6 +5505,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5806,6 +5520,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5813,12 +5528,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5837,6 +5554,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -5917,7 +5635,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -5929,6 +5648,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -6014,7 +5734,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6050,6 +5771,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6069,6 +5791,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6112,12 +5835,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -6269,6 +5994,7 @@ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, + "optional": true, "requires": { "glob-parent": "^2.0.0", "is-glob": "^2.0.0" @@ -6279,6 +6005,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, + "optional": true, "requires": { "is-glob": "^2.0.0" } @@ -6298,41 +6025,6 @@ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", "dev": true }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "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" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, "globule": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", @@ -6384,12 +6076,6 @@ "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", "dev": true }, - "growly": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", - "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", - "dev": true - }, "gud": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", @@ -6648,15 +6334,6 @@ "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", "dev": true }, - "html-encoding-sniffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", - "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.1" - } - }, "html-minifier": { "version": "2.1.7", "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-2.1.7.tgz", @@ -6841,9 +6518,9 @@ "dev": true }, "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, "immediate": { @@ -6851,6 +6528,16 @@ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" }, + "import-fresh": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, "import-jsx": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-jsx/-/import-jsx-2.0.0.tgz", @@ -6936,16 +6623,6 @@ } } }, - "import-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", - "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", - "dev": true, - "requires": { - "pkg-dir": "^2.0.0", - "resolve-cwd": "^2.0.0" - } - }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -7108,31 +6785,30 @@ } }, "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.0.tgz", + "integrity": "sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", - "external-editor": "^2.0.4", + "external-editor": "^3.0.3", "figures": "^2.0.0", - "lodash": "^4.3.0", + "lodash": "^4.17.12", "mute-stream": "0.0.7", "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", + "rxjs": "^6.4.0", "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", + "strip-ansi": "^5.1.0", "through": "^2.3.6" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "ansi-styles": { @@ -7162,12 +6838,12 @@ "dev": true }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^4.1.0" } }, "supports-color": { @@ -7249,12 +6925,6 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, - "ip-regex": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", - "dev": true - }, "ipaddr.js": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", @@ -7293,7 +6963,8 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true }, "is-callable": { "version": "1.1.4", @@ -7352,13 +7023,15 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true + "dev": true, + "optional": true }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, + "optional": true, "requires": { "is-primitive": "^2.0.0" } @@ -7373,7 +7046,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "dev": true, + "optional": true }, "is-finite": { "version": "1.0.2", @@ -7395,17 +7069,12 @@ "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" }, - "is-generator-fn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-1.0.0.tgz", - "integrity": "sha1-lp1J4bszKfa7fwkIm+JleLLd1Go=", - "dev": true - }, "is-glob": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, + "optional": true, "requires": { "is-extglob": "^1.0.0" } @@ -7424,34 +7093,11 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, + "optional": true, "requires": { "kind-of": "^3.0.2" } }, - "is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", - "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", - "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -7479,13 +7125,15 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true + "dev": true, + "optional": true }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true + "dev": true, + "optional": true }, "is-promise": { "version": "2.1.0", @@ -7501,16 +7149,11 @@ "has": "^1.0.1" } }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true }, "is-svg": { "version": "2.1.0", @@ -7543,12 +7186,6 @@ "upper-case": "^1.1.0" } }, - "is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "dev": true - }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -7561,23 +7198,6 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - }, - "is2": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.1.tgz", - "integrity": "sha512-+WaJvnaA7aJySz2q/8sLjMb2Mw14KTplHmSwcSpZ/fWJPkUmqw3YTzSWbPJ7OAwRvdYTWF2Wg+yYJ1AdP5Z8CA==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "ip-regex": "^2.1.0", - "is-url": "^1.2.2" - } - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -7606,6 +7226,7 @@ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, + "optional": true, "requires": { "isarray": "1.0.0" } @@ -7614,6 +7235,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "dev": true, "requires": { "node-fetch": "^1.0.1", "whatwg-fetch": ">=0.10.0" @@ -7624,162 +7246,6 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, - "istanbul-api": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", - "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", - "dev": true, - "requires": { - "async": "^2.1.4", - "fileset": "^2.0.2", - "istanbul-lib-coverage": "^1.2.1", - "istanbul-lib-hook": "^1.2.2", - "istanbul-lib-instrument": "^1.10.2", - "istanbul-lib-report": "^1.1.5", - "istanbul-lib-source-maps": "^1.2.6", - "istanbul-reports": "^1.5.1", - "js-yaml": "^3.7.0", - "mkdirp": "^0.5.1", - "once": "^1.4.0" - }, - "dependencies": { - "append-transform": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", - "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true, - "requires": { - "default-require-extensions": "^1.0.0" - } - }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "default-require-extensions": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", - "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", - "dev": true, - "requires": { - "strip-bom": "^2.0.0" - } - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "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" - } - }, - "istanbul-lib-coverage": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", - "dev": true - }, - "istanbul-lib-hook": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", - "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", - "dev": true, - "requires": { - "append-transform": "^0.4.0" - } - }, - "istanbul-lib-instrument": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", - "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true, - "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.1", - "semver": "^5.3.0" - } - }, - "istanbul-lib-report": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", - "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^1.2.1", - "mkdirp": "^0.5.1", - "path-parse": "^1.0.5", - "supports-color": "^3.1.2" - } - }, - "istanbul-lib-source-maps": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", - "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^1.2.1", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" - } - }, - "istanbul-reports": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", - "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", - "dev": true, - "requires": { - "handlebars": "^4.0.3" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, "istanbul-lib-coverage": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", @@ -8022,1249 +7488,6 @@ } } }, - "jest": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-23.6.0.tgz", - "integrity": "sha512-lWzcd+HSiqeuxyhG+EnZds6iO3Y3ZEnMrfZq/OTGvF/C+Z4fPMCdhWTGSAiO2Oym9rbEXfwddHhh6jqrTF3+Lw==", - "dev": true, - "requires": { - "import-local": "^1.0.0", - "jest-cli": "^23.6.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "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" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, - "istanbul-lib-coverage": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", - "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", - "dev": true, - "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.1", - "semver": "^5.3.0" - } - }, - "istanbul-lib-source-maps": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", - "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", - "dev": true, - "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^1.2.1", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" - } - }, - "jest-cli": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-23.6.0.tgz", - "integrity": "sha512-hgeD1zRUp1E1zsiyOXjEn4LzRLWdJBV//ukAHGlx6s5mfCNJTbhbHjgxnDUXA8fsKWN/HqFFF6X5XcCwC/IvYQ==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "import-local": "^1.0.0", - "is-ci": "^1.0.10", - "istanbul-api": "^1.3.1", - "istanbul-lib-coverage": "^1.2.0", - "istanbul-lib-instrument": "^1.10.1", - "istanbul-lib-source-maps": "^1.2.4", - "jest-changed-files": "^23.4.2", - "jest-config": "^23.6.0", - "jest-environment-jsdom": "^23.4.0", - "jest-get-type": "^22.1.0", - "jest-haste-map": "^23.6.0", - "jest-message-util": "^23.4.0", - "jest-regex-util": "^23.3.0", - "jest-resolve-dependencies": "^23.6.0", - "jest-runner": "^23.6.0", - "jest-runtime": "^23.6.0", - "jest-snapshot": "^23.6.0", - "jest-util": "^23.4.0", - "jest-validate": "^23.6.0", - "jest-watcher": "^23.4.0", - "jest-worker": "^23.2.0", - "micromatch": "^2.3.11", - "node-notifier": "^5.2.1", - "prompts": "^0.1.9", - "realpath-native": "^1.0.0", - "rimraf": "^2.5.4", - "slash": "^1.0.0", - "string-length": "^2.0.0", - "strip-ansi": "^4.0.0", - "which": "^1.2.12", - "yargs": "^11.0.0" - } - }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "yargs": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", - "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" - } - }, - "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - } - } - } - }, - "jest-changed-files": { - "version": "23.4.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-23.4.2.tgz", - "integrity": "sha512-EyNhTAUWEfwnK0Is/09LxoqNDOn7mU7S3EHskG52djOFS/z+IT0jT3h3Ql61+dklcG7bJJitIWEMB4Sp1piHmA==", - "dev": true, - "requires": { - "throat": "^4.0.0" - } - }, - "jest-config": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-23.6.0.tgz", - "integrity": "sha512-i8V7z9BeDXab1+VNo78WM0AtWpBRXJLnkT+lyT+Slx/cbP5sZJ0+NDuLcmBE5hXAoK0aUp7vI+MOxR+R4d8SRQ==", - "dev": true, - "requires": { - "babel-core": "^6.0.0", - "babel-jest": "^23.6.0", - "chalk": "^2.0.1", - "glob": "^7.1.1", - "jest-environment-jsdom": "^23.4.0", - "jest-environment-node": "^23.4.0", - "jest-get-type": "^22.1.0", - "jest-jasmine2": "^23.6.0", - "jest-regex-util": "^23.3.0", - "jest-resolve": "^23.6.0", - "jest-util": "^23.4.0", - "jest-validate": "^23.6.0", - "micromatch": "^2.3.11", - "pretty-format": "^23.6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "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" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-diff": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-23.6.0.tgz", - "integrity": "sha512-Gz9l5Ov+X3aL5L37IT+8hoCUsof1CVYBb2QEkOupK64XyRR3h+uRpYIm97K7sY8diFxowR8pIGEdyfMKTixo3g==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "diff": "^3.2.0", - "jest-get-type": "^22.1.0", - "pretty-format": "^23.6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-docblock": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-23.2.0.tgz", - "integrity": "sha1-8IXh8YVI2Z/dabICB+b9VdkTg6c=", - "dev": true, - "requires": { - "detect-newline": "^2.1.0" - } - }, - "jest-each": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-23.6.0.tgz", - "integrity": "sha512-x7V6M/WGJo6/kLoissORuvLIeAoyo2YqLOoCDkohgJ4XOXSqOtyvr8FbInlAWS77ojBsZrafbozWoKVRdtxFCg==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "pretty-format": "^23.6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-environment-jsdom": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-23.4.0.tgz", - "integrity": "sha1-BWp5UrP+pROsYqFAosNox52eYCM=", - "dev": true, - "requires": { - "jest-mock": "^23.2.0", - "jest-util": "^23.4.0", - "jsdom": "^11.5.1" - } - }, - "jest-environment-node": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-23.4.0.tgz", - "integrity": "sha1-V+gO0IQd6jAxZ8zozXlSHeuv3hA=", - "dev": true, - "requires": { - "jest-mock": "^23.2.0", - "jest-util": "^23.4.0" - } - }, - "jest-get-type": { - "version": "22.4.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-22.4.3.tgz", - "integrity": "sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w==", - "dev": true - }, - "jest-haste-map": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-23.6.0.tgz", - "integrity": "sha512-uyNhMyl6dr6HaXGHp8VF7cK6KpC6G9z9LiMNsst+rJIZ8l7wY0tk8qwjPmEghczojZ2/ZhtEdIabZ0OQRJSGGg==", - "dev": true, - "requires": { - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.1.11", - "invariant": "^2.2.4", - "jest-docblock": "^23.2.0", - "jest-serializer": "^23.0.1", - "jest-worker": "^23.2.0", - "micromatch": "^2.3.11", - "sane": "^2.0.0" - } - }, - "jest-jasmine2": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-23.6.0.tgz", - "integrity": "sha512-pe2Ytgs1nyCs8IvsEJRiRTPC0eVYd8L/dXJGU08GFuBwZ4sYH/lmFDdOL3ZmvJR8QKqV9MFuwlsAi/EWkFUbsQ==", - "dev": true, - "requires": { - "babel-traverse": "^6.0.0", - "chalk": "^2.0.1", - "co": "^4.6.0", - "expect": "^23.6.0", - "is-generator-fn": "^1.0.0", - "jest-diff": "^23.6.0", - "jest-each": "^23.6.0", - "jest-matcher-utils": "^23.6.0", - "jest-message-util": "^23.4.0", - "jest-snapshot": "^23.6.0", - "jest-util": "^23.4.0", - "pretty-format": "^23.6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-leak-detector": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-23.6.0.tgz", - "integrity": "sha512-f/8zA04rsl1Nzj10HIyEsXvYlMpMPcy0QkQilVZDFOaPbv2ur71X5u2+C4ZQJGyV/xvVXtCCZ3wQ99IgQxftCg==", - "dev": true, - "requires": { - "pretty-format": "^23.6.0" - } - }, - "jest-matcher-utils": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-23.6.0.tgz", - "integrity": "sha512-rosyCHQfBcol4NsckTn01cdelzWLU9Cq7aaigDf8VwwpIRvWE/9zLgX2bON+FkEW69/0UuYslUe22SOdEf2nog==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "jest-get-type": "^22.1.0", - "pretty-format": "^23.6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-message-util": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-23.4.0.tgz", - "integrity": "sha1-F2EMUJQjSVCNAaPR4L2iwHkIap8=", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0-beta.35", - "chalk": "^2.0.1", - "micromatch": "^2.3.11", - "slash": "^1.0.0", - "stack-utils": "^1.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-mock": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-23.2.0.tgz", - "integrity": "sha1-rRxg8p6HGdR8JuETgJi20YsmETQ=", - "dev": true - }, - "jest-regex-util": { - "version": "23.3.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-23.3.0.tgz", - "integrity": "sha1-X4ZylUfCeFxAAs6qj4Sf6MpHG8U=", - "dev": true - }, - "jest-resolve": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-23.6.0.tgz", - "integrity": "sha512-XyoRxNtO7YGpQDmtQCmZjum1MljDqUCob7XlZ6jy9gsMugHdN2hY4+Acz9Qvjz2mSsOnPSH7skBmDYCHXVZqkA==", - "dev": true, - "requires": { - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "realpath-native": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-resolve-dependencies": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-23.6.0.tgz", - "integrity": "sha512-EkQWkFWjGKwRtRyIwRwI6rtPAEyPWlUC2MpzHissYnzJeHcyCn1Hc8j7Nn1xUVrS5C6W5+ZL37XTem4D4pLZdA==", - "dev": true, - "requires": { - "jest-regex-util": "^23.3.0", - "jest-snapshot": "^23.6.0" - } - }, - "jest-runner": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-23.6.0.tgz", - "integrity": "sha512-kw0+uj710dzSJKU6ygri851CObtCD9cN8aNkg8jWJf4ewFyEa6kwmiH/r/M1Ec5IL/6VFa0wnAk6w+gzUtjJzA==", - "dev": true, - "requires": { - "exit": "^0.1.2", - "graceful-fs": "^4.1.11", - "jest-config": "^23.6.0", - "jest-docblock": "^23.2.0", - "jest-haste-map": "^23.6.0", - "jest-jasmine2": "^23.6.0", - "jest-leak-detector": "^23.6.0", - "jest-message-util": "^23.4.0", - "jest-runtime": "^23.6.0", - "jest-util": "^23.4.0", - "jest-worker": "^23.2.0", - "source-map-support": "^0.5.6", - "throat": "^4.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } - } - }, - "jest-runtime": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-23.6.0.tgz", - "integrity": "sha512-ycnLTNPT2Gv+TRhnAYAQ0B3SryEXhhRj1kA6hBPSeZaNQkJ7GbZsxOLUkwg6YmvWGdX3BB3PYKFLDQCAE1zNOw==", - "dev": true, - "requires": { - "babel-core": "^6.0.0", - "babel-plugin-istanbul": "^4.1.6", - "chalk": "^2.0.1", - "convert-source-map": "^1.4.0", - "exit": "^0.1.2", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.1.11", - "jest-config": "^23.6.0", - "jest-haste-map": "^23.6.0", - "jest-message-util": "^23.4.0", - "jest-regex-util": "^23.3.0", - "jest-resolve": "^23.6.0", - "jest-snapshot": "^23.6.0", - "jest-util": "^23.4.0", - "jest-validate": "^23.6.0", - "micromatch": "^2.3.11", - "realpath-native": "^1.0.0", - "slash": "^1.0.0", - "strip-bom": "3.0.0", - "write-file-atomic": "^2.1.0", - "yargs": "^11.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", - "dev": true, - "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "yargs": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", - "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" - } - }, - "yargs-parser": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - } - } - } - }, - "jest-serializer": { - "version": "23.0.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-23.0.1.tgz", - "integrity": "sha1-o3dq6zEekP6D+rnlM+hRAr0WQWU=", - "dev": true - }, - "jest-snapshot": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-23.6.0.tgz", - "integrity": "sha512-tM7/Bprftun6Cvj2Awh/ikS7zV3pVwjRYU2qNYS51VZHgaAMBs5l4o/69AiDHhQrj5+LA2Lq4VIvK7zYk/bswg==", - "dev": true, - "requires": { - "babel-types": "^6.0.0", - "chalk": "^2.0.1", - "jest-diff": "^23.6.0", - "jest-matcher-utils": "^23.6.0", - "jest-message-util": "^23.4.0", - "jest-resolve": "^23.6.0", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^23.6.0", - "semver": "^5.5.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-util": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-23.4.0.tgz", - "integrity": "sha1-TQY8uSe68KI4Mf9hvsLLv0l5NWE=", - "dev": true, - "requires": { - "callsites": "^2.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.11", - "is-ci": "^1.0.10", - "jest-message-util": "^23.4.0", - "mkdirp": "^0.5.1", - "slash": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-validate": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-23.6.0.tgz", - "integrity": "sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "jest-get-type": "^22.1.0", - "leven": "^2.1.0", - "pretty-format": "^23.6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-watcher": { - "version": "23.4.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-23.4.0.tgz", - "integrity": "sha1-0uKM50+NrWxq/JIrksq+9u0FyRw=", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "string-length": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jest-worker": { - "version": "23.2.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-23.2.0.tgz", - "integrity": "sha1-+vcGqNo2+uYOsmlXJX+ntdjqArk=", - "dev": true, - "requires": { - "merge-stream": "^1.0.1" - } - }, "joi": { "version": "6.10.1", "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", @@ -9322,130 +7545,12 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, - "jsdom": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", - "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "acorn": "^5.5.3", - "acorn-globals": "^4.1.0", - "array-equal": "^1.0.0", - "cssom": ">= 0.3.2 < 0.4.0", - "cssstyle": "^1.0.0", - "data-urls": "^1.0.0", - "domexception": "^1.0.1", - "escodegen": "^1.9.1", - "html-encoding-sniffer": "^1.0.2", - "left-pad": "^1.3.0", - "nwsapi": "^2.0.7", - "parse5": "4.0.0", - "pn": "^1.1.0", - "request": "^2.87.0", - "request-promise-native": "^1.0.5", - "sax": "^1.2.4", - "symbol-tree": "^3.2.2", - "tough-cookie": "^2.3.4", - "w3c-hr-time": "^1.0.1", - "webidl-conversions": "^4.0.2", - "whatwg-encoding": "^1.0.3", - "whatwg-mimetype": "^2.1.0", - "whatwg-url": "^6.4.1", - "ws": "^5.2.0", - "xml-name-validator": "^3.0.0" - }, - "dependencies": { - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true - } - } - }, "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true }, - "jshint": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.10.2.tgz", - "integrity": "sha512-e7KZgCSXMJxznE/4WULzybCMNXNAd/bf5TSrvVEq78Q/K8ZwFpmBqQeDtNiHc3l49nV4E/+YeHU/JZjSUIrLAA==", - "dev": true, - "requires": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "~4.17.11", - "minimatch": "~3.0.2", - "shelljs": "0.3.x", - "strip-json-comments": "1.0.x" - }, - "dependencies": { - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", - "dev": true, - "requires": { - "domelementtype": "1" - } - }, - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", - "dev": true - }, - "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", - "dev": true, - "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", - "dev": true - } - } - }, "json-loader": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.2.tgz", @@ -9477,6 +7582,12 @@ "jsonify": "~0.0.0" } }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -9560,6 +7671,12 @@ } } }, + "jsonc-parser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.1.0.tgz", + "integrity": "sha512-n9GrT8rrr2fhvBbANa1g+xFmgGK5X91KFeDwlKQ3+SJfmH5+tKv/M/kahx/TXOMflfWHKGKqKyfHQaLKTNzJ6w==", + "dev": true + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -9645,12 +7762,6 @@ "is-buffer": "^1.1.5" } }, - "kleur": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-2.0.2.tgz", - "integrity": "sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==", - "dev": true - }, "lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -9672,18 +7783,6 @@ "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", "dev": true }, - "left-pad": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", - "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", - "dev": true - }, - "leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", - "dev": true - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -9931,57 +8030,6 @@ "requires": { "lodash._basefor": "^3.0.0", "lodash.keysin": "^3.0.0" - }, - "dependencies": { - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==" - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "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" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "requires": { - "has-flag": "^2.0.0" - } - } } }, "lodash._root": { @@ -10187,12 +8235,6 @@ "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", "dev": true }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, "lodash.tail": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", @@ -10384,7 +8426,8 @@ "lower-case": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=" + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true }, "lower-case-first": { "version": "1.0.2", @@ -10428,15 +8471,6 @@ "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", "dev": true }, - "makeerror": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", - "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", - "dev": true, - "requires": { - "tmpl": "1.0.x" - } - }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -10486,7 +8520,8 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", - "dev": true + "dev": true, + "optional": true }, "md5.js": { "version": "1.3.5", @@ -10595,15 +8630,6 @@ } } }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -10620,6 +8646,7 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, + "optional": true, "requires": { "arr-diff": "^2.0.0", "array-unique": "^0.2.1", @@ -10710,8 +8737,7 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "minipass": { "version": "2.3.5", @@ -10780,7 +8806,6 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" } @@ -10824,12 +8849,6 @@ "ms": "2.0.0" } }, - "diff": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz", - "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==", - "dev": true - }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -10885,11 +8904,13 @@ }, "mv": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", "optional": true, "requires": { - "no-case": "^2.2.0" + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" } }, "nan": { @@ -10951,6 +8972,12 @@ "xml-char-classes": "^1.0.0" } }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", + "optional": true + }, "ndjson": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-1.5.0.tgz", @@ -11206,6 +9233,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, "requires": { "lower-case": "^1.1.1" } @@ -11223,6 +9251,7 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "dev": true, "requires": { "encoding": "^0.1.11", "is-stream": "^1.0.1" @@ -11279,12 +9308,6 @@ } } }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true - }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -11377,19 +9400,6 @@ "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", "dev": true }, - "node-notifier": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.0.tgz", - "integrity": "sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ==", - "dev": true, - "requires": { - "growly": "^1.3.0", - "is-wsl": "^1.1.0", - "semver": "^5.5.0", - "shellwords": "^0.1.1", - "which": "^1.3.0" - } - }, "node-sass": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.6.1.tgz", @@ -11468,6 +9478,7 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, + "optional": true, "requires": { "remove-trailing-separator": "^1.0.1" } @@ -11529,12 +9540,7 @@ "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "nwsapi": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", - "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "nyc": { @@ -11898,14 +9904,28 @@ "object-keys": "^1.0.11" } }, - "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.fromentries": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz", + "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==", "dev": true, "requires": { "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" + "es-abstract": "^1.11.0", + "function-bind": "^1.1.1", + "has": "^1.0.1" } }, "object.omit": { @@ -11913,6 +9933,7 @@ "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, + "optional": true, "requires": { "for-own": "^0.1.4", "is-extendable": "^0.1.1" @@ -11935,6 +9956,18 @@ } } }, + "object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -12102,12 +10135,6 @@ "p-limit": "^1.1.0" } }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - }, "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", @@ -12139,18 +10166,15 @@ "dev": true, "requires": { "no-case": "^2.2.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - } + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" } }, "parse-asn1": { @@ -12172,6 +10196,7 @@ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, + "optional": true, "requires": { "glob-base": "^0.3.0", "is-dotfile": "^1.0.0", @@ -12314,12 +10339,6 @@ "sha.js": "^2.4.8" } }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -12369,18 +10388,6 @@ "find-up": "^2.1.0" } }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true - }, - "pn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", - "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", - "dev": true - }, "po2icu": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/po2icu/-/po2icu-0.0.2.tgz", @@ -13147,7 +11154,8 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true + "dev": true, + "optional": true }, "pretty-error": { "version": "2.1.1", @@ -13159,33 +11167,6 @@ "utila": "~0.4" } }, - "pretty-format": { - "version": "23.6.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz", - "integrity": "sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - } - } - }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -13211,24 +11192,16 @@ "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "requires": { - "asap": "~2.0.3" - } - }, - "prompts": { - "version": "0.1.14", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-0.1.14.tgz", - "integrity": "sha512-rxkyiE9YH6zAz/rZpywySLKkpaj0NMVyNw1qhsubdbjjSgcayjTShDreZGlFMcGSu5sab3bAKPfFk78PB90+8w==", "dev": true, "requires": { - "kleur": "^2.0.1", - "sisteransi": "^0.1.1" + "asap": "~2.0.3" } }, "prop-types": { "version": "15.6.0", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz", "integrity": "sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY=", + "dev": true, "requires": { "fbjs": "^0.8.16", "loose-envify": "^1.3.1", @@ -13336,6 +11309,7 @@ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", "dev": true, + "optional": true, "requires": { "is-number": "^4.0.0", "kind-of": "^6.0.0", @@ -13346,13 +11320,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true + "dev": true, + "optional": true }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true + "dev": true, + "optional": true } } }, @@ -13463,6 +11439,18 @@ "object-assign": "^4.1.1", "prop-types": "^15.5.4", "react-side-effect": "^1.1.0" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + } } }, "react-intl": { @@ -13498,8 +11486,7 @@ "react-is": { "version": "16.8.6", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", - "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==", - "dev": true + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" }, "react-lifecycles-compat": { "version": "3.0.4", @@ -13994,15 +11981,6 @@ } } }, - "realpath-native": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", - "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", - "dev": true, - "requires": { - "util.promisify": "^1.0.0" - } - }, "recast": { "version": "0.10.43", "resolved": "https://registry.npmjs.org/recast/-/recast-0.10.43.tgz", @@ -14135,6 +12113,7 @@ "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", "dev": true, + "optional": true, "requires": { "is-equal-shallow": "^0.1.3" } @@ -14149,6 +12128,12 @@ "safe-regex": "^1.1.0" } }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, "regexpu-core": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", @@ -14277,26 +12262,6 @@ } } }, - "request-promise-core": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", - "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", - "dev": true, - "requires": { - "lodash": "^4.17.11" - } - }, - "request-promise-native": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", - "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", - "dev": true, - "requires": { - "request-promise-core": "1.1.2", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -14315,16 +12280,6 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } - }, "resolve": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", @@ -14334,27 +12289,10 @@ "path-parse": "^1.0.6" } }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, "resolve-url": { @@ -14389,24 +12327,21 @@ } }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", "requires": { - "glob": "^7.1.3" + "glob": "^6.0.1" }, "dependencies": { "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", "requires": { - "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "2 || 3", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } @@ -14423,12 +12358,6 @@ "inherits": "^2.0.1" } }, - "rsvp": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", - "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", - "dev": true - }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -14438,19 +12367,13 @@ "is-promise": "^2.1.0" } }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "rxjs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", + "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", "dev": true, "requires": { - "rx-lite": "*" + "tslib": "^1.9.0" } }, "safe-buffer": { @@ -14478,347 +12401,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "sane": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/sane/-/sane-2.5.2.tgz", - "integrity": "sha1-tNwYYcIbQn6SlQej51HiosuKs/o=", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "capture-exit": "^1.2.0", - "exec-sh": "^0.2.0", - "fb-watchman": "^2.0.0", - "fsevents": "^1.2.3", - "micromatch": "^3.1.4", - "minimist": "^1.1.1", - "walker": "~1.0.5", - "watch": "~0.18.0" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "watch": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/watch/-/watch-0.18.0.tgz", - "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=", - "dev": true, - "requires": { - "exec-sh": "^0.2.0", - "minimist": "^1.2.0" - } - } - } - }, "sass-graph": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", @@ -14963,9 +12545,9 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20190722181739", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190722181739.tgz", - "integrity": "sha512-lVSP9nmdH7LNM6Al4VgNycCmfj0YppcynhwnmIeVKk3rqfQE9op660T4+LFXqpv/bCRz8GUBLhN8XLgu8dYNNw==", + "version": "0.1.0-prerelease.20190717220516", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190717220516.tgz", + "integrity": "sha512-UBCotdotxBOsvPZLMo2BQIKaioWmbGziWPGN4SO2eYG+wUOqEnF8HMR8gT1heUa6EBcO0nlG/tvgjEVsPFJe0A==", "dev": true }, "scratch-l10n": { @@ -15036,52 +12618,6 @@ } } }, - "selenium-webdriver": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", - "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", - "dev": true, - "requires": { - "jszip": "^3.1.3", - "rimraf": "^2.5.4", - "tmp": "0.0.30", - "xml2js": "^0.4.17" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "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" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "tmp": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", - "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.1" - } - } - } - }, "semver": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", @@ -15176,7 +12712,8 @@ "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true }, "setprototypeof": { "version": "1.1.0", @@ -15242,18 +12779,6 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, - "shelljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", - "dev": true - }, - "shellwords": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", - "dev": true - }, "should": { "version": "13.2.3", "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", @@ -15314,12 +12839,6 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, - "sisteransi": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-0.1.1.tgz", - "integrity": "sha512-PmGOd02bM9YO5ifxpw36nrNMBTptEtfRl4qUYl9SndkolplkrZZOW7PGHjrZL53QvMVj9nQ+TKqUnRsw4tJa4g==", - "dev": true - }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -15723,12 +13242,6 @@ "readable-stream": "^2.0.1" } }, - "stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true - }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", @@ -15979,26 +13492,36 @@ "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=", "dev": true }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, "table": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", - "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.4.tgz", + "integrity": "sha512-IIfEAUx5QlODLblLrGTTLJA7Tk0iLSGBvgY8essPRVNGHAzThujww1YqHLs6h3HfTg55h++RzLHH5Xw/rfv+mg==", "dev": true, "requires": { - "ajv": "^6.0.1", - "ajv-keywords": "^3.0.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" }, "dependencies": { + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -16008,30 +13531,47 @@ "color-convert": "^1.9.0" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" } } } @@ -16379,33 +13919,6 @@ "integrity": "sha512-fAfA73uFtFGybWGt4+IYT6UPLYVZQ4NfsP+IXEZGY0vh8e2IF7LVKafcQNMRBLqP0wzEA65LM9Tqj+FSmO8GLw==", "dev": true }, - "tcp-port-used": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.1.tgz", - "integrity": "sha512-rwi5xJeU6utXoEIiMvVBMc9eJ2/ofzB+7nLOdnZuFTmNCLqRiQh2sMG9MqCxHU/69VC/Fwp5dV9306Qd54ll1Q==", - "dev": true, - "requires": { - "debug": "4.1.0", - "is2": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", - "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, "test-exclude": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", @@ -16558,12 +14071,6 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "throat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", - "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", - "dev": true - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -16630,12 +14137,6 @@ "os-tmpdir": "~1.0.2" } }, - "tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", - "dev": true - }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", @@ -16721,15 +14222,6 @@ } } }, - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, "transifex": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/transifex/-/transifex-1.6.6.tgz", @@ -16940,12 +14432,6 @@ "mime-types": "~2.1.24" } }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -16964,7 +14450,8 @@ "ua-parser-js": { "version": "0.7.20", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.20.tgz", - "integrity": "sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw==" + "integrity": "sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw==", + "dev": true }, "uglify-js": { "version": "2.6.4", @@ -17219,16 +14706,6 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, - "util.promisify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", - "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" - } - }, "utila": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", @@ -17297,31 +14774,35 @@ "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", "dev": true }, - "w3c-hr-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", - "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "vscode-json-languageservice": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.3.0.tgz", + "integrity": "sha512-upq1PhwDItazdtRJ/R7uU0Fgrf9iaYa1xLK4WFLExR0DgbPojd0YgMpfyknVyXGlxsg3fJQ0H7J++QeByXHh9w==", "dev": true, "requires": { - "browser-process-hrtime": "^0.1.2" - }, - "dependencies": { - "browser-process-hrtime": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", - "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", - "dev": true - } + "jsonc-parser": "^2.1.0", + "vscode-languageserver-types": "^3.15.0-next.2", + "vscode-nls": "^4.1.1", + "vscode-uri": "^2.0.1" } }, - "walker": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", - "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", - "dev": true, - "requires": { - "makeerror": "1.0.x" - } + "vscode-languageserver-types": { + "version": "3.15.0-next.2", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.2.tgz", + "integrity": "sha512-2JkrMWWUi2rlVLSo9OFR2PIGUzdiowEM8NgNYiwLKnXTjpwpjjIrJbNNxDik7Rv4oo9KtikcFQZKXbrKilL/MQ==", + "dev": true + }, + "vscode-nls": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-4.1.1.tgz", + "integrity": "sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A==", + "dev": true + }, + "vscode-uri": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-2.0.3.tgz", + "integrity": "sha512-4D3DI3F4uRy09WNtDGD93H9q034OHImxiIcSq664Hq1Y1AScehlP3qqZyTkX/RWxeu0MRMHGkrxYqm2qlDF/aw==", + "dev": true }, "warning": { "version": "4.0.3", @@ -17735,12 +15216,6 @@ } } }, - "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true - }, "webpack": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-2.7.0.tgz", @@ -18037,48 +15512,12 @@ } } }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, "whatwg-fetch": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", - "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==", "dev": true }, - "whatwg-url": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", - "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, "whet.extend": { "version": "0.9.9", "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", @@ -18168,9 +15607,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", "dev": true, "requires": { "mkdirp": "^0.5.1" @@ -18188,15 +15627,6 @@ "typedarray-to-buffer": "^3.1.5" } }, - "ws": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - }, "xhr": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.2.0.tgz", @@ -18224,28 +15654,6 @@ "integrity": "sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0=", "dev": true }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "dev": true, - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - } - }, - "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", - "dev": true - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -18307,15 +15715,6 @@ } } }, - "yauzl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", - "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", - "dev": true, - "requires": { - "fd-slicer": "~1.0.1" - } - }, "yn": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.0.tgz", diff --git a/package.json b/package.json index 15d64b1cd..0809be587 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "autoprefixer": "6.3.6", "babel-cli": "6.26.0", "babel-core": "6.23.1", - "babel-eslint": "8.0.2", + "babel-eslint": "10.0.2", "babel-loader": "7.1.0", "babel-plugin-transform-object-rest-spread": "6.26.0", "babel-preset-es2015": "6.22.0", @@ -71,11 +71,11 @@ "copy-webpack-plugin": "0.2.0", "create-react-class": "15.6.2", "css-loader": "0.23.1", - "eslint": "4.7.1", + "eslint": "5.16.0", "eslint-config-scratch": "5.0.0", "eslint-plugin-cypress": "^2.0.1", - "eslint-plugin-json": "1.2.0", - "eslint-plugin-react": "7.4.0", + "eslint-plugin-json": "1.4.0", + "eslint-plugin-react": "7.14.2", "exenv": "1.2.0", "fastly": "1.2.1", "file-loader": "4.0.0", From 87c1bc58581ed9b316a7a33b2947f8243e8fd472 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Sun, 21 Jul 2019 21:11:34 -0400 Subject: [PATCH 24/32] add noopener noreferrer to fix lint errors --- src/components/extension-landing/install-scratch-link.jsx | 1 + src/components/extension-landing/project-card.jsx | 1 + src/components/modal/ttt/modal.jsx | 2 ++ src/views/ideas/ideas.jsx | 1 + 4 files changed, 5 insertions(+) diff --git a/src/components/extension-landing/install-scratch-link.jsx b/src/components/extension-landing/install-scratch-link.jsx index d1c4c4919..b8186fbcf 100644 --- a/src/components/extension-landing/install-scratch-link.jsx +++ b/src/components/extension-landing/install-scratch-link.jsx @@ -31,6 +31,7 @@ const InstallScratchLink = ({ 'https://www.microsoft.com/store/productId/9N48XLLCZH0X' : 'https://itunes.apple.com/us/app/scratch-link/id1408863490' } + rel="noopener noreferrer" target="_blank" > (
diff --git a/src/components/modal/ttt/modal.jsx b/src/components/modal/ttt/modal.jsx index afe56cae8..e54bcb085 100644 --- a/src/components/modal/ttt/modal.jsx +++ b/src/components/modal/ttt/modal.jsx @@ -56,6 +56,7 @@ const TTTModal = props => (
@@ -72,6 +73,7 @@ const TTTModal = props => (
diff --git a/src/views/ideas/ideas.jsx b/src/views/ideas/ideas.jsx index 0269f919d..18f2c81c3 100644 --- a/src/views/ideas/ideas.jsx +++ b/src/views/ideas/ideas.jsx @@ -158,6 +158,7 @@ class Ideas extends React.Component { href={this.props.intl.formatMessage({ id: 'cards.scratch-cards-allLink' })} + rel="noopener noreferrer" target="_blank" >