React.Context was overkill for this purpose, not using it
Also using Gatsby's built-in location property
This commit is contained in:
parent
2d754227b1
commit
13cfcca85e
@ -1,11 +1,62 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import * as Sentry from '@sentry/browser';
|
import * as Sentry from '@sentry/browser';
|
||||||
|
import URLSearchParams from '@ungap/url-search-params';
|
||||||
|
|
||||||
import { AppContextProvider } from 'components/AppContext';
|
|
||||||
import Form from 'components/Form';
|
import Form from 'components/Form';
|
||||||
import Loader from 'components/Loader';
|
import Loader from 'components/Loader';
|
||||||
import Message from 'components/Message';
|
import Message from 'components/Message';
|
||||||
|
|
||||||
|
const toUrl = params => new URLSearchParams(params).toString();
|
||||||
|
|
||||||
|
const createSvgLink = async ({ svg }) => {
|
||||||
|
try {
|
||||||
|
const type = 'image/svg+xml';
|
||||||
|
const blob = new Blob([svg], { type });
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: URL.createObjectURL(blob),
|
||||||
|
label: 'Download SVG',
|
||||||
|
filename: 'image.svg',
|
||||||
|
type
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error(e); // eslint-disable-line no-console
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const createPngLink = async ({ svg, width, height }) => {
|
||||||
|
try {
|
||||||
|
const type = 'image/png';
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
const context = canvas.getContext('2d');
|
||||||
|
const loader = new Image();
|
||||||
|
|
||||||
|
loader.width = canvas.width = Number(width) * 2;
|
||||||
|
loader.height = canvas.height = Number(height) * 2;
|
||||||
|
|
||||||
|
await new Promise(resolve => {
|
||||||
|
loader.onload = resolve;
|
||||||
|
loader.src = 'data:image/svg+xml,' + encodeURIComponent(svg);
|
||||||
|
});
|
||||||
|
|
||||||
|
context.drawImage(loader, 0, 0, loader.width, loader.height);
|
||||||
|
|
||||||
|
const blob = await new Promise(resolve => canvas.toBlob(resolve, type));
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: URL.createObjectURL(blob),
|
||||||
|
label: 'Download PNG',
|
||||||
|
filename: 'image.png',
|
||||||
|
type
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error(e); // eslint-disable-line no-console
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class App extends React.PureComponent {
|
class App extends React.PureComponent {
|
||||||
state = {
|
state = {
|
||||||
loading: false,
|
loading: false,
|
||||||
@ -13,15 +64,43 @@ class App extends React.PureComponent {
|
|||||||
Render: null
|
Render: null
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRender = async ({ syntax, expr }) => {
|
componentDidMount() {
|
||||||
|
if (this.props.expr) {
|
||||||
|
this.handleRender();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps) {
|
||||||
|
const { syntax, expr } = this.props;
|
||||||
|
|
||||||
|
if (syntax !== prevProps.syntax || expr !== prevProps.expr) {
|
||||||
|
this.handleRender();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubmit = ({ syntax, expr }) => {
|
||||||
|
if (expr) {
|
||||||
|
document.location.hash = toUrl({ syntax, expr });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleRender = async () => {
|
||||||
|
const { syntax, expr } = this.props;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
syntax,
|
loading: false,
|
||||||
expr,
|
|
||||||
loading: true,
|
|
||||||
loadingError: null,
|
loadingError: null,
|
||||||
Render: null
|
Render: null
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!expr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
loading: true
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const Render = await import(
|
const Render = await import(
|
||||||
/* webpackChunkName: "render-[index]" */
|
/* webpackChunkName: "render-[index]" */
|
||||||
@ -51,18 +130,51 @@ class App extends React.PureComponent {
|
|||||||
|
|
||||||
handleRetry = event => {
|
handleRetry = event => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.handleRender(this.state);
|
this.handleRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSvgMarkup = async ({ svg, width, height }) => {
|
||||||
|
if (svg !== this.state.svg) {
|
||||||
|
this.setState({
|
||||||
|
svg,
|
||||||
|
svgLink: await createSvgLink({ svg }),
|
||||||
|
pngLink: await createPngLink({ svg, width, height })
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const {
|
||||||
|
syntax,
|
||||||
|
expr,
|
||||||
|
permalinkUrl
|
||||||
|
} = this.props;
|
||||||
const {
|
const {
|
||||||
loading,
|
loading,
|
||||||
loadingError,
|
loadingError,
|
||||||
Render
|
Render,
|
||||||
|
svgLink,
|
||||||
|
pngLink
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
return <AppContextProvider onExpressionChange={ this.handleRender }>
|
const formProps = {
|
||||||
<Form />
|
onSubmit: this.handleSubmit,
|
||||||
|
syntax,
|
||||||
|
expr,
|
||||||
|
actions: {
|
||||||
|
permalinkUrl,
|
||||||
|
svgLink,
|
||||||
|
pngLink
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const renderProps = {
|
||||||
|
onRender: this.handleSvgMarkup,
|
||||||
|
syntax,
|
||||||
|
expr
|
||||||
|
};
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<Form { ...formProps } />
|
||||||
|
|
||||||
{ loading && <Loader /> }
|
{ loading && <Loader /> }
|
||||||
|
|
||||||
@ -71,9 +183,15 @@ class App extends React.PureComponent {
|
|||||||
<a href="#retry" onClick={ this.handleRetry }>Retry</a>
|
<a href="#retry" onClick={ this.handleRetry }>Retry</a>
|
||||||
</Message> }
|
</Message> }
|
||||||
|
|
||||||
{ Render && <Render /> }
|
{ Render && <Render { ...renderProps } /> }
|
||||||
</AppContextProvider>;
|
</>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
App.propTypes = {
|
||||||
|
syntax: PropTypes.string,
|
||||||
|
expr: PropTypes.string,
|
||||||
|
permalinkUrl: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
@ -1,149 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import URLSearchParams from '@ungap/url-search-params';
|
|
||||||
|
|
||||||
const AppContext = React.createContext();
|
|
||||||
|
|
||||||
const toUrl = params => new URLSearchParams(params).toString();
|
|
||||||
|
|
||||||
const readURLHash = () => {
|
|
||||||
const query = document.location.hash.slice(1);
|
|
||||||
const params = new URLSearchParams(query);
|
|
||||||
|
|
||||||
if (params.get('syntax')) {
|
|
||||||
return {
|
|
||||||
syntax: params.get('syntax'),
|
|
||||||
expr: params.get('expr')
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// Assuming old-style URL
|
|
||||||
return {
|
|
||||||
syntax: 'js',
|
|
||||||
expr: query
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const createSvgLink = async ({ svg }) => {
|
|
||||||
try {
|
|
||||||
const type = 'image/svg+xml';
|
|
||||||
const blob = new Blob([svg], { type });
|
|
||||||
|
|
||||||
return {
|
|
||||||
url: URL.createObjectURL(blob),
|
|
||||||
label: 'Download SVG',
|
|
||||||
filename: 'image.svg',
|
|
||||||
type
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
console.error(e); // eslint-disable-line no-console
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const createPngLink = async ({ svg, width, height }) => {
|
|
||||||
try {
|
|
||||||
const type = 'image/png';
|
|
||||||
const canvas = document.createElement('canvas');
|
|
||||||
const context = canvas.getContext('2d');
|
|
||||||
const loader = new Image();
|
|
||||||
|
|
||||||
loader.width = canvas.width = Number(width) * 2;
|
|
||||||
loader.height = canvas.height = Number(height) * 2;
|
|
||||||
|
|
||||||
await new Promise(resolve => {
|
|
||||||
loader.onload = resolve;
|
|
||||||
loader.src = 'data:image/svg+xml,' + encodeURIComponent(svg);
|
|
||||||
});
|
|
||||||
|
|
||||||
context.drawImage(loader, 0, 0, loader.width, loader.height);
|
|
||||||
|
|
||||||
const blob = await new Promise(resolve => canvas.toBlob(resolve, type));
|
|
||||||
|
|
||||||
return {
|
|
||||||
url: URL.createObjectURL(blob),
|
|
||||||
label: 'Download PNG',
|
|
||||||
filename: 'image.png',
|
|
||||||
type
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
console.error(e); // eslint-disable-line no-console
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class AppContextProvider extends React.PureComponent {
|
|
||||||
state = {}
|
|
||||||
|
|
||||||
mutations = {
|
|
||||||
setSvgMarkup: async ({ svg, width, height }) => {
|
|
||||||
if (svg !== this.state.svg) {
|
|
||||||
this.setState({
|
|
||||||
svg,
|
|
||||||
svgLink: await createSvgLink({ svg }),
|
|
||||||
pngLink: await createPngLink({ svg, width, height })
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
renderExpr: ({ syntax, expr }) => {
|
|
||||||
if (expr) {
|
|
||||||
document.location.hash = toUrl({ syntax, expr });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
// Gatsby doesn't have document.location, so readURLHash can't be called
|
|
||||||
// until here
|
|
||||||
this.setState(readURLHash());
|
|
||||||
|
|
||||||
window.addEventListener('hashchange', this.handleHashChange);
|
|
||||||
this.handleHashChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
window.removeEventListener('hashchange', this.handleHashChange);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleHashChange = () => {
|
|
||||||
const { expr, syntax } = readURLHash();
|
|
||||||
|
|
||||||
if (!expr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
syntax,
|
|
||||||
expr,
|
|
||||||
permalinkUrl: document.location.toString()
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.props.onExpressionChange) {
|
|
||||||
this.props.onExpressionChange({ syntax, expr });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { children } = this.props;
|
|
||||||
const context = {
|
|
||||||
...this.state,
|
|
||||||
...this.mutations
|
|
||||||
};
|
|
||||||
|
|
||||||
return <AppContext.Provider value={ context }>
|
|
||||||
{ children }
|
|
||||||
</AppContext.Provider>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AppContextProvider.propTypes = {
|
|
||||||
onExpressionChange: PropTypes.func,
|
|
||||||
children: PropTypes.oneOfType([
|
|
||||||
PropTypes.arrayOf(PropTypes.node),
|
|
||||||
PropTypes.node
|
|
||||||
]).isRequired
|
|
||||||
};
|
|
||||||
|
|
||||||
export { AppContextProvider };
|
|
||||||
export default AppContext;
|
|
@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import ExpandIcon from 'react-feather/dist/icons/chevrons-down';
|
import ExpandIcon from 'react-feather/dist/icons/chevrons-down';
|
||||||
|
|
||||||
import style from './style.module.css';
|
import style from './style.module.css';
|
||||||
|
|
||||||
import AppContext from 'components/AppContext';
|
|
||||||
import FormActions from 'components/FormActions';
|
import FormActions from 'components/FormActions';
|
||||||
|
|
||||||
const syntaxList = [
|
const syntaxList = [
|
||||||
@ -13,20 +13,9 @@ const syntaxList = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
class Form extends React.PureComponent {
|
class Form extends React.PureComponent {
|
||||||
static contextType = AppContext
|
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
expr: this.context.expr,
|
expr: this.props.expr,
|
||||||
syntax: this.context.syntax
|
syntax: this.props.syntax
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
if (this.state.expr === undefined && this.state.syntax === undefined) {
|
|
||||||
this.setState({
|
|
||||||
syntax: this.context.syntax,
|
|
||||||
expr: this.context.expr
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSubmit = event => {
|
handleSubmit = event => {
|
||||||
@ -34,7 +23,7 @@ class Form extends React.PureComponent {
|
|||||||
|
|
||||||
const { expr, syntax } = this.state;
|
const { expr, syntax } = this.state;
|
||||||
|
|
||||||
this.context.renderExpr({ expr, syntax });
|
this.props.onSubmit({ expr, syntax });
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKeyPress = event => {
|
handleKeyPress = event => {
|
||||||
@ -48,6 +37,9 @@ class Form extends React.PureComponent {
|
|||||||
})
|
})
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const {
|
||||||
|
actions
|
||||||
|
} = this.props;
|
||||||
const { expr, syntax } = this.state;
|
const { expr, syntax } = this.state;
|
||||||
|
|
||||||
return <div className={ style.form }>
|
return <div className={ style.form }>
|
||||||
@ -71,10 +63,17 @@ class Form extends React.PureComponent {
|
|||||||
</select>
|
</select>
|
||||||
<ExpandIcon />
|
<ExpandIcon />
|
||||||
</div>
|
</div>
|
||||||
<FormActions />
|
<FormActions { ...actions } />
|
||||||
</form>
|
</form>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Form.propTypes = {
|
||||||
|
expr: PropTypes.string,
|
||||||
|
syntax: PropTypes.string,
|
||||||
|
actions: PropTypes.object,
|
||||||
|
onSubmit: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
export default Form;
|
export default Form;
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import DownloadIcon from 'react-feather/dist/icons/download';
|
import DownloadIcon from 'react-feather/dist/icons/download';
|
||||||
import LinkIcon from 'react-feather/dist/icons/link';
|
import LinkIcon from 'react-feather/dist/icons/link';
|
||||||
|
|
||||||
import style from './style.module.css';
|
import style from './style.module.css';
|
||||||
|
|
||||||
import AppContext from 'components/AppContext';
|
|
||||||
|
|
||||||
class FormActions extends React.PureComponent {
|
class FormActions extends React.PureComponent {
|
||||||
static contextType = AppContext
|
|
||||||
|
|
||||||
downloadLink({ url, filename, type, label }) {
|
downloadLink({ url, filename, type, label }) {
|
||||||
return <li>
|
return <li>
|
||||||
<a href={ url } download={ filename } type={ type }>
|
<a href={ url } download={ filename } type={ type }>
|
||||||
@ -23,7 +20,7 @@ class FormActions extends React.PureComponent {
|
|||||||
permalinkUrl,
|
permalinkUrl,
|
||||||
svgLink,
|
svgLink,
|
||||||
pngLink
|
pngLink
|
||||||
} = this.context;
|
} = this.props;
|
||||||
|
|
||||||
return <ul className={ style.actions }>
|
return <ul className={ style.actions }>
|
||||||
{ pngLink && this.downloadLink(pngLink) }
|
{ pngLink && this.downloadLink(pngLink) }
|
||||||
@ -35,4 +32,10 @@ class FormActions extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FormActions.propTypes = {
|
||||||
|
permalinkUrl: PropTypes.string,
|
||||||
|
svgLink: PropTypes.object,
|
||||||
|
pngLink: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
export default FormActions;
|
export default FormActions;
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import PlaceholderIcon from 'react-feather/dist/icons/file-text';
|
import PlaceholderIcon from 'react-feather/dist/icons/file-text';
|
||||||
|
|
||||||
import style from './style.module.css';
|
import style from './style.module.css';
|
||||||
|
|
||||||
import AppContext from 'components/AppContext';
|
|
||||||
|
|
||||||
class Render extends React.PureComponent {
|
class Render extends React.PureComponent {
|
||||||
static contextType = AppContext
|
|
||||||
|
|
||||||
svgContainer = React.createRef()
|
svgContainer = React.createRef()
|
||||||
|
|
||||||
provideSVGData() {
|
provideSVGData() {
|
||||||
@ -17,7 +14,7 @@ class Render extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const svg = this.svgContainer.current.querySelector('svg');
|
const svg = this.svgContainer.current.querySelector('svg');
|
||||||
this.context.setSvgMarkup({
|
this.props.onRender({
|
||||||
svg: svg.outerHTML,
|
svg: svg.outerHTML,
|
||||||
width: svg.getAttribute('width'),
|
width: svg.getAttribute('width'),
|
||||||
height: svg.getAttribute('height')
|
height: svg.getAttribute('height')
|
||||||
@ -33,7 +30,7 @@ class Render extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { syntax, expr } = this.context;
|
const { syntax, expr } = this.props;
|
||||||
|
|
||||||
console.log('Render:', syntax, expr); // eslint-disable-line no-console
|
console.log('Render:', syntax, expr); // eslint-disable-line no-console
|
||||||
|
|
||||||
@ -44,4 +41,10 @@ class Render extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Render.propTypes = {
|
||||||
|
syntax: PropTypes.string,
|
||||||
|
expr: PropTypes.string,
|
||||||
|
onRender: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
export default Render;
|
export default Render;
|
||||||
|
@ -22,6 +22,40 @@ exports[`Index Page rendering 1`] = `
|
|||||||
</p>
|
</p>
|
||||||
</Message>
|
</Message>
|
||||||
</noscript>
|
</noscript>
|
||||||
<App />
|
<App
|
||||||
|
expr=""
|
||||||
|
permalinkUrl={null}
|
||||||
|
syntax="js"
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Index Page rendering with an expression on the URL 1`] = `
|
||||||
|
<Fragment>
|
||||||
|
<Metadata />
|
||||||
|
<noscript>
|
||||||
|
<Message
|
||||||
|
heading="JavaScript Required"
|
||||||
|
type="error"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
You need JavaScript to use Regexper.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
If you have concerns regarding the use of tracking code on Regexper, please see the
|
||||||
|
<mockConstructor
|
||||||
|
to="/privacy"
|
||||||
|
>
|
||||||
|
Privacy Policy
|
||||||
|
</mockConstructor>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
</Message>
|
||||||
|
</noscript>
|
||||||
|
<App
|
||||||
|
expr="testing"
|
||||||
|
permalinkUrl="http://example.com"
|
||||||
|
syntax="test"
|
||||||
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
`;
|
`;
|
||||||
|
@ -1,11 +1,34 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import { Link } from 'gatsby';
|
import { Link } from 'gatsby';
|
||||||
|
import URLSearchParams from '@ungap/url-search-params';
|
||||||
|
|
||||||
import Metadata from 'components/Metadata';
|
import Metadata from 'components/Metadata';
|
||||||
import Message from 'components/Message';
|
import Message from 'components/Message';
|
||||||
import App from 'components/App';
|
import App from 'components/App';
|
||||||
|
|
||||||
export const IndexPage = () => <>
|
const readURLHash = location => {
|
||||||
|
const query = location.hash.slice(1);
|
||||||
|
const params = new URLSearchParams(query);
|
||||||
|
const permalinkUrl = query ? location.href : null;
|
||||||
|
|
||||||
|
if (params.get('syntax')) {
|
||||||
|
return {
|
||||||
|
syntax: params.get('syntax'),
|
||||||
|
expr: params.get('expr'),
|
||||||
|
permalinkUrl
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Assuming old-style URL
|
||||||
|
return {
|
||||||
|
syntax: 'js',
|
||||||
|
expr: query,
|
||||||
|
permalinkUrl
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const IndexPage = ({ location }) => <>
|
||||||
<Metadata/>
|
<Metadata/>
|
||||||
<noscript>
|
<noscript>
|
||||||
<Message type="error" heading="JavaScript Required">
|
<Message type="error" heading="JavaScript Required">
|
||||||
@ -14,7 +37,11 @@ export const IndexPage = () => <>
|
|||||||
please see the <Link to="/privacy">Privacy Policy</Link>.</p>
|
please see the <Link to="/privacy">Privacy Policy</Link>.</p>
|
||||||
</Message>
|
</Message>
|
||||||
</noscript>
|
</noscript>
|
||||||
<App />
|
<App { ...readURLHash(location) } />
|
||||||
</>;
|
</>;
|
||||||
|
|
||||||
|
IndexPage.propTypes = {
|
||||||
|
location: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
export default IndexPage;
|
export default IndexPage;
|
||||||
|
@ -6,7 +6,17 @@ import { IndexPage } from 'pages/index';
|
|||||||
describe('Index Page', () => {
|
describe('Index Page', () => {
|
||||||
test('rendering', () => {
|
test('rendering', () => {
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
<IndexPage />
|
<IndexPage location={{ hash: '' }} />
|
||||||
|
);
|
||||||
|
expect(component).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('rendering with an expression on the URL', () => {
|
||||||
|
const component = shallow(
|
||||||
|
<IndexPage location={{
|
||||||
|
hash: '#syntax=test&expr=testing',
|
||||||
|
href: 'http://example.com'
|
||||||
|
}} />
|
||||||
);
|
);
|
||||||
expect(component).toMatchSnapshot();
|
expect(component).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user