Merge pull request #24 from kawwong/display-vlt
Consume viewportLoadTime information in view layer
This commit is contained in:
Коммит
946f947cf3
|
@ -22,31 +22,42 @@ class App extends Component {
|
|||
|
||||
componentDidMount () {
|
||||
MezzuriteInspector.isMezzuritePresentAsync().then(() => {
|
||||
MezzuriteInspector.listenForTimingEvents(event => {
|
||||
MezzuriteInspector.listenForTimingEvents((event) => this.handleTimingEvent(event));
|
||||
});
|
||||
}
|
||||
|
||||
handleTimingEvent (event) {
|
||||
const formattedTimings = formatTimingsEvent(event);
|
||||
|
||||
if (formattedTimings.applicationLoadTime != null) {
|
||||
if (formattedTimings != null) {
|
||||
if (formattedTimings.applicationLoadTime != null && this.state.applicationLoadTime == null) {
|
||||
this.setState({ applicationLoadTime: formattedTimings.applicationLoadTime });
|
||||
}
|
||||
|
||||
if (formattedTimings.componentTimings != null && formattedTimings.componentTimings !== []) {
|
||||
this.setState((previousState) => {
|
||||
const captureCycles = {
|
||||
componentTimings: formattedTimings.componentTimings,
|
||||
time: formattedTimings.time
|
||||
if (this.state.framework.name == null && this.state.framework.version == null) {
|
||||
this.setState({ framework: formattedTimings.framework });
|
||||
}
|
||||
|
||||
if (
|
||||
formattedTimings.insideViewportComponents != null ||
|
||||
formattedTimings.outsideViewportComponents != null
|
||||
) {
|
||||
const captureCycle = {
|
||||
insideViewportComponents: formattedTimings.insideViewportComponents,
|
||||
outsideViewportComponents: formattedTimings.outsideViewportComponents,
|
||||
time: formattedTimings.time,
|
||||
viewportLoadTime: formattedTimings.viewportLoadTime
|
||||
};
|
||||
|
||||
this.setState((previousState) => {
|
||||
if (previousState.captureCycles != null) {
|
||||
return { captureCycles: [ captureCycles, ...previousState.captureCycles ] };
|
||||
return { captureCycles: [ captureCycle, ...previousState.captureCycles ] };
|
||||
} else {
|
||||
return { captureCycles: [ captureCycles ] };
|
||||
return { captureCycles: [ captureCycle ] };
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({ framework: formattedTimings.framework });
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
|
|
|
@ -11,12 +11,8 @@
|
|||
margin: 0 16px 12px;
|
||||
}
|
||||
|
||||
.capture-cycle--components {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
list-style-type: none;
|
||||
margin: 16px;
|
||||
padding: 0;
|
||||
.capture-cycle--statistic {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.capture-cycle--timestamp {
|
||||
|
@ -27,6 +23,18 @@
|
|||
padding: 8px 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.capture-cycle--tooltip {
|
||||
background-color: var(--microsoft-blue);
|
||||
border-radius: 16px;
|
||||
color: var(--microsoft-white);
|
||||
font-size: 10px;
|
||||
font-weight: 500;
|
||||
margin-left: 2px;
|
||||
padding: 0 4px;
|
||||
text-decoration: none;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 540px) {
|
||||
|
|
|
@ -1,31 +1,64 @@
|
|||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import { arrayOf, number, shape, string } from 'prop-types';
|
||||
|
||||
import './CaptureCycle.css';
|
||||
import ComponentTiming from '../ComponentTiming/ComponentTiming.js';
|
||||
import CaptureCycleSection from '../CaptureCycleSection/CaptureCycleSection';
|
||||
|
||||
const CaptureCycle = (props) => (
|
||||
props != null && props.timings != null && props.timings.length > 0 && <section className='capture-cycle--card'>
|
||||
<h2 className='capture-cycle--timestamp'>Capture Cycle{props.timestamp != null && <span> at {props.timestamp}:</span>}</h2>
|
||||
<ul className='capture-cycle--components'>
|
||||
{props.timings.map((timing, timingIndex) =>
|
||||
<ComponentTiming
|
||||
key={`capture-cycle-${props.captureCycleIndex}-component-${timingIndex}`}
|
||||
name={timing.componentName}
|
||||
loadTime={timing.componentLoadTime}
|
||||
const CaptureCycle = (props) => {
|
||||
const captureCycleHeader = <h2 className='capture-cycle--timestamp'>
|
||||
{props.routeUrl == null ? 'Capture Cycle' : props.routeUrl}
|
||||
{props.timestamp != null && <span> at {props.timestamp}:</span>}
|
||||
</h2>;
|
||||
const insideViewportHeading = 'Inside Viewport';
|
||||
const insideViewportSubheading = props.viewportLoadTime != null && <Fragment>
|
||||
Viewport Load Time: <span className='capture-cycle--statistic'>{props.viewportLoadTime.toFixed(1)}</span>ms
|
||||
<a
|
||||
aria-label='What is viewport load time?'
|
||||
className='capture-cycle--tooltip'
|
||||
href='https://github.com/Microsoft/Mezzurite#viewport-load-time-vlt'
|
||||
target='_blank'
|
||||
>?</a>
|
||||
</Fragment>;
|
||||
const outsideViewportHeading = 'Outside Viewport';
|
||||
const shouldRenderInsideViewportComponents = props.insideViewportComponents != null && props.insideViewportComponents.length > 0;
|
||||
const shouldRenderOutsideViewportComponents = props.outsideViewportComponents != null && props.outsideViewportComponents.length > 0;
|
||||
|
||||
return (
|
||||
props != null && (shouldRenderInsideViewportComponents || shouldRenderOutsideViewportComponents) &&
|
||||
<section className='capture-cycle--card'>
|
||||
{captureCycleHeader}
|
||||
{shouldRenderInsideViewportComponents &&
|
||||
<CaptureCycleSection
|
||||
captureCycleIndex={props.captureCycleIndex}
|
||||
components={props.insideViewportComponents}
|
||||
heading={insideViewportHeading}
|
||||
subheading={insideViewportSubheading}
|
||||
/>
|
||||
)}
|
||||
</ul>
|
||||
}
|
||||
{shouldRenderOutsideViewportComponents &&
|
||||
<CaptureCycleSection
|
||||
captureCycleIndex={props.captureCycleIndex}
|
||||
components={props.outsideViewportComponents}
|
||||
heading={outsideViewportHeading}
|
||||
/>
|
||||
}
|
||||
</section>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
CaptureCycle.propTypes = {
|
||||
captureCycleIndex: number,
|
||||
timestamp: string,
|
||||
timings: arrayOf(shape({
|
||||
insideViewportComponents: arrayOf(shape({
|
||||
componentLoadTime: number,
|
||||
componentName: string
|
||||
}))
|
||||
})),
|
||||
outsideViewportComponents: arrayOf(shape({
|
||||
componentLoadTime: number,
|
||||
componentName: string
|
||||
})),
|
||||
routeUrl: string,
|
||||
timestamp: string,
|
||||
viewportLoadTime: number
|
||||
};
|
||||
|
||||
export default CaptureCycle;
|
||||
|
|
|
@ -12,36 +12,136 @@ describe('CaptureCycle.js', () => {
|
|||
expect(tree).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not render when the timings are null', () => {
|
||||
it('should not render when insideViewportComponents and outsideViewportComponents are null', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycle timings={null} />);
|
||||
.render(<CaptureCycle insideViewportComponents={null} outsideViewportComponents={null} />);
|
||||
expect(tree).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not render when there are no timings', () => {
|
||||
it('should not render when insideViewportComponents and outsideViewportComponents are empty', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycle timings={[]} />);
|
||||
.render(<CaptureCycle insideViewportComponents={[]} outsideViewportComponents={[]} />);
|
||||
expect(tree).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not error out when there is no timestamp', () => {
|
||||
it('should render when there are only insideViewportComponents', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycle captureCycleIndex={0} timings={[ { componentLoadTime: 9.2, componentName: 'componentName' } ]} />);
|
||||
.render(<CaptureCycle insideViewportComponents={[
|
||||
{
|
||||
componentLoadTime: 12.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]} />);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should not error out when there is no captureCycleIndex', () => {
|
||||
it('should render when there are only outsideViewportComponents', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycle timestamp={new Date(2019, 1, 23).toLocaleTimeString()} timings={[ { componentLoadTime: 9.2, componentName: 'componentName' } ]} />);
|
||||
.render(<CaptureCycle outsideViewportComponents={[
|
||||
{
|
||||
componentLoadTime: 12.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]} />);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render the capture cycle', () => {
|
||||
it('should render when there are both insideViewportComponents and outsideViewportComponents', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycle
|
||||
captureCycleIndex={0}
|
||||
timestamp={new Date(2019, 1, 23).toLocaleTimeString()}
|
||||
timings={[ { componentLoadTime: 9.2, componentName: 'componentName' } ]}
|
||||
insideViewportComponents={[
|
||||
{
|
||||
componentLoadTime: 12.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
outsideViewportComponents={[
|
||||
{
|
||||
componentLoadTime: 12.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
/>);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render with a routeUrl', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycle
|
||||
insideViewportComponents={[
|
||||
{
|
||||
componentLoadTime: 12.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
outsideViewportComponents={[
|
||||
{
|
||||
componentLoadTime: 12.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
routeUrl='routeUrl'
|
||||
/>);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render with a timestamp', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycle
|
||||
insideViewportComponents={[
|
||||
{
|
||||
componentLoadTime: 12.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
outsideViewportComponents={[
|
||||
{
|
||||
componentLoadTime: 12.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
timestamp='timestamp'
|
||||
/>);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render with both a routeUrl and timestamp', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycle
|
||||
insideViewportComponents={[
|
||||
{
|
||||
componentLoadTime: 12.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
outsideViewportComponents={[
|
||||
{
|
||||
componentLoadTime: 12.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
routeUrl='routeUrl'
|
||||
timestamp='timestamp'
|
||||
/>);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render with a viewportLoadTime', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycle
|
||||
insideViewportComponents={[
|
||||
{
|
||||
componentLoadTime: 12.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
outsideViewportComponents={[
|
||||
{
|
||||
componentLoadTime: 12.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
viewportLoadTime={15.4}
|
||||
/>);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -1,6 +1,123 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CaptureCycle.js should not error out when there is no captureCycleIndex 1`] = `
|
||||
exports[`CaptureCycle.js should render when there are both insideViewportComponents and outsideViewportComponents 1`] = `
|
||||
<section
|
||||
className="capture-cycle--card"
|
||||
>
|
||||
<h2
|
||||
className="capture-cycle--timestamp"
|
||||
>
|
||||
Capture Cycle
|
||||
</h2>
|
||||
<CaptureCycleSection
|
||||
components={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 12.2,
|
||||
"componentName": "componentName",
|
||||
},
|
||||
]
|
||||
}
|
||||
heading="Inside Viewport"
|
||||
subheading={false}
|
||||
/>
|
||||
<CaptureCycleSection
|
||||
components={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 12.2,
|
||||
"componentName": "componentName",
|
||||
},
|
||||
]
|
||||
}
|
||||
heading="Outside Viewport"
|
||||
/>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`CaptureCycle.js should render when there are only insideViewportComponents 1`] = `
|
||||
<section
|
||||
className="capture-cycle--card"
|
||||
>
|
||||
<h2
|
||||
className="capture-cycle--timestamp"
|
||||
>
|
||||
Capture Cycle
|
||||
</h2>
|
||||
<CaptureCycleSection
|
||||
components={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 12.2,
|
||||
"componentName": "componentName",
|
||||
},
|
||||
]
|
||||
}
|
||||
heading="Inside Viewport"
|
||||
subheading={false}
|
||||
/>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`CaptureCycle.js should render when there are only outsideViewportComponents 1`] = `
|
||||
<section
|
||||
className="capture-cycle--card"
|
||||
>
|
||||
<h2
|
||||
className="capture-cycle--timestamp"
|
||||
>
|
||||
Capture Cycle
|
||||
</h2>
|
||||
<CaptureCycleSection
|
||||
components={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 12.2,
|
||||
"componentName": "componentName",
|
||||
},
|
||||
]
|
||||
}
|
||||
heading="Outside Viewport"
|
||||
/>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`CaptureCycle.js should render with a routeUrl 1`] = `
|
||||
<section
|
||||
className="capture-cycle--card"
|
||||
>
|
||||
<h2
|
||||
className="capture-cycle--timestamp"
|
||||
>
|
||||
routeUrl
|
||||
</h2>
|
||||
<CaptureCycleSection
|
||||
components={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 12.2,
|
||||
"componentName": "componentName",
|
||||
},
|
||||
]
|
||||
}
|
||||
heading="Inside Viewport"
|
||||
subheading={false}
|
||||
/>
|
||||
<CaptureCycleSection
|
||||
components={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 12.2,
|
||||
"componentName": "componentName",
|
||||
},
|
||||
]
|
||||
}
|
||||
heading="Outside Viewport"
|
||||
/>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`CaptureCycle.js should render with a timestamp 1`] = `
|
||||
<section
|
||||
className="capture-cycle--card"
|
||||
>
|
||||
|
@ -10,22 +127,37 @@ exports[`CaptureCycle.js should not error out when there is no captureCycleIndex
|
|||
Capture Cycle
|
||||
<span>
|
||||
at
|
||||
12:00:00 AM
|
||||
timestamp
|
||||
:
|
||||
</span>
|
||||
</h2>
|
||||
<ul
|
||||
className="capture-cycle--components"
|
||||
>
|
||||
<ComponentTiming
|
||||
loadTime={9.2}
|
||||
name="componentName"
|
||||
<CaptureCycleSection
|
||||
components={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 12.2,
|
||||
"componentName": "componentName",
|
||||
},
|
||||
]
|
||||
}
|
||||
heading="Inside Viewport"
|
||||
subheading={false}
|
||||
/>
|
||||
<CaptureCycleSection
|
||||
components={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 12.2,
|
||||
"componentName": "componentName",
|
||||
},
|
||||
]
|
||||
}
|
||||
heading="Outside Viewport"
|
||||
/>
|
||||
</ul>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`CaptureCycle.js should not error out when there is no timestamp 1`] = `
|
||||
exports[`CaptureCycle.js should render with a viewportLoadTime 1`] = `
|
||||
<section
|
||||
className="capture-cycle--card"
|
||||
>
|
||||
|
@ -34,38 +166,86 @@ exports[`CaptureCycle.js should not error out when there is no timestamp 1`] = `
|
|||
>
|
||||
Capture Cycle
|
||||
</h2>
|
||||
<ul
|
||||
className="capture-cycle--components"
|
||||
<CaptureCycleSection
|
||||
components={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 12.2,
|
||||
"componentName": "componentName",
|
||||
},
|
||||
]
|
||||
}
|
||||
heading="Inside Viewport"
|
||||
subheading={
|
||||
<React.Fragment>
|
||||
Viewport Load Time:
|
||||
<span
|
||||
className="capture-cycle--statistic"
|
||||
>
|
||||
<ComponentTiming
|
||||
loadTime={9.2}
|
||||
name="componentName"
|
||||
15.4
|
||||
</span>
|
||||
ms
|
||||
<a
|
||||
aria-label="What is viewport load time?"
|
||||
className="capture-cycle--tooltip"
|
||||
href="https://github.com/Microsoft/Mezzurite#viewport-load-time-vlt"
|
||||
target="_blank"
|
||||
>
|
||||
?
|
||||
</a>
|
||||
</React.Fragment>
|
||||
}
|
||||
/>
|
||||
<CaptureCycleSection
|
||||
components={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 12.2,
|
||||
"componentName": "componentName",
|
||||
},
|
||||
]
|
||||
}
|
||||
heading="Outside Viewport"
|
||||
/>
|
||||
</ul>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`CaptureCycle.js should render the capture cycle 1`] = `
|
||||
exports[`CaptureCycle.js should render with both a routeUrl and timestamp 1`] = `
|
||||
<section
|
||||
className="capture-cycle--card"
|
||||
>
|
||||
<h2
|
||||
className="capture-cycle--timestamp"
|
||||
>
|
||||
Capture Cycle
|
||||
routeUrl
|
||||
<span>
|
||||
at
|
||||
12:00:00 AM
|
||||
timestamp
|
||||
:
|
||||
</span>
|
||||
</h2>
|
||||
<ul
|
||||
className="capture-cycle--components"
|
||||
>
|
||||
<ComponentTiming
|
||||
loadTime={9.2}
|
||||
name="componentName"
|
||||
<CaptureCycleSection
|
||||
components={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 12.2,
|
||||
"componentName": "componentName",
|
||||
},
|
||||
]
|
||||
}
|
||||
heading="Inside Viewport"
|
||||
subheading={false}
|
||||
/>
|
||||
<CaptureCycleSection
|
||||
components={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 12.2,
|
||||
"componentName": "componentName",
|
||||
},
|
||||
]
|
||||
}
|
||||
heading="Outside Viewport"
|
||||
/>
|
||||
</ul>
|
||||
</section>
|
||||
`;
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
@media only screen {
|
||||
.capture-cycle--components {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
list-style-type: none;
|
||||
margin: 16px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.capture-cycle--section-header {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
margin: 12px 16px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.capture-cycle--section-sub-header {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
margin: 8px 16px 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 540px) {
|
||||
.capture-cycle--section-header,
|
||||
.capture-cycle--section-sub-header {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
import React from 'react';
|
||||
import { arrayOf, node, number, shape, string } from 'prop-types';
|
||||
|
||||
import ComponentTiming from '../ComponentTiming/ComponentTiming';
|
||||
import './CaptureCycleSection.css';
|
||||
|
||||
const CaptureCycleSection = (props) => (
|
||||
props != null && props.components != null && props.components.length > 0 && <section>
|
||||
{props.heading != null && <h3 className='capture-cycle--section-header'>{props.heading}</h3>}
|
||||
{props.subheading != null && <h4 className='capture-cycle--section-sub-header'>{props.subheading}</h4>}
|
||||
<ul className='capture-cycle--components'>
|
||||
{props.components.map((component, timingIndex) =>
|
||||
<ComponentTiming
|
||||
key={`capture-cycle-${props.captureCycleIndex}-component-${timingIndex}`}
|
||||
name={component.componentName}
|
||||
loadTime={component.componentLoadTime}
|
||||
/>
|
||||
)}
|
||||
</ul>
|
||||
</section>
|
||||
);
|
||||
|
||||
CaptureCycleSection.propTypes = {
|
||||
captureCycleIndex: number,
|
||||
components: arrayOf(shape({
|
||||
componentLoadTime: number,
|
||||
componentName: string
|
||||
})),
|
||||
heading: string,
|
||||
subheading: node
|
||||
};
|
||||
|
||||
export default CaptureCycleSection;
|
|
@ -0,0 +1,79 @@
|
|||
import React from 'react';
|
||||
import ShallowRenderer from 'react-test-renderer/shallow';
|
||||
|
||||
import CaptureCycleSection from './CaptureCycleSection';
|
||||
|
||||
describe('CaptureCycleSection.js', () => {
|
||||
const renderer = new ShallowRenderer();
|
||||
|
||||
it('should not render when the props are null', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycleSection />);
|
||||
expect(tree).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not render when the components are null', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycleSection components={null} />);
|
||||
expect(tree).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not render when the components are empty', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycleSection components={null} />);
|
||||
expect(tree).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should render the capture cycle section', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycleSection components={[
|
||||
{
|
||||
componentLoadTime: 14.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]} />);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render the capture cycle section with a captureCycleIndex', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycleSection
|
||||
captureCycleIndex={4}
|
||||
components={[
|
||||
{
|
||||
componentLoadTime: 14.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
/>);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render the capture cycle section with a heading', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycleSection
|
||||
components={[
|
||||
{
|
||||
componentLoadTime: 14.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
heading='heading'
|
||||
/>);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render the capture cycle section with a subheading', () => {
|
||||
const tree = renderer
|
||||
.render(<CaptureCycleSection
|
||||
components={[
|
||||
{
|
||||
componentLoadTime: 14.2,
|
||||
componentName: 'componentName'
|
||||
}
|
||||
]}
|
||||
subheading={<span>subheading</span>}
|
||||
/>);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,65 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CaptureCycleSection.js should render the capture cycle section 1`] = `
|
||||
<section>
|
||||
<ul
|
||||
className="capture-cycle--components"
|
||||
>
|
||||
<ComponentTiming
|
||||
loadTime={14.2}
|
||||
name="componentName"
|
||||
/>
|
||||
</ul>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`CaptureCycleSection.js should render the capture cycle section with a captureCycleIndex 1`] = `
|
||||
<section>
|
||||
<ul
|
||||
className="capture-cycle--components"
|
||||
>
|
||||
<ComponentTiming
|
||||
loadTime={14.2}
|
||||
name="componentName"
|
||||
/>
|
||||
</ul>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`CaptureCycleSection.js should render the capture cycle section with a heading 1`] = `
|
||||
<section>
|
||||
<h3
|
||||
className="capture-cycle--section-header"
|
||||
>
|
||||
heading
|
||||
</h3>
|
||||
<ul
|
||||
className="capture-cycle--components"
|
||||
>
|
||||
<ComponentTiming
|
||||
loadTime={14.2}
|
||||
name="componentName"
|
||||
/>
|
||||
</ul>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`CaptureCycleSection.js should render the capture cycle section with a subheading 1`] = `
|
||||
<section>
|
||||
<h4
|
||||
className="capture-cycle--section-sub-header"
|
||||
>
|
||||
<span>
|
||||
subheading
|
||||
</span>
|
||||
</h4>
|
||||
<ul
|
||||
className="capture-cycle--components"
|
||||
>
|
||||
<ComponentTiming
|
||||
loadTime={14.2}
|
||||
name="componentName"
|
||||
/>
|
||||
</ul>
|
||||
</section>
|
||||
`;
|
|
@ -12,14 +12,14 @@
|
|||
|
||||
.component-timing--detail {
|
||||
display: flex;
|
||||
margin: 0 8px;
|
||||
margin: 12px;
|
||||
}
|
||||
|
||||
.component-timing--name {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 18px;
|
||||
margin-left: 8px;
|
||||
margin: 12px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@ import './ComponentTiming.css';
|
|||
|
||||
const ComponentTiming = (props) => (
|
||||
props != null && (props.name != null || props.loadTime != null) && <li className='component-timing--card'>
|
||||
{props.name != null && <h3 className='component-timing--name'>{props.name}</h3>}
|
||||
{props.name != null && <h4 className='component-timing--name'>{props.name}</h4>}
|
||||
{props.loadTime != null &&
|
||||
<p className='component-timing--detail'>
|
||||
<span className='mobile-hidden'>Load time:</span>
|
||||
<span className='component-timing--statistic'>{props.loadTime}</span>
|
||||
<span className='component-timing--statistic'>{props.loadTime.toFixed(1)}</span>
|
||||
ms
|
||||
</p>}
|
||||
</li>
|
||||
|
|
|
@ -4,11 +4,11 @@ exports[`ComponentTiming.js should render the componentTiming 1`] = `
|
|||
<li
|
||||
className="component-timing--card"
|
||||
>
|
||||
<h3
|
||||
<h4
|
||||
className="component-timing--name"
|
||||
>
|
||||
ComponentName
|
||||
</h3>
|
||||
</h4>
|
||||
<p
|
||||
className="component-timing--detail"
|
||||
>
|
||||
|
@ -53,10 +53,10 @@ exports[`ComponentTiming.js should render the componentTiming with only a name 1
|
|||
<li
|
||||
className="component-timing--card"
|
||||
>
|
||||
<h3
|
||||
<h4
|
||||
className="component-timing--name"
|
||||
>
|
||||
ComponentName
|
||||
</h3>
|
||||
</h4>
|
||||
</li>
|
||||
`;
|
||||
|
|
|
@ -19,8 +19,11 @@ const Main = (props) => {
|
|||
<CaptureCycle
|
||||
captureCycleIndex={captureCycleIndex}
|
||||
key={`capture-cycle-${captureCycleIndex}`}
|
||||
insideViewportComponents={captureCycle.insideViewportComponents}
|
||||
outsideViewportComponents={captureCycle.outsideViewportComponents}
|
||||
routeUrl={props.routeUrl}
|
||||
timestamp={captureCycle.time}
|
||||
timings={captureCycle.componentTimings}
|
||||
viewportLoadTime={captureCycle.viewportLoadTime}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -34,11 +37,17 @@ Main.propTypes = {
|
|||
applicationLoadTime: number,
|
||||
captureCycles: arrayOf(
|
||||
shape({
|
||||
componentTimings: arrayOf(shape({
|
||||
insideViewportComponents: arrayOf(shape({
|
||||
componentLoadTime: number,
|
||||
componentName: string
|
||||
})),
|
||||
time: string
|
||||
outsideViewportComponents: arrayOf(shape({
|
||||
componentLoadTime: number,
|
||||
componentName: string
|
||||
})),
|
||||
routeUrl: string,
|
||||
time: string,
|
||||
viewportLoadTime: number
|
||||
})
|
||||
)
|
||||
};
|
||||
|
|
|
@ -34,7 +34,7 @@ describe('Main.js', () => {
|
|||
const tree = renderer
|
||||
.render(<Main captureCycles={[
|
||||
{
|
||||
componentTimings: [
|
||||
insideViewportComponents: [
|
||||
{
|
||||
componentLoadTime: 5.23,
|
||||
componentName: 'ComponentName'
|
||||
|
|
|
@ -61,8 +61,7 @@ exports[`Main.js should render without applicationLoadTime 1`] = `
|
|||
>
|
||||
<CaptureCycle
|
||||
captureCycleIndex={0}
|
||||
timestamp="time"
|
||||
timings={
|
||||
insideViewportComponents={
|
||||
Array [
|
||||
Object {
|
||||
"componentLoadTime": 5.23,
|
||||
|
@ -70,6 +69,7 @@ exports[`Main.js should render without applicationLoadTime 1`] = `
|
|||
},
|
||||
]
|
||||
}
|
||||
timestamp="time"
|
||||
/>
|
||||
</main>
|
||||
`;
|
||||
|
|
Загрузка…
Ссылка в новой задаче