Refactor: Move data fetch into MainContainer & generic metrics
Also make fetching metrics for a component generic in order to add a full summary of various metrics in a future detailed view for a specific Bugzilla component.
This commit is contained in:
Родитель
626af8c429
Коммит
76662b7794
|
@ -45,6 +45,7 @@
|
|||
"lint-staged": "^8.1.0",
|
||||
"neutrino": "^9.0.0-beta.1",
|
||||
"node-fetch": "^2.3.0",
|
||||
"react-test-renderer": "^16.6.3",
|
||||
"webpack": "^4",
|
||||
"webpack-cli": "^3",
|
||||
"webpack-dev-server": "^3"
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const linkToQuery = (key, metrics, alt) => (
|
||||
<a href={metrics[key].link} alt={alt}>{metrics[key].count}</a>
|
||||
);
|
||||
|
||||
const BugzillaComponent = ({ product, component, metrics }) => (
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<span style={{ margin: '0 1rem 0 0' }}>{`${product}::${component}`}</span>
|
||||
{metrics.untriaged
|
||||
&& linkToQuery('untriaged', metrics, 'Number of untriaged bugs')
|
||||
}
|
||||
</div>
|
||||
);
|
||||
|
||||
BugzillaComponent.propTypes = {
|
||||
product: PropTypes.string.isRequired,
|
||||
component: PropTypes.string.isRequired,
|
||||
metrics: PropTypes.shape({}),
|
||||
};
|
||||
|
||||
BugzillaComponent.defaultProps = {
|
||||
metrics: {},
|
||||
};
|
||||
|
||||
export default BugzillaComponent;
|
|
@ -0,0 +1,48 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import BugzillaComponent from '../BugzillaComponent';
|
||||
import Reportees from '../Reportees';
|
||||
|
||||
const sortByComponentName = (a, b) => {
|
||||
let result = (a.product <= b.product);
|
||||
if (a.product === b.product) {
|
||||
result = a.component <= b.component;
|
||||
}
|
||||
return result ? -1 : 1;
|
||||
};
|
||||
|
||||
const MainView = ({ ldapEmail, partialOrg, bugzillaComponents }) => (
|
||||
<div key={ldapEmail}>
|
||||
<h3>{partialOrg[ldapEmail].cn}</h3>
|
||||
<div style={{ display: 'flex' }}>
|
||||
<Reportees ldapEmail={ldapEmail} partialOrg={partialOrg} />
|
||||
{Object.values(bugzillaComponents).length > 0 && (
|
||||
<div>
|
||||
<h4>Components</h4>
|
||||
{Object.values(bugzillaComponents)
|
||||
.sort(sortByComponentName)
|
||||
.map(({ component, product, metrics }) => (
|
||||
<BugzillaComponent
|
||||
key={`${product}::${component}`}
|
||||
product={product}
|
||||
component={component}
|
||||
metrics={metrics}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
MainView.propTypes = {
|
||||
ldapEmail: PropTypes.string.isRequired,
|
||||
partialOrg: PropTypes.shape({}).isRequired,
|
||||
bugzillaComponents: PropTypes.shape({}),
|
||||
};
|
||||
|
||||
MainView.defaultProps = {
|
||||
bugzillaComponents: {},
|
||||
};
|
||||
|
||||
export default MainView;
|
|
@ -0,0 +1,25 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const sortByPersonName = (a, b) => (a.cn <= b.cn ? -1 : 1);
|
||||
|
||||
const Reportees = ({ ldapEmail, partialOrg }) => (
|
||||
<div style={{ margin: '0 1rem 0 0' }}>
|
||||
<h4>Reportees</h4>
|
||||
{Object.values(partialOrg)
|
||||
.filter(({ cn }) => cn !== ldapEmail)
|
||||
.sort(sortByPersonName)
|
||||
.map(({ cn, mail }) => (
|
||||
<div key={mail}>
|
||||
<span>{`${cn} `}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
Reportees.propTypes = {
|
||||
ldapEmail: PropTypes.string.isRequired,
|
||||
partialOrg: PropTypes.shape({}).isRequired,
|
||||
};
|
||||
|
||||
export default Reportees;
|
|
@ -1,59 +0,0 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import OpenInNew from '@material-ui/icons/OpenInNew';
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import getLinkToComponent from '../../utils/bugzilla/getLinkToComponent';
|
||||
import getUntriagedBugsCount from '../../utils/bugzilla/getUntriagedBugsCount';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
icon: {
|
||||
margin: 0,
|
||||
fontSize: '1rem',
|
||||
verticalAlign: 'text-top',
|
||||
},
|
||||
});
|
||||
|
||||
class BugzillaComponentSummary extends React.Component {
|
||||
state = {
|
||||
untriaged: undefined,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
classes: PropTypes.shape({}).isRequired,
|
||||
product: PropTypes.string.isRequired,
|
||||
component: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
async componentDidMount() {
|
||||
this.fetchData(this.props);
|
||||
}
|
||||
|
||||
async fetchData({ product, component }) {
|
||||
const untriaged = await getUntriagedBugsCount(product, component);
|
||||
this.setState({ untriaged });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes, product, component } = this.props;
|
||||
const { untriaged } = this.state;
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<span>{`${product}::${component}`}</span>
|
||||
<a
|
||||
href={getLinkToComponent(product, component)}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title="Link to component's untriaged bugs"
|
||||
>
|
||||
<OpenInNew className={classes.icon} />
|
||||
</a>
|
||||
{!!untriaged && <span title="Number of untriaged bugs">{untriaged}</span>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(BugzillaComponentSummary);
|
|
@ -1,23 +1,14 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import BugzillaComponentSummary from '../BugzillaComponentSummary';
|
||||
import MainView from '../../components/MainView';
|
||||
import getAllReportees from '../../utils/getAllReportees';
|
||||
import getBugzillaOwners from '../../utils/getBugzillaOwners';
|
||||
|
||||
const sortByPersonName = (a, b) => (a.cn <= b.cn ? -1 : 1);
|
||||
|
||||
const sortByComponentName = (a, b) => {
|
||||
let result = (a.product <= b.product);
|
||||
if (a.product === b.product) {
|
||||
result = a.component <= b.component;
|
||||
}
|
||||
return result ? -1 : 1;
|
||||
};
|
||||
import getBugsCountAndLink from '../../utils/bugzilla/getBugsCountAndLink';
|
||||
|
||||
class MainContainer extends Component {
|
||||
state = {
|
||||
ldapEmail: '',
|
||||
reporteesComponents: undefined,
|
||||
bugzillaComponents: undefined,
|
||||
partialOrg: undefined,
|
||||
};
|
||||
|
||||
|
@ -50,24 +41,45 @@ class MainContainer extends Component {
|
|||
return partialOrg;
|
||||
}
|
||||
|
||||
async reporteeComponents(bzOwners, partialOrg) {
|
||||
async bugzillaComponents(bzOwners, partialOrg) {
|
||||
// bzOwners uses the bugzilla email address as the key
|
||||
// while partialOrg uses the LDAP email address
|
||||
const reporteesComponents = Object.values(partialOrg)
|
||||
/* eslint-disable no-param-reassign */
|
||||
const bugzillaComponents = Object.values(partialOrg)
|
||||
.reduce((result, { bugzillaEmail, mail }) => {
|
||||
const componentsOwned = bzOwners[bugzillaEmail] || bzOwners[mail];
|
||||
if (componentsOwned) {
|
||||
componentsOwned.forEach(({ product, component }) => {
|
||||
result.push({
|
||||
if (!result[`${product}::${component}`]) {
|
||||
result[`${product}::${component}`] = {};
|
||||
}
|
||||
result[`${product}::${component}`] = {
|
||||
bugzillaEmail: bugzillaEmail || mail,
|
||||
product,
|
||||
component,
|
||||
});
|
||||
metrics: {},
|
||||
};
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}, []);
|
||||
this.setState({ reporteesComponents });
|
||||
}, {});
|
||||
/* eslint-enable no-param-reassign */
|
||||
// This will list the components but will not show metrics
|
||||
this.setState({ bugzillaComponents });
|
||||
|
||||
// Let's fetch the metrics for each component
|
||||
Object.values(bugzillaComponents)
|
||||
.map(async ({ product, component }) => {
|
||||
const metric = 'untriaged';
|
||||
const { count, link } = await getBugsCountAndLink(product, component, metric);
|
||||
bugzillaComponents[`${product}::${component}`].metrics = {
|
||||
[metric]: {
|
||||
count,
|
||||
link,
|
||||
},
|
||||
};
|
||||
this.setState({ bugzillaComponents });
|
||||
});
|
||||
}
|
||||
|
||||
async retrieveData(ldapEmail) {
|
||||
|
@ -75,13 +87,13 @@ class MainContainer extends Component {
|
|||
getBugzillaOwners(),
|
||||
this.getReportees(ldapEmail),
|
||||
]);
|
||||
this.reporteeComponents(bzOwners, partialOrg);
|
||||
this.bugzillaComponents(bzOwners, partialOrg);
|
||||
}
|
||||
|
||||
handleChange(event) {
|
||||
this.setState({
|
||||
ldapEmail: event.target.value,
|
||||
reporteesComponents: undefined,
|
||||
bugzillaComponents: undefined,
|
||||
partialOrg: undefined,
|
||||
});
|
||||
}
|
||||
|
@ -93,43 +105,18 @@ class MainContainer extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { ldapEmail, reporteesComponents, partialOrg } = this.state;
|
||||
const {
|
||||
ldapEmail, bugzillaComponents, partialOrg,
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{partialOrg && (
|
||||
<div key={ldapEmail}>
|
||||
<h3>{partialOrg[ldapEmail].cn}</h3>
|
||||
<div style={{ display: 'flex' }}>
|
||||
{partialOrg && (
|
||||
<div style={{ margin: '0 1rem 0 0' }}>
|
||||
<h4>Reportees</h4>
|
||||
{Object.values(partialOrg)
|
||||
.filter(({ cn }) => cn !== ldapEmail)
|
||||
.sort(sortByPersonName)
|
||||
.map(({ cn, mail }) => (
|
||||
<div key={mail}>
|
||||
<span>{`${cn} `}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{reporteesComponents && reporteesComponents.length > 0 && (
|
||||
<div>
|
||||
<h4>Components</h4>
|
||||
{reporteesComponents
|
||||
.sort(sortByComponentName)
|
||||
.map(({ product, component }) => (
|
||||
<BugzillaComponentSummary
|
||||
key={`${product}::${component}`}
|
||||
product={product}
|
||||
component={component}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<MainView
|
||||
ldapEmail={ldapEmail}
|
||||
partialOrg={partialOrg}
|
||||
bugzillaComponents={bugzillaComponents}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import { stringify } from 'query-string';
|
||||
import fetchJson from '../fetchJson';
|
||||
import settings from './settings';
|
||||
import METRICS from './metrics';
|
||||
|
||||
const queryBugzilla = async queryParameters => (
|
||||
fetchJson(`${settings.BZ_HOST}/rest/bug?${queryParameters}`));
|
||||
|
||||
const getBugzillaComponentLink = queryParameters => (
|
||||
`${settings.BZ_HOST}/buglist.cgi?${stringify(queryParameters)}`);
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
const getBugsCountAndLink = async (product, component, metric) => {
|
||||
const baseParams = {
|
||||
product,
|
||||
component,
|
||||
...METRICS[metric],
|
||||
};
|
||||
const link = getBugzillaComponentLink(baseParams);
|
||||
const { bug_count = 0 } = await queryBugzilla(
|
||||
stringify({ ...baseParams, count_only: 1 }),
|
||||
);
|
||||
return { count: bug_count, link };
|
||||
};
|
||||
|
||||
export default getBugsCountAndLink;
|
|
@ -1,8 +0,0 @@
|
|||
import { stringify } from 'query-string';
|
||||
import settings from './settings';
|
||||
import untriagedParameters from './untriagedParameters';
|
||||
|
||||
const getBugzillaComponentLink = (product, component) => (
|
||||
`${settings.BZ_HOST}/buglist.cgi?${stringify({ product, component, ...untriagedParameters() })}`);
|
||||
|
||||
export default getBugzillaComponentLink;
|
|
@ -1,23 +0,0 @@
|
|||
import { stringify } from 'query-string';
|
||||
import untriagedParameters from './untriagedParameters';
|
||||
import fetchJson from '../fetchJson';
|
||||
import settings from './settings';
|
||||
|
||||
const queryBugzilla = async queryParameters => (
|
||||
fetchJson(`${settings.BZ_HOST}/rest/bug?${queryParameters}`));
|
||||
|
||||
const getUntriagedBugsCount = async (product, component) => {
|
||||
// eslint-disable-next-line camelcase
|
||||
const { bug_count = 0 } = await queryBugzilla(
|
||||
stringify({
|
||||
product,
|
||||
component,
|
||||
...untriagedParameters(),
|
||||
count_only: 1, // This only returns the bug count
|
||||
}),
|
||||
);
|
||||
// eslint-disable-next-line camelcase
|
||||
return bug_count;
|
||||
};
|
||||
|
||||
export default getUntriagedBugsCount;
|
|
@ -0,0 +1,13 @@
|
|||
/* eslint-disable indent */
|
||||
/* eslint-disable object-property-newline */
|
||||
/* eslint-disable no-multi-spaces */
|
||||
const METRICS = {
|
||||
untriaged: {
|
||||
f1: 'bug_severity', o1: 'notequals', v1: 'enhancement',
|
||||
f2: 'keywords', o2: 'notsubstring', v2: 'meta',
|
||||
f3: 'resolution', o3: 'isempty',
|
||||
limit: 0,
|
||||
},
|
||||
};
|
||||
|
||||
export default METRICS;
|
|
@ -0,0 +1,72 @@
|
|||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import MainView from '../../src/components/MainView';
|
||||
|
||||
const partialOrg = {
|
||||
'someone@mozilla.com': {
|
||||
cn: 'Someone',
|
||||
mail: 'someone@mozilla.com',
|
||||
manager: {
|
||||
dn: 'mail=manager@mozilla.com,o=com,dc=mozilla',
|
||||
},
|
||||
},
|
||||
'manager@mozilla.com': {
|
||||
cn: 'Manager',
|
||||
mail: 'manager@mozilla.com',
|
||||
manager: null,
|
||||
},
|
||||
};
|
||||
const bugzillaComponents = {
|
||||
'Core::DOM: IndexedDB': {
|
||||
bugzillaEmail: 'someone@mozilla.com',
|
||||
component: 'DOM: IndexedDB',
|
||||
product: 'Core',
|
||||
},
|
||||
'Core::JavaScript Engine': {
|
||||
bugzillaEmail: 'someone@mozilla.com',
|
||||
component: 'JavaScript Engine',
|
||||
product: 'Core',
|
||||
},
|
||||
'Core::DOM: Core & HTML': {
|
||||
bugzillaEmail: 'someone@mozilla.com',
|
||||
component: 'DOM: Core & HTML',
|
||||
product: 'Core',
|
||||
metrics: {
|
||||
untriaged: {
|
||||
count: 944,
|
||||
link: 'https://bugzilla.mozilla.org/buglist.cgi?component=DOM%3A%20Core%20%26%20HTML&f1=bug_severity&f2=keywords&f3=resolution&limit=0&o1=notequals&o2=notsubstring&o3=isempty&product=Core&v1=enhancement&v2=meta',
|
||||
},
|
||||
},
|
||||
},
|
||||
'Toolkit::Async Tooling': {
|
||||
bugzillaEmail: 'manager@mozilla.com',
|
||||
component: 'Async Tooling',
|
||||
product: 'Toolkit',
|
||||
},
|
||||
};
|
||||
|
||||
it('renders Someone with no reportees', () => {
|
||||
const tree = renderer
|
||||
.create((
|
||||
<MainView
|
||||
ldapEmail="someone@mozilla.com"
|
||||
partialOrg={partialOrg}
|
||||
bugzillaComponents={bugzillaComponents}
|
||||
/>
|
||||
))
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders Manager who has reportees', () => {
|
||||
const tree = renderer
|
||||
.create((
|
||||
<MainView
|
||||
ldapEmail="manager@mozilla.com"
|
||||
partialOrg={partialOrg}
|
||||
bugzillaComponents={bugzillaComponents}
|
||||
/>
|
||||
))
|
||||
.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
|
@ -0,0 +1,241 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders Manager who has reportees 1`] = `
|
||||
<div>
|
||||
<h3>
|
||||
Manager
|
||||
</h3>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"margin": "0 1rem 0 0",
|
||||
}
|
||||
}
|
||||
>
|
||||
<h4>
|
||||
Reportees
|
||||
</h4>
|
||||
<div>
|
||||
<span>
|
||||
Manager
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>
|
||||
Someone
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4>
|
||||
Components
|
||||
</h4>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"margin": "0 1rem 0 0",
|
||||
}
|
||||
}
|
||||
>
|
||||
Core::DOM: Core & HTML
|
||||
</span>
|
||||
<a
|
||||
alt="Number of untriaged bugs"
|
||||
href="https://bugzilla.mozilla.org/buglist.cgi?component=DOM%3A%20Core%20%26%20HTML&f1=bug_severity&f2=keywords&f3=resolution&limit=0&o1=notequals&o2=notsubstring&o3=isempty&product=Core&v1=enhancement&v2=meta"
|
||||
>
|
||||
944
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"margin": "0 1rem 0 0",
|
||||
}
|
||||
}
|
||||
>
|
||||
Core::DOM: IndexedDB
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"margin": "0 1rem 0 0",
|
||||
}
|
||||
}
|
||||
>
|
||||
Core::JavaScript Engine
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"margin": "0 1rem 0 0",
|
||||
}
|
||||
}
|
||||
>
|
||||
Toolkit::Async Tooling
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders Someone with no reportees 1`] = `
|
||||
<div>
|
||||
<h3>
|
||||
Someone
|
||||
</h3>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"margin": "0 1rem 0 0",
|
||||
}
|
||||
}
|
||||
>
|
||||
<h4>
|
||||
Reportees
|
||||
</h4>
|
||||
<div>
|
||||
<span>
|
||||
Manager
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span>
|
||||
Someone
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4>
|
||||
Components
|
||||
</h4>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"margin": "0 1rem 0 0",
|
||||
}
|
||||
}
|
||||
>
|
||||
Core::DOM: Core & HTML
|
||||
</span>
|
||||
<a
|
||||
alt="Number of untriaged bugs"
|
||||
href="https://bugzilla.mozilla.org/buglist.cgi?component=DOM%3A%20Core%20%26%20HTML&f1=bug_severity&f2=keywords&f3=resolution&limit=0&o1=notequals&o2=notsubstring&o3=isempty&product=Core&v1=enhancement&v2=meta"
|
||||
>
|
||||
944
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"margin": "0 1rem 0 0",
|
||||
}
|
||||
}
|
||||
>
|
||||
Core::DOM: IndexedDB
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"margin": "0 1rem 0 0",
|
||||
}
|
||||
}
|
||||
>
|
||||
Core::JavaScript Engine
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"margin": "0 1rem 0 0",
|
||||
}
|
||||
}
|
||||
>
|
||||
Toolkit::Async Tooling
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
|
@ -1,5 +0,0 @@
|
|||
describe('simple', () => {
|
||||
it('should be sane', () => {
|
||||
expect(false).not.toBe(true);
|
||||
});
|
||||
});
|
12
yarn.lock
12
yarn.lock
|
@ -7055,7 +7055,7 @@ react-hot-loader@^4:
|
|||
react-lifecycles-compat "^3.0.4"
|
||||
shallowequal "^1.0.2"
|
||||
|
||||
react-is@^16.3.2:
|
||||
react-is@^16.3.2, react-is@^16.6.3:
|
||||
version "16.6.3"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.6.3.tgz#d2d7462fcfcbe6ec0da56ad69047e47e56e7eac0"
|
||||
integrity sha512-u7FDWtthB4rWibG/+mFbVd5FvdI20yde86qKGx4lVUTWmPlSWQ4QxbBIrrs+HnXGbxOUlUzTAP/VDmvCwaP2yA==
|
||||
|
@ -7090,6 +7090,16 @@ react-router@^4.3.1:
|
|||
prop-types "^15.6.1"
|
||||
warning "^4.0.1"
|
||||
|
||||
react-test-renderer@^16.6.3:
|
||||
version "16.6.3"
|
||||
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.6.3.tgz#5f3a1a7d5c3379d46f7052b848b4b72e47c89f38"
|
||||
integrity sha512-B5bCer+qymrQz/wN03lT0LppbZUDRq6AMfzMKrovzkGzfO81a9T+PWQW6MzkWknbwODQH/qpJno/yFQLX5IWrQ==
|
||||
dependencies:
|
||||
object-assign "^4.1.1"
|
||||
prop-types "^15.6.2"
|
||||
react-is "^16.6.3"
|
||||
scheduler "^0.11.2"
|
||||
|
||||
react-transition-group@^2.2.1:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.5.0.tgz#70bca0e3546102c4dc5cf3f5f57f73447cce6874"
|
||||
|
|
Загрузка…
Ссылка в новой задаче