Merge pull request #26 from kawwong/detect-mezzurite

Add loading and not found view states
This commit is contained in:
C. Naoto Abreu Takemura 2019-01-30 15:29:41 -08:00 коммит произвёл GitHub
Родитель 946f947cf3 4b9a9c1fda
Коммит 3735174a46
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 284 добавлений и 42 удалений

Просмотреть файл

@ -13,6 +13,7 @@ class App extends Component {
this.state = {
applicationLoadTime: null,
captureCycles: null,
loading: true,
framework: {
name: null,
version: null
@ -21,8 +22,12 @@ class App extends Component {
}
componentDidMount () {
MezzuriteInspector.isMezzuritePresentAsync().then(() => {
MezzuriteInspector.listenForTimingEvents((event) => this.handleTimingEvent(event));
MezzuriteInspector.isMezzuritePresentAsync().then((mezzuritePresent) => {
if (mezzuritePresent) {
MezzuriteInspector.listenForTimingEvents((timingEvent) => this.handleTimingEvent(timingEvent));
} else {
this.setState({ loading: false });
}
});
}
@ -57,6 +62,8 @@ class App extends Component {
}
});
}
this.setState({ loading: false });
}
}
@ -64,7 +71,7 @@ class App extends Component {
return (
<div className='app'>
<Header />
<Main applicationLoadTime={this.state.applicationLoadTime} captureCycles={this.state.captureCycles} />
<Main applicationLoadTime={this.state.applicationLoadTime} captureCycles={this.state.captureCycles} loading={this.state.loading} />
<Footer packageName={this.state.framework.name} packageVersion={this.state.framework.version} />
</div>
);

Просмотреть файл

@ -8,6 +8,31 @@
margin: 16px;
text-align: center;
}
.main--header-center {
align-items: center;
display: flex;
flex-direction: column;
height: 100%;
justify-content: center;
line-height: 24px;
margin: 0;
}
.main--header-link {
color: var(--microsoft-blue);
text-decoration: none;
}
.main--header-link:active {
color: var(--microsoft-gray-darker);
}
.main--header-text {
max-width: 80%;
margin: 0;
text-align: center;
}
}
@media only screen and (min-width: 540px) {

Просмотреть файл

@ -1,18 +1,19 @@
import React from 'react';
import { arrayOf, number, shape, string } from 'prop-types';
import React, { Fragment } from 'react';
import { arrayOf, bool, number, shape, string } from 'prop-types';
import './Main.css';
import CaptureCycle from '../CaptureCycle/CaptureCycle';
import MainLoading from './MainLoading';
const Main = (props) => {
const noActiveCaptureCycles = props.captureCycles != null && props.captureCycles.length === 0 && props.applicationLoadTime != null;
return (
props != null && <main className='main'>
{props.applicationLoadTime == null && props.captureCycles == null &&
<h2 className='main--header'>Mezzurite is working...</h2>
}
{props.applicationLoadTime != null && <h2 className='main--header'>App<span className='mobile-hidden'>lication</span> Load Time: {props.applicationLoadTime} ms</h2>}
<h2 className={props.applicationLoadTime != null || props.loading ? 'main--header' : 'main--header main--header-center'}>
{renderHeader(props.applicationLoadTime, props.loading)}
</h2>
{props.loading && <MainLoading />}
{props.captureCycles != null && props.captureCycles.length > 0 && props.captureCycles.map((captureCycle, captureCycleIndex) => {
if (captureCycle != null) {
return (
@ -33,6 +34,24 @@ const Main = (props) => {
);
};
const renderHeader = (applicationLoadTime, loading) => {
if (applicationLoadTime == null) {
if (loading) {
return <Fragment>
Mezzurite is working...
</Fragment>;
} else {
return <span className='main--header-text'>
Mezzurite was not detected. Follow <a className='main--header-link' href='https://github.com/Microsoft/Mezzurite#onboarding' target='_blank'>the instructions</a> to install Mezzurite.
</span>;
}
} else {
return <Fragment>
App<span className='mobile-hidden'>lication</span> Load Time: {applicationLoadTime.toFixed(1)}ms
</Fragment>;
}
};
Main.propTypes = {
applicationLoadTime: number,
captureCycles: arrayOf(
@ -49,7 +68,8 @@ Main.propTypes = {
time: string,
viewportLoadTime: number
})
)
),
loading: bool
};
export default Main;

Просмотреть файл

@ -12,9 +12,21 @@ describe('Main.js', () => {
expect(tree).toMatchSnapshot();
});
it('should render without captureCycles', () => {
it('should render with loading as true', () => {
const tree = renderer
.render(<Main applicationLoadTime={5.42} />);
.render(<Main loading />);
expect(tree).toMatchSnapshot();
});
it('should render without captureCycles and loading as true', () => {
const tree = renderer
.render(<Main applicationLoadTime={5.42} loading />);
expect(tree).toMatchSnapshot();
});
it('should render without captureCycles and loading as false', () => {
const tree = renderer
.render(<Main applicationLoadTime={5.42} loading={false} />);
expect(tree).toMatchSnapshot();
});

Просмотреть файл

@ -0,0 +1,51 @@
@media only screen {
.capture-cycle--skeleton {
padding-bottom: 4px;
}
.capture-cycle--skeleton-component {
border-radius: 8px;
height: 28px;
margin: 0 16px 16px;
}
.capture-cycle--skeleton-title {
height: 24px;
border-radius: 8px;
margin: 16px auto 36px;
max-width: 50%;
}
.shimmer {
background: var(--microsoft-gray-lightest);
background-image: -webkit-gradient(linear, left top, right top, from(var(--microsoft-gray-lightest)), color-stop(20%, var(--microsoft-gray-lighter)), color-stop(60%, var(--microsoft-gray-lightest)), to(var(--microsoft-gray-lightest)));
background-image: -webkit-linear-gradient(left, var(--microsoft-gray-lightest) 0%, var(--microsoft-gray-lighter) 20%, var(--microsoft-gray-lightest) 60%, var(--microsoft-gray-lightest) 100%);
background-image: -o-linear-gradient(left, var(--microsoft-gray-lightest) 0%, var(--microsoft-gray-lighter) 20%, var(--microsoft-gray-lightest) 60%, var(--microsoft-gray-lightest) 100%);
background-image: linear-gradient(to right, var(--microsoft-gray-lightest) 0%, var(--microsoft-gray-lighter) 20%, var(--microsoft-gray-lightest) 60%, var(--microsoft-gray-lightest) 100%);
background-repeat: no-repeat;
background-size: 200vw 200vw;
opacity: 0.6;
-webkit-animation-duration: 2s;
-webkit-animation-fill-mode: forwards;
-webkit-animation-iteration-count: infinite;
-webkit-animation-name: placeholderShimmer;
-webkit-animation-timing-function: linear;
}
}
@media only screen and (min-width: 540px) {
.capture-cycle--skeleton-title {
margin: 16px 16px 36px;
max-width: 30%;
}
}
@-webkit-keyframes placeholderShimmer {
0% {
background-position: -100vw 0;
}
100% {
background-position: 100vw 0;
}
}

Просмотреть файл

@ -0,0 +1,16 @@
import React from 'react';
import './MainLoading.css';
const MainLoading = () => (
<div className='capture-cycle--card capture-cycle--skeleton'>
<div className='capture-cycle--skeleton-title shimmer' />
<div className='capture-cycle--skeleton-container'>
<div className='capture-cycle--skeleton-component shimmer' />
<div className='capture-cycle--skeleton-component shimmer' />
<div className='capture-cycle--skeleton-component shimmer' />
</div>
</div>
);
export default MainLoading;

Просмотреть файл

@ -0,0 +1,14 @@
import React from 'react';
import ShallowRenderer from 'react-test-renderer/shallow';
import MainLoading from './MainLoading';
describe('MainLoading.js', () => {
const renderer = new ShallowRenderer();
it('should render the main loading view', () => {
const tree = renderer
.render(<MainLoading />);
expect(tree).toMatchSnapshot();
});
});

Просмотреть файл

@ -5,9 +5,21 @@ exports[`Main.js should be loading when the props are null 1`] = `
className="main"
>
<h2
className="main--header"
className="main--header main--header-center"
>
Mezzurite is working...
<span
className="main--header-text"
>
Mezzurite was not detected. Follow
<a
className="main--header-link"
href="https://github.com/Microsoft/Mezzurite#onboarding"
target="_blank"
>
the instructions
</a>
to install Mezzurite.
</span>
</h2>
</main>
`;
@ -19,15 +31,17 @@ exports[`Main.js should not error out when captureCycles contains a null element
<h2
className="main--header"
>
App
<span
className="mobile-hidden"
>
lication
</span>
Load Time:
5.42
ms
<React.Fragment>
App
<span
className="mobile-hidden"
>
lication
</span>
Load Time:
5.4
ms
</React.Fragment>
</h2>
</main>
`;
@ -39,15 +53,17 @@ exports[`Main.js should render when captureCycles is an empty array 1`] = `
<h2
className="main--header"
>
App
<span
className="mobile-hidden"
>
lication
</span>
Load Time:
5.42
ms
<React.Fragment>
App
<span
className="mobile-hidden"
>
lication
</span>
Load Time:
5.4
ms
</React.Fragment>
</h2>
<h3>
No active capture cycles have completed.
@ -55,10 +71,42 @@ exports[`Main.js should render when captureCycles is an empty array 1`] = `
</main>
`;
exports[`Main.js should render with loading as true 1`] = `
<main
className="main"
>
<h2
className="main--header"
>
<React.Fragment>
Mezzurite is working...
</React.Fragment>
</h2>
<MainLoading />
</main>
`;
exports[`Main.js should render without applicationLoadTime 1`] = `
<main
className="main"
>
<h2
className="main--header main--header-center"
>
<span
className="main--header-text"
>
Mezzurite was not detected. Follow
<a
className="main--header-link"
href="https://github.com/Microsoft/Mezzurite#onboarding"
target="_blank"
>
the instructions
</a>
to install Mezzurite.
</span>
</h2>
<CaptureCycle
captureCycleIndex={0}
insideViewportComponents={
@ -74,22 +122,47 @@ exports[`Main.js should render without applicationLoadTime 1`] = `
</main>
`;
exports[`Main.js should render without captureCycles 1`] = `
exports[`Main.js should render without captureCycles and loading as false 1`] = `
<main
className="main"
>
<h2
className="main--header"
>
App
<span
className="mobile-hidden"
>
lication
</span>
Load Time:
5.42
ms
<React.Fragment>
App
<span
className="mobile-hidden"
>
lication
</span>
Load Time:
5.4
ms
</React.Fragment>
</h2>
</main>
`;
exports[`Main.js should render without captureCycles and loading as true 1`] = `
<main
className="main"
>
<h2
className="main--header"
>
<React.Fragment>
App
<span
className="mobile-hidden"
>
lication
</span>
Load Time:
5.4
ms
</React.Fragment>
</h2>
<MainLoading />
</main>
`;

Просмотреть файл

@ -0,0 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`MainLoading.js should render the main loading view 1`] = `
<div
className="capture-cycle--card capture-cycle--skeleton"
>
<div
className="capture-cycle--skeleton-title shimmer"
/>
<div
className="capture-cycle--skeleton-container"
>
<div
className="capture-cycle--skeleton-component shimmer"
/>
<div
className="capture-cycle--skeleton-component shimmer"
/>
<div
className="capture-cycle--skeleton-component shimmer"
/>
</div>
</div>
`;