[7.2] [SIEM] Fix bytes formatting (#37545) (#37701)

* [SIEM] Fix bytes formatting  (#37545)

## Summary

This PR is for https://github.com/elastic/ingest-dev/issues/326, and fixes how bytes are formatted across the app to be consistent with what is configured in Kibana Advanced Settings

### Checklist

Use ~~strikethroughs~~ to remove checklist items you don't feel are applicable to this PR.

- [ ] ~This was checked for cross-browser compatibility, [including a check against IE11](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility)~
- [ ] ~Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/master/packages/kbn-i18n/README.md)~
- [ ] ~[Documentation](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#writing-documentation) was added for features that require explanation or tutorials~
- [x] [Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios
- [ ] ~This was checked for [keyboard-only and screenreader accessibility](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Accessibility_testing_checklist)~

### For maintainers

- [ ] ~This was checked for breaking API changes and was [labeled appropriately](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#release-notes-process)~
- [ ] ~This includes a feature addition or change that requires a release note and was [labeled appropriately](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#release-notes-process)~


### Fix Includes:
#### Network Top Talkers Table:
![image](https://user-images.githubusercontent.com/2946766/58660744-611d2d80-82e3-11e9-9c1e-889316b56e0b.png)

#### Network Top DNS Table:
![image](https://user-images.githubusercontent.com/2946766/58660725-54003e80-82e3-11e9-926b-570a947a0118.png)

#### IP Details Domains Table:
![image](https://user-images.githubusercontent.com/2946766/58660776-75f9c100-82e3-11e9-8360-325c73b87f23.png)

#### Timeline Netflow Renderer:
![image](https://user-images.githubusercontent.com/2946766/58660684-3c28ba80-82e3-11e9-88c3-adf0c4126fa0.png)

* Backporting update of enzyme-adapter-react-16 devDependency to fix failing tests
This commit is contained in:
Garrett Spong 2019-06-04 18:35:00 -06:00 committed by GitHub
parent bc5d6e59b4
commit 3b150af756
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 244 additions and 47 deletions

View file

@ -347,7 +347,7 @@
"dedent": "^0.7.0",
"delete-empty": "^2.0.0",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16": "^1.9.0",
"enzyme-adapter-react-16": "^1.10.0",
"enzyme-adapter-utils": "^1.10.0",
"enzyme-to-json": "^3.3.4",
"eslint": "5.16.0",

View file

@ -115,7 +115,7 @@
"del": "^3.0.0",
"dotenv": "2.0.0",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16": "^1.9.0",
"enzyme-adapter-react-16": "^1.10.0",
"enzyme-adapter-utils": "^1.10.0",
"enzyme-to-json": "^3.3.4",
"execa": "^1.0.0",

View file

@ -18,7 +18,7 @@ import { pluck } from 'rxjs/operators';
import { I18nContext } from 'ui/i18n';
import { ErrorToast } from '../components/error_toast';
import { KibanaConfigContext } from '../components/formatted_date';
import { KibanaConfigContext } from '../lib/adapters/framework/kibana_framework_adapter';
import { AppFrontendLibs } from '../lib/lib';
import { PageRouter } from '../routes';
import { createStore } from '../store';

View file

@ -0,0 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`formatted_bytes PreferenceFormattedBytes rendering renders correctly against snapshot 1`] = `
<Fragment>
2.676MB
</Fragment>
`;

View file

@ -0,0 +1,62 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { mount, shallow } from 'enzyme';
import toJson from 'enzyme-to-json';
import * as React from 'react';
import { mockFrameworks, TestProviders } from '../../mock';
import { PreferenceFormattedBytes } from '.';
describe('formatted_bytes', () => {
describe('PreferenceFormattedBytes', () => {
describe('rendering', () => {
const bytes = '2806422';
test('renders correctly against snapshot', () => {
const wrapper = shallow(<PreferenceFormattedBytes value={bytes} />);
expect(toJson(wrapper)).toMatchSnapshot();
});
test('it renders bytes to hardcoded format when no configuration exists', () => {
const wrapper = mount(
<TestProviders mockFramework={{}}>
<PreferenceFormattedBytes value={bytes} />
</TestProviders>
);
expect(wrapper.text()).toEqual('2.676MB');
});
test('it renders bytes according to the default format', () => {
const wrapper = mount(
<TestProviders mockFramework={mockFrameworks.default_browser}>
<PreferenceFormattedBytes value={bytes} />
</TestProviders>
);
expect(wrapper.text()).toEqual('2.676MB');
});
test('it renders bytes supplied as a number according to the default format', () => {
const wrapper = mount(
<TestProviders mockFramework={mockFrameworks.default_browser}>
<PreferenceFormattedBytes value={+bytes} />
</TestProviders>
);
expect(wrapper.text()).toEqual('2.676MB');
});
test('it renders bytes according to new format', () => {
const wrapper = mount(
<TestProviders mockFramework={mockFrameworks.bytes_short}>
<PreferenceFormattedBytes value={bytes} />
</TestProviders>
);
expect(wrapper.text()).toEqual('3MB');
});
});
});
});

View file

@ -0,0 +1,25 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import * as React from 'react';
import { useContext } from 'react';
import numeral from '@elastic/numeral';
import {
AppKibanaFrameworkAdapter,
KibanaConfigContext,
} from '../../lib/adapters/framework/kibana_framework_adapter';
export const PreferenceFormattedBytes = React.memo<{ value: string | number }>(({ value }) => {
const config: Partial<AppKibanaFrameworkAdapter> = useContext(KibanaConfigContext);
return (
<>
{config.bytesFormat
? numeral(value).format(config.bytesFormat)
: numeral(value).format('0,0.[000]b')}
</>
);
});

View file

@ -12,8 +12,9 @@ import * as React from 'react';
import { AppTestingFrameworkAdapter } from '../../lib/adapters/framework/testing_framework_adapter';
import { mockFrameworks, TestProviders } from '../../mock';
import { KibanaConfigContext, PreferenceFormattedDate, FormattedDate, getMaybeDate } from '.';
import { PreferenceFormattedDate, FormattedDate, getMaybeDate } from '.';
import { getEmptyValue } from '../empty_value';
import { KibanaConfigContext } from '../../lib/adapters/framework/kibana_framework_adapter';
describe('formatted_date', () => {
describe('PreferenceFormattedDate', () => {

View file

@ -6,26 +6,29 @@
import moment from 'moment-timezone';
import * as React from 'react';
import { useContext } from 'react';
import { pure } from 'recompose';
import { isString } from 'lodash/fp';
import { AppKibanaFrameworkAdapter } from '../../lib/adapters/framework/kibana_framework_adapter';
import {
AppKibanaFrameworkAdapter,
KibanaConfigContext,
} from '../../lib/adapters/framework/kibana_framework_adapter';
import { getOrEmptyTagFromValue } from '../empty_value';
import { LocalizedDateTooltip } from '../localized_date_tooltip';
export const KibanaConfigContext = React.createContext<Partial<AppKibanaFrameworkAdapter>>({});
export const PreferenceFormattedDate = pure<{ value: Date }>(({ value }) => (
<KibanaConfigContext.Consumer>
{(config: Partial<AppKibanaFrameworkAdapter>) => {
return config && config.dateFormat && config.dateFormatTz && config.timezone
export const PreferenceFormattedDate = pure<{ value: Date }>(({ value }) => {
const config: Partial<AppKibanaFrameworkAdapter> = useContext(KibanaConfigContext);
return (
<>
{config.dateFormat && config.dateFormatTz && config.timezone
? moment
.tz(value, config.dateFormatTz === 'Browser' ? config.timezone : config.dateFormatTz)
.format(config.dateFormat)
: moment.utc(value).toISOString();
}}
</KibanaConfigContext.Consumer>
));
: moment.utc(value).toISOString()}
</>
);
});
export const getMaybeDate = (value: string | number): moment.Moment => {
if (isString(value) && value.trim() !== '') {

View file

@ -143,7 +143,7 @@ describe('Netflow', () => {
.find('[data-test-subj="destination-bytes"]')
.first()
.text()
).toEqual('40.000 B');
).toEqual('40B');
});
test('it renders destination.geo.continent_name', () => {
@ -278,7 +278,7 @@ describe('Netflow', () => {
.find('[data-test-subj="network-bytes"]')
.first()
.text()
).toEqual('100.000 B');
).toEqual('100B');
});
test('it renders network.community_id', () => {
@ -355,7 +355,7 @@ describe('Netflow', () => {
.find('[data-test-subj="source-bytes"]')
.first()
.text()
).toEqual('60.000 B');
).toEqual('60B');
});
test('it renders source.geo.continent_name', () => {

View file

@ -4,6 +4,7 @@ exports[`Load More Table Component rendering it renders the default Hosts table
<ContextProvider
value={
Object {
"bytesFormat": "0,0.[000]b",
"dateFormat": "MMM D, YYYY @ HH:mm:ss.SSS",
"dateFormatTz": "UTC",
"timezone": "UTC",

View file

@ -19,10 +19,10 @@ import {
TestProviders,
} from '../../../../mock';
import { createStore, hostsModel, State } from '../../../../store';
import { KibanaConfigContext } from '../../../formatted_date';
import { HostsTable } from './index';
import { mockData } from './mock';
import { KibanaConfigContext } from '../../../../lib/adapters/framework/kibana_framework_adapter';
describe('Load More Table Component', () => {
const loadMore = jest.fn();

View file

@ -12,11 +12,11 @@ import React from 'react';
import { StaticIndexPattern } from 'ui/index_patterns';
import {
DomainsEdges,
DomainsItem,
DomainsNetworkField,
FlowDirection,
FlowTarget,
DomainsEdges,
} from '../../../../graphql/types';
import { assertUnreachable } from '../../../../lib/helpers';
import { escapeQueryValue } from '../../../../lib/keury';
@ -28,6 +28,7 @@ import { PreferenceFormattedDate } from '../../../formatted_date';
import { Columns } from '../../../load_more_table';
import { LocalizedDateTooltip } from '../../../localized_date_tooltip';
import { IS_OPERATOR } from '../../../timeline/data_providers/data_provider';
import { PreferenceFormattedBytes } from '../../../formatted_bytes';
import { Provider } from '../../../timeline/data_providers/provider';
import { AddToKql } from '../../add_to_kql';
@ -122,7 +123,7 @@ export const getDomainsColumns = (
sortable: true,
render: bytes => {
if (bytes != null) {
return numeral(bytes).format('0.000b');
return <PreferenceFormattedBytes value={bytes} />;
} else {
return getEmptyTagValue();
}

View file

@ -14,6 +14,7 @@ import { escapeDataProviderId } from '../../../drag_and_drop/helpers';
import { defaultToEmptyTag, getEmptyTagValue } from '../../../empty_value';
import { Columns } from '../../../load_more_table';
import { IS_OPERATOR } from '../../../timeline/data_providers/data_provider';
import { PreferenceFormattedBytes } from '../../../formatted_bytes';
import { Provider } from '../../../timeline/data_providers/provider';
import * as i18n from './translations';
@ -104,7 +105,7 @@ export const getNetworkDnsColumns = (
hideForMobile: false,
render: dnsBytesIn => {
if (dnsBytesIn != null) {
return numeral(dnsBytesIn).format('0.000b');
return <PreferenceFormattedBytes value={dnsBytesIn} />;
} else {
return getEmptyTagValue();
}
@ -118,7 +119,7 @@ export const getNetworkDnsColumns = (
hideForMobile: false,
render: dnsBytesOut => {
if (dnsBytesOut != null) {
return numeral(dnsBytesOut).format('0.000b');
return <PreferenceFormattedBytes value={dnsBytesOut} />;
} else {
return getEmptyTagValue();
}

View file

@ -14,6 +14,7 @@ import {
FlowTarget,
TopNFlowNetworkEcsField,
NetworkTopNFlowEdges,
TopNFlowItem,
} from '../../../../graphql/types';
import { assertUnreachable } from '../../../../lib/helpers';
import { escapeQueryValue } from '../../../../lib/keury';
@ -29,6 +30,7 @@ import { AddToKql } from '../../add_to_kql';
import * as i18n from './translations';
import { getRowItemDraggables } from '../../../tables/helpers';
import { PreferenceFormattedBytes } from '../../../formatted_bytes';
export const getNetworkTopNFlowColumns = (
indexPattern: StaticIndexPattern,
@ -41,8 +43,8 @@ export const getNetworkTopNFlowColumns = (
Columns<NetworkTopNFlowEdges>,
Columns<TopNFlowNetworkEcsField['direction']>,
Columns<TopNFlowNetworkEcsField['bytes']>,
Columns<TopNFlowNetworkEcsField['bytes']>,
Columns<TopNFlowNetworkEcsField['bytes']>
Columns<TopNFlowNetworkEcsField['packets']>,
Columns<TopNFlowItem['count']>
] => [
{
name: getIpTitle(flowTarget),
@ -138,7 +140,7 @@ export const getNetworkTopNFlowColumns = (
sortable: true,
render: bytes => {
if (bytes != null) {
return numeral(bytes).format('0.000b');
return <PreferenceFormattedBytes value={bytes} />;
} else {
return getEmptyTagValue();
}

View file

@ -121,7 +121,7 @@ describe('SourceDestination', () => {
.find('[data-test-subj="destination-bytes"]')
.first()
.text()
).toEqual('40.000 B');
).toEqual('40B');
});
test('it renders destination.geo.continent_name', () => {
@ -223,7 +223,7 @@ describe('SourceDestination', () => {
.find('[data-test-subj="network-bytes"]')
.first()
.text()
).toEqual('100.000 B');
).toEqual('100B');
});
test('it renders network.community_id', () => {
@ -289,7 +289,7 @@ describe('SourceDestination', () => {
.find('[data-test-subj="source-bytes"]')
.first()
.text()
).toEqual('60.000 B');
).toEqual('60B');
});
test('it renders source.geo.continent_name', () => {

View file

@ -5,7 +5,6 @@
*/
import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
import numeral from '@elastic/numeral';
import { uniq } from 'lodash/fp';
import * as React from 'react';
import { pure } from 'recompose';
@ -16,12 +15,13 @@ import { DefaultDraggable, DraggableBadge } from '../draggables';
import * as i18n from './translations';
import {
NETWORK_PROTOCOL_FIELD_NAME,
NETWORK_BYTES_FIELD_NAME,
NETWORK_PACKETS_FIELD_NAME,
NETWORK_COMMUNITY_ID_FIELD_NAME,
NETWORK_PACKETS_FIELD_NAME,
NETWORK_PROTOCOL_FIELD_NAME,
NETWORK_TRANSPORT_FIELD_NAME,
} from './field_names';
import { PreferenceFormattedBytes } from '../formatted_bytes';
const EuiFlexItemMarginRight = styled(EuiFlexItem)`
margin-right: 3px;
@ -78,7 +78,9 @@ export const Network = pure<{
value={b}
>
<Stats size="xs">
<span data-test-subj="network-bytes">{numeral(b).format('0.000 b')}</span>
<span data-test-subj="network-bytes">
<PreferenceFormattedBytes value={b} />
</span>
</Stats>
</DefaultDraggable>
</EuiFlexItemMarginRight>

View file

@ -18,6 +18,7 @@ import {
hasOneValue,
} from '../arrows/helpers';
import { DefaultDraggable } from '../draggables';
import { PreferenceFormattedBytes } from '../formatted_bytes';
import * as i18n from './translations';
@ -73,7 +74,9 @@ const SourceArrow = pure<{
{`(${numeral(sourceBytesPercent).format('0.00')}%)`}
</Percent>
) : null}
<span data-test-subj="source-bytes">{numeral(sourceBytes).format('0.000 b')}</span>
<span data-test-subj="source-bytes">
<PreferenceFormattedBytes value={sourceBytes} />
</span>
</Data>
</DefaultDraggable>
</EuiFlexItem>
@ -148,7 +151,7 @@ const DestinationArrow = pure<{
</Percent>
) : null}
<span data-test-subj="destination-bytes">
{numeral(destinationBytes).format('0.000 b')}
<PreferenceFormattedBytes value={destinationBytes} />
</span>
</Data>
</DefaultDraggable>

View file

@ -129,6 +129,6 @@ describe('netflowRowRenderer', () => {
.find('[data-test-subj="destination-bytes"]')
.first()
.text()
).toEqual('40.000 B');
).toEqual('40B');
});
});

View file

@ -23,7 +23,10 @@ import {
const ROOT_ELEMENT_ID = 'react-siem-root';
const BREADCRUMBS_ELEMENT_ID = 'react-siem-breadcrumbs';
export const KibanaConfigContext = React.createContext<Partial<AppKibanaFrameworkAdapter>>({});
export class AppKibanaFrameworkAdapter implements AppFrameworkAdapter {
public bytesFormat?: string;
public dateFormat?: string;
public dateFormatTz?: string;
public darkMode?: boolean;
@ -131,6 +134,7 @@ export class AppKibanaFrameworkAdapter implements AppFrameworkAdapter {
) => {
this.timezone = Private(this.timezoneProvider)();
this.kbnVersion = kbnVersion;
this.bytesFormat = config.get('format:bytes:defaultPattern');
this.dateFormat = config.get('dateFormat');
this.dateFormatTz = config.get('dateFormat:tz');
try {

View file

@ -8,6 +8,7 @@ import { AppFrameworkAdapter } from '../../lib';
export class AppTestingFrameworkAdapter implements AppFrameworkAdapter {
public appState?: object;
public bytesFormat?: string;
public dateFormat?: string;
public dateFormatTz?: string;
public kbnVersion?: string;

View file

@ -22,6 +22,7 @@ export type AppApolloClient = ApolloClient<NormalizedCacheObject>;
export interface AppFrameworkAdapter {
appState?: object;
bytesFormat?: string;
dateFormat?: string;
dateFormatTz?: string;
darkMode?: boolean;

View file

@ -7,22 +7,32 @@
import { AppTestingFrameworkAdapter } from '../lib/adapters/framework/testing_framework_adapter';
export const mockFrameworks: Readonly<Record<string, Partial<AppTestingFrameworkAdapter>>> = {
bytes_short: {
bytesFormat: '0b',
dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS',
dateFormatTz: 'Browser',
timezone: 'America/Denver',
},
default_browser: {
bytesFormat: '0,0.[000]b',
dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS',
dateFormatTz: 'Browser',
timezone: 'America/Denver',
},
default_ET: {
bytesFormat: '0,0.[000]b',
dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS',
dateFormatTz: 'America/New_York',
timezone: 'America/New_York',
},
default_MT: {
bytesFormat: '0,0.[000]b',
dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS',
dateFormatTz: 'America/Denver',
timezone: 'America/Denver',
},
default_UTC: {
bytesFormat: '0,0.[000]b',
dateFormat: 'MMM D, YYYY @ HH:mm:ss.SSS',
dateFormatTz: 'UTC',
timezone: 'UTC',

View file

@ -18,7 +18,7 @@ import { Store } from 'redux';
import { BehaviorSubject } from 'rxjs';
import { ThemeProvider } from 'styled-components';
import { KibanaConfigContext } from '../components/formatted_date';
import { KibanaConfigContext } from '../lib/adapters/framework/kibana_framework_adapter';
import { AppTestingFrameworkAdapter } from '../lib/adapters/framework/testing_framework_adapter';
import { createStore, State } from '../store';
import { mockGlobalState } from './global_state';

View file

@ -4402,6 +4402,22 @@ aggregate-error@^1.0.0:
string.prototype.padstart "^3.0.0"
symbol.prototype.description "^1.0.0"
airbnb-prop-types@^2.13.2:
version "2.13.2"
resolved "https://registry.yarnpkg.com/airbnb-prop-types/-/airbnb-prop-types-2.13.2.tgz#43147a5062dd2a4a5600e748a47b64004cc5f7fc"
integrity sha512-2FN6DlHr6JCSxPPi25EnqGaXC4OC3/B3k1lCd6MMYrZ51/Gf/1qDfaR+JElzWa+Tl7cY2aYOlsYJGFeQyVHIeQ==
dependencies:
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"
ajv-errors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.0.tgz#ecf021fa108fd17dfb5e6b383f2dd233e31ffc59"
@ -5140,6 +5156,14 @@ array-unique@^0.3.2:
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
array.prototype.find@^2.0.4:
version "2.1.0"
resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.1.0.tgz#630f2eaf70a39e608ac3573e45cf8ccd0ede9ad7"
integrity sha512-Wn41+K1yuO5p7wRZDl7890c3xvv5UBrfVXTVIe28rSQb6LS0fZMDrQB6PAcxQFRFy6vJTLDc3A2+3CjQdzVKRg==
dependencies:
define-properties "^1.1.3"
es-abstract "^1.13.0"
array.prototype.flat@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz#812db8f02cad24d3fab65dd67eabe3b8903494a4"
@ -10125,18 +10149,19 @@ env-variable@0.0.x:
resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.5.tgz#913dd830bef11e96a039c038d4130604eba37f88"
integrity sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==
enzyme-adapter-react-16@^1.9.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.9.1.tgz#6d49a3a31c3a0fccf527610f31b837e0f307128a"
integrity sha512-Egzogv1y77DUxdnq/CyHxLHaNxmSSKDDSDNNB/EiAXCZVFXdFibaNy2uUuRQ1n24T2m6KH/1Rw16XDRq+1yVEg==
enzyme-adapter-react-16@^1.10.0:
version "1.14.0"
resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.14.0.tgz#204722b769172bcf096cb250d33e6795c1f1858f"
integrity sha512-7PcOF7pb4hJUvjY7oAuPGpq3BmlCig3kxXGi2kFx0YzJHppqX1K8IIV9skT1IirxXlu8W7bneKi+oQ10QRnhcA==
dependencies:
enzyme-adapter-utils "^1.10.0"
function.prototype.name "^1.1.0"
enzyme-adapter-utils "^1.12.0"
has "^1.0.3"
object.assign "^4.1.0"
object.values "^1.1.0"
prop-types "^15.6.2"
react-is "^16.7.0"
prop-types "^15.7.2"
react-is "^16.8.6"
react-test-renderer "^16.0.0-0"
semver "^5.7.0"
enzyme-adapter-utils@^1.10.0:
version "1.10.0"
@ -10149,6 +10174,18 @@ enzyme-adapter-utils@^1.10.0:
prop-types "^15.6.2"
semver "^5.6.0"
enzyme-adapter-utils@^1.12.0:
version "1.12.0"
resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.12.0.tgz#96e3730d76b872f593e54ce1c51fa3a451422d93"
integrity sha512-wkZvE0VxcFx/8ZsBw0iAbk3gR1d9hK447ebnSYBf95+r32ezBq+XDSAvRErkc4LZosgH8J7et7H7/7CtUuQfBA==
dependencies:
airbnb-prop-types "^2.13.2"
function.prototype.name "^1.1.0"
object.assign "^4.1.0"
object.fromentries "^2.0.0"
prop-types "^15.7.2"
semver "^5.6.0"
enzyme-to-json@^3.3.4:
version "3.3.5"
resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.3.5.tgz#f8eb82bd3d5941c9d8bc6fd9140030777d17d0af"
@ -10219,6 +10256,18 @@ es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.4.
is-callable "^1.1.3"
is-regex "^1.0.4"
es-abstract@^1.13.0:
version "1.13.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9"
integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==
dependencies:
es-to-primitive "^1.2.0"
function-bind "^1.1.1"
has "^1.0.3"
is-callable "^1.1.4"
is-regex "^1.0.4"
object-keys "^1.0.12"
es-abstract@^1.5.1, es-abstract@^1.7.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864"
@ -10230,7 +10279,7 @@ es-abstract@^1.5.1, es-abstract@^1.7.0:
is-callable "^1.1.3"
is-regex "^1.0.4"
es-to-primitive@^1.1.1:
es-to-primitive@^1.1.1, es-to-primitive@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377"
integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==
@ -19075,7 +19124,7 @@ object.defaults@^1.1.0:
for-own "^1.0.0"
isobject "^3.0.0"
object.entries@^1.0.4:
object.entries@^1.0.4, object.entries@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.0.tgz#2024fc6d6ba246aee38bdb0ffd5cfbcf371b7519"
integrity sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==
@ -20531,6 +20580,15 @@ prompts@^2.0.1:
kleur "^3.0.2"
sisteransi "^1.0.0"
prop-types-exact@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/prop-types-exact/-/prop-types-exact-1.2.0.tgz#825d6be46094663848237e3925a98c6e944e9869"
integrity sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==
dependencies:
has "^1.0.3"
object.assign "^4.1.0"
reflect.ownkeys "^0.2.0"
prop-types@15.5.8:
version "15.5.8"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.8.tgz#6b7b2e141083be38c8595aa51fc55775c7199394"
@ -21426,6 +21484,11 @@ react-is@^16.8.4:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.5.tgz#c54ac229dd66b5afe0de5acbe47647c3da692ff8"
integrity sha512-sudt2uq5P/2TznPV4Wtdi+Lnq3yaYW8LfvPKLM9BKD8jJNBkxMVyB0C9/GmVhLw7Jbdmndk/73n7XQGeN9A3QQ==
react-is@^16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
react-is@~16.3.0:
version "16.3.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.3.2.tgz#f4d3d0e2f5fbb6ac46450641eb2e25bf05d36b22"
@ -22240,6 +22303,11 @@ redux@^4.0.1:
loose-envify "^1.4.0"
symbol-observable "^1.2.0"
reflect.ownkeys@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460"
integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=
refractor@^2.4.1:
version "2.8.0"
resolved "https://registry.yarnpkg.com/refractor/-/refractor-2.8.0.tgz#29d7b2254e823edd2e3e476af286af1c11472bfa"
@ -23392,6 +23460,11 @@ semver@^5.6.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
semver@^5.7.0:
version "5.7.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
semver@~5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"