From 88f07d6562d3655ace6040149c69c9662894823b Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Mon, 22 Jul 2019 17:22:07 -0400 Subject: [PATCH 01/67] Add first test to my-stuff.test.js --- test/integration/my-stuff.test.js | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 test/integration/my-stuff.test.js diff --git a/test/integration/my-stuff.test.js b/test/integration/my-stuff.test.js new file mode 100644 index 000000000..23f55b3d9 --- /dev/null +++ b/test/integration/my-stuff.test.js @@ -0,0 +1,50 @@ +const SeleniumHelper = require('./selenium-helpers.js'); + +const { + clickText, + findByXpath, + clickXpath, + clickButton, + buildDriver +} = new SeleniumHelper(); + +let username = process.env.SMOKE_USERNAME; +let password = process.env.SMOKE_PASSWORD; +let rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; +let url = rootUrl + '/users/' + username; + +let driver; + +describe('www-smoke my-stuff', () => { + beforeAll(() => { + driver = buildDriver('www-smoke my-stuff'); + }); + + beforeEach(() => { + 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')); + }); + + afterEach(() => { + return clickXpath('//span[@class="user-name dropdown-toggle"]') + .then(() => clickXpath('//li[@id="logout"] ')) + .then(() => findByXpath('//div[@class="title-banner intro-banner"]')); + }); + + afterAll(() => { + driver.quit(); + }); + + + test('Sign into Scratch using scratchr2 navbar', () => { + findByXpath('//li[contains(@class, "logged-in-user")' + + 'and contains(@class, "dropdown")]/span') + .then((element) => element.getText('span')) + .then((text) => expect(text.toLowerCase()).toEqual(username.toLowerCase())); + }); +}); From 8c385e3e4de9f2bd46926cd336f2571d55d33402 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Mon, 5 Aug 2019 13:34:30 -0400 Subject: [PATCH 02/67] Update chrome version for remote tests and chromedriver --- package.json | 2 +- test/integration-legacy/selenium-helpers.js | 2 +- test/integration/selenium-helpers.js | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 01ab42fda..ec73da9b2 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "babel-preset-react": "6.22.0", "bowser": "1.9.4", "cheerio": "1.0.0-rc.2", - "chromedriver": "75.1.0", + "chromedriver": "76.0.0", "classnames": "2.2.5", "cookie": "0.2.2", "copy-webpack-plugin": "0.2.0", diff --git a/test/integration-legacy/selenium-helpers.js b/test/integration-legacy/selenium-helpers.js index 710c00110..99e0b8ceb 100644 --- a/test/integration-legacy/selenium-helpers.js +++ b/test/integration-legacy/selenium-helpers.js @@ -68,7 +68,7 @@ class SeleniumHelper { let driverConfig = { browserName: 'chrome', platform: 'macOS 10.14', - version: '75.0' + version: '76.0' }; var driver = new webdriver.Builder() .withCapabilities({ diff --git a/test/integration/selenium-helpers.js b/test/integration/selenium-helpers.js index 2b2dfdfb0..99e0b8ceb 100644 --- a/test/integration/selenium-helpers.js +++ b/test/integration/selenium-helpers.js @@ -67,8 +67,8 @@ class SeleniumHelper { // https://wiki.saucelabs.com/display/DOCS/Platform+Configurator let driverConfig = { browserName: 'chrome', - platform: 'macOS 10.13', - version: '70.0' + platform: 'macOS 10.14', + version: '76.0' }; var driver = new webdriver.Builder() .withCapabilities({ From b2eabeddfc87b4eecd5a8f03a4b3de6b3d88260e Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Mon, 5 Aug 2019 13:36:57 -0400 Subject: [PATCH 03/67] Rename new integration tests to differentiate from old ones --- test/integration/my-stuff.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/my-stuff.test.js b/test/integration/my-stuff.test.js index 23f55b3d9..fb5a2d08c 100644 --- a/test/integration/my-stuff.test.js +++ b/test/integration/my-stuff.test.js @@ -15,9 +15,9 @@ let url = rootUrl + '/users/' + username; let driver; -describe('www-smoke my-stuff', () => { +describe('www-integration my-stuff', () => { beforeAll(() => { - driver = buildDriver('www-smoke my-stuff'); + driver = buildDriver('www-integration my-stuff'); }); beforeEach(() => { From 8213466c2c9994fe1b04dfc8d54f26fdce97a43f Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Mon, 5 Aug 2019 13:37:50 -0400 Subject: [PATCH 04/67] set up jest integration tests to run with saucelabs --- package.json | 1 + test/integration/my-stuff.test.js | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ec73da9b2..99d36e789 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "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:integration:jest:remote": "SMOKE_REMOTE=true 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", diff --git a/test/integration/my-stuff.test.js b/test/integration/my-stuff.test.js index fb5a2d08c..15060c087 100644 --- a/test/integration/my-stuff.test.js +++ b/test/integration/my-stuff.test.js @@ -10,9 +10,14 @@ const { let username = process.env.SMOKE_USERNAME; let password = process.env.SMOKE_PASSWORD; +let remote = process.env.SMOKE_REMOTE || false; let rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; let url = rootUrl + '/users/' + username; +if (remote){ + jest.setTimeout(60000); +} + let driver; describe('www-integration my-stuff', () => { @@ -36,8 +41,9 @@ describe('www-integration my-stuff', () => { .then(() => findByXpath('//div[@class="title-banner intro-banner"]')); }); - afterAll(() => { - driver.quit(); + // afterAll must be async in order to actually call driver.quit + afterAll(async () => { + await driver.quit(); }); From 7af2ee79c36cb199980f8e6881512079ba0d7ddd Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Tue, 13 Aug 2019 15:09:31 -0400 Subject: [PATCH 05/67] Move Sign In and Sign Out tests to Jest --- .../test_signing_in_and_out_discuss.js | 62 ----------- .../test_signing_in_and_out_homepage.js | 59 ----------- test/integration/sign-in-and-out.test.js | 100 ++++++++++++++++++ 3 files changed, 100 insertions(+), 121 deletions(-) delete mode 100644 test/integration-legacy/smoke-testing/test_signing_in_and_out_discuss.js delete mode 100644 test/integration-legacy/smoke-testing/test_signing_in_and_out_homepage.js create mode 100644 test/integration/sign-in-and-out.test.js 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 deleted file mode 100644 index e95426548..000000000 --- a/test/integration-legacy/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-legacy/smoke-testing/test_signing_in_and_out_homepage.js b/test/integration-legacy/smoke-testing/test_signing_in_and_out_homepage.js deleted file mode 100644 index 15687b0cf..000000000 --- a/test/integration-legacy/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/sign-in-and-out.test.js b/test/integration/sign-in-and-out.test.js new file mode 100644 index 000000000..7e2bdf974 --- /dev/null +++ b/test/integration/sign-in-and-out.test.js @@ -0,0 +1,100 @@ +const SeleniumHelper = require('./selenium-helpers.js'); + +const { + clickText, + findByXpath, + clickXpath, + clickButton, + buildDriver +} = new SeleniumHelper(); + +let username = process.env.SMOKE_USERNAME; +let password = process.env.SMOKE_PASSWORD; +let remote = process.env.SMOKE_REMOTE || false; +let rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; +let scratchr2url = rootUrl + '/users/' + username; +let wwwURL = rootUrl; + +if (remote){ + jest.setTimeout(60000); +} + +let driver; + +describe('www-integration sign-in-and-out', () => { + beforeAll(async () => { + driver = await buildDriver('www-integration sign-in-out'); + }); + + describe('sign in', () => { + afterEach(async () => { + await driver.get(wwwURL); + await clickXpath('//div[@class="account-nav"]'); + await clickText('Sign out'); + }); + + test('sign in on www', async () => { + await driver.get(wwwURL); + await driver.sleep(1000); + await clickXpath('//li[@class="link right login-item"]/a'); + let name = await findByXpath('//input[@id="frc-username-1088"]'); + await name.sendKeys(username); + let word = await findByXpath('//input[@id="frc-password-1088"]'); + await word.sendKeys(password); + await clickXpath('//button[contains(@class, "button") and ' + + 'contains(@class, "submit-button") and contains(@class, "white")]'); + let element = await findByXpath('//span[contains(@class, "profile-name")]'); + let text = await element.getText(); + await expect(text.toLowerCase()).toEqual(username.toLowerCase()); + }); + + test('sign in on scratchr2', async () => { + await driver.get(scratchr2url); + await clickXpath('//li[@class="sign-in dropdown"]/span'); + let name = await findByXpath('//input[@id="login_dropdown_username"]'); + await name.sendKeys(username); + let word = await findByXpath('//input[@name="password"]'); + await word.sendKeys(password); + await clickButton('Sign in'); + let element = await findByXpath('//span[@class="user-name dropdown-toggle"]'); + let text = await element.getText(); + await expect(text.toLowerCase()).toEqual(username.toLowerCase()); + }); + }); + + describe('sign out', () => { + beforeEach(async () => { + await driver.get(wwwURL); + await clickXpath('//li[@class="link right login-item"]'); + let name = await findByXpath('//input[@id="frc-username-1088"]'); + await name.sendKeys(username); + let word = await findByXpath('//input[@id="frc-password-1088"]'); + await word.sendKeys(password); + await clickXpath('//button[contains(@class, "button") and ' + + 'contains(@class, "submit-button") and contains(@class, "white")]'); + }); + + test('sign out on www', async () => { + await clickXpath('//a[contains(@class, "user-info")]'); + await clickText('Sign out'); + let element = await findByXpath('//li[@class="link right login-item"]/a/span'); + let text = await element.getText(); + await expect(text.toLowerCase()).toEqual('Sign In'.toLowerCase()); + }); + + test('sign out on scratchr2', async () => { + await driver.get(scratchr2url); + await clickXpath('//span[@class="user-name dropdown-toggle"]'); + await clickXpath('//li[@id="logout"]'); + let element = await findByXpath('//li[@class="link right login-item"]/a/span'); + let text = await element.getText(); + await expect(text.toLowerCase()).toEqual('Sign In'.toLowerCase()); + }); + + }); + + afterAll(async () => { + await driver.quit(); + }); + +}); From a86a97587662b23ff19047f6f173c8ae2951aa52 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Tue, 13 Aug 2019 15:10:29 -0400 Subject: [PATCH 06/67] Remove stub integration for Jest --- test/integration/test-integration.test.js | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 test/integration/test-integration.test.js diff --git a/test/integration/test-integration.test.js b/test/integration/test-integration.test.js deleted file mode 100644 index 44c96735d..000000000 --- a/test/integration/test-integration.test.js +++ /dev/null @@ -1,5 +0,0 @@ -describe('test jest integration', () => { - test('testing test', () => { - expect('integration').toEqual('integration'); - }); -}); From 303863fd42021814a232aa635e13b407cadf6745 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Tue, 13 Aug 2019 15:11:07 -0400 Subject: [PATCH 07/67] Remove first attempt at a my-stuff test in Jest --- test/integration/my-stuff.test.js | 56 ------------------------------- 1 file changed, 56 deletions(-) delete mode 100644 test/integration/my-stuff.test.js diff --git a/test/integration/my-stuff.test.js b/test/integration/my-stuff.test.js deleted file mode 100644 index 15060c087..000000000 --- a/test/integration/my-stuff.test.js +++ /dev/null @@ -1,56 +0,0 @@ -const SeleniumHelper = require('./selenium-helpers.js'); - -const { - clickText, - findByXpath, - clickXpath, - clickButton, - buildDriver -} = new SeleniumHelper(); - -let username = process.env.SMOKE_USERNAME; -let password = process.env.SMOKE_PASSWORD; -let remote = process.env.SMOKE_REMOTE || false; -let rootUrl = process.env.ROOT_URL || 'https://scratch.ly'; -let url = rootUrl + '/users/' + username; - -if (remote){ - jest.setTimeout(60000); -} - -let driver; - -describe('www-integration my-stuff', () => { - beforeAll(() => { - driver = buildDriver('www-integration my-stuff'); - }); - - beforeEach(() => { - 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')); - }); - - afterEach(() => { - return clickXpath('//span[@class="user-name dropdown-toggle"]') - .then(() => clickXpath('//li[@id="logout"] ')) - .then(() => findByXpath('//div[@class="title-banner intro-banner"]')); - }); - - // afterAll must be async in order to actually call driver.quit - afterAll(async () => { - await driver.quit(); - }); - - - test('Sign into Scratch using scratchr2 navbar', () => { - findByXpath('//li[contains(@class, "logged-in-user")' + - 'and contains(@class, "dropdown")]/span') - .then((element) => element.getText('span')) - .then((text) => expect(text.toLowerCase()).toEqual(username.toLowerCase())); - }); -}); From 5d8ca458599ad4360345a332be890d5b549974b6 Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Tue, 13 Aug 2019 15:14:52 -0400 Subject: [PATCH 08/67] Run Jest integration tests remotely --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 99d36e789..0d3a9e114 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "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:integration:remote": "npm run test:integration:jest:remote && npm run test:smoke:sauce", "test:integration:jest:remote": "SMOKE_REMOTE=true 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", From 697f5fdf3f7dd25d406a6585f2ce68c65f8cdcdf Mon Sep 17 00:00:00 2001 From: BryceLTaylor Date: Tue, 13 Aug 2019 15:18:42 -0400 Subject: [PATCH 09/67] Update package lock --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3ef93d031..4884b0b97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3245,9 +3245,9 @@ } }, "chromedriver": { - "version": "75.1.0", - "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-75.1.0.tgz", - "integrity": "sha512-N2P0fg6FS4c+tTG0R7cCOD5qiVo+E6uAz6xVjmbZesYv1xs1iGdcCUo0IqOY+ppD/4OOObG+XWV1CFWXT6UIgA==", + "version": "76.0.0", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-76.0.0.tgz", + "integrity": "sha512-jGyqs0N+lMo9iaNQxGKNPiLJWb2L9s2rwbRr1jJeQ37n6JQ1+5YMGviv/Fx5Z08vBWYbAvrKEzFsuYf8ppl+lw==", "dev": true, "requires": { "del": "^4.1.1", From 110ce59cc713824e82baa6d9048f2e2f93bf00b1 Mon Sep 17 00:00:00 2001 From: Benjamin Wheeler Date: Mon, 26 Aug 2019 15:41:32 -0400 Subject: [PATCH 10/67] Revert "Revert "on complete join flow, take user to new project"" --- src/components/navigation/www/navigation.jsx | 1 + src/components/registration/scratch3-registration.jsx | 9 +++++++-- src/redux/navigation.js | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/components/navigation/www/navigation.jsx b/src/components/navigation/www/navigation.jsx index 7bc3ca663..90d34bcad 100644 --- a/src/components/navigation/www/navigation.jsx +++ b/src/components/navigation/www/navigation.jsx @@ -217,6 +217,7 @@ class Navigation extends React.Component { {this.props.registrationOpen && ( this.props.useScratch3Registration ? ( diff --git a/src/components/registration/scratch3-registration.jsx b/src/components/registration/scratch3-registration.jsx index 03f53d763..c345c168e 100644 --- a/src/components/registration/scratch3-registration.jsx +++ b/src/components/registration/scratch3-registration.jsx @@ -23,17 +23,22 @@ const Registration = ({ ); Registration.propTypes = { + createProjectOnComplete: PropTypes.bool, handleCloseRegistration: PropTypes.func, handleCompleteRegistration: PropTypes.func, isOpen: PropTypes.bool }; -const mapDispatchToProps = dispatch => ({ +Registration.defaultProps = { + createProjectOnComplete: false +}; + +const mapDispatchToProps = (dispatch, ownProps) => ({ handleCloseRegistration: () => { dispatch(navigationActions.setRegistrationOpen(false)); }, handleCompleteRegistration: () => { - dispatch(navigationActions.handleCompleteRegistration()); + dispatch(navigationActions.handleCompleteRegistration(ownProps.createProjectOnComplete)); } }); diff --git a/src/redux/navigation.js b/src/redux/navigation.js index 0e71090ae..957f9d4e7 100644 --- a/src/redux/navigation.js +++ b/src/redux/navigation.js @@ -92,9 +92,10 @@ module.exports.setSearchTerm = searchTerm => ({ searchTerm: searchTerm }); -module.exports.handleCompleteRegistration = () => (dispatch => { +module.exports.handleCompleteRegistration = createProject => (dispatch => { dispatch(sessionActions.refreshSession()); dispatch(module.exports.setRegistrationOpen(false)); + if (createProject) window.location = '/projects/editor/?tutorial=getStarted'; }); module.exports.handleLogIn = (formData, callback) => (dispatch => { From 0ebc168f2167ba7c9bb6ece09ac9c8e936cf9047 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Mon, 26 Aug 2019 15:35:17 -0400 Subject: [PATCH 11/67] comment prop for eslint # Conflicts: # src/components/registration/scratch3-registration.jsx --- src/components/registration/scratch3-registration.jsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/registration/scratch3-registration.jsx b/src/components/registration/scratch3-registration.jsx index c345c168e..220c01433 100644 --- a/src/components/registration/scratch3-registration.jsx +++ b/src/components/registration/scratch3-registration.jsx @@ -23,16 +23,13 @@ const Registration = ({ ); Registration.propTypes = { - createProjectOnComplete: PropTypes.bool, + // used in mapDispatchToProps; eslint doesn't understand that this prop is used + createProjectOnComplete: PropTypes.bool, // eslint-disable-line react/no-unused-prop-types handleCloseRegistration: PropTypes.func, handleCompleteRegistration: PropTypes.func, isOpen: PropTypes.bool }; -Registration.defaultProps = { - createProjectOnComplete: false -}; - const mapDispatchToProps = (dispatch, ownProps) => ({ handleCloseRegistration: () => { dispatch(navigationActions.setRegistrationOpen(false)); From 65b6475ed67c3502c085f464790ff1bae07d1f8b Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Tue, 27 Aug 2019 12:15:49 -0400 Subject: [PATCH 12/67] smarter handling of handleCompleteRegistration --- src/redux/navigation.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/redux/navigation.js b/src/redux/navigation.js index 957f9d4e7..d8dd5ee31 100644 --- a/src/redux/navigation.js +++ b/src/redux/navigation.js @@ -93,9 +93,11 @@ module.exports.setSearchTerm = searchTerm => ({ }); module.exports.handleCompleteRegistration = createProject => (dispatch => { - dispatch(sessionActions.refreshSession()); - dispatch(module.exports.setRegistrationOpen(false)); - if (createProject) window.location = '/projects/editor/?tutorial=getStarted'; + if (createProject) { + window.location = '/projects/editor/?tutorial=getStarted'; + } else { + dispatch(module.exports.setRegistrationOpen(false)); + } }); module.exports.handleLogIn = (formData, callback) => (dispatch => { From 2a78723ce42f7b9ff20005f60125ce7ea279f924 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 28 Aug 2019 10:23:15 -0400 Subject: [PATCH 13/67] restyle next button to remove border, add hover color --- src/_colors.scss | 1 + src/components/join-flow/next-step-button.scss | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/_colors.scss b/src/_colors.scss index a963d81d2..0246a43a1 100644 --- a/src/_colors.scss +++ b/src/_colors.scss @@ -8,6 +8,7 @@ $ui-orange: hsla(38, 100, 55, 1); // #FFAB19 Control Primary $ui-orange-high-contrast: hsla(30, 100, 55, 1); // #FFAB19 Control Primary $ui-orange-10percent: hsla(35, 90, 55, .1); $ui-orange-25percent: hsla(35, 90, 55, .25); +$ui-orange-75percent: hsla(38, 100, 55, .75); $ui-dark-orange: hsla(30, 100, 55, 1); // ##FF8C1A Variables Primary diff --git a/src/components/join-flow/next-step-button.scss b/src/components/join-flow/next-step-button.scss index 2831adcbd..965b6f9a3 100644 --- a/src/components/join-flow/next-step-button.scss +++ b/src/components/join-flow/next-step-button.scss @@ -4,10 +4,15 @@ .modal-flush-bottom-button { margin: 0; width: 100%; + border: none; border-bottom-left-radius: 1rem; border-bottom-right-radius: 1rem; height: 5.1875rem; background-color: $ui-orange; + + &:hover { + background-color: $ui-orange-75percent; + } } .next-step-title { From 7422efd202411ecf26acda706d33f6fb0b337a97 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 28 Aug 2019 21:20:30 -0400 Subject: [PATCH 14/67] update to release version of GUI for 2019-08-28 --- package-lock.json | 292 ++++++++++++++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 190 insertions(+), 104 deletions(-) diff --git a/package-lock.json b/package-lock.json index ce4127ae2..9ebb2def4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3085,7 +3085,7 @@ }, "compression": { "version": "1.6.1", - "resolved": "http://registry.npmjs.org/compression/-/compression-1.6.1.tgz", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.6.1.tgz", "integrity": "sha1-G/T5b9cgGaP9EVE7T8Tc070W21U=", "requires": { "accepts": "~1.3.1", @@ -5011,7 +5011,7 @@ "dependencies": { "form-data": { "version": "0.0.3", - "bundled": true, + "resolved": false, "dev": true, "requires": { "async": "~0.1.9", @@ -5021,12 +5021,12 @@ "dependencies": { "async": { "version": "0.1.9", - "bundled": true, + "resolved": false, "dev": true }, "combined-stream": { "version": "0.0.3", - "bundled": true, + "resolved": false, "dev": true, "requires": { "delayed-stream": "0.0.5" @@ -5034,7 +5034,7 @@ "dependencies": { "delayed-stream": { "version": "0.0.5", - "bundled": true, + "resolved": false, "dev": true } } @@ -5043,7 +5043,7 @@ }, "mime": { "version": "1.2.7", - "bundled": true, + "resolved": false, "dev": true } } @@ -5473,25 +5473,29 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, "requires": { @@ -5501,13 +5505,15 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "bundled": true, + "resolved": false, + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "optional": true, "requires": { @@ -5517,37 +5523,43 @@ }, "chownr": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true }, "debug": { "version": "4.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "optional": true, "requires": { @@ -5556,25 +5568,29 @@ }, "deep-extend": { "version": "0.6.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", "dev": true, "optional": true, "requires": { @@ -5583,13 +5599,15 @@ }, "fs.realpath": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "bundled": true, + "resolved": false, + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, "requires": { @@ -5605,7 +5623,8 @@ }, "glob": { "version": "7.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "optional": true, "requires": { @@ -5619,13 +5638,15 @@ }, "has-unicode": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "bundled": true, + "resolved": false, + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, "requires": { @@ -5634,7 +5655,8 @@ }, "ignore-walk": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", "dev": true, "optional": true, "requires": { @@ -5643,7 +5665,8 @@ }, "inflight": { "version": "1.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, "requires": { @@ -5653,19 +5676,22 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true, "optional": true }, "ini": { "version": "1.3.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "optional": true, "requires": { @@ -5674,13 +5700,15 @@ }, "isarray": { "version": "1.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "optional": true, "requires": { @@ -5689,13 +5717,15 @@ }, "minimist": { "version": "0.0.8", - "bundled": true, + "resolved": false, + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true, "optional": true }, "minipass": { "version": "2.3.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", "dev": true, "optional": true, "requires": { @@ -5705,7 +5735,8 @@ }, "minizlib": { "version": "1.2.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "optional": true, "requires": { @@ -5714,7 +5745,8 @@ }, "mkdirp": { "version": "0.5.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "optional": true, "requires": { @@ -5723,13 +5755,15 @@ }, "ms": { "version": "2.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true, "optional": true }, "needle": { "version": "2.3.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg==", "dev": true, "optional": true, "requires": { @@ -5740,7 +5774,8 @@ }, "node-pre-gyp": { "version": "0.12.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A==", "dev": true, "optional": true, "requires": { @@ -5758,7 +5793,8 @@ }, "nopt": { "version": "4.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, "requires": { @@ -5768,13 +5804,15 @@ }, "npm-bundled": { "version": "1.0.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", "dev": true, "optional": true }, "npm-packlist": { "version": "1.4.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", "dev": true, "optional": true, "requires": { @@ -5784,7 +5822,8 @@ }, "npmlog": { "version": "4.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, "requires": { @@ -5796,19 +5835,22 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "optional": true, "requires": { @@ -5817,19 +5859,22 @@ }, "os-homedir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "bundled": true, + "resolved": false, + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, "requires": { @@ -5839,19 +5884,22 @@ }, "path-is-absolute": { "version": "1.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true, "optional": true }, "rc": { "version": "1.2.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, "requires": { @@ -5863,7 +5911,8 @@ "dependencies": { "minimist": { "version": "1.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true } @@ -5871,7 +5920,8 @@ }, "readable-stream": { "version": "2.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, "requires": { @@ -5886,7 +5936,8 @@ }, "rimraf": { "version": "2.6.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "optional": true, "requires": { @@ -5895,43 +5946,50 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "bundled": true, + "resolved": false, + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "bundled": true, + "resolved": false, + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true }, "semver": { "version": "5.7.0", - "bundled": true, + "resolved": false, + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "optional": true, "requires": { @@ -5942,7 +6000,8 @@ }, "string_decoder": { "version": "1.1.1", - "bundled": true, + "resolved": false, + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, "requires": { @@ -5951,7 +6010,8 @@ }, "strip-ansi": { "version": "3.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "optional": true, "requires": { @@ -5960,13 +6020,15 @@ }, "strip-json-comments": { "version": "2.0.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true }, "tar": { "version": "4.4.8", - "bundled": true, + "resolved": false, + "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", "dev": true, "optional": true, "requires": { @@ -5981,13 +6043,15 @@ }, "util-deprecate": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, "requires": { @@ -5996,13 +6060,15 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, + "resolved": false, + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "optional": true }, "yallist": { "version": "3.0.3", - "bundled": true, + "resolved": false, + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", "dev": true, "optional": true } @@ -10946,7 +11012,8 @@ "dependencies": { "concat-stream": { "version": "1.5.1", - "bundled": true, + "resolved": false, + "integrity": "sha1-87gKz54fSOOHXAaItBtsMWAu6hw=", "requires": { "inherits": "~2.0.1", "readable-stream": "~2.0.0", @@ -10955,11 +11022,13 @@ "dependencies": { "inherits": { "version": "2.0.1", - "bundled": true + "resolved": false, + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" }, "readable-stream": { "version": "2.0.5", - "bundled": true, + "resolved": false, + "integrity": "sha1-okJvjc1FUcd6M/lu3yiGojyClmk=", "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -10971,35 +11040,41 @@ "dependencies": { "core-util-is": { "version": "1.0.2", - "bundled": true + "resolved": false, + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "isarray": { "version": "0.0.1", - "bundled": true + "resolved": false }, "process-nextick-args": { "version": "1.0.6", - "bundled": true + "resolved": false, + "integrity": "sha1-D5awAc6pCxJZLOVm7bl+wR5pvQU=" }, "string_decoder": { "version": "0.10.31", - "bundled": true + "resolved": false, + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, "util-deprecate": { "version": "1.0.2", - "bundled": true + "resolved": false, + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" } } }, "typedarray": { "version": "0.0.6", - "bundled": true + "resolved": false, + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" } } }, "https-proxy-agent": { "version": "0.3.6", - "bundled": true, + "resolved": false, + "integrity": "sha1-cT+jjl01P1DrFKNC/r4pAz7RYZs=", "requires": { "agent-base": "~1.0.1", "debug": "2", @@ -11008,34 +11083,40 @@ "dependencies": { "agent-base": { "version": "1.0.2", - "bundled": true + "resolved": false, + "integrity": "sha1-aJDT+yFwBLYrcPiSjg+uX4lSpwY=" }, "debug": { "version": "2.2.0", - "bundled": true, + "resolved": false, + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "requires": { "ms": "0.7.1" }, "dependencies": { "ms": { "version": "0.7.1", - "bundled": true + "resolved": false, + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" } } }, "extend": { "version": "3.0.0", - "bundled": true + "resolved": false, + "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=" } } }, "json-stringify-safe": { "version": "5.0.1", - "bundled": true + "resolved": false, + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "readable-stream": { "version": "1.1.13", - "bundled": true, + "resolved": false, + "integrity": "sha1-9u73ZPUUyJ4rniMUanW6EGdW0j4=", "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -11045,29 +11126,34 @@ "dependencies": { "core-util-is": { "version": "1.0.2", - "bundled": true + "resolved": false, + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "inherits": { "version": "2.0.1", - "bundled": true + "resolved": false, + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" }, "isarray": { "version": "0.0.1", - "bundled": true + "resolved": false }, "string_decoder": { "version": "0.10.31", - "bundled": true + "resolved": false, + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" } } }, "semver": { "version": "4.3.6", - "bundled": true + "resolved": false, + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" }, "yakaa": { "version": "1.0.1", - "bundled": true + "resolved": false, + "integrity": "sha1-PsqucvPQidpYCJQDEmIEzsdy5go=" } } }, @@ -14956,15 +15042,15 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20190828141612", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190828141612.tgz", - "integrity": "sha512-jNgMIXta4d30VFALA0KiJqOHy6cFkEi4puqYovbsY1tJ0zKD0QdaSqVntnAO96FTOZ5stMwagRva8q4GmiSmMQ==", + "version": "0.1.0-prerelease.20190828224521", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190828224521.tgz", + "integrity": "sha512-kpcGP/l0SABRzTEOwlZsYI2My9D7ufecnoFQWoN0z433ThMHwjb3Ce/UDqumnw/97Lh8ndaVZq4TWwEfJxmskw==", "dev": true }, "scratch-l10n": { - "version": "3.5.20190827223456", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.5.20190827223456.tgz", - "integrity": "sha512-Zsl9lrNW69omsxGRgwMN0i54SxPI/yJqWi1GubQw8qu2plkFHCC0ngoyaRkTxoYpHEJYSB6s8T8v6VrcEI1Y0A==", + "version": "3.5.20190813223429", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.5.20190813223429.tgz", + "integrity": "sha512-rSxUSwv0RgZTXUknAWuc7BFZWewiNhrgyPUMos/qAw4GgVMdY1ZRSIHBEIItpCXXYLOzw4ObcNafIim6Taq9NA==", "dev": true, "requires": { "@babel/cli": "^7.1.2", @@ -15060,9 +15146,9 @@ } }, "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "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": { diff --git a/package.json b/package.json index dcce1385d..1298622fa 100644 --- a/package.json +++ b/package.json @@ -124,7 +124,7 @@ "redux": "3.5.2", "redux-thunk": "2.0.1", "sass-loader": "6.0.6", - "scratch-gui": "0.1.0-prerelease.20190828141612", + "scratch-gui": "0.1.0-prerelease.20190828224521", "scratch-l10n": "latest", "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0", From 3daba3b9075adc29e63523fb81c8db4d679212f0 Mon Sep 17 00:00:00 2001 From: picklesrus Date: Tue, 20 Aug 2019 17:05:43 -0400 Subject: [PATCH 15/67] Initial work for captcha in new join flow. TODOS: - handle error states - Setup keys for different environments. - Make sure remote validators are run before captcha. --- src/components/join-flow/email-step.jsx | 41 ++++++++++++++++++++++--- src/components/join-flow/join-flow.jsx | 10 ++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index 98836f1e7..0f16d9992 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -19,13 +19,30 @@ class EmailStep extends React.Component { bindAll(this, [ 'handleSetEmailRef', 'handleValidSubmit', - 'validateEmail', - 'validateForm' + 'validateEmailIfPresent', + 'validateForm', + 'setCaptchaRef', + 'captchaSolved' ]); } + componentDidMount () { // automatically start with focus on username field if (this.emailInput) this.emailInput.focus(); + this.grecaptcha = window.grecaptcha; + if (!this.grecaptcha) { + // Captcha doesn't exist on the window. There must have been a + // problem downloading the script. There isn't much we can do about it though. + // TODO: put up the error screen when we have it. + return; + } + // TODO: Add in error callback for this once we have an error screen. + this.widgetId = this.grecaptcha.render(this.captchaRef, + { + callback: this.captchaSolved, + sitekey: '' + }, + true); } handleSetEmailRef (emailInputRef) { this.emailInput = emailInputRef; @@ -42,8 +59,17 @@ class EmailStep extends React.Component { return {}; } handleValidSubmit (formData, formikBag) { - formikBag.setSubmitting(false); - this.props.onNextStep(formData); + this.formData = formData; + this.formikBag = formikBag; + this.grecaptcha.execute(this.widgetId); + } + captchaSolved (token) { + this.formData['g-recaptcha-response'] = token; + this.formikBag.setSubmitting(false); + this.props.onNextStep(this.formData); + } + setCaptchaRef (ref) { + this.captchaRef = ref; } render () { return ( @@ -116,6 +142,13 @@ class EmailStep extends React.Component { name="subscribe" /> +
); }} diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index f743dc088..2a55ff536 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -29,6 +29,16 @@ class JoinFlow extends React.Component { step: 0 }; } + + componentDidMount () { + // Load Google Captcha script so that it is ready to go when we get to + // the last step. + const script = document.createElement('script'); + script.src = `https://www.recaptcha.net/recaptcha/api.js?render=explicit&hl=${window._locale}`; + script.async = true; + document.body.appendChild(script); + } + handleAdvanceStep (formData) { formData = formData || {}; this.setState({ From 9d4d2f3c670d1511f607d5c0877d8e6f24106f57 Mon Sep 17 00:00:00 2001 From: picklesrus Date: Tue, 20 Aug 2019 17:37:52 -0400 Subject: [PATCH 16/67] Put the captcha badge in the bottom right. --- src/components/join-flow/email-step.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index 0f16d9992..30db18a5d 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -144,7 +144,7 @@ class EmailStep extends React.Component {
Date: Wed, 21 Aug 2019 13:59:49 -0400 Subject: [PATCH 17/67] Maybe setup captcha site keys properly? --- .travis.yml | 5 +++++ src/components/join-flow/email-step.jsx | 4 ++-- webpack.config.js | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index aaf414d4e..b60270840 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,6 +33,11 @@ env: - CLOUDDATA_HOST_VAR=CLOUDDATA_HOST_$TRAVIS_BRANCH - CLOUDDATA_HOST=${!CLOUDDATA_HOST_VAR} - CLOUDDATA_HOST=${CLOUDDATA_HOST:-$CLOUDDATA_HOST_STAGING} + - RECAPTCHA_SITE_KEY_master=6LeRbUwUAAAAAFYhKgk3G9OKWqE_OJ7Z-7VTUCbl + - RECAPTCHA_SITE_KEY_STAGING=6LfukK4UAAAAAFR44yoZMhv8fj6xh-PMiIxwryG3 + - RECAPTCHA_SITE=RECAPTCHA_SITE_KEY_$TRAVIS_BRANCH + - RECAPTCHA_SITE_KEY=${!RECAPTCHA_SITE_KEY_VAR} + - RECAPTCHA_SITE_KEY=${RECAPTCHA_SITE_KEY:-$RECAPTCHA_SITE_KEY_STAGING} - ROOT_URL_master=https://scratch.mit.edu - ROOT_URL_STAGING=https://scratch.ly - ROOT_URL_VAR=ROOT_URL_$TRAVIS_BRANCH diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index 30db18a5d..4e2b28d57 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -40,7 +40,7 @@ class EmailStep extends React.Component { this.widgetId = this.grecaptcha.render(this.captchaRef, { callback: this.captchaSolved, - sitekey: '' + sitekey: process.env.RECAPTCHA_SITE_KEY }, true); } @@ -145,7 +145,7 @@ class EmailStep extends React.Component {
diff --git a/webpack.config.js b/webpack.config.js index 3118a4bb5..a2fe4fcbc 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -173,6 +173,8 @@ module.exports = { new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"' + (process.env.NODE_ENV || 'development') + '"', 'process.env.API_HOST': '"' + (process.env.API_HOST || 'https://api.scratch.mit.edu') + '"', + 'process.env.RECAPTCHA_SITE_KEY': '"' + + (process.env.RECAPTCHA_SITE_KEY || '6Lf6kK4UAAAAABKTyvdSqgcSVASEnMrCquiAkjVW') + '"', 'process.env.ASSET_HOST': '"' + (process.env.ASSET_HOST || 'https://assets.scratch.mit.edu') + '"', 'process.env.BACKPACK_HOST': '"' + (process.env.BACKPACK_HOST || 'https://backpack.scratch.mit.edu') + '"', 'process.env.CLOUDDATA_HOST': '"' + (process.env.CLOUDDATA_HOST || 'clouddata.scratch.mit.edu') + '"', From f83fa4390c1cdc5d746dc24d70facb66428ed4aa Mon Sep 17 00:00:00 2001 From: picklesrus Date: Tue, 27 Aug 2019 15:42:33 -0400 Subject: [PATCH 18/67] - Undo bad merge changing name of validateEmail function - Move loading of capcha js to final step - add in onload and onerror callbacks for catpcha js loading --- src/components/join-flow/email-step.jsx | 15 ++++++++------- src/components/join-flow/join-flow.jsx | 9 --------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index 4e2b28d57..b5c5d9ce0 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -19,10 +19,12 @@ class EmailStep extends React.Component { bindAll(this, [ 'handleSetEmailRef', 'handleValidSubmit', - 'validateEmailIfPresent', + 'validateEmail', 'validateForm', 'setCaptchaRef', - 'captchaSolved' + 'captchaSolved', + 'onCaptchaLoad', + 'onCaptchaError' ]); } @@ -31,12 +33,11 @@ class EmailStep extends React.Component { if (this.emailInput) this.emailInput.focus(); this.grecaptcha = window.grecaptcha; if (!this.grecaptcha) { - // Captcha doesn't exist on the window. There must have been a - // problem downloading the script. There isn't much we can do about it though. - // TODO: put up the error screen when we have it. - return; + // According to the reCaptcha documentation, this callback shouldn't get + // called unless window.grecaptcha exists. This is just here to be extra defensive. + // TODO: Put up the error screen when we have one. } - // TODO: Add in error callback for this once we have an error screen. + // TODO: Add in error callback for render once we have an error screen. this.widgetId = this.grecaptcha.render(this.captchaRef, { callback: this.captchaSolved, diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index 2a55ff536..d6867a7da 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -30,15 +30,6 @@ class JoinFlow extends React.Component { }; } - componentDidMount () { - // Load Google Captcha script so that it is ready to go when we get to - // the last step. - const script = document.createElement('script'); - script.src = `https://www.recaptcha.net/recaptcha/api.js?render=explicit&hl=${window._locale}`; - script.async = true; - document.body.appendChild(script); - } - handleAdvanceStep (formData) { formData = formData || {}; this.setState({ From b8b76f69ba123d52e92d9acb181c7aada313a66a Mon Sep 17 00:00:00 2001 From: picklesrus Date: Tue, 27 Aug 2019 15:51:48 -0400 Subject: [PATCH 19/67] Make sure the "create account" button is clickable until captcha is actually solved. --- src/components/join-flow/email-step.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index b5c5d9ce0..33125f8b8 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -62,11 +62,15 @@ class EmailStep extends React.Component { handleValidSubmit (formData, formikBag) { this.formData = formData; this.formikBag = formikBag; + // Change set submitting to false so that if the user clicks out of + // the captcha, the button is clickable again (instead of a disabled button with a spinner). + this.formikBag.setSubmitting(false); this.grecaptcha.execute(this.widgetId); } captchaSolved (token) { + // Now thatcaptcha is done, we can tell Formik we're submitting. + this.formikBag.setSubmitting(true); this.formData['g-recaptcha-response'] = token; - this.formikBag.setSubmitting(false); this.props.onNextStep(this.formData); } setCaptchaRef (ref) { From 350f6e6bab219cb93f07bf294a41e92e4b33873e Mon Sep 17 00:00:00 2001 From: picklesrus Date: Tue, 27 Aug 2019 16:29:54 -0400 Subject: [PATCH 20/67] Make it so Create Account button is not clickable until captcha js loads. --- src/components/join-flow/email-step.jsx | 26 ++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index 33125f8b8..d93a21a53 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -26,11 +26,35 @@ class EmailStep extends React.Component { 'onCaptchaLoad', 'onCaptchaError' ]); + this.state = { + captchaIsLoading: true + }; } componentDidMount () { +<<<<<<< HEAD // automatically start with focus on username field if (this.emailInput) this.emailInput.focus(); +======= + // ReCaptcha calls a callback when the grecatpcha object is usable. That callback + // needs to be global so set it on the window. + window.grecaptchaOnLoad = this.onCaptchaLoad; + // Load Google ReCaptcha script. + const script = document.createElement('script'); + script.async = true; + script.onerror = this.onCaptchaError; + script.src = `https://www.recaptcha.net/recaptcha/api.js?onload=grecaptchaOnLoad&render=explicit&hl=${window._locale}`; + document.body.appendChild(script); + } + componentWillUnmount () { + window.grecaptchaOnLoad = null; + } + onCaptchaError () { + // TODO send user to error step once we have one. + } + onCaptchaLoad () { + this.setState({captchaIsLoading: false}); +>>>>>>> Make it so Create Account button is not clickable until captcha js loads. this.grecaptcha = window.grecaptcha; if (!this.grecaptcha) { // According to the reCaptcha documentation, this callback shouldn't get @@ -119,7 +143,7 @@ class EmailStep extends React.Component { innerClassName="join-flow-inner-email-step" nextButton={this.props.intl.formatMessage({id: 'registration.createAccount'})} title={this.props.intl.formatMessage({id: 'registration.emailStepTitle'})} - waiting={isSubmitting} + waiting={isSubmitting || this.state.captchaIsLoading} onSubmit={handleSubmit} > Date: Tue, 27 Aug 2019 16:36:10 -0400 Subject: [PATCH 21/67] Only load the captcha js if it hasn't been loaded yet. --- src/components/join-flow/email-step.jsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index d93a21a53..c550e3de6 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -32,6 +32,7 @@ class EmailStep extends React.Component { } componentDidMount () { +<<<<<<< HEAD <<<<<<< HEAD // automatically start with focus on username field if (this.emailInput) this.emailInput.focus(); @@ -45,6 +46,20 @@ class EmailStep extends React.Component { script.onerror = this.onCaptchaError; script.src = `https://www.recaptcha.net/recaptcha/api.js?onload=grecaptchaOnLoad&render=explicit&hl=${window._locale}`; document.body.appendChild(script); +======= + // If grecaptcha doesn't exist on window, we havent loaded the captcha js yet. Load it. + if (!window.grecaptcha) { + // ReCaptcha calls a callback when the grecatpcha object is usable. That callback + // needs to be global so set it on the window. + window.grecaptchaOnLoad = this.onCaptchaLoad; + // Load Google ReCaptcha script. + const script = document.createElement('script'); + script.async = true; + script.onerror = this.onCaptchaError; + script.src = `https://www.recaptcha.net/recaptcha/api.js?onload=grecaptchaOnLoad&render=explicit&hl=${window._locale}`; + document.body.appendChild(script); + } +>>>>>>> Only load the captcha js if it hasn't been loaded yet. } componentWillUnmount () { window.grecaptchaOnLoad = null; From c4d6e3dcef31ef90fdecd06e027616f07e417d5f Mon Sep 17 00:00:00 2001 From: picklesrus Date: Tue, 27 Aug 2019 16:38:38 -0400 Subject: [PATCH 22/67] space fixes --- src/components/join-flow/email-step.jsx | 2 +- src/components/join-flow/join-flow.jsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index c550e3de6..77f5d7e54 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -107,7 +107,7 @@ class EmailStep extends React.Component { this.grecaptcha.execute(this.widgetId); } captchaSolved (token) { - // Now thatcaptcha is done, we can tell Formik we're submitting. + // Now that captcha is done, we can tell Formik we're submitting. this.formikBag.setSubmitting(true); this.formData['g-recaptcha-response'] = token; this.props.onNextStep(this.formData); diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index d6867a7da..f743dc088 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -29,7 +29,6 @@ class JoinFlow extends React.Component { step: 0 }; } - handleAdvanceStep (formData) { formData = formData || {}; this.setState({ From 3c716af744eb0a18ea2c0fbfa619b62ada50e997 Mon Sep 17 00:00:00 2001 From: picklesrus Date: Thu, 29 Aug 2019 11:33:50 -0400 Subject: [PATCH 23/67] Fix merge conflicts. --- src/components/join-flow/email-step.jsx | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index 77f5d7e54..88a24c97a 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -32,21 +32,9 @@ class EmailStep extends React.Component { } componentDidMount () { -<<<<<<< HEAD -<<<<<<< HEAD // automatically start with focus on username field if (this.emailInput) this.emailInput.focus(); -======= - // ReCaptcha calls a callback when the grecatpcha object is usable. That callback - // needs to be global so set it on the window. - window.grecaptchaOnLoad = this.onCaptchaLoad; - // Load Google ReCaptcha script. - const script = document.createElement('script'); - script.async = true; - script.onerror = this.onCaptchaError; - script.src = `https://www.recaptcha.net/recaptcha/api.js?onload=grecaptchaOnLoad&render=explicit&hl=${window._locale}`; - document.body.appendChild(script); -======= + // If grecaptcha doesn't exist on window, we havent loaded the captcha js yet. Load it. if (!window.grecaptcha) { // ReCaptcha calls a callback when the grecatpcha object is usable. That callback @@ -59,17 +47,18 @@ class EmailStep extends React.Component { script.src = `https://www.recaptcha.net/recaptcha/api.js?onload=grecaptchaOnLoad&render=explicit&hl=${window._locale}`; document.body.appendChild(script); } ->>>>>>> Only load the captcha js if it hasn't been loaded yet. } componentWillUnmount () { window.grecaptchaOnLoad = null; } + handleSetEmailRef (emailInputRef) { + this.emailInput = emailInputRef; + } onCaptchaError () { // TODO send user to error step once we have one. } onCaptchaLoad () { this.setState({captchaIsLoading: false}); ->>>>>>> Make it so Create Account button is not clickable until captcha js loads. this.grecaptcha = window.grecaptcha; if (!this.grecaptcha) { // According to the reCaptcha documentation, this callback shouldn't get @@ -84,9 +73,6 @@ class EmailStep extends React.Component { }, true); } - handleSetEmailRef (emailInputRef) { - this.emailInput = emailInputRef; - } validateEmail (email) { if (!email) return this.props.intl.formatMessage({id: 'general.required'}); const isValidLocally = emailValidator.validate(email); @@ -107,7 +93,7 @@ class EmailStep extends React.Component { this.grecaptcha.execute(this.widgetId); } captchaSolved (token) { - // Now that captcha is done, we can tell Formik we're submitting. + // Now thatcaptcha is done, we can tell Formik we're submitting. this.formikBag.setSubmitting(true); this.formData['g-recaptcha-response'] = token; this.props.onNextStep(this.formData); From bd33b166f7474c0128f37c4b64478fb24e26e07a Mon Sep 17 00:00:00 2001 From: picklesrus Date: Thu, 29 Aug 2019 18:34:07 -0400 Subject: [PATCH 24/67] Add a unittest for the EmailStep. --- test/unit/components/email-step.test.jsx | 134 +++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 test/unit/components/email-step.test.jsx diff --git a/test/unit/components/email-step.test.jsx b/test/unit/components/email-step.test.jsx new file mode 100644 index 000000000..f19edf8e8 --- /dev/null +++ b/test/unit/components/email-step.test.jsx @@ -0,0 +1,134 @@ +import React from 'react'; +import {shallowWithIntl} from '../../helpers/intl-helpers.jsx'; +import EmailStep from '../../../src/components/join-flow/email-step.jsx'; +import JoinFlowStep from '../../../src/components/join-flow/join-flow-step.jsx'; +const FormikInput = require('../../../src/components/formik-forms/formik-input.jsx'); +const FormikCheckbox = require('../../../src/components/formik-forms/formik-checkbox.jsx'); + +describe('EmailStep test', () => { + test('send correct props to formik', () => { + const wrapper = shallowWithIntl(); + + const formikWrapper = wrapper.dive(); + expect(formikWrapper.props().initialValues.subscribe).toBe(false); + expect(formikWrapper.props().initialValues.email).toBe(''); + expect(formikWrapper.props().validateOnBlur).toBe(false); + expect(formikWrapper.props().validateOnChange).toBe(false); + expect(formikWrapper.props().validate).toBe(formikWrapper.instance().validateForm); + expect(formikWrapper.props().onSubmit).toBe(formikWrapper.instance().handleValidSubmit); + }); + + test('props sent to JoinFlowStep', () => { + const wrapper = shallowWithIntl(); + // Dive to get past the intl wrapper + const formikWrapper = wrapper.dive(); + // Dive to get past the anonymous component. + const joinFlowWrapper = formikWrapper.dive().find(JoinFlowStep); + expect(joinFlowWrapper).toHaveLength(1); + expect(joinFlowWrapper.props().description).toBe('registration.emailStepDescription'); + expect(joinFlowWrapper.props().footerContent.props.id).toBe('registration.acceptTermsOfUse'); + expect(joinFlowWrapper.props().headerImgSrc).toBe('/images/join-flow/email-header.png'); + expect(joinFlowWrapper.props().innerClassName).toBe('join-flow-inner-email-step'); + expect(joinFlowWrapper.props().nextButton).toBe('registration.createAccount'); + expect(joinFlowWrapper.props().title).toBe('registration.emailStepTitle'); + expect(joinFlowWrapper.props().waiting).toBe(true); + }); + + test('props sent to FormikInput for email', () => { + const wrapper = shallowWithIntl(); + // Dive to get past the intl wrapper + const formikWrapper = wrapper.dive(); + // Dive to get past the anonymous component. + const joinFlowWrapper = formikWrapper.dive().find(JoinFlowStep); + expect(joinFlowWrapper).toHaveLength(1); + const emailInputWrapper = joinFlowWrapper.find(FormikInput).first(); + expect(emailInputWrapper.props().id).toEqual('email'); + expect(emailInputWrapper.props().error).toBeUndefined(); + expect(emailInputWrapper.props().name).toEqual('email'); + expect(emailInputWrapper.props().placeholder).toEqual('general.emailAddress'); + expect(emailInputWrapper.props().validationClassName).toEqual('validation-full-width-input'); + expect(emailInputWrapper.props().onSetRef).toEqual(formikWrapper.instance().handleSetEmailRef); + expect(emailInputWrapper.props().validate).toEqual(formikWrapper.instance().validateEmail); + }); + test('props sent to FormikCheckbox for subscribe', () => { + const wrapper = shallowWithIntl(); + // Dive to get past the intl wrapper + const formikWrapper = wrapper.dive(); + // Dive to get past the anonymous component. + const joinFlowWrapper = formikWrapper.dive().find(JoinFlowStep); + expect(joinFlowWrapper).toHaveLength(1); + const checkboxWrapper = joinFlowWrapper.find(FormikCheckbox).first(); + expect(checkboxWrapper).toHaveLength(1); + expect(checkboxWrapper.first().props().id).toEqual('subscribeCheckbox'); + expect(checkboxWrapper.first().props().label).toEqual('registration.receiveEmails'); + expect(checkboxWrapper.first().props().name).toEqual('subscribe'); + }); + test('handleValidSubmit passes formData to next step', () => { + const formikBag = { + setSubmitting: jest.fn() + }; + global.window.grecaptcha = { + execute: jest.fn(), + render: jest.fn() + }; + const formData = {some: 'data}', is: 'here'}; + const wrapper = shallowWithIntl( + ); + + const formikWrapper = wrapper.dive(); + formikWrapper.instance().onCaptchaLoad(); // to setup catpcha state + formikWrapper.instance().handleValidSubmit(formData, formikBag); + + expect(formikBag.setSubmitting).toHaveBeenCalledWith(false); + expect(global.window.grecaptcha.execute).toHaveBeenCalled(); + }); + test('captchaSolved sets token and goes to next step', () => { + const props = { + onNextStep: jest.fn() + }; + const formikBag = { + setSubmitting: jest.fn() + }; + global.window.grecaptcha = { + execute: jest.fn(), + render: jest.fn() + }; + const formData = {some: 'data}', is: 'here'}; + const wrapper = shallowWithIntl( + ); + + const formikWrapper = wrapper.dive(); + // Call these to setup captcha. + formikWrapper.instance().onCaptchaLoad(); // to setup catpcha state + formikWrapper.instance().handleValidSubmit(formData, formikBag); + + const captchaToken = 'abcd'; + formikWrapper.instance().captchaSolved(captchaToken); + formData['gre-captcha-response'] = captchaToken; + expect(props.onNextStep).toHaveBeenCalledWith(formData); + expect(formikBag.setSubmitting).toHaveBeenCalledWith(true); + }); + test('validateEmail test email empty', () => { + const wrapper = shallowWithIntl( + ); + const formikWrapper = wrapper.dive(); + const val = formikWrapper.instance().validateEmail(''); + expect(val).toBe('general.required'); + }); + test('validateEmail test email null', () => { + const wrapper = shallowWithIntl( + ); + const formikWrapper = wrapper.dive(); + const val = formikWrapper.instance().validateEmail(null); + expect(val).toBe('general.required'); + }); + test('validateEmail test email undefined', () => { + const wrapper = shallowWithIntl( + ); + const formikWrapper = wrapper.dive(); + const val = formikWrapper.instance().validateEmail(); + expect(val).toBe('general.required'); + }); +}); From 8993304e76a4bbcd842e24c40192aecc54aedf79 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2019 16:18:05 +0000 Subject: [PATCH 25/67] chore(package): update scratch-gui to version 0.1.0-prerelease.20190830160439 Closes #3320 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1298622fa..76b124919 100644 --- a/package.json +++ b/package.json @@ -124,7 +124,7 @@ "redux": "3.5.2", "redux-thunk": "2.0.1", "sass-loader": "6.0.6", - "scratch-gui": "0.1.0-prerelease.20190828224521", + "scratch-gui": "0.1.0-prerelease.20190830160439", "scratch-l10n": "latest", "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0", From 2e86a72dbf39b28f0590d27785df4949de1fb677 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2019 16:18:10 +0000 Subject: [PATCH 26/67] chore(package): update lockfile package-lock.json --- package-lock.json | 967 +++++++++++++++++++++++----------------------- 1 file changed, 487 insertions(+), 480 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9ebb2def4..1b590723a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,471 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/cli": { + "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", + "commander": "^2.8.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.13", + "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.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "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", @@ -5011,22 +5476,25 @@ "dependencies": { "form-data": { "version": "0.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.0.3.tgz", + "integrity": "sha1-buoXtFeQtC13mh1YHRs2AP4MfA0=", "dev": true, "requires": { - "async": "~0.1.9", + "async": "0.1.9", "combined-stream": "0.0.3", - "mime": "~1.2.2" + "mime": "1.2.2" }, "dependencies": { "async": { "version": "0.1.9", - "resolved": false, + "resolved": "https://registry.npmjs.org/async/-/async-0.1.9.tgz", + "integrity": "sha1-+YTQc5tTgslJzDvqcC0h0NvVIEA=", "dev": true }, "combined-stream": { "version": "0.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.3.tgz", + "integrity": "sha1-odYiPEY6AAshyZN8SxXvQboAH3g=", "dev": true, "requires": { "delayed-stream": "0.0.5" @@ -5034,7 +5502,8 @@ "dependencies": { "delayed-stream": { "version": "0.0.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", "dev": true } } @@ -5043,7 +5512,8 @@ }, "mime": { "version": "1.2.7", - "resolved": false, + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.7.tgz", + "integrity": "sha1-x6E/M6cHPZkA8ohDawazoWIAhls=", "dev": true } } @@ -11045,7 +11515,8 @@ }, "isarray": { "version": "0.0.1", - "resolved": false + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, "process-nextick-args": { "version": "1.0.6", @@ -11136,7 +11607,8 @@ }, "isarray": { "version": "0.0.1", - "resolved": false + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, "string_decoder": { "version": "0.10.31", @@ -15042,486 +15514,21 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20190828224521", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190828224521.tgz", - "integrity": "sha512-kpcGP/l0SABRzTEOwlZsYI2My9D7ufecnoFQWoN0z433ThMHwjb3Ce/UDqumnw/97Lh8ndaVZq4TWwEfJxmskw==", + "version": "0.1.0-prerelease.20190830160439", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190830160439.tgz", + "integrity": "sha512-NOfeSIA6R4vvJZ46E3Gj/g0nZKBtCvdi3v8kVIphe8jt0ss09hIgRI1hE+BHjUAYxvlnzRz5JDgc6gXwpE6ECg==", "dev": true }, "scratch-l10n": { - "version": "3.5.20190813223429", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.5.20190813223429.tgz", - "integrity": "sha512-rSxUSwv0RgZTXUknAWuc7BFZWewiNhrgyPUMos/qAw4GgVMdY1ZRSIHBEIItpCXXYLOzw4ObcNafIim6Taq9NA==", + "version": "3.5.20190827223456", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.5.20190827223456.tgz", + "integrity": "sha512-Zsl9lrNW69omsxGRgwMN0i54SxPI/yJqWi1GubQw8qu2plkFHCC0ngoyaRkTxoYpHEJYSB6s8T8v6VrcEI1Y0A==", "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.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", - "commander": "^2.8.1", - "convert-source-map": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.0.0", - "lodash": "^4.17.13", - "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": { From c9d729311915ee37d7fedbfb78ed75a60f541594 Mon Sep 17 00:00:00 2001 From: picklesrus Date: Fri, 30 Aug 2019 13:42:49 -0400 Subject: [PATCH 27/67] use global.recaptcha instead of global.window.grecaptcha. --- test/unit/components/email-step.test.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/components/email-step.test.jsx b/test/unit/components/email-step.test.jsx index f19edf8e8..2613bad51 100644 --- a/test/unit/components/email-step.test.jsx +++ b/test/unit/components/email-step.test.jsx @@ -67,7 +67,7 @@ describe('EmailStep test', () => { const formikBag = { setSubmitting: jest.fn() }; - global.window.grecaptcha = { + global.grecaptcha = { execute: jest.fn(), render: jest.fn() }; @@ -80,7 +80,7 @@ describe('EmailStep test', () => { formikWrapper.instance().handleValidSubmit(formData, formikBag); expect(formikBag.setSubmitting).toHaveBeenCalledWith(false); - expect(global.window.grecaptcha.execute).toHaveBeenCalled(); + expect(global.grecaptcha.execute).toHaveBeenCalled(); }); test('captchaSolved sets token and goes to next step', () => { const props = { @@ -89,7 +89,7 @@ describe('EmailStep test', () => { const formikBag = { setSubmitting: jest.fn() }; - global.window.grecaptcha = { + global.grecaptcha = { execute: jest.fn(), render: jest.fn() }; From 48bfbb0d897bfe18c9fb0137fbcf7207d4f0a8cb Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2019 15:00:52 +0000 Subject: [PATCH 28/67] chore(package): update scratch-gui to version 0.1.0-prerelease.20190903144730 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 685b14edb..91c868019 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "redux": "3.5.2", "redux-thunk": "2.0.1", "sass-loader": "6.0.6", - "scratch-gui": "0.1.0-prerelease.20190830160439", + "scratch-gui": "0.1.0-prerelease.20190903144730", "scratch-l10n": "latest", "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0", From fa79a1c6a546d5fd738a7020c41cae9310c2e622 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2019 15:00:56 +0000 Subject: [PATCH 29/67] chore(package): update lockfile package-lock.json --- package-lock.json | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93c8cf26e..270f76094 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5507,6 +5507,12 @@ "dev": true } } + }, + "mime": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.2.tgz", + "integrity": "sha1-udY1W/U+jX1WaTEw5FHa/zQBSM8=", + "dev": true } } }, @@ -15514,9 +15520,9 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20190830160439", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190830160439.tgz", - "integrity": "sha512-NOfeSIA6R4vvJZ46E3Gj/g0nZKBtCvdi3v8kVIphe8jt0ss09hIgRI1hE+BHjUAYxvlnzRz5JDgc6gXwpE6ECg==", + "version": "0.1.0-prerelease.20190903144730", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190903144730.tgz", + "integrity": "sha512-AyXgNc+/MI8M/gmBkwrP+nUaQpyJ8n288baZOltbzJDL+900l9LF0svkUbPAKxEaGJtFziwTBEVH/mjxMZJhRA==", "dev": true }, "scratch-l10n": { From 49ed43e3972497d1149a4b78ae468fa1b29afc0b Mon Sep 17 00:00:00 2001 From: picklesrus Date: Tue, 3 Sep 2019 16:38:38 -0400 Subject: [PATCH 30/67] Join flow standalone with no extra stuff. --- src/routes.json | 7 +++++++ src/views/join/join.jsx | 15 +++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/views/join/join.jsx diff --git a/src/routes.json b/src/routes.json index 43ea0737a..c1494768f 100644 --- a/src/routes.json +++ b/src/routes.json @@ -161,6 +161,13 @@ "view": "jobs/moderator/moderator", "title": "Community Moderator" }, + { + "name": "join", + "pattern": "^/join/?$", + "routeAlias": "/join/?$", + "view": "join/join", + "title": "Join Scratch" + }, { "name": "messages", "pattern": "^/messages/?$", diff --git a/src/views/join/join.jsx b/src/views/join/join.jsx new file mode 100644 index 000000000..70628dbb0 --- /dev/null +++ b/src/views/join/join.jsx @@ -0,0 +1,15 @@ +const React = require('react'); +const render = require('../../lib/render.jsx'); +const JoinModal = require('../../components/modal/join/modal.jsx'); +const ErrorBoundary = require('../../components/errorboundary/errorboundary.jsx'); + +const openModal = true; +const Register = () => ( + + + +); +render(, document.getElementById('app')); From 84be22f335814f1a481424a15681f5cc142a39bd Mon Sep 17 00:00:00 2001 From: picklesrus Date: Tue, 3 Sep 2019 16:57:43 -0400 Subject: [PATCH 31/67] add in unused Page for testing webpack memory. --- src/views/join/join.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/join/join.jsx b/src/views/join/join.jsx index 70628dbb0..7d14be8b0 100644 --- a/src/views/join/join.jsx +++ b/src/views/join/join.jsx @@ -2,6 +2,7 @@ const React = require('react'); const render = require('../../lib/render.jsx'); const JoinModal = require('../../components/modal/join/modal.jsx'); const ErrorBoundary = require('../../components/errorboundary/errorboundary.jsx'); +const Page = require('../../components/page/www/page.jsx'); // eslint-disable-line no-unused-vars const openModal = true; const Register = () => ( From 3d58fc4d125c69e5dd2945d4918a886fa3adecff Mon Sep 17 00:00:00 2001 From: picklesrus Date: Tue, 3 Sep 2019 17:32:31 -0400 Subject: [PATCH 32/67] Standardize on using require instead of import. Also fix a silly mistaake aand change the way I'm matching the contents of formData to be more specific. --- test/unit/components/email-step.test.jsx | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/test/unit/components/email-step.test.jsx b/test/unit/components/email-step.test.jsx index 2613bad51..88af9b8b2 100644 --- a/test/unit/components/email-step.test.jsx +++ b/test/unit/components/email-step.test.jsx @@ -1,7 +1,7 @@ -import React from 'react'; -import {shallowWithIntl} from '../../helpers/intl-helpers.jsx'; -import EmailStep from '../../../src/components/join-flow/email-step.jsx'; -import JoinFlowStep from '../../../src/components/join-flow/join-flow-step.jsx'; +const React = require('react'); +const {shallowWithIntl} = require('../../helpers/intl-helpers.jsx'); +const EmailStep = require('../../../src/components/join-flow/email-step.jsx'); +const JoinFlowStep = require('../../../src/components/join-flow/join-flow-step.jsx'); const FormikInput = require('../../../src/components/formik-forms/formik-input.jsx'); const FormikCheckbox = require('../../../src/components/formik-forms/formik-checkbox.jsx'); @@ -71,7 +71,7 @@ describe('EmailStep test', () => { execute: jest.fn(), render: jest.fn() }; - const formData = {some: 'data}', is: 'here'}; + const formData = {item1: 'thing', item2: 'otherthing'}; const wrapper = shallowWithIntl( ); @@ -93,7 +93,7 @@ describe('EmailStep test', () => { execute: jest.fn(), render: jest.fn() }; - const formData = {some: 'data}', is: 'here'}; + const formData = {item1: 'thing', item2: 'otherthing'}; const wrapper = shallowWithIntl( { const captchaToken = 'abcd'; formikWrapper.instance().captchaSolved(captchaToken); - formData['gre-captcha-response'] = captchaToken; - expect(props.onNextStep).toHaveBeenCalledWith(formData); + // Make sure captchaSolved calls onNextStep with formData that has + // a captcha token and left everything else in the object in place. + expect(props.onNextStep).toHaveBeenCalledWith( + expect.objectContaining({ + 'item1': formData.item1, + 'item2': formData.item2, + 'g-recaptcha-response': captchaToken + })); expect(formikBag.setSubmitting).toHaveBeenCalledWith(true); }); test('validateEmail test email empty', () => { From 6e5a2292a63d5155274c81d46b004c10e4edf53b Mon Sep 17 00:00:00 2001 From: picklesrus Date: Wed, 4 Sep 2019 10:51:13 -0400 Subject: [PATCH 33/67] Requiring the Page component (even though we don't use it) allows www to build without running out of memory. --- src/views/join/join.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/views/join/join.jsx b/src/views/join/join.jsx index 7d14be8b0..ebb4019fc 100644 --- a/src/views/join/join.jsx +++ b/src/views/join/join.jsx @@ -2,6 +2,7 @@ const React = require('react'); const render = require('../../lib/render.jsx'); const JoinModal = require('../../components/modal/join/modal.jsx'); const ErrorBoundary = require('../../components/errorboundary/errorboundary.jsx'); +// Require this even though we don't use it because, without it, webpack runs out of memory... const Page = require('../../components/page/www/page.jsx'); // eslint-disable-line no-unused-vars const openModal = true; From c92c0af3961917f7828c5540fd8aaa40b8098f07 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 4 Sep 2019 12:06:59 -0400 Subject: [PATCH 34/67] more subtle Next hover state --- src/_colors.scss | 2 +- src/components/join-flow/next-step-button.scss | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/_colors.scss b/src/_colors.scss index 0246a43a1..03ffef6f4 100644 --- a/src/_colors.scss +++ b/src/_colors.scss @@ -8,7 +8,7 @@ $ui-orange: hsla(38, 100, 55, 1); // #FFAB19 Control Primary $ui-orange-high-contrast: hsla(30, 100, 55, 1); // #FFAB19 Control Primary $ui-orange-10percent: hsla(35, 90, 55, .1); $ui-orange-25percent: hsla(35, 90, 55, .25); -$ui-orange-75percent: hsla(38, 100, 55, .75); +$ui-orange-90percent: hsla(38, 100, 55, .9); $ui-dark-orange: hsla(30, 100, 55, 1); // ##FF8C1A Variables Primary diff --git a/src/components/join-flow/next-step-button.scss b/src/components/join-flow/next-step-button.scss index 965b6f9a3..0b4bfc7ad 100644 --- a/src/components/join-flow/next-step-button.scss +++ b/src/components/join-flow/next-step-button.scss @@ -11,7 +11,8 @@ background-color: $ui-orange; &:hover { - background-color: $ui-orange-75percent; + transition: background-color .25s ease; + background-color: $ui-orange-90percent; } } From e8a90667ce167cd67fd10d20a155463ef9107bbd Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2019 00:43:45 +0000 Subject: [PATCH 35/67] chore(package): update scratch-gui to version 0.1.0-prerelease.20190905003010 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 91c868019..0dd1e8ed8 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "redux": "3.5.2", "redux-thunk": "2.0.1", "sass-loader": "6.0.6", - "scratch-gui": "0.1.0-prerelease.20190903144730", + "scratch-gui": "0.1.0-prerelease.20190905003010", "scratch-l10n": "latest", "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0", From 52ecc0300e7ad73976b816b1389d30d11232dfdb Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2019 00:43:49 +0000 Subject: [PATCH 36/67] chore(package): update lockfile package-lock.json --- package-lock.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 270f76094..c2c930a1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -981,9 +981,9 @@ } }, "@types/babel__core": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.2.tgz", - "integrity": "sha512-cfCCrFmiGY/yq0NuKNxIQvZFy9kY/1immpSpTngOnyIbD4+eJOG5mxphhHDv3CHL9GltO4GcKr54kGBg3RNdbg==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", + "integrity": "sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -15520,15 +15520,15 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20190903144730", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190903144730.tgz", - "integrity": "sha512-AyXgNc+/MI8M/gmBkwrP+nUaQpyJ8n288baZOltbzJDL+900l9LF0svkUbPAKxEaGJtFziwTBEVH/mjxMZJhRA==", + "version": "0.1.0-prerelease.20190905003010", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190905003010.tgz", + "integrity": "sha512-ZWKZacdgqj01djQdnMTWQZwgd7B/EE3K6xtZz/iNqce4BIjM1Yqf6EgW8I/omHLyQI1N12UlgVGmVWDa/+t3xw==", "dev": true }, "scratch-l10n": { - "version": "3.5.20190827223456", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.5.20190827223456.tgz", - "integrity": "sha512-Zsl9lrNW69omsxGRgwMN0i54SxPI/yJqWi1GubQw8qu2plkFHCC0ngoyaRkTxoYpHEJYSB6s8T8v6VrcEI1Y0A==", + "version": "3.5.20190903223516", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.5.20190903223516.tgz", + "integrity": "sha512-loXTVKRoostwA1HRLe2AuPU1j0KbLwilGzPmdnwd3yPTsdTjElEecZWprPVOIlIr9epvJVIybCNixuHtWbyCkg==", "dev": true, "requires": { "@babel/cli": "^7.1.2", From 020231bb02313bc3f3fe575da57809edb9452a33 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Sun, 25 Aug 2019 11:30:24 -0400 Subject: [PATCH 37/67] add local, remote email validation to validate library --- src/lib/validate.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/lib/validate.js b/src/lib/validate.js index b4fd84f31..c4deee007 100644 --- a/src/lib/validate.js +++ b/src/lib/validate.js @@ -1,5 +1,6 @@ module.exports = {}; const api = require('./api'); +const emailValidator = require('email-validator'); module.exports.validateUsernameLocally = username => { if (!username || username === '') { @@ -67,3 +68,37 @@ module.exports.validatePasswordConfirm = (password, passwordConfirm) => { } return {valid: true}; }; + +module.exports.validateEmailLocally = email => { + if (!email || email === '') { + return {valid: false, errMsgId: 'general.required'}; + } else if (emailValidator.validate(email)) { + return {valid: true}; + } + return ({valid: false, errMsgId: 'registration.validationEmailInvalid'}); +}; + +module.exports.validateEmailRemotely = email => ( + new Promise(resolve => { + api({ + uri: `/accounts/check_email/?email=${email}`, + host: '' // Not handled by the API, use existing infrastructure + }, (err, body, res) => { + if (err || res.statusCode !== 200 || !body || body.length < 1 || !body[0].msg) { + resolve({valid: false, errMsgId: 'general.apiError'}); + } + switch (body[0].msg) { + case 'valid email': + resolve({valid: true}); + break; + case 'Scratch is not allowed to send email to this address.': // e.g., bad TLD or block-listed + resolve({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + break; + case 'Enter a valid email address.': + default: + resolve({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + break; + } + }); + }) +); From d6e5637dbe1c6cc05a6b680ef0a9d896cfab1372 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Sun, 25 Aug 2019 11:31:07 -0400 Subject: [PATCH 38/67] in email step, use remote validation --- src/components/join-flow/email-step.jsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index 88a24c97a..54105a107 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -4,9 +4,9 @@ const React = require('react'); const PropTypes = require('prop-types'); import {Formik} from 'formik'; const {injectIntl, intlShape} = require('react-intl'); -const emailValidator = require('email-validator'); const FormattedMessage = require('react-intl').FormattedMessage; +const validate = require('../../lib/validate'); const JoinFlowStep = require('./join-flow-step.jsx'); const FormikInput = require('../../components/formik-forms/formik-input.jsx'); const FormikCheckbox = require('../../components/formik-forms/formik-checkbox.jsx'); @@ -75,11 +75,16 @@ class EmailStep extends React.Component { } validateEmail (email) { if (!email) return this.props.intl.formatMessage({id: 'general.required'}); - const isValidLocally = emailValidator.validate(email); - if (isValidLocally) { - return null; // TODO: validate email address remotely - } - return this.props.intl.formatMessage({id: 'registration.validationEmailInvalid'}); + const localResult = validate.validateEmailLocally(email); + if (!localResult.valid) return this.props.intl.formatMessage({id: localResult.errMsgId}); + return validate.validateEmailRemotely(email).then( + remoteResult => { + if (remoteResult.valid === true) { + return null; + } + return this.props.intl.formatMessage({id: remoteResult.errMsgId}); + } + ); } validateForm () { return {}; From fa91a57b355a0bc27f9915ef395d2c7d428ea8c6 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Sun, 25 Aug 2019 11:31:29 -0400 Subject: [PATCH 39/67] show email validation error until you make a change --- src/components/join-flow/email-step.jsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index 54105a107..5e42edeac 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -124,6 +124,8 @@ class EmailStep extends React.Component { handleSubmit, isSubmitting, setFieldError, + setFieldTouched, + setFieldValue, validateField } = props; return ( @@ -166,7 +168,11 @@ class EmailStep extends React.Component { validationClassName="validation-full-width-input" /* eslint-disable react/jsx-no-bind */ onBlur={() => validateField('email')} - onFocus={() => setFieldError('email', null)} + onChange={e => { + setFieldValue('email', e.target.value); + setFieldTouched('email'); + setFieldError('email', null); + }} /* eslint-enable react/jsx-no-bind */ onSetRef={this.handleSetEmailRef} /> From ee8cdac7481f6c67b4cce2f97a95db51ec6789ad Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Tue, 27 Aug 2019 12:18:53 -0400 Subject: [PATCH 40/67] add tests for local email validation --- test/unit/lib/validate.test.js | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/test/unit/lib/validate.test.js b/test/unit/lib/validate.test.js index 03922882f..a051e1faa 100644 --- a/test/unit/lib/validate.test.js +++ b/test/unit/lib/validate.test.js @@ -63,4 +63,52 @@ describe('unit test lib/validate.js', () => { response = validate.validatePasswordConfirm('', 'abcdefg'); expect(response).toEqual({valid: false, errMsgId: 'registration.validationPasswordConfirmNotEquals'}); }); + + test('validate email address locally', () => { + let response; + expect(typeof validate.validateEmailLocally).toBe('function'); + + // permitted addresses: + response = validate.validateEmailLocally('abc@def.com'); + expect(response).toEqual({valid: true}); + response = validate.validateEmailLocally('abcdefghijklmnopqrst@abcdefghijklmnopqrst.info'); + expect(response).toEqual({valid: true}); + response = validate.validateEmailLocally('abc-def-ghi@jkl-mno.org'); + expect(response).toEqual({valid: true}); + response = validate.validateEmailLocally('_______@example.com'); + expect(response).toEqual({valid: true}); + response = validate.validateEmailLocally('email@example.museum'); + expect(response).toEqual({valid: true}); + response = validate.validateEmailLocally('email@example.co.jp'); + expect(response).toEqual({valid: true}); + + // non-permitted addresses: + response = validate.validateEmailLocally(''); + expect(response).toEqual({valid: false, errMsgId: 'general.required'}); + response = validate.validateEmailLocally('a'); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + response = validate.validateEmailLocally('abc@def'); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + response = validate.validateEmailLocally('abc@def.c'); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + response = validate.validateEmailLocally('abc😄def@emoji.pizza'); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + response = validate.validateEmailLocally('あいうえお@example.com'); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + response = validate.validateEmailLocally('Abc..123@example.com'); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + response = validate.validateEmailLocally('Joe Smith '); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + response = validate.validateEmailLocally('email@example@example.com'); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + response = validate.validateEmailLocally('email@example..com'); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + + // edge cases: + // these are strictly legal according to email addres spec, but rejected by library we use: + response = validate.validateEmailLocally('email@123.123.123.123'); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + response = validate.validateEmailLocally('much."more unusual"@example.com'); + expect(response).toEqual({valid: false, errMsgId: 'registration.validationEmailInvalid'}); + }); }); From 55cb112ee995e1d17a1d872d152931239935af7a Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Tue, 27 Aug 2019 12:26:56 -0400 Subject: [PATCH 41/67] use params prop instead of inline query params --- src/lib/validate.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib/validate.js b/src/lib/validate.js index c4deee007..b2ce9ab5a 100644 --- a/src/lib/validate.js +++ b/src/lib/validate.js @@ -81,8 +81,9 @@ module.exports.validateEmailLocally = email => { module.exports.validateEmailRemotely = email => ( new Promise(resolve => { api({ - uri: `/accounts/check_email/?email=${email}`, - host: '' // Not handled by the API, use existing infrastructure + host: '', // not handled by API; use existing infrastructure + params: {email: email}, + uri: '/accounts/check_email/' }, (err, body, res) => { if (err || res.statusCode !== 200 || !body || body.length < 1 || !body[0].msg) { resolve({valid: false, errMsgId: 'general.apiError'}); From 46351c116dff2adf224a1d832b93290e74625ffb Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 28 Aug 2019 10:35:39 -0400 Subject: [PATCH 42/67] collapse switch cases --- src/lib/validate.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib/validate.js b/src/lib/validate.js index b2ce9ab5a..5df20b0e4 100644 --- a/src/lib/validate.js +++ b/src/lib/validate.js @@ -93,8 +93,6 @@ module.exports.validateEmailRemotely = email => ( resolve({valid: true}); break; case 'Scratch is not allowed to send email to this address.': // e.g., bad TLD or block-listed - resolve({valid: false, errMsgId: 'registration.validationEmailInvalid'}); - break; case 'Enter a valid email address.': default: resolve({valid: false, errMsgId: 'registration.validationEmailInvalid'}); From c8548b9cf43889f679397448dde4c46503abde01 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2019 00:14:21 +0000 Subject: [PATCH 43/67] chore(package): update scratch-gui to version 0.1.0-prerelease.20190909235840 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0dd1e8ed8..c7f8f8b1c 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,7 @@ "redux": "3.5.2", "redux-thunk": "2.0.1", "sass-loader": "6.0.6", - "scratch-gui": "0.1.0-prerelease.20190905003010", + "scratch-gui": "0.1.0-prerelease.20190909235840", "scratch-l10n": "latest", "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0", From 7e8a160ea9bbffabf5a23b6c02333cf36014d465 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2019 00:14:26 +0000 Subject: [PATCH 44/67] chore(package): update lockfile package-lock.json --- package-lock.json | 150 +++++++++++++++++++++++++++------------------- 1 file changed, 87 insertions(+), 63 deletions(-) diff --git a/package-lock.json b/package-lock.json index c2c930a1c..9f34ded3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,12 +5,12 @@ "requires": true, "dependencies": { "@babel/cli": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.5.5.tgz", - "integrity": "sha512-UHI+7pHv/tk9g6WXQKYz+kmXTI77YtuY3vqC59KIqcoWEjsJJSG6rAxKaLsgj3LDyadsPrCB929gVOKM6Hui0w==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.6.0.tgz", + "integrity": "sha512-1CTDyGUjQqW3Mz4gfKZ04KGOckyyaNmKneAMlABPS+ZyuxWv3FrVEVz7Ag08kNIztVx8VaJ8YgvYLSNlMKAT5Q==", "dev": true, "requires": { - "chokidar": "^2.0.4", + "chokidar": "^2.1.8", "commander": "^2.8.1", "convert-source-map": "^1.1.0", "fs-readdir-recursive": "^1.1.0", @@ -479,18 +479,18 @@ } }, "@babel/core": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", - "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.6.0.tgz", + "integrity": "sha512-FuRhDRtsd6IptKpHXAa+4WPZYY2ZzgowkbLBecEDDSje1X/apG7jQM33or3NdOmjXBKWGOg4JmSiRfUfuTtHXw==", "dev": true, "requires": { "@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.5", - "@babel/types": "^7.5.5", + "@babel/generator": "^7.6.0", + "@babel/helpers": "^7.6.0", + "@babel/parser": "^7.6.0", + "@babel/template": "^7.6.0", + "@babel/traverse": "^7.6.0", + "@babel/types": "^7.6.0", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", @@ -510,12 +510,12 @@ } }, "@babel/generator": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", - "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.0.tgz", + "integrity": "sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA==", "dev": true, "requires": { - "@babel/types": "^7.5.5", + "@babel/types": "^7.6.0", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0", @@ -523,32 +523,43 @@ } }, "@babel/parser": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", - "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.0.tgz", + "integrity": "sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ==", "dev": true }, + "@babel/template": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", + "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0" + } + }, "@babel/traverse": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", - "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.0.tgz", + "integrity": "sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", + "@babel/generator": "^7.6.0", "@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", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0", "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==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", + "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -675,32 +686,23 @@ } }, "@babel/helpers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", - "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.6.0.tgz", + "integrity": "sha512-W9kao7OBleOjfXtFGgArGRX6eCP0UEcA2ZWEWNkJdRZnHhW4eEbeswbG3EwaRsnQUAEGWYgMq1HsIXuNNNy2eQ==", "dev": true, "requires": { - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" + "@babel/template": "^7.6.0", + "@babel/traverse": "^7.6.0", + "@babel/types": "^7.6.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==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.0.tgz", + "integrity": "sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA==", "dev": true, "requires": { - "@babel/types": "^7.5.5", + "@babel/types": "^7.6.0", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0", @@ -708,32 +710,54 @@ } }, "@babel/parser": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", - "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.0.tgz", + "integrity": "sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ==", "dev": true }, + "@babel/template": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", + "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0" + } + }, "@babel/traverse": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", - "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.0.tgz", + "integrity": "sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", + "@babel/generator": "^7.6.0", "@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", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" + }, + "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/types": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", - "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", + "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -15520,9 +15544,9 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20190905003010", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190905003010.tgz", - "integrity": "sha512-ZWKZacdgqj01djQdnMTWQZwgd7B/EE3K6xtZz/iNqce4BIjM1Yqf6EgW8I/omHLyQI1N12UlgVGmVWDa/+t3xw==", + "version": "0.1.0-prerelease.20190909235840", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190909235840.tgz", + "integrity": "sha512-Okhb8+iHrs0hCmF93zcTk8dQmKfepjnuTJwestJV9tIy/J0r53qN9FsgWdptx0Cc5iV0nIOVHX+C/ZO9fB//bw==", "dev": true }, "scratch-l10n": { From 5269cf7330ea5ac1f90eac04bb85d57537ba43ae Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Tue, 20 Aug 2019 02:45:16 +0200 Subject: [PATCH 45/67] join flow register user function, registration error component * add yesno checkbox * allow checkbox to be hidden * add registration error, waiting prop to join flow steps * use redux to dispatch session refresh * call register function in join flow * make join flow modal stay showing even when session is refreshed --- .../formik-forms/formik-checkbox.jsx | 11 +- src/components/join-flow/country-step.jsx | 7 + src/components/join-flow/email-step.jsx | 5 +- src/components/join-flow/join-flow-steps.scss | 8 + src/components/join-flow/join-flow.jsx | 143 +++++++++++++++--- .../join-flow/registration-error.jsx | 44 ++++++ src/l10n.json | 1 + 7 files changed, 195 insertions(+), 24 deletions(-) create mode 100644 src/components/join-flow/registration-error.jsx diff --git a/src/components/formik-forms/formik-checkbox.jsx b/src/components/formik-forms/formik-checkbox.jsx index 804c4b855..0c3253c0e 100644 --- a/src/components/formik-forms/formik-checkbox.jsx +++ b/src/components/formik-forms/formik-checkbox.jsx @@ -12,9 +12,10 @@ const FormikCheckboxSubComponent = ({ id, label, labelClassName, + outerClassName, ...props }) => ( -
+
( ); @@ -75,7 +79,8 @@ FormikCheckbox.propTypes = { id: PropTypes.string, label: PropTypes.string, labelClassName: PropTypes.string, - name: PropTypes.string + name: PropTypes.string, + outerClassName: PropTypes.string }; module.exports = FormikCheckbox; diff --git a/src/components/join-flow/country-step.jsx b/src/components/join-flow/country-step.jsx index 86eee7497..de1cfa8e5 100644 --- a/src/components/join-flow/country-step.jsx +++ b/src/components/join-flow/country-step.jsx @@ -8,6 +8,7 @@ const {injectIntl, intlShape} = require('react-intl'); const countryData = require('../../lib/country-data'); const FormikSelect = require('../../components/formik-forms/formik-select.jsx'); const JoinFlowStep = require('./join-flow-step.jsx'); +const FormikCheckbox = require('../../components/formik-forms/formik-checkbox.jsx'); require('./join-flow-steps.scss'); @@ -94,6 +95,12 @@ class CountryStep extends React.Component { validate={this.validateSelect} validationClassName="validation-full-width-input" /> +
); diff --git a/src/components/join-flow/email-step.jsx b/src/components/join-flow/email-step.jsx index 5e42edeac..3da7ef5f1 100644 --- a/src/components/join-flow/email-step.jsx +++ b/src/components/join-flow/email-step.jsx @@ -151,7 +151,7 @@ class EmailStep extends React.Component { innerClassName="join-flow-inner-email-step" nextButton={this.props.intl.formatMessage({id: 'registration.createAccount'})} title={this.props.intl.formatMessage({id: 'registration.emailStepTitle'})} - waiting={isSubmitting || this.state.captchaIsLoading} + waiting={this.props.waiting || isSubmitting || this.state.captchaIsLoading} onSubmit={handleSubmit} > { + api({ + host: '', + uri: '/accounts/register_new_user/', + method: 'post', + useCsrf: true, + formData: { + username: formData.username, + email: formData.email, + password: formData.password, + birth_month: formData.birth_month, + birth_year: formData.birth_year, + gender: ( + formData.gender === 'other' ? + formData.genderOther : + formData.gender + ), + country: formData.country, + subscribe: true, + is_robot: formData.yesno + // csrfmiddlewaretoken: 'abc' + } + }, (err, body, res) => { + this.setState({waiting: false}, () => { + let errStr = ''; + if (!err && res.statusCode === 200) { + if (body && body[0]) { + if (body[0].success) { + this.props.refreshSession(); + this.setState({ + step: this.state.step + 1 + }); + return; + } + if (body[0].errors) { + const errorKeys = Object.keys(body[0].errors); + errorKeys.forEach(key => { + const val = body[0].errors[key]; + if (val && val[0]) { + if (errStr.length) errStr += '; '; + errStr += `${key}: ${val[0]}`; + } + }); + } + if (!errStr.length && body[0].msg) errStr = body[0].msg; + } + } + this.setState({ + registrationError: errStr || + `${this.props.intl.formatMessage({ + id: 'registration.generalError' + })} (${res.statusCode})` + }); + }); + }); + }); + } + handleAdvanceStep (newFormData) { + newFormData = newFormData || {}; + const newState = { + formData: defaults({}, newFormData, this.state.formData) + }; + // for the first 4 steps, automatically advance to next step. + // but for email step, we need to submit registration and wait. + const shouldAdvance = (this.state.step < 4); + const shouldRegister = (this.state.step === 4); + if (shouldAdvance) newState.step = this.state.step + 1; + this.setState(newState, () => { + if (shouldRegister) this.handleRegister(this.state.formData); + }); + } + handleResetForm () { this.setState({ - step: this.state.step + 1, - formData: defaults({}, formData, this.state.formData) + formData: {}, + registrationError: null, + step: 0, + waiting: false }); } render () { return ( - - - - - - - this.handleRegister(this.state.formData)} + /* eslint-enable react/jsx-no-bind */ /> - + ) : ( + + + + + + + + + )} ); } @@ -58,11 +150,24 @@ class JoinFlow extends React.Component { JoinFlow.propTypes = { intl: intlShape, - onCompleteRegistration: PropTypes.func + onCompleteRegistration: PropTypes.func, + refreshSession: PropTypes.func }; -module.exports = injectIntl(JoinFlow); +const IntlJoinFlow = injectIntl(JoinFlow); +const mapDispatchToProps = dispatch => ({ + refreshSession: () => { + dispatch(sessionActions.refreshSession()); + } +}); + +const ConnectedJoinFlow = connect( + () => ({}), + mapDispatchToProps +)(IntlJoinFlow); + +module.exports = ConnectedJoinFlow; /* eslint-enable */ diff --git a/src/components/join-flow/registration-error.jsx b/src/components/join-flow/registration-error.jsx new file mode 100644 index 000000000..3f0431e80 --- /dev/null +++ b/src/components/join-flow/registration-error.jsx @@ -0,0 +1,44 @@ +const bindAll = require('lodash.bindall'); +const React = require('react'); +const PropTypes = require('prop-types'); +const {injectIntl, intlShape} = require('react-intl'); + +const JoinFlowStep = require('./join-flow-step.jsx'); + +require('./join-flow-steps.scss'); + +class RegistrationError extends React.Component { + constructor (props) { + super(props); + bindAll(this, [ + 'handleSubmit' + ]); + this.state = { + }; + } + handleSubmit (e) { + e.preventDefault(); // prevent page reload + this.props.onTryAgain(); + } + render () { + return ( + + ); + } +} + +RegistrationError.propTypes = { + errorMsg: PropTypes.string, + intl: intlShape, + onTryAgain: PropTypes.func +}; + +const IntlRegistrationError = injectIntl(RegistrationError); + +module.exports = IntlRegistrationError; diff --git a/src/l10n.json b/src/l10n.json index 555cbbe39..a88926612 100644 --- a/src/l10n.json +++ b/src/l10n.json @@ -89,6 +89,7 @@ "general.ideas": "Ideas", "general.tipsWindow": "Tips Window", "general.termsOfUse": "Terms of Use", + "general.tryAgain": "Try again", "general.unhandledError": "We are so sorry, but it looks like Scratch has crashed. This bug has been automatically reported to the Scratch Team.", "general.username": "Username", "general.validationEmail": "Please enter a valid email address", From e44d52b735840e07bee2cae221ca62fbf8a41c44 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Mon, 26 Aug 2019 15:46:04 -0400 Subject: [PATCH 46/67] added placeholder for g-recaptcha-response --- src/components/join-flow/join-flow.jsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index 3804d8561..52ef77a15 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -43,12 +43,14 @@ class JoinFlow extends React.Component { uri: '/accounts/register_new_user/', method: 'post', useCsrf: true, + /* eslint-disable quote-props */ formData: { username: formData.username, email: formData.email, password: formData.password, birth_month: formData.birth_month, birth_year: formData.birth_year, + 'g-recaptcha-response': null, gender: ( formData.gender === 'other' ? formData.genderOther : @@ -59,6 +61,7 @@ class JoinFlow extends React.Component { is_robot: formData.yesno // csrfmiddlewaretoken: 'abc' } + /* eslint-enable quote-props */ }, (err, body, res) => { this.setState({waiting: false}, () => { let errStr = ''; From f7a70475e2960e3d152bef22ab054bcfe7874e55 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Fri, 30 Aug 2019 16:19:27 -0400 Subject: [PATCH 47/67] added explanatory join flow comments --- src/components/join-flow/country-step.jsx | 1 + src/components/join-flow/join-flow.jsx | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/join-flow/country-step.jsx b/src/components/join-flow/country-step.jsx index de1cfa8e5..a99f10506 100644 --- a/src/components/join-flow/country-step.jsx +++ b/src/components/join-flow/country-step.jsx @@ -95,6 +95,7 @@ class CountryStep extends React.Component { validate={this.validateSelect} validationClassName="validation-full-width-input" /> + {/* note that this is a hidden checkbox the user will never see */} { @@ -75,6 +77,9 @@ class JoinFlow extends React.Component { return; } if (body[0].errors) { + // body can include zero or more error objects, each + // with its own key and description. Here we assemble + // all of them into a single string, errStr. const errorKeys = Object.keys(body[0].errors); errorKeys.forEach(key => { const val = body[0].errors[key]; From 3809d83c366a616c434d24e64fb5c9589d2b88da Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Fri, 30 Aug 2019 16:20:05 -0400 Subject: [PATCH 48/67] rename RegistrationError to RegistrationErrorStep --- src/components/join-flow/join-flow.jsx | 4 ++-- ...istration-error.jsx => registration-error-step.jsx} | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) rename src/components/join-flow/{registration-error.jsx => registration-error-step.jsx} (82%) diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index 632288b74..3efb29b09 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -16,7 +16,7 @@ const GenderStep = require('./gender-step.jsx'); const CountryStep = require('./country-step.jsx'); const EmailStep = require('./email-step.jsx'); const WelcomeStep = require('./welcome-step.jsx'); -const RegistrationError = require('./registration-error.jsx'); +const RegistrationErrorStep = require('./registration-error-step.jsx'); /* eslint-disable react/prefer-stateless-function, react/no-unused-prop-types, no-useless-constructor @@ -128,7 +128,7 @@ class JoinFlow extends React.Component { return ( {this.state.registrationError ? ( - this.handleRegister(this.state.formData)} diff --git a/src/components/join-flow/registration-error.jsx b/src/components/join-flow/registration-error-step.jsx similarity index 82% rename from src/components/join-flow/registration-error.jsx rename to src/components/join-flow/registration-error-step.jsx index 3f0431e80..0f4bd26fe 100644 --- a/src/components/join-flow/registration-error.jsx +++ b/src/components/join-flow/registration-error-step.jsx @@ -7,14 +7,12 @@ const JoinFlowStep = require('./join-flow-step.jsx'); require('./join-flow-steps.scss'); -class RegistrationError extends React.Component { +class RegistrationErrorStep extends React.Component { constructor (props) { super(props); bindAll(this, [ 'handleSubmit' ]); - this.state = { - }; } handleSubmit (e) { e.preventDefault(); // prevent page reload @@ -33,12 +31,12 @@ class RegistrationError extends React.Component { } } -RegistrationError.propTypes = { +RegistrationErrorStep.propTypes = { errorMsg: PropTypes.string, intl: intlShape, onTryAgain: PropTypes.func }; -const IntlRegistrationError = injectIntl(RegistrationError); +const IntlRegistrationErrorStep = injectIntl(RegistrationErrorStep); -module.exports = IntlRegistrationError; +module.exports = IntlRegistrationErrorStep; From ce5558f8e2627cbb5ecc21494c7d2824ab0bff26 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Fri, 30 Aug 2019 16:20:26 -0400 Subject: [PATCH 49/67] refactor advance step and register functions --- src/components/join-flow/join-flow.jsx | 38 +++++++++++--------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index 3efb29b09..a3710b638 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -26,8 +26,8 @@ class JoinFlow extends React.Component { super(props); bindAll(this, [ 'handleAdvanceStep', - 'handleRegister', - 'handleResetForm' + 'handlePrepareToRegister', + 'handleSubmitRegistration' ]); this.state = { formData: {}, @@ -36,7 +36,16 @@ class JoinFlow extends React.Component { waiting: false }; } - handleRegister (formData) { + handlePrepareToRegister (newFormData) { + newFormData = newFormData || {}; + const newState = { + formData: defaults({}, newFormData, this.state.formData) + }; + this.setState(newState, () => { + this.handleSubmitRegistration(this.state.formData); + }); + } + handleSubmitRegistration (formData) { this.setState({waiting: true}, () => { api({ host: '', @@ -104,24 +113,9 @@ class JoinFlow extends React.Component { } handleAdvanceStep (newFormData) { newFormData = newFormData || {}; - const newState = { - formData: defaults({}, newFormData, this.state.formData) - }; - // for the first 4 steps, automatically advance to next step. - // but for email step, we need to submit registration and wait. - const shouldAdvance = (this.state.step < 4); - const shouldRegister = (this.state.step === 4); - if (shouldAdvance) newState.step = this.state.step + 1; - this.setState(newState, () => { - if (shouldRegister) this.handleRegister(this.state.formData); - }); - } - handleResetForm () { this.setState({ - formData: {}, - registrationError: null, - step: 0, - waiting: false + formData: defaults({}, newFormData, this.state.formData), + step: this.state.step + 1 }); } render () { @@ -131,7 +125,7 @@ class JoinFlow extends React.Component { this.handleRegister(this.state.formData)} + onTryAgain={() => this.handleSubmitRegistration(this.state.formData)} /* eslint-enable react/jsx-no-bind */ /> ) : ( @@ -142,7 +136,7 @@ class JoinFlow extends React.Component { Date: Tue, 3 Sep 2019 17:41:22 -0400 Subject: [PATCH 50/67] use consistent quotes in object keys --- src/components/join-flow/join-flow.jsx | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index a3710b638..09ad742fb 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -52,27 +52,21 @@ class JoinFlow extends React.Component { uri: '/accounts/register_new_user/', method: 'post', useCsrf: true, - /* eslint-disable quote-props */ formData: { - username: formData.username, - email: formData.email, - password: formData.password, - birth_month: formData.birth_month, - birth_year: formData.birth_year, + 'username': formData.username, + 'email': formData.email, + 'password': formData.password, + 'birth_month': formData.birth_month, + 'birth_year': formData.birth_year, 'g-recaptcha-response': null, - gender: ( - formData.gender === 'other' ? - formData.genderOther : - formData.gender - ), - country: formData.country, - subscribe: true, - is_robot: formData.yesno + 'gender': formData.gender, + 'country': formData.country, + 'subscribe': true, + 'is_robot': formData.yesno // no need to include csrfmiddlewaretoken; will be provided in // X-CSRFToken header, which scratchr2 looks for in // scratchr2/middleware/csrf.py line 237. } - /* eslint-enable quote-props */ }, (err, body, res) => { this.setState({waiting: false}, () => { let errStr = ''; From 643b4a611b7a848895daaf038d74a809d7a469ea Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Tue, 3 Sep 2019 17:41:40 -0400 Subject: [PATCH 51/67] comment preventDefault() --- src/components/join-flow/registration-error-step.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/join-flow/registration-error-step.jsx b/src/components/join-flow/registration-error-step.jsx index 0f4bd26fe..24457d26a 100644 --- a/src/components/join-flow/registration-error-step.jsx +++ b/src/components/join-flow/registration-error-step.jsx @@ -15,7 +15,10 @@ class RegistrationErrorStep extends React.Component { ]); } handleSubmit (e) { - e.preventDefault(); // prevent page reload + // JoinFlowStep includes a
that handles a submit action. + // But here, we're not really submitting, so we need to prevent + // the form from navigating away from the current page. + e.preventDefault(); this.props.onTryAgain(); } render () { From 1d976c7cdff8c9c342cf19774dcdf24b45d7ded3 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Tue, 3 Sep 2019 18:27:11 -0400 Subject: [PATCH 52/67] refactor handleRegistrationResponse --- src/components/join-flow/join-flow.jsx | 72 ++++++++++++++------------ 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index 09ad742fb..82351bb92 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -27,6 +27,7 @@ class JoinFlow extends React.Component { bindAll(this, [ 'handleAdvanceStep', 'handlePrepareToRegister', + 'handleRegistrationResponse', 'handleSubmitRegistration' ]); this.state = { @@ -45,6 +46,42 @@ class JoinFlow extends React.Component { this.handleSubmitRegistration(this.state.formData); }); } + handleRegistrationResponse (err, body, res) { + this.setState({waiting: false}, () => { + let errStr = ''; + if (!err && res.statusCode === 200) { + if (body && body[0]) { + if (body[0].success) { + this.props.refreshSession(); + this.setState({ + step: this.state.step + 1 + }); + return; + } + if (body[0].errors) { + // body can include zero or more error objects, each + // with its own key and description. Here we assemble + // all of them into a single string, errStr. + const errorKeys = Object.keys(body[0].errors); + errorKeys.forEach(key => { + const val = body[0].errors[key]; + if (val && val[0]) { + if (errStr.length) errStr += '; '; + errStr += `${key}: ${val[0]}`; + } + }); + } + if (!errStr.length && body[0].msg) errStr = body[0].msg; + } + } + this.setState({ + registrationError: errStr || + `${this.props.intl.formatMessage({ + id: 'registration.generalError' + })} (${res.statusCode})` + }); + }); + } handleSubmitRegistration (formData) { this.setState({waiting: true}, () => { api({ @@ -68,40 +105,7 @@ class JoinFlow extends React.Component { // scratchr2/middleware/csrf.py line 237. } }, (err, body, res) => { - this.setState({waiting: false}, () => { - let errStr = ''; - if (!err && res.statusCode === 200) { - if (body && body[0]) { - if (body[0].success) { - this.props.refreshSession(); - this.setState({ - step: this.state.step + 1 - }); - return; - } - if (body[0].errors) { - // body can include zero or more error objects, each - // with its own key and description. Here we assemble - // all of them into a single string, errStr. - const errorKeys = Object.keys(body[0].errors); - errorKeys.forEach(key => { - const val = body[0].errors[key]; - if (val && val[0]) { - if (errStr.length) errStr += '; '; - errStr += `${key}: ${val[0]}`; - } - }); - } - if (!errStr.length && body[0].msg) errStr = body[0].msg; - } - } - this.setState({ - registrationError: errStr || - `${this.props.intl.formatMessage({ - id: 'registration.generalError' - })} (${res.statusCode})` - }); - }); + this.handleRegistrationResponse(err, body, res); }); }); } From a9a1f9a3b1824c1000c6dcc529a93a501a37509a Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 4 Sep 2019 22:54:49 -0400 Subject: [PATCH 53/67] add redux mock store --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index c7f8f8b1c..d6a9e314a 100644 --- a/package.json +++ b/package.json @@ -123,6 +123,7 @@ "react-string-replace": "0.4.1", "react-telephone-input": "4.3.4", "redux": "3.5.2", + "redux-mock-store": "^1.2.3", "redux-thunk": "2.0.1", "sass-loader": "6.0.6", "scratch-gui": "0.1.0-prerelease.20190909235840", From aec4d9020168cae5c3c67d575aeef15130a7fd31 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 4 Sep 2019 23:32:39 -0400 Subject: [PATCH 54/67] join flow test --- test/unit/components/join-flow.test.jsx | 136 ++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 test/unit/components/join-flow.test.jsx diff --git a/test/unit/components/join-flow.test.jsx b/test/unit/components/join-flow.test.jsx new file mode 100644 index 000000000..09dcd204f --- /dev/null +++ b/test/unit/components/join-flow.test.jsx @@ -0,0 +1,136 @@ +import React from 'react'; +const {shallowWithIntl} = require('../../helpers/intl-helpers.jsx'); +import configureStore from 'redux-mock-store'; +import JoinFlow from '../../../src/components/join-flow/join-flow'; + +describe('JoinFlow', () => { + const mockStore = configureStore(); + let store; + + beforeEach(() => { + store = mockStore({sessionActions: { + refreshSession: jest.fn() + }}); + }); + + const getJoinFlowInstance = props => { + const wrapper = shallowWithIntl( + + , {context: {store}}); + return wrapper + .dive() // unwrap redux connect(injectIntl(JoinFlow)) + .dive() // unwrap injectIntl(JoinFlow) + .instance(); // JoinFlow + } + + test('handleRegistrationResponse with successful response', () => { + const props = { + refreshSession: jest.fn() + }; + const joinFlowInstance = getJoinFlowInstance(props); + const responseErr = null; + const responseBody = [ + { + success: true + } + ]; + const responseObj = { + statusCode: 200 + }; + joinFlowInstance.handleRegistrationResponse(responseErr, responseBody, responseObj); + expect(joinFlowInstance.props.refreshSession).toHaveBeenCalled(); + expect(joinFlowInstance.state.registrationError).toBe(null); + }); + + test('handleRegistrationResponse with healthy response, indicating failure', () => { + const props = { + refreshSession: jest.fn() + }; + const joinFlowInstance = getJoinFlowInstance(props); + const responseErr = null; + const responseBody = [ + { + msg: 'This field is required.', + errors: { + username: ['This field is required.'] + }, + success: false + } + ]; + const responseObj = { + statusCode: 200 + }; + joinFlowInstance.handleRegistrationResponse(responseErr, responseBody, responseObj); + expect(joinFlowInstance.props.refreshSession).not.toHaveBeenCalled(); + expect(joinFlowInstance.state.registrationError).toBe('username: This field is required.'); + }); + + test('handleRegistrationResponse with failure response, with error fields missing', () => { + const props = { + refreshSession: jest.fn() + }; + const joinFlowInstance = getJoinFlowInstance(props); + const responseErr = null; + const responseBody = [ + { + msg: 'This field is required.', + success: false + } + ]; + const responseObj = { + statusCode: 200 + }; + joinFlowInstance.handleRegistrationResponse(responseErr, responseBody, responseObj); + expect(joinFlowInstance.props.refreshSession).not.toHaveBeenCalled(); + expect(joinFlowInstance.state.registrationError).toBe('This field is required.'); + }); + + test('handleRegistrationResponse with failure response, with no text explanation', () => { + const props = { + refreshSession: jest.fn() + }; + const joinFlowInstance = getJoinFlowInstance(props); + const responseErr = null; + const responseBody = [ + { + success: false + } + ]; + const responseObj = { + statusCode: 200 + }; + joinFlowInstance.handleRegistrationResponse(responseErr, responseBody, responseObj); + expect(joinFlowInstance.props.refreshSession).not.toHaveBeenCalled(); + expect(joinFlowInstance.state.registrationError).toBe('registration.generalError (200)'); + }); + + test('handleRegistrationResponse with failure status code', () => { + const props = { + refreshSession: jest.fn() + }; + const joinFlowInstance = getJoinFlowInstance(props); + const responseErr = null; + const responseBody = [ + { + success: false + } + ]; + const responseObj = { + statusCode: 400 + }; + joinFlowInstance.handleRegistrationResponse(responseErr, responseBody, responseObj); + expect(joinFlowInstance.props.refreshSession).not.toHaveBeenCalled(); + expect(joinFlowInstance.state.registrationError).toBe('registration.generalError (400)'); + }); + + test('handleAdvanceStep', () => { + const joinFlowInstance = getJoinFlowInstance(); + joinFlowInstance.setState({formData: {username: 'ScratchCat123'}, step: 2}); + joinFlowInstance.handleAdvanceStep({email: 'scratchcat123@scratch.mit.edu'}); + expect(joinFlowInstance.state.formData.username).toBe('ScratchCat123'); + expect(joinFlowInstance.state.formData.email).toBe('scratchcat123@scratch.mit.edu'); + expect(joinFlowInstance.state.step).toBe(3); + }); +}); From 74dbec2d6637e036d3028b38459407a4bae4d9af Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 4 Sep 2019 23:32:49 -0400 Subject: [PATCH 55/67] registration error test --- .../registration-error-step.test.jsx | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 test/unit/components/registration-error-step.test.jsx diff --git a/test/unit/components/registration-error-step.test.jsx b/test/unit/components/registration-error-step.test.jsx new file mode 100644 index 000000000..e87e9b88a --- /dev/null +++ b/test/unit/components/registration-error-step.test.jsx @@ -0,0 +1,33 @@ +import React from 'react'; +import {shallowWithIntl} from '../../helpers/intl-helpers.jsx'; +import JoinFlowStep from '../../../src/components/join-flow/join-flow-step'; +import RegistrationErrorStep from '../../../src/components/join-flow/registration-error-step'; + +describe('RegistrationErrorStep', () => { + const onTryAgain = jest.fn(); + let wrapper; + + beforeEach(() => { + wrapper = shallowWithIntl( + + ); + }); + + test('shows JoinFlowStep with props', () => { + // Dive to get past the anonymous component. + const joinFlowStepWrapper = wrapper.dive().find(JoinFlowStep); + expect(joinFlowStepWrapper).toHaveLength(1); + expect(joinFlowStepWrapper.props().description).toBe('error message'); + expect(joinFlowStepWrapper.props().nextButton).toBe('general.tryAgain'); + }); + + test('when submitted, onTryAgain is called', () => { + // Dive to get past the anonymous component. + const joinFlowStepWrapper = wrapper.dive().find(JoinFlowStep); + joinFlowStepWrapper.props().onSubmit(new Event('event')); // eslint-disable-line no-undef + expect(onTryAgain).toHaveBeenCalled(); + }); +}); From 45629620b35996b6c0e45be69afceef7f15a144f Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 4 Sep 2019 23:33:01 -0400 Subject: [PATCH 56/67] package-lock --- package-lock.json | 1085 ++++++++++++++++++++++----------------------- 1 file changed, 539 insertions(+), 546 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9f34ded3f..286376895 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,471 +4,6 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@babel/cli": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.6.0.tgz", - "integrity": "sha512-1CTDyGUjQqW3Mz4gfKZ04KGOckyyaNmKneAMlABPS+ZyuxWv3FrVEVz7Ag08kNIztVx8VaJ8YgvYLSNlMKAT5Q==", - "dev": true, - "requires": { - "chokidar": "^2.1.8", - "commander": "^2.8.1", - "convert-source-map": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.0.0", - "lodash": "^4.17.13", - "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.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "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", @@ -479,18 +14,18 @@ } }, "@babel/core": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.6.0.tgz", - "integrity": "sha512-FuRhDRtsd6IptKpHXAa+4WPZYY2ZzgowkbLBecEDDSje1X/apG7jQM33or3NdOmjXBKWGOg4JmSiRfUfuTtHXw==", + "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.5.5", - "@babel/generator": "^7.6.0", - "@babel/helpers": "^7.6.0", - "@babel/parser": "^7.6.0", - "@babel/template": "^7.6.0", - "@babel/traverse": "^7.6.0", - "@babel/types": "^7.6.0", + "@babel/generator": "^7.5.5", + "@babel/helpers": "^7.5.5", + "@babel/parser": "^7.5.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", @@ -510,12 +45,12 @@ } }, "@babel/generator": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.0.tgz", - "integrity": "sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA==", + "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.6.0", + "@babel/types": "^7.5.5", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0", @@ -523,43 +58,32 @@ } }, "@babel/parser": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.0.tgz", - "integrity": "sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", "dev": true }, - "@babel/template": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", - "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.6.0", - "@babel/types": "^7.6.0" - } - }, "@babel/traverse": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.0.tgz", - "integrity": "sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ==", + "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.6.0", + "@babel/generator": "^7.5.5", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.6.0", - "@babel/types": "^7.6.0", + "@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.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", + "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", @@ -686,23 +210,32 @@ } }, "@babel/helpers": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.6.0.tgz", - "integrity": "sha512-W9kao7OBleOjfXtFGgArGRX6eCP0UEcA2ZWEWNkJdRZnHhW4eEbeswbG3EwaRsnQUAEGWYgMq1HsIXuNNNy2eQ==", + "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.6.0", - "@babel/traverse": "^7.6.0", - "@babel/types": "^7.6.0" + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" }, "dependencies": { - "@babel/generator": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.0.tgz", - "integrity": "sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA==", + "@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/types": "^7.6.0", + "@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", @@ -710,54 +243,32 @@ } }, "@babel/parser": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.0.tgz", - "integrity": "sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", "dev": true }, - "@babel/template": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", - "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.6.0", - "@babel/types": "^7.6.0" - } - }, "@babel/traverse": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.0.tgz", - "integrity": "sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ==", + "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.6.0", + "@babel/generator": "^7.5.5", "@babel/helper-function-name": "^7.1.0", "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.6.0", - "@babel/types": "^7.6.0", + "@babel/parser": "^7.5.5", + "@babel/types": "^7.5.5", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" - }, - "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/types": { - "version": "7.6.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", - "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", + "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", @@ -14686,6 +14197,23 @@ "symbol-observable": "^0.2.3" } }, + "redux-mock-store": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/redux-mock-store/-/redux-mock-store-1.5.3.tgz", + "integrity": "sha512-ryhkkb/4D4CUGpAV2ln1GOY/uh51aczjcRz9k2L2bPx/Xja3c5pSGJJPyR25GNVRXtKIExScdAgFdiXp68GmJA==", + "dev": true, + "requires": { + "lodash.isplainobject": "^4.0.6" + }, + "dependencies": { + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + } + } + }, "redux-thunk": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.0.1.tgz", @@ -15559,6 +15087,471 @@ "@babel/core": "^7.1.2", "babel-plugin-react-intl": "^3.0.1", "transifex": "1.6.6" + }, + "dependencies": { + "@babel/cli": { + "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", + "commander": "^2.8.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.13", + "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.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "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": { From 9ea6cc8d4232857fe579d72c460f450940388952 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 4 Sep 2019 23:33:43 -0400 Subject: [PATCH 57/67] use mergeProps to make tests work --- src/components/join-flow/join-flow.jsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index 82351bb92..ff8727c77 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -162,9 +162,15 @@ const mapDispatchToProps = dispatch => ({ } }); +// Allow incoming props to override redux-provided props. Used to mock in tests. +const mergeProps = (stateProps, dispatchProps, ownProps) => Object.assign( + {}, stateProps, dispatchProps, ownProps +); + const ConnectedJoinFlow = connect( () => ({}), - mapDispatchToProps + mapDispatchToProps, + mergeProps )(IntlJoinFlow); module.exports = ConnectedJoinFlow; From ce3921bec5ff9f49936078fbb11d152a7409fe58 Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 4 Sep 2019 23:34:03 -0400 Subject: [PATCH 58/67] update join flow lint exceptions --- src/components/join-flow/join-flow.jsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index ff8727c77..879e4b227 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -18,9 +18,6 @@ const EmailStep = require('./email-step.jsx'); const WelcomeStep = require('./welcome-step.jsx'); const RegistrationErrorStep = require('./registration-error-step.jsx'); -/* -eslint-disable react/prefer-stateless-function, react/no-unused-prop-types, no-useless-constructor -*/ class JoinFlow extends React.Component { constructor (props) { super(props); @@ -174,6 +171,3 @@ const ConnectedJoinFlow = connect( )(IntlJoinFlow); module.exports = ConnectedJoinFlow; -/* -eslint-enable -*/ From 7587c6858281d6b65650ebb474664d0549de08ec Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Wed, 4 Sep 2019 23:34:17 -0400 Subject: [PATCH 59/67] include example of failing response --- src/components/join-flow/join-flow.jsx | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index 879e4b227..989ce7f14 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -44,6 +44,17 @@ class JoinFlow extends React.Component { }); } handleRegistrationResponse (err, body, res) { + // example of failing response: + // [ + // { + // "msg": "This field is required.", + // "errors": { + // "username": ["This field is required."], + // "recaptcha": ["Incorrect, please try again."] + // }, + // "success": false + // } + // ] this.setState({waiting: false}, () => { let errStr = ''; if (!err && res.statusCode === 200) { From 2c2de08ed325c7dae37ebcc7d5221093bf37005d Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Thu, 5 Sep 2019 11:21:09 -0400 Subject: [PATCH 60/67] added tests for RegistrationErrorStep vs Progression --- test/unit/components/join-flow.test.jsx | 51 +++++++++++++++++++------ 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/test/unit/components/join-flow.test.jsx b/test/unit/components/join-flow.test.jsx index 09dcd204f..80dfe5a14 100644 --- a/test/unit/components/join-flow.test.jsx +++ b/test/unit/components/join-flow.test.jsx @@ -2,6 +2,8 @@ import React from 'react'; const {shallowWithIntl} = require('../../helpers/intl-helpers.jsx'); import configureStore from 'redux-mock-store'; import JoinFlow from '../../../src/components/join-flow/join-flow'; +import Progression from '../../../src/components/progression/progression.jsx'; +import RegistrationErrorStep from '../../../src/components/join-flow/registration-error-step'; describe('JoinFlow', () => { const mockStore = configureStore(); @@ -13,23 +15,23 @@ describe('JoinFlow', () => { }}); }); - const getJoinFlowInstance = props => { + const getJoinFlowWrapper = props => { const wrapper = shallowWithIntl( - , {context: {store}}); + , {context: {store}} + ); return wrapper .dive() // unwrap redux connect(injectIntl(JoinFlow)) - .dive() // unwrap injectIntl(JoinFlow) - .instance(); // JoinFlow - } + .dive(); // unwrap injectIntl(JoinFlow) + }; test('handleRegistrationResponse with successful response', () => { const props = { refreshSession: jest.fn() }; - const joinFlowInstance = getJoinFlowInstance(props); + const joinFlowInstance = getJoinFlowWrapper(props).instance(); const responseErr = null; const responseBody = [ { @@ -48,7 +50,7 @@ describe('JoinFlow', () => { const props = { refreshSession: jest.fn() }; - const joinFlowInstance = getJoinFlowInstance(props); + const joinFlowInstance = getJoinFlowWrapper(props).instance(); const responseErr = null; const responseBody = [ { @@ -71,7 +73,7 @@ describe('JoinFlow', () => { const props = { refreshSession: jest.fn() }; - const joinFlowInstance = getJoinFlowInstance(props); + const joinFlowInstance = getJoinFlowWrapper(props).instance(); const responseErr = null; const responseBody = [ { @@ -91,7 +93,7 @@ describe('JoinFlow', () => { const props = { refreshSession: jest.fn() }; - const joinFlowInstance = getJoinFlowInstance(props); + const joinFlowInstance = getJoinFlowWrapper(props).instance(); const responseErr = null; const responseBody = [ { @@ -110,7 +112,7 @@ describe('JoinFlow', () => { const props = { refreshSession: jest.fn() }; - const joinFlowInstance = getJoinFlowInstance(props); + const joinFlowInstance = getJoinFlowWrapper(props).instance(); const responseErr = null; const responseBody = [ { @@ -126,11 +128,38 @@ describe('JoinFlow', () => { }); test('handleAdvanceStep', () => { - const joinFlowInstance = getJoinFlowInstance(); + const joinFlowInstance = getJoinFlowWrapper().instance(); joinFlowInstance.setState({formData: {username: 'ScratchCat123'}, step: 2}); joinFlowInstance.handleAdvanceStep({email: 'scratchcat123@scratch.mit.edu'}); expect(joinFlowInstance.state.formData.username).toBe('ScratchCat123'); expect(joinFlowInstance.state.formData.email).toBe('scratchcat123@scratch.mit.edu'); expect(joinFlowInstance.state.step).toBe(3); }); + + test('when state.registrationError has error message, we show RegistrationErrorStep', () => { + const joinFlowWrapper = getJoinFlowWrapper(); + joinFlowWrapper.instance().setState({registrationError: 'halp there is a errors!!'}); + const registrationErrorWrapper = joinFlowWrapper.find(RegistrationErrorStep); + const progressionWrapper = joinFlowWrapper.find(Progression); + expect(registrationErrorWrapper).toHaveLength(1); + expect(progressionWrapper).toHaveLength(0); + }); + + test('when state.registrationError has null error message, we show Progression', () => { + const joinFlowWrapper = getJoinFlowWrapper(); + joinFlowWrapper.instance().setState({registrationError: null}); + const registrationErrorWrapper = joinFlowWrapper.find(RegistrationErrorStep); + const progressionWrapper = joinFlowWrapper.find(Progression); + expect(registrationErrorWrapper).toHaveLength(0); + expect(progressionWrapper).toHaveLength(1); + }); + + test('when state.registrationError has empty error message, we show Progression', () => { + const joinFlowWrapper = getJoinFlowWrapper(); + joinFlowWrapper.instance().setState({registrationError: ''}); + const registrationErrorWrapper = joinFlowWrapper.find(RegistrationErrorStep); + const progressionWrapper = joinFlowWrapper.find(Progression); + expect(registrationErrorWrapper).toHaveLength(0); + expect(progressionWrapper).toHaveLength(1); + }); }); From b15dcaa2bcf421d8dd0def31389626af3d16a522 Mon Sep 17 00:00:00 2001 From: picklesrus Date: Wed, 11 Sep 2019 12:36:56 -0400 Subject: [PATCH 61/67] Add captcha token to ther request. It was left out of #3291. --- src/components/join-flow/join-flow.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/join-flow/join-flow.jsx b/src/components/join-flow/join-flow.jsx index 989ce7f14..93554102d 100644 --- a/src/components/join-flow/join-flow.jsx +++ b/src/components/join-flow/join-flow.jsx @@ -103,7 +103,7 @@ class JoinFlow extends React.Component { 'password': formData.password, 'birth_month': formData.birth_month, 'birth_year': formData.birth_year, - 'g-recaptcha-response': null, + 'g-recaptcha-response': formData['g-recaptcha-response'], 'gender': formData.gender, 'country': formData.country, 'subscribe': true, From e5d6e8ad1d202b3578bc4186ca5a3b52f236a477 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2019 21:52:14 +0000 Subject: [PATCH 62/67] chore(package): update scratch-gui to version 0.1.0-prerelease.20190911174033 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d6a9e314a..0fe65f8be 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "redux-mock-store": "^1.2.3", "redux-thunk": "2.0.1", "sass-loader": "6.0.6", - "scratch-gui": "0.1.0-prerelease.20190909235840", + "scratch-gui": "0.1.0-prerelease.20190911174033", "scratch-l10n": "latest", "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0", From d0a71c761ba361c7e54594a11b1ae08c817a1894 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Wed, 11 Sep 2019 21:52:18 +0000 Subject: [PATCH 63/67] chore(package): update lockfile package-lock.json --- package-lock.json | 1078 +++++++++++++++++++++++---------------------- 1 file changed, 551 insertions(+), 527 deletions(-) diff --git a/package-lock.json b/package-lock.json index 286376895..6490e5815 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,471 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/cli": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.6.0.tgz", + "integrity": "sha512-1CTDyGUjQqW3Mz4gfKZ04KGOckyyaNmKneAMlABPS+ZyuxWv3FrVEVz7Ag08kNIztVx8VaJ8YgvYLSNlMKAT5Q==", + "dev": true, + "requires": { + "chokidar": "^2.1.8", + "commander": "^2.8.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.13", + "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.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "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", @@ -14,18 +479,18 @@ } }, "@babel/core": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", - "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.6.0.tgz", + "integrity": "sha512-FuRhDRtsd6IptKpHXAa+4WPZYY2ZzgowkbLBecEDDSje1X/apG7jQM33or3NdOmjXBKWGOg4JmSiRfUfuTtHXw==", "dev": true, "requires": { "@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.5", - "@babel/types": "^7.5.5", + "@babel/generator": "^7.6.0", + "@babel/helpers": "^7.6.0", + "@babel/parser": "^7.6.0", + "@babel/template": "^7.6.0", + "@babel/traverse": "^7.6.0", + "@babel/types": "^7.6.0", "convert-source-map": "^1.1.0", "debug": "^4.1.0", "json5": "^2.1.0", @@ -45,12 +510,12 @@ } }, "@babel/generator": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", - "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.0.tgz", + "integrity": "sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA==", "dev": true, "requires": { - "@babel/types": "^7.5.5", + "@babel/types": "^7.6.0", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0", @@ -58,32 +523,43 @@ } }, "@babel/parser": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", - "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.0.tgz", + "integrity": "sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ==", "dev": true }, + "@babel/template": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", + "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0" + } + }, "@babel/traverse": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", - "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.0.tgz", + "integrity": "sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", + "@babel/generator": "^7.6.0", "@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", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0", "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==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", + "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -210,32 +686,23 @@ } }, "@babel/helpers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", - "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.6.0.tgz", + "integrity": "sha512-W9kao7OBleOjfXtFGgArGRX6eCP0UEcA2ZWEWNkJdRZnHhW4eEbeswbG3EwaRsnQUAEGWYgMq1HsIXuNNNy2eQ==", "dev": true, "requires": { - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" + "@babel/template": "^7.6.0", + "@babel/traverse": "^7.6.0", + "@babel/types": "^7.6.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==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.0.tgz", + "integrity": "sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA==", "dev": true, "requires": { - "@babel/types": "^7.5.5", + "@babel/types": "^7.6.0", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0", @@ -243,32 +710,54 @@ } }, "@babel/parser": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", - "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.0.tgz", + "integrity": "sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ==", "dev": true }, + "@babel/template": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz", + "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0" + } + }, "@babel/traverse": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", - "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.0.tgz", + "integrity": "sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ==", "dev": true, "requires": { "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", + "@babel/generator": "^7.6.0", "@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", + "@babel/parser": "^7.6.0", + "@babel/types": "^7.6.0", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" + }, + "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/types": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", - "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz", + "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -15072,486 +15561,21 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20190909235840", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190909235840.tgz", - "integrity": "sha512-Okhb8+iHrs0hCmF93zcTk8dQmKfepjnuTJwestJV9tIy/J0r53qN9FsgWdptx0Cc5iV0nIOVHX+C/ZO9fB//bw==", + "version": "0.1.0-prerelease.20190911174033", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190911174033.tgz", + "integrity": "sha512-xgxD3iHnbKkdpkpzZzLcpsimbHnRy/XpZfTw+/ByaXKnMMOPkK11IOjU/yFfRcFLzotrfMqJyC7dF9hNGqHUxQ==", "dev": true }, "scratch-l10n": { - "version": "3.5.20190903223516", - "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.5.20190903223516.tgz", - "integrity": "sha512-loXTVKRoostwA1HRLe2AuPU1j0KbLwilGzPmdnwd3yPTsdTjElEecZWprPVOIlIr9epvJVIybCNixuHtWbyCkg==", + "version": "3.5.20190910223701", + "resolved": "https://registry.npmjs.org/scratch-l10n/-/scratch-l10n-3.5.20190910223701.tgz", + "integrity": "sha512-WArZ1OZZz8KcTyEHcUnRJJE6gyh3CDcZ3KYxK8TNoHqzdLi+Gl/1QR/Xs+rJ1U587hnI2JLRfhFfvVPwsdmZag==", "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.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", - "commander": "^2.8.1", - "convert-source-map": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.0.0", - "lodash": "^4.17.13", - "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.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "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": { From cc578109fa3af398f800233273a4e716b9adcc1c Mon Sep 17 00:00:00 2001 From: Ben Wheeler Date: Thu, 12 Sep 2019 10:45:48 -0400 Subject: [PATCH 64/67] put back missing refreshSession() call --- src/redux/navigation.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/redux/navigation.js b/src/redux/navigation.js index d8dd5ee31..a7ff091a8 100644 --- a/src/redux/navigation.js +++ b/src/redux/navigation.js @@ -96,6 +96,7 @@ module.exports.handleCompleteRegistration = createProject => (dispatch => { if (createProject) { window.location = '/projects/editor/?tutorial=getStarted'; } else { + dispatch(sessionActions.refreshSession()); dispatch(module.exports.setRegistrationOpen(false)); } }); From ab35d1ee64189314ea71604902e0dbd6e6574570 Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Thu, 12 Sep 2019 09:46:06 -0700 Subject: [PATCH 65/67] release Scratch Desktop 3.6.0 --- src/views/download/download.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/download/download.jsx b/src/views/download/download.jsx index 35c5994ca..2c935f04b 100644 --- a/src/views/download/download.jsx +++ b/src/views/download/download.jsx @@ -114,8 +114,8 @@ class Download extends React.Component { className="download-button" href={ this.state.OS === OS_ENUM.WINDOWS ? - 'https://downloads.scratch.mit.edu/desktop/Scratch%20Desktop%20Setup%203.5.0.exe' : - 'https://downloads.scratch.mit.edu/desktop/Scratch%20Desktop-3.5.0.dmg' + 'https://downloads.scratch.mit.edu/desktop/Scratch%20Desktop%20Setup%203.6.0.exe' : + 'https://downloads.scratch.mit.edu/desktop/Scratch%20Desktop-3.6.0.dmg' } > From ea5bbee3a96bca8bf81104c481b8872f081251a8 Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2019 18:23:20 +0000 Subject: [PATCH 66/67] chore(package): update scratch-gui to version 0.1.0-prerelease.20190912180550 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0fe65f8be..4b1735e83 100644 --- a/package.json +++ b/package.json @@ -126,7 +126,7 @@ "redux-mock-store": "^1.2.3", "redux-thunk": "2.0.1", "sass-loader": "6.0.6", - "scratch-gui": "0.1.0-prerelease.20190911174033", + "scratch-gui": "0.1.0-prerelease.20190912180550", "scratch-l10n": "latest", "selenium-webdriver": "3.6.0", "slick-carousel": "1.6.0", From ce62a0da9348ce2e9c31f583c3d40623c9170eca Mon Sep 17 00:00:00 2001 From: "greenkeeper[bot]" <23040076+greenkeeper[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2019 18:23:24 +0000 Subject: [PATCH 67/67] chore(package): update lockfile package-lock.json --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6490e5815..636680aed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15561,9 +15561,9 @@ } }, "scratch-gui": { - "version": "0.1.0-prerelease.20190911174033", - "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190911174033.tgz", - "integrity": "sha512-xgxD3iHnbKkdpkpzZzLcpsimbHnRy/XpZfTw+/ByaXKnMMOPkK11IOjU/yFfRcFLzotrfMqJyC7dF9hNGqHUxQ==", + "version": "0.1.0-prerelease.20190912180550", + "resolved": "https://registry.npmjs.org/scratch-gui/-/scratch-gui-0.1.0-prerelease.20190912180550.tgz", + "integrity": "sha512-FPOuX1Za4vNAhOJfViEigGJ5t+dWzebgrUQWAvJDwrkhfKKHD2VE9vtaGH6H+6NNZIdW+2qcSqBPxutevdHlyA==", "dev": true }, "scratch-l10n": {