From ae72d8dce5cd6855d6a64a5aa6ee029d7209f3e5 Mon Sep 17 00:00:00 2001 From: Keith Grant Date: Thu, 18 Apr 2019 10:03:06 -0400 Subject: [PATCH] Context test tools (#168) * add enzyme test helper with lingui provider * add router context to enzyme test helper * get 18n, router, & config contexts rendering together in enzyme helper * add config context to enzyme helpers * add network and dialog contexts to enzymeHelpers * convert OrganizationForm tests to use new mountWithContexts helper * default all context value keys to default unless provided * document use of mountWithContexts() * fix typo in CONTRIBUTING.md * update Organizations to use mountWithContext --- CONTRIBUTING.md | 31 +- .../__snapshots__/enzymeHelpers.test.jsx.snap | 78 ++++ __tests__/enzymeHelpers.jsx | 151 +++++++ __tests__/enzymeHelpers.test.jsx | 194 +++++++++ .../Organizations/Organizations.test.jsx | 18 +- .../components/OrganizationForm.test.jsx | 241 +++++------ jest.config.js | 3 + package-lock.json | 405 ++++++++++++------ package.json | 5 +- src/contexts/Network.jsx | 1 - src/contexts/RootDialog.jsx | 3 +- 11 files changed, 834 insertions(+), 296 deletions(-) create mode 100644 __tests__/__snapshots__/enzymeHelpers.test.jsx.snap create mode 100644 __tests__/enzymeHelpers.jsx create mode 100644 __tests__/enzymeHelpers.test.jsx diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 40ca6c517f..d6d958fe92 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -183,4 +183,33 @@ this.state = { somethingD: {}, somethingE: '', } -``` \ No newline at end of file +``` + +### Testing components that use contexts + +We have several React contexts that wrap much of the app, including those from react-router, lingui, and some of our own. When testing a component that depends on one or more of these, you can use the `mountWithContexts()` helper function found in `__tests__/enzymeHelpers.jsx`. This can be used just like Enzyme's `mount()` function, except it will wrap the component tree with the necessary context providers and basic stub data. + +If you want to stub the value of a context, or assert actions taken on it, you can customize a contexts value by passing a second parameter to `mountWithContexts`. For example, this provides a custom value for the `Network` context: + +``` +const network = { + api: { + getOrganizationInstanceGroups: jest.fn(), + } +}; +mountWithContexts(, { + context: { network }, +}); +``` + +In this test, when the `OrganizationForm` calls `api.getOrganizationInstanceGroups` from the network context, it will invoke the provided stub. You can assert that this stub is invoked when you expect or to provide stubbed data. + +The object containing context values looks for five known contexts, identified by the keys `linguiPublisher`, `router`, `config`, `network`, and `dialog` — the latter three each referring to the contexts defined in `src/contexts`. You can pass `false` for any of these values, and the corresponding context will be omitted from your test. For example, this will mount your component without the dialog context: + +``` +mountWithContexts(< { + context: { + dialog: false, + } +}); +``` diff --git a/__tests__/__snapshots__/enzymeHelpers.test.jsx.snap b/__tests__/__snapshots__/enzymeHelpers.test.jsx.snap new file mode 100644 index 0000000000..87ef1a6565 --- /dev/null +++ b/__tests__/__snapshots__/enzymeHelpers.test.jsx.snap @@ -0,0 +1,78 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`mountWithContexts injected ConfigProvider should mount and render with custom Config value 1`] = ` + + +
+ Fizz + 1.1 +
+
+
+`; + +exports[`mountWithContexts injected ConfigProvider should mount and render with default values 1`] = ` + + +
+ + +`; + +exports[`mountWithContexts injected I18nProvider should mount and render 1`] = ` +
+ + + Text content + + +
+`; + +exports[`mountWithContexts injected I18nProvider should mount and render deeply nested consumer 1`] = ` + + + +
+ Text content +
+
+
+
+`; + +exports[`mountWithContexts injected Network should mount and render 1`] = ` + +
+ test +
+
+`; + +exports[`mountWithContexts injected Router should mount and render 1`] = ` +
+ + + home + + +
+`; diff --git a/__tests__/enzymeHelpers.jsx b/__tests__/enzymeHelpers.jsx new file mode 100644 index 0000000000..c4e31909a7 --- /dev/null +++ b/__tests__/enzymeHelpers.jsx @@ -0,0 +1,151 @@ +/* + * Enzyme helpers for injecting top-level contexts + * derived from https://lingui.js.org/guides/testing.html + */ +import React from 'react'; +import { shape, object, string, arrayOf, func } from 'prop-types'; +import { mount, shallow } from 'enzyme'; +import { I18nProvider } from '@lingui/react'; +import { ConfigProvider } from '../src/contexts/Config'; +import { _NetworkProvider } from '../src/contexts/Network'; +import { RootDialogProvider } from '../src/contexts/RootDialog'; + +const language = 'en-US'; +const intlProvider = new I18nProvider( + { + language, + catalogs: { + [language]: {} + } + }, + {} +); +const { + linguiPublisher: { i18n: originalI18n } +} = intlProvider.getChildContext(); + +const defaultContexts = { + linguiPublisher: { + i18n: { + ...originalI18n, + _: key => key.id, // provide _ macro, for just passing down the key + toJSON: () => '/i18n/', + }, + }, + config: { + ansible_version: null, + custom_virtualenvs: [], + version: null, + custom_logo: null, + custom_login_info: null, + toJSON: () => '/config/' + }, + router: { + history: { + push: () => {}, + replace: () => {}, + createHref: () => {}, + }, + route: { + location: { + hash: '', + pathname: '', + search: '', + state: '', + }, + match: { + params: {}, + isExact: false, + path: '', + url: '', + }, + }, + toJSON: () => '/router/', + }, + network: { + api: { + getConfig: () => {}, + }, + handleHttpError: () => {}, + }, + dialog: {} +}; + +const providers = { + config: ConfigProvider, + network: _NetworkProvider, + dialog: RootDialogProvider, +}; + +function wrapContexts (node, context) { + let wrapped = node; + let isFirst = true; + Object.keys(providers).forEach(key => { + if (context[key]) { + const Provider = providers[key]; + wrapped = ( + + {wrapped} + + ); + isFirst = false; + } + }); + return wrapped; +} + +function applyDefaultContexts (context) { + if (!context) { + return defaultContexts; + } + const newContext = {}; + Object.keys(defaultContexts).forEach(key => { + newContext[key] = { + ...defaultContexts[key], + ...context[key], + }; + }); + return newContext; +} + +export function shallowWithContexts (node, options = {}) { + const context = applyDefaultContexts(options.context); + return shallow(wrapContexts(node, context)); +} + +export function mountWithContexts (node, options = {}) { + const context = applyDefaultContexts(options.context); + const childContextTypes = { + linguiPublisher: shape({ + i18n: object.isRequired + }).isRequired, + config: shape({ + ansible_version: string, + custom_virtualenvs: arrayOf(string), + version: string, + custom_logo: string, + custom_login_info: string, + }), + router: shape({ + route: shape({ + location: shape({}), + match: shape({}), + }).isRequired, + history: shape({}).isRequired, + }), + network: shape({ + api: shape({}).isRequired, + handleHttpError: func.isRequired, + }), + dialog: shape({ + title: string, + setRootDialogMessage: func, + clearRootDialogMessage: func, + }), + ...options.childContextTypes + }; + return mount(wrapContexts(node, context), { context, childContextTypes }); +} diff --git a/__tests__/enzymeHelpers.test.jsx b/__tests__/enzymeHelpers.test.jsx new file mode 100644 index 0000000000..dd355d8874 --- /dev/null +++ b/__tests__/enzymeHelpers.test.jsx @@ -0,0 +1,194 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +// import { mount } from 'enzyme'; +import { I18n } from '@lingui/react'; +import { t } from '@lingui/macro'; +import { mountWithContexts } from './enzymeHelpers'; +import { Config } from '../src/contexts/Config'; +import { withNetwork } from '../src/contexts/Network'; +import { withRootDialog } from '../src/contexts/RootDialog'; + +describe('mountWithContexts', () => { + describe('injected I18nProvider', () => { + test('should mount and render', () => { + const wrapper = mountWithContexts( +
+ + {({ i18n }) => ( + {i18n._(t`Text content`)} + )} + +
+ ); + expect(wrapper.find('div')).toMatchSnapshot(); + }); + + test('should mount and render deeply nested consumer', () => { + const Child = () => ( + + {({ i18n }) => ( +
{i18n._(t`Text content`)}
+ )} +
+ ); + const Parent = () => (); + const wrapper = mountWithContexts(); + expect(wrapper.find('Parent')).toMatchSnapshot(); + }); + }); + + describe('injected Router', () => { + it('should mount and render', () => { + const wrapper = mountWithContexts( +
+ home +
+ ); + + expect(wrapper.find('div')).toMatchSnapshot(); + }); + + it('should mount and render with stubbed context', () => { + const context = { + router: { + history: { + push: jest.fn(), + replace: jest.fn(), + createHref: jest.fn(), + }, + route: { + location: {}, + match: {} + } + } + }; + const wrapper = mountWithContexts( + ( +
+ home +
+ ), + { context } + ); + + const link = wrapper.find('Link'); + expect(link).toHaveLength(1); + link.simulate('click', { button: 0 }); + wrapper.update(); + + expect(context.router.history.push).toHaveBeenCalledWith('/'); + }); + }); + + describe('injected ConfigProvider', () => { + it('should mount and render with default values', () => { + const Foo = () => ( + + {value => ( +
+ {value.custom_virtualenvs[0]} + {value.version} +
+ )} +
+ ); + const wrapper = mountWithContexts(); + expect(wrapper.find('Foo')).toMatchSnapshot(); + }); + + it('should mount and render with custom Config value', () => { + const config = { + custom_virtualenvs: ['Fizz', 'Buzz'], + version: '1.1', + }; + const Foo = () => ( + + {value => ( +
+ {value.custom_virtualenvs[0]} + {value.version} +
+ )} +
+ ); + const wrapper = mountWithContexts( + , + { context: { config } } + ); + expect(wrapper.find('Foo')).toMatchSnapshot(); + }); + }); + + describe('injected Network', () => { + it('should mount and render', () => { + const Foo = () => ( +
test
+ ); + const Bar = withNetwork(Foo); + const wrapper = mountWithContexts(); + expect(wrapper.find('Foo')).toMatchSnapshot(); + }); + + it('should mount and render with stubbed api', () => { + const network = { + api: { + getFoo: jest.fn().mockReturnValue('foo value'), + }, + }; + const Foo = ({ api }) => ( +
{api.getFoo()}
+ ); + const Bar = withNetwork(Foo); + const wrapper = mountWithContexts(, { context: { network } }); + expect(network.api.getFoo).toHaveBeenCalledTimes(1); + expect(wrapper.find('div').text()).toEqual('foo value'); + }); + }); + + describe('injected root dialog', () => { + it('should mount and render', () => { + const Foo = ({ title, setRootDialogMessage }) => ( +
+ {title} + +
+ ); + const Bar = withRootDialog(Foo); + const wrapper = mountWithContexts(); + + expect(wrapper.find('span').text()).toEqual(''); + wrapper.find('button').simulate('click'); + wrapper.update(); + expect(wrapper.find('span').text()).toEqual('error'); + }); + + it('should mount and render with stubbed value', () => { + const dialog = { + title: 'this be the title', + setRootDialogMessage: jest.fn(), + }; + const Foo = ({ title, setRootDialogMessage }) => ( +
+ {title} + +
+ ); + const Bar = withRootDialog(Foo); + const wrapper = mountWithContexts(, { context: { dialog } }); + + expect(wrapper.find('span').text()).toEqual('this be the title'); + wrapper.find('button').simulate('click'); + expect(dialog.setRootDialogMessage).toHaveBeenCalledWith('error'); + }); + }); +}); diff --git a/__tests__/pages/Organizations/Organizations.test.jsx b/__tests__/pages/Organizations/Organizations.test.jsx index 3f288050cd..b772b462d0 100644 --- a/__tests__/pages/Organizations/Organizations.test.jsx +++ b/__tests__/pages/Organizations/Organizations.test.jsx @@ -1,20 +1,14 @@ import React from 'react'; -import { MemoryRouter } from 'react-router-dom'; -import { mount } from 'enzyme'; -import { I18nProvider } from '@lingui/react'; +import { mountWithContexts } from '../../enzymeHelpers'; import Organizations from '../../../src/pages/Organizations/Organizations'; describe('', () => { test('initially renders succesfully', () => { - mount( - - - - - + mountWithContexts( + ); }); }); diff --git a/__tests__/pages/Organizations/components/OrganizationForm.test.jsx b/__tests__/pages/Organizations/components/OrganizationForm.test.jsx index 7078ea504e..2a2c98a19b 100644 --- a/__tests__/pages/Organizations/components/OrganizationForm.test.jsx +++ b/__tests__/pages/Organizations/components/OrganizationForm.test.jsx @@ -1,15 +1,10 @@ import React from 'react'; -import { mount } from 'enzyme'; -import { MemoryRouter } from 'react-router-dom'; -import { I18nProvider } from '@lingui/react'; +import { mountWithContexts } from '../../../enzymeHelpers'; import { sleep } from '../../../testUtils'; -import { ConfigProvider } from '../../../../src/contexts/Config'; -import { NetworkProvider } from '../../../../src/contexts/Network'; -import OrganizationForm, { _OrganizationForm } from '../../../../src/pages/Organizations/components/OrganizationForm'; +import OrganizationForm from '../../../../src/pages/Organizations/components/OrganizationForm'; describe('', () => { - let api; - let networkProviderValue; + let network; const mockData = { id: 1, @@ -22,14 +17,11 @@ describe('', () => { }; beforeEach(() => { - api = { - getInstanceGroups: jest.fn(), - }; + network = {}; + }); - networkProviderValue = { - api, - handleHttpError: () => {} - }; + afterEach(() => { + jest.clearAllMocks(); }); test('should request related instance groups from api', () => { @@ -37,25 +29,24 @@ describe('', () => { { name: 'One', id: 1 }, { name: 'Two', id: 2 } ]; - api.getOrganizationInstanceGroups = jest.fn(() => ( - Promise.resolve({ data: { results: mockInstanceGroups } }) - )); - mount( - - - - <_OrganizationForm - api={api} - organization={mockData} - handleSubmit={jest.fn()} - handleCancel={jest.fn()} - /> - - - - ).find('OrganizationForm'); + network.api = { + getOrganizationInstanceGroups: jest.fn(() => ( + Promise.resolve({ data: { results: mockInstanceGroups } }) + )) + }; + mountWithContexts( + ( + + ), { + context: { network }, + } + ); - expect(api.getOrganizationInstanceGroups).toHaveBeenCalledTimes(1); + expect(network.api.getOrganizationInstanceGroups).toHaveBeenCalledTimes(1); }); test('componentDidMount should set instanceGroups to state', async () => { @@ -63,42 +54,36 @@ describe('', () => { { name: 'One', id: 1 }, { name: 'Two', id: 2 } ]; - api.getOrganizationInstanceGroups = jest.fn(() => ( - Promise.resolve({ data: { results: mockInstanceGroups } }) - )); - const wrapper = mount( - - - - <_OrganizationForm - organization={mockData} - api={api} - handleSubmit={jest.fn()} - handleCancel={jest.fn()} - /> - - - - ).find('OrganizationForm'); + network.api = { + getOrganizationInstanceGroups: jest.fn(() => ( + Promise.resolve({ data: { results: mockInstanceGroups } }) + )) + }; + const wrapper = mountWithContexts( + ( + + ), { + context: { network }, + } + ); - await wrapper.instance().componentDidMount(); - expect(wrapper.state().instanceGroups).toEqual(mockInstanceGroups); + await sleep(0); + expect(network.api.getOrganizationInstanceGroups).toHaveBeenCalled(); + expect(wrapper.find('OrganizationForm').state().instanceGroups).toEqual(mockInstanceGroups); }); test('changing instance group successfully sets instanceGroups state', () => { - const wrapper = mount( - - - - - - - - ).find('OrganizationForm'); + const wrapper = mountWithContexts( + + ); const lookup = wrapper.find('InstanceGroupsLookup'); expect(lookup.length).toBe(1); @@ -109,7 +94,7 @@ describe('', () => { name: 'foo' } ], 'instanceGroups'); - expect(wrapper.state().instanceGroups).toEqual([ + expect(wrapper.find('OrganizationForm').state().instanceGroups).toEqual([ { id: 1, name: 'foo' @@ -118,19 +103,13 @@ describe('', () => { }); test('changing inputs should update form values', () => { - const wrapper = mount( - - - - - - - - ).find('OrganizationForm'); + const wrapper = mountWithContexts( + + ); const form = wrapper.find('Formik'); wrapper.find('input#org-name').simulate('change', { @@ -147,20 +126,16 @@ describe('', () => { const config = { custom_virtualenvs: ['foo', 'bar'], }; - const wrapper = mount( - - - - - - - - - + const wrapper = mountWithContexts( + ( + + ), { + context: { config }, + } ); expect(wrapper.find('FormSelect')).toHaveLength(1); expect(wrapper.find('FormSelectOption')).toHaveLength(2); @@ -168,20 +143,13 @@ describe('', () => { test('calls handleSubmit when form submitted', async () => { const handleSubmit = jest.fn(); - const wrapper = mount( - - - - - - - - ).find('OrganizationForm'); + const wrapper = mountWithContexts( + + ); expect(handleSubmit).not.toHaveBeenCalled(); wrapper.find('button[aria-label="Save"]').simulate('click'); await sleep(1); @@ -197,34 +165,33 @@ describe('', () => { { name: 'One', id: 1 }, { name: 'Two', id: 2 } ]; - api.getOrganizationInstanceGroups = jest.fn(() => ( - Promise.resolve({ data: { results: mockInstanceGroups } }) - )); + network.api = { + getOrganizationInstanceGroups: jest.fn(() => ( + Promise.resolve({ data: { results: mockInstanceGroups } }) + )) + }; const mockDataForm = { name: 'Foo', description: 'Bar', custom_virtualenv: 'Fizz', }; const handleSubmit = jest.fn(); - api.updateOrganizationDetails = jest.fn().mockResolvedValue(1, mockDataForm); - api.associateInstanceGroup = jest.fn().mockResolvedValue('done'); - api.disassociate = jest.fn().mockResolvedValue('done'); - const wrapper = mount( - - - - <_OrganizationForm - organization={mockData} - api={api} - handleSubmit={handleSubmit} - handleCancel={jest.fn()} - /> - - - - ).find('OrganizationForm'); + network.api.updateOrganizationDetails = jest.fn().mockResolvedValue(1, mockDataForm); + network.api.associateInstanceGroup = jest.fn().mockResolvedValue('done'); + network.api.disassociate = jest.fn().mockResolvedValue('done'); + const wrapper = mountWithContexts( + ( + + ), { + context: { network }, + } + ); - await wrapper.instance().componentDidMount(); + await sleep(0); wrapper.find('InstanceGroupsLookup').prop('onChange')([ { name: 'One', id: 1 }, @@ -238,18 +205,12 @@ describe('', () => { test('calls "handleCancel" when Cancel button is clicked', () => { const handleCancel = jest.fn(); - const wrapper = mount( - - - - - - - + const wrapper = mountWithContexts( + ); expect(handleCancel).not.toHaveBeenCalled(); wrapper.find('button[aria-label="Cancel"]').prop('onClick')(); diff --git a/jest.config.js b/jest.config.js index c03e1ac6f2..c0f2b6ece0 100644 --- a/jest.config.js +++ b/jest.config.js @@ -9,6 +9,9 @@ module.exports = { '\\.(css|scss|less)$': '/__mocks__/styleMock.js' }, setupFilesAfterEnv: ['/jest.setup.js'], + snapshotSerializers: [ + "enzyme-to-json/serializer" + ], testMatch: [ '/__tests__/**/*.test.{js,jsx}' ], diff --git a/package-lock.json b/package-lock.json index 47dafb051b..d48da6c8e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1877,9 +1877,9 @@ "dev": true }, "@types/node": { - "version": "10.12.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.1.tgz", - "integrity": "sha512-i1sl+WCX2OCHeUi9oi7PiCNUtYFrpWhpcx878vpeq/tlZTKzcFdHePlyFHVbWqeuKN0SRPl/9ZFDSTsfv9h7VQ==", + "version": "11.13.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.4.tgz", + "integrity": "sha512-+rabAZZ3Yn7tF/XPGHupKIL5EcAbrLxnTr/hgQICxbeuAfWtT0UZSfULE+ndusckBItcv4o6ZeOJplQikVcLvQ==", "dev": true }, "@types/stack-utils": { @@ -2139,6 +2139,51 @@ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.0.tgz", "integrity": "sha512-ugTb7Lq7u4GfWSqqpwE0bGyoBZNMTok/zDBXxfEG0QM50jNlGhIWjRC1pPN7bvV1anhF+bs+/gNcRw+o55Evbg==" }, + "airbnb-prop-types": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.13.2.tgz", + "integrity": "sha512-2FN6DlHr6JCSxPPi25EnqGaXC4OC3/B3k1lCd6MMYrZ51/Gf/1qDfaR+JElzWa+Tl7cY2aYOlsYJGFeQyVHIeQ==", + "requires": { + "array.prototype.find": "^2.0.4", + "function.prototype.name": "^1.1.0", + "has": "^1.0.3", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0", + "prop-types": "^15.7.2", + "prop-types-exact": "^1.2.0", + "react-is": "^16.8.6" + }, + "dependencies": { + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" + } + } + }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", @@ -2633,6 +2678,12 @@ "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -2681,6 +2732,15 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "array.prototype.find": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz", + "integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=", + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, "array.prototype.flat": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz", @@ -4128,13 +4188,13 @@ "dev": true }, "cheerio": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", - "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", "dev": true, "requires": { "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", + "dom-serializer": "~0.1.1", "entities": "~1.1.1", "htmlparser2": "^3.9.1", "lodash": "^4.15.0", @@ -4494,12 +4554,6 @@ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, - "colors": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", - "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=", - "dev": true - }, "combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", @@ -4904,9 +4958,9 @@ } }, "css-what": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.2.tgz", - "integrity": "sha512-wan8dMWQ0GUeF7DGEPVjhHemVW/vy6xUYmFzRY8RYqgA0JtXC9rJmbScBjqSu6dg9q0lwPQy6ZAmJVr3PPTvqQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", "dev": true }, "cssesc": { @@ -5101,7 +5155,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" }, @@ -5109,8 +5162,7 @@ "object-keys": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", - "dev": true + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==" } } }, @@ -5293,21 +5345,13 @@ } }, "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", "dev": true, "requires": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - } + "domelementtype": "^1.3.0", + "entities": "^1.1.1" } }, "dom-walk": { @@ -5323,9 +5367,9 @@ "dev": true }, "domelementtype": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.2.1.tgz", - "integrity": "sha512-SQVCLFS2E7G5CRCMdn6K9bIhRj1bS6QBWZfF0TUPh4V/BbqrQ619IdSS3/izn0FZ+9l+uODzaZjb08fjOfablA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, "domexception": { @@ -5542,18 +5586,20 @@ "dev": true }, "enzyme": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.7.0.tgz", - "integrity": "sha512-QLWx+krGK6iDNyR1KlH5YPZqxZCQaVF6ike1eDJAOg0HvSkSCVImPsdWaNw6v+VrnK92Kg8jIOYhuOSS9sBpyg==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.9.0.tgz", + "integrity": "sha512-JqxI2BRFHbmiP7/UFqvsjxTirWoM1HfeaJrmVSZ9a1EADKkZgdPcAuISPMpoUiHlac9J4dYt81MC5BBIrbJGMg==", "dev": true, "requires": { "array.prototype.flat": "^1.2.1", "cheerio": "^1.0.0-rc.2", "function.prototype.name": "^1.1.0", "has": "^1.0.3", + "html-element-map": "^1.0.0", "is-boolean-object": "^1.0.0", "is-callable": "^1.1.4", "is-number-object": "^1.0.3", + "is-regex": "^1.0.4", "is-string": "^1.0.4", "is-subset": "^0.1.1", "lodash.escape": "^4.0.1", @@ -5569,29 +5615,73 @@ } }, "enzyme-adapter-react-16": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.6.0.tgz", - "integrity": "sha512-ay9eGFpChyUDnjTFMMJHzrb681LF3hPWJLEA7RoLFG9jSWAdAm2V50pGmFV9dYGJgh5HfdiqM+MNvle41Yf/PA==", - "dev": true, + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.12.1.tgz", + "integrity": "sha512-GB61gvY97XvrA6qljExGY+lgI6BBwz+ASLaRKct9VQ3ozu0EraqcNn3CcrUckSGIqFGa1+CxO5gj5is5t3lwrw==", "requires": { - "enzyme-adapter-utils": "^1.8.0", - "function.prototype.name": "^1.1.0", + "enzyme-adapter-utils": "^1.11.0", "object.assign": "^4.1.0", - "object.values": "^1.0.4", - "prop-types": "^15.6.2", - "react-is": "^16.5.2", - "react-test-renderer": "^16.0.0-0" + "object.values": "^1.1.0", + "prop-types": "^15.7.2", + "react-is": "^16.8.6", + "react-test-renderer": "^16.0.0-0", + "semver": "^5.6.0" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" + } } }, "enzyme-adapter-utils": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.8.1.tgz", - "integrity": "sha512-s3QB3xQAowaDS2sHhmEqrT13GJC4+n5bG015ZkLv60n9k5vhxxHTQRIneZmQ4hmdCZEBrvUJ89PG6fRI5OEeuQ==", - "dev": true, + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.11.0.tgz", + "integrity": "sha512-0VZeoE9MNx+QjTfsjmO1Mo+lMfunucYB4wt5ficU85WB/LoetTJrbuujmHP3PJx6pSoaAuLA+Mq877x4LoxdNg==", "requires": { + "airbnb-prop-types": "^2.12.0", "function.prototype.name": "^1.1.0", "object.assign": "^4.1.0", - "prop-types": "^15.6.2" + "object.fromentries": "^2.0.0", + "prop-types": "^15.7.2", + "semver": "^5.6.0" + }, + "dependencies": { + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" + } + } + }, + "enzyme-to-json": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.3.5.tgz", + "integrity": "sha512-DmH1wJ68HyPqKSYXdQqB33ZotwfUhwQZW3IGXaNXgR69Iodaoj8TF/D9RjLdz4pEhGq2Tx2zwNUIjBuqoZeTgA==", + "dev": true, + "requires": { + "lodash": "^4.17.4" } }, "errno": { @@ -5615,7 +5705,6 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", - "dev": true, "requires": { "es-to-primitive": "^1.1.1", "function-bind": "^1.1.1", @@ -5628,7 +5717,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -7448,14 +7536,12 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "function.prototype.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.0.tgz", "integrity": "sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg==", - "dev": true, "requires": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", @@ -7665,7 +7751,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -7687,8 +7772,7 @@ "has-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" }, "has-unicode": { "version": "2.0.1", @@ -7869,6 +7953,15 @@ } } }, + "html-element-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.0.1.tgz", + "integrity": "sha512-BZSfdEm6n706/lBfXKWa4frZRZcT5k1cOusw95ijZsHlI+GdgY0v95h6IzO3iIDf2ROwq570YTwqNPqHcNMozw==", + "dev": true, + "requires": { + "array-filter": "^1.0.0" + } + }, "html-encoding-sniffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", @@ -7896,29 +7989,23 @@ } }, "htmlparser2": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.0.tgz", - "integrity": "sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", "dev": true, "requires": { - "domelementtype": "^1.3.0", + "domelementtype": "^1.3.1", "domhandler": "^2.3.0", "domutils": "^1.5.1", "entities": "^1.1.1", "inherits": "^2.0.1", - "readable-stream": "^3.0.6" + "readable-stream": "^3.1.1" }, "dependencies": { - "domelementtype": { - "version": "1.3.0", - "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true - }, "readable-stream": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.0.6.tgz", - "integrity": "sha512-9E1oLoOWfhSXHGv6QlwXJim7uNzd9EVlWK+21tCU9Ju/kR0/p2AZYPz4qSchgO8PlLIH4FpZYfzwS+rEksZjIg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", + "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -7927,9 +8014,9 @@ } }, "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", + "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", "dev": true, "requires": { "safe-buffer": "~5.1.0" @@ -8647,8 +8734,7 @@ "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" }, "is-ci": { "version": "2.0.0", @@ -8682,8 +8768,7 @@ "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" }, "is-decimal": { "version": "1.0.2", @@ -8818,7 +8903,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, "requires": { "has": "^1.0.1" } @@ -8850,7 +8934,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true, "requires": { "has-symbols": "^1.0.0" } @@ -10935,7 +11018,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { @@ -11333,13 +11416,13 @@ "dev": true }, "nearley": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.15.1.tgz", - "integrity": "sha512-8IUY/rUrKz2mIynUGh8k+tul1awMKEjeHHC5G3FHvvyAW6oq4mQfNp2c0BMea+sYZJvYcrrM6GmZVIle/GRXGw==", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.16.0.tgz", + "integrity": "sha512-Tr9XD3Vt/EujXbZBv6UAHYoLUSMQAxSsTnm9K3koXzjzNWY195NqALeyrzLZBKzAkL3gl92BcSogqrHjD8QuUg==", "dev": true, "requires": { + "commander": "^2.19.0", "moo": "^0.4.3", - "nomnom": "~1.6.2", "railroad-diagrams": "^1.0.0", "randexp": "0.4.6", "semver": "^5.4.1" @@ -11571,16 +11654,6 @@ } } }, - "nomnom": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", - "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=", - "dev": true, - "requires": { - "colors": "0.5.x", - "underscore": "~1.4.4" - } - }, "nopt": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", @@ -11700,8 +11773,7 @@ "object-is": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", - "dev": true + "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=" }, "object-keys": { "version": "0.4.0", @@ -11729,7 +11801,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, "requires": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", @@ -11740,8 +11811,7 @@ "object-keys": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", - "dev": true + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==" } } }, @@ -11757,6 +11827,17 @@ "has": "^1.0.1" } }, + "object.fromentries": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz", + "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==", + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.11.0", + "function-bind": "^1.1.1", + "has": "^1.0.1" + } + }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", @@ -11785,15 +11866,14 @@ } }, "object.values": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", - "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", - "dev": true, + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.6.1", - "function-bind": "^1.1.0", - "has": "^1.0.1" + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" } }, "obuf": { @@ -12615,6 +12695,16 @@ "object-assign": "^4.1.1" } }, + "prop-types-exact": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", + "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", + "requires": { + "has": "^1.0.3", + "object.assign": "^4.1.0", + "reflect.ownkeys": "^0.2.0" + } + }, "proxy-addr": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", @@ -12714,9 +12804,9 @@ "dev": true }, "raf": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.0.tgz", - "integrity": "sha512-pDP/NMRAXoTfrhCfyfSEwJAKLaxBU9eApMeBPB1TkDouZmvPerIClV8lTAd+uF8ZiTaVl69e1FCxQrAd/VTjGw==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", "dev": true, "requires": { "performance-now": "^2.1.0" @@ -12793,25 +12883,47 @@ } }, "react": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.6.0.tgz", - "integrity": "sha512-zJPnx/jKtuOEXCbQ9BKaxDMxR0001/hzxXwYxG8septeyYGfsgAei6NgfbVgOhbY1WOP2o3VPs/E9HaN+9hV3Q==", + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react/-/react-16.8.6.tgz", + "integrity": "sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "scheduler": "^0.10.0" + "scheduler": "^0.13.6" + }, + "dependencies": { + "scheduler": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", + "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } } }, "react-dom": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.6.0.tgz", - "integrity": "sha512-Stm2D9dXEUUAQdvpvhvFj/DEXwC2PAL/RwEMhoN4dvvD2ikTlJegEXf97xryg88VIAU22ZAP7n842l+9BTz6+w==", + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz", + "integrity": "sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "scheduler": "^0.10.0" + "scheduler": "^0.13.6" + }, + "dependencies": { + "scheduler": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", + "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } } }, "react-fast-compare": { @@ -12872,15 +12984,30 @@ } }, "react-test-renderer": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.6.0.tgz", - "integrity": "sha512-w+Y3YT7OX1LP5KO7HCd0YR34Ol1qmISHaooPNMRYa6QzmwtcWhEGuZPr34wO8UCBIokswuhyLQUq7rjPDcEtJA==", - "dev": true, + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.8.6.tgz", + "integrity": "sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==", "requires": { "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "scheduler": "^0.10.0" + "react-is": "^16.8.6", + "scheduler": "^0.13.6" + }, + "dependencies": { + "react-is": { + "version": "16.8.6", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", + "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" + }, + "scheduler": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", + "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } } }, "read-pkg": { @@ -13293,6 +13420,11 @@ "strip-indent": "^1.0.1" } }, + "reflect.ownkeys": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", + "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=" + }, "regenerate": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", @@ -13673,7 +13805,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -13806,6 +13938,7 @@ "version": "0.10.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.10.0.tgz", "integrity": "sha512-+TSTVTCBAA3h8Anei3haDc1IRwMeDmtI/y/o3iBe3Mjl2vwYF9DtPDt929HyRmV/e7au7CLu8sc4C4W0VOs29w==", + "dev": true, "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -15329,12 +15462,6 @@ } } }, - "underscore": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.4.4.tgz", - "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", - "dev": true - }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -15643,9 +15770,9 @@ } }, "warning": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.2.tgz", - "integrity": "sha512-wbTp09q/9C+jJn4KKJfJfoS6VleK/Dti0yqWSm6KMvJ4MRCXFQNapHuJXutJIrWV0Cf4AhTdeIe4qdKHR1+Hug==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", "requires": { "loose-envify": "^1.0.0" } diff --git a/package.json b/package.json index 988fcb4335..4900ec1de0 100644 --- a/package.json +++ b/package.json @@ -28,8 +28,9 @@ "babel-loader": "^8.0.4", "babel-plugin-macros": "^2.4.2", "css-loader": "^1.0.0", - "enzyme": "^3.7.0", - "enzyme-adapter-react-16": "^1.6.0", + "enzyme": "^3.9.0", + "enzyme-adapter-react-16": "^1.12.1", + "enzyme-to-json": "^3.3.5", "eslint": "^5.6.0", "eslint-config-airbnb": "^17.1.0", "eslint-plugin-import": "^2.14.0", diff --git a/src/contexts/Network.jsx b/src/contexts/Network.jsx index 10f12ccb1e..2fba529e3e 100644 --- a/src/contexts/Network.jsx +++ b/src/contexts/Network.jsx @@ -82,4 +82,3 @@ export function withNetwork (Child) { ); } - diff --git a/src/contexts/RootDialog.jsx b/src/contexts/RootDialog.jsx index 089c59087f..6a938b1e99 100644 --- a/src/contexts/RootDialog.jsx +++ b/src/contexts/RootDialog.jsx @@ -16,7 +16,8 @@ export class RootDialogProvider extends Component { clearRootDialogMessage: () => { const { value } = this.state; this.setState({ value: { ...value, title: null, bodyText: null, variant: null } }); - } + }, + ...props.value, } }; }