Merge branch 'feature/gatsby-no-enzyme' into 'gatsby'

Replacing Enzyme with react-testing-library

See merge request javallone/regexper-static!42
This commit is contained in:
Jeff Avallone 2019-03-25 01:51:26 +00:00
commit dd8c405482
54 changed files with 2549 additions and 2055 deletions

View File

@ -1,8 +1,3 @@
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Enzyme.configure({ adapter: new Adapter() });
global.___loader = {
enqueue: jest.fn()
};

View File

@ -56,11 +56,9 @@
"node_modules"
],
"setupFilesAfterEnv": [
"react-testing-library/cleanup-after-each",
"<rootDir>/jest/setup.js"
],
"snapshotSerializers": [
"enzyme-to-json/serializer"
],
"testPathIgnorePatterns": [
"node_modules",
".cache"
@ -85,9 +83,6 @@
"babel-jest": "^24.5.0",
"babel-plugin-dynamic-import-node": "^2.2.0",
"babel-preset-gatsby": "^0.1.6",
"enzyme": "^3.8.0",
"enzyme-adapter-react-16": "^1.7.1",
"enzyme-to-json": "^3.3.5",
"eslint": "^5.11.1",
"eslint-plugin-jest": "^22.1.2",
"eslint-plugin-react": "^7.12.1",
@ -114,6 +109,7 @@
"react-feather": "^1.1.5",
"react-helmet": "^5.2.0",
"react-i18next": "^10.5.3",
"react-modal": "^3.8.1"
"react-modal": "^3.8.1",
"react-testing-library": "^6.0.2"
}
}

View File

@ -0,0 +1,19 @@
const React = require('react');
const buildMock = component => {
const componentName = component.displayName || component.name || 'Component';
const Mock = ({ children, ...props }) => (
<span
data-component={ componentName }
data-props={ JSON.stringify(props, null, ' ') }>{ children }</span>
);
Mock.propTypes = component.propTypes;
return Mock;
};
module.exports = path => {
const actual = jest.requireActual(path);
return buildMock(actual.default || actual);
};
module.exports.buildMock = buildMock;

6
src/__mocks__/react-i18next.js vendored Normal file
View File

@ -0,0 +1,6 @@
const reactI18next = jest.requireActual('react-i18next');
module.exports = {
...reactI18next,
Trans: require('__mocks__/component-mock').buildMock(reactI18next.Trans)
};

View File

@ -1,293 +1,255 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`App removing rendered expression 1`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"js\\",
\\"expr\\": \\"test expression\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
>
<withI18nextTranslation(FormActions) />
</withI18nextTranslation(Form)>
<Render
data="LAYOUT(PARSED(test expression))"
onRender={[Function]}
<span
data-component="withI18nextTranslation(FormActions)"
data-props="{}"
/>
</span>
<span
data-component="Render"
data-props="{
\\"data\\": \\"LAYOUT(PARSED(test expression))\\"
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App removing rendered expression 2`] = `
<Fragment>
<withI18nextTranslation(Form)
expr=""
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"js\\",
\\"expr\\": \\"\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App rendering 1`] = `
<Fragment>
<withI18nextTranslation(Form)
expr=""
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"js\\",
\\"expr\\": \\"\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App rendering an expression 1`] = `
<Fragment>
<withI18nextTranslation(Form)
expr=""
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"js\\",
\\"expr\\": \\"\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App rendering an expression 2`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"js\\",
\\"expr\\": \\"test expression\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
<withI18nextTranslation(Loader) />
</Fragment>
<span
data-component="withI18nextTranslation(Loader)"
data-props="{}"
/>
</DocumentFragment>
`;
exports[`App rendering an expression 3`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"js\\",
\\"expr\\": \\"test expression\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
>
<withI18nextTranslation(FormActions) />
</withI18nextTranslation(Form)>
<Render
data="LAYOUT(PARSED(test expression))"
onRender={[Function]}
/>
</Fragment>
`;
exports[`App rendering image details 1`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
}
>
<withI18nextTranslation(FormActions) />
</withI18nextTranslation(Form)>
<Render
data="LAYOUT(PARSED(test expression))"
onRender={[Function]}
/>
</Fragment>
`;
exports[`App rendering image details 2`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="js"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
}
>
<withI18nextTranslation(FormActions)
imageDetails={
Object {
"svg": "test svg content",
}
}
<span
data-component="withI18nextTranslation(FormActions)"
data-props="{}"
/>
</withI18nextTranslation(Form)>
<Render
data="LAYOUT(PARSED(test expression))"
onRender={[Function]}
</span>
<span
data-component="Render"
data-props="{
\\"data\\": \\"LAYOUT(PARSED(test expression))\\"
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App rendering with an invalid syntax 1`] = `
<Fragment>
<withI18nextTranslation(Form)
expr=""
onSubmit={[Function]}
syntax="invalid"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"invalid\\",
\\"expr\\": \\"\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`App rendering with an invalid syntax 2`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="invalid"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"invalid\\",
\\"expr\\": \\"test expression\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
<withI18nextTranslation(Loader) />
</Fragment>
<span
data-component="withI18nextTranslation(Loader)"
data-props="{}"
/>
</DocumentFragment>
`;
exports[`App rendering with an invalid syntax 3`] = `
<Fragment>
<withI18nextTranslation(Form)
expr="test expression"
onSubmit={[Function]}
syntax="invalid"
syntaxList={
Array [
Object {
"id": "testJS",
"label": "Testing JS",
},
Object {
"id": "other",
"label": "Other",
},
]
<DocumentFragment>
<span
data-component="withI18nextTranslation(Form)"
data-props="{
\\"syntax\\": \\"invalid\\",
\\"expr\\": \\"test expression\\",
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"label\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"label\\": \\"Other\\"
}
]
}"
/>
<Message
heading="TRANSLATE(Render Failure)"
type="error"
<span
data-component="Message"
data-props="{
\\"type\\": \\"error\\",
\\"heading\\": \\"TRANSLATE(Render Failure)\\"
}"
>
<p>
<Trans>
<span
data-component="Trans"
data-props="{}"
>
An error occurred while rendering the regular expression.
</Trans>
</span>
</p>
<a
href="#retry"
onClick={[Function]}
>
<Trans>
<span
data-component="Trans"
data-props="{}"
>
Retry
</Trans>
</span>
</a>
</Message>
</Fragment>
</span>
</DocumentFragment>
`;

View File

@ -1,5 +1,14 @@
jest.mock('components/Form', () =>
require('__mocks__/component-mock')('components/Form'));
jest.mock('components/FormActions', () =>
require('__mocks__/component-mock')('components/FormActions'));
jest.mock('components/Loader', () =>
require('__mocks__/component-mock')('components/Loader'));
jest.mock('components/Message', () =>
require('__mocks__/component-mock')('components/Message'));
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import { mockT } from 'i18n';
import { App } from 'components/App';
@ -7,7 +16,7 @@ import { App } from 'components/App';
jest.mock('syntax/js', () => ({
parse: expr => `PARSED(${ expr })`,
layout: parsed => `LAYOUT(${ parsed })`,
Render: () => ''
Render: require('__mocks__/component-mock').buildMock(function Render() {})
}));
const syntaxList = [
@ -18,115 +27,64 @@ const commonProps = { syntaxList, t: mockT };
describe('App', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<App expr="" syntax="js" { ...commonProps } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering an expression', async () => {
const component = shallow(
const { asFragment, rerender } = render(
<App expr="" syntax="js" { ...commonProps } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
component.setProps({
expr: 'test expression'
});
rerender(
<App expr="test expression" syntax="js" { ...commonProps } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
// Give a beat for module to load
await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with an invalid syntax', async () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
const component = shallow(
const { asFragment, rerender } = render(
<App expr="" syntax="invalid" { ...commonProps } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
component.setProps({
expr: 'test expression'
});
expect(component).toMatchSnapshot();
// Give a beat for module to load
await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot();
});
test('removing rendered expression', async () => {
const component = shallow(
<App expr="test expression" syntax="js" { ...commonProps } />
);
// Give a beat for module to load
await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot();
component.setProps({
expr: ''
});
expect(component).toMatchSnapshot();
});
test('rendering image details', async () => {
const component = shallow(
<App expr="test expression" syntax="js" { ...commonProps } />
);
// Give a beat for module to load
await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot();
component.instance().handleSvg({
svg: 'test svg content'
});
expect(component).toMatchSnapshot();
});
test('retrying expression rendering', () => {
jest.spyOn(console, 'error').mockImplementation(() => {});
const component = shallow(
rerender(
<App expr="test expression" syntax="invalid" { ...commonProps } />
);
const instance = component.instance();
const event = { preventDefault: jest.fn() };
expect(asFragment()).toMatchSnapshot();
jest.spyOn(instance, 'handleRender');
// Give a beat for module to load
await new Promise(resolve => setTimeout(resolve));
instance.handleRetry(event);
expect(event.preventDefault).toHaveBeenCalled();
expect(instance.handleRender).toHaveBeenCalled();
expect(asFragment()).toMatchSnapshot();
});
test('submitting an expression to render', () => {
const component = shallow(
test('removing rendered expression', async () => {
const { asFragment, rerender } = render(
<App expr="test expression" syntax="js" { ...commonProps } />
);
// Give a beat for module to load
await new Promise(resolve => setTimeout(resolve));
expect(asFragment()).toMatchSnapshot();
rerender(
<App expr="" syntax="js" { ...commonProps } />
);
const instance = component.instance();
instance.handleSubmit({ syntax: 'test', expr: '' });
expect(document.location.hash).toEqual('');
instance.handleSubmit({ syntax: 'test', expr: 'test expression' });
expect(document.location.hash).toEqual('#syntax=test&expr=test+expression');
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,42 +1,50 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Footer rendering 1`] = `
<footer
className="footer"
>
<ul
className="list"
<DocumentFragment>
<footer
class="footer"
>
<li>
<Trans>
Created by
<a
href="mailto:jeff.avallone@gmail.com"
<ul
class="list"
>
<li>
<span
data-component="Trans"
data-props="{}"
>
Jeff Avallone
</a>
</Trans>
</li>
<li>
<Trans>
Generated images licensed:
<a
href="http://creativecommons.org/licenses/by/3.0/"
rel="license external noopener noreferrer"
target="_blank"
Created by
<a
href="mailto:jeff.avallone@gmail.com"
>
Jeff Avallone
</a>
</span>
</li>
<li>
<span
data-component="Trans"
data-props="{}"
>
<img
alt="TRANSLATE(Creative Commons CC-BY-3.0 License)"
src="cc-by.svg"
/>
</a>
</Trans>
</li>
</ul>
<div
className="buildId"
>
abc-123
</div>
</footer>
Generated images licensed:
<a
href="http://creativecommons.org/licenses/by/3.0/"
rel="license external noopener noreferrer"
target="_blank"
>
<img
alt="TRANSLATE(Creative Commons CC-BY-3.0 License)"
src="cc-by.svg"
/>
</a>
</span>
</li>
</ul>
<div
class="buildId"
>
abc-123
</div>
</footer>
</DocumentFragment>
`;

View File

@ -1,14 +1,14 @@
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import { mockT } from 'i18n';
import { Footer } from 'components/Footer';
describe('Footer', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<Footer buildId="abc-123" t={ mockT } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,53 +1,54 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Form rendering 1`] = `
<div
className="form"
data-requires-js={true}
>
<form
onSubmit={[Function]}
<DocumentFragment>
<div
class="form"
data-requires-js="true"
>
<textarea
autoFocus={true}
name="expr"
onChange={[Function]}
onKeyPress={[Function]}
placeholder="TRANSLATE(Enter regular expression to display)"
/>
<button
type="submit"
<form
data-testid="form"
>
<Trans>
Display
</Trans>
</button>
<div
className="select"
>
<select
name="syntax"
onChange={[Function]}
>
<option
key="testJS"
value="testJS"
>
TRANSLATE(Testing JS)
</option>
<option
key="other"
value="other"
>
TRANSLATE(Other)
</option>
</select>
<ChevronsDown
color="currentColor"
size="24"
<textarea
data-testid="expr-input"
name="expr"
placeholder="TRANSLATE(Enter regular expression to display)"
/>
</div>
Actions
</form>
</div>
<button
type="submit"
>
<span
data-component="Trans"
data-props="{}"
>
Display
</span>
</button>
<div
class="select"
>
<select
data-testid="syntax-select"
name="syntax"
>
<option
value="testJS"
>
TRANSLATE(Testing JS)
</option>
<option
value="other"
>
TRANSLATE(Other)
</option>
</select>
<span
data-component="ChevronsDown"
data-props="{}"
/>
</div>
Actions
</form>
</div>
</DocumentFragment>
`;

View File

@ -54,8 +54,9 @@ class Form extends React.PureComponent {
const { expr, syntax } = this.state;
return <div className={ style.form } data-requires-js>
<form onSubmit={ this.handleSubmit }>
<form data-testid="form" onSubmit={ this.handleSubmit }>
<textarea
data-testid="expr-input"
name="expr"
value={ expr }
onKeyPress={ this.handleKeyPress }
@ -65,6 +66,7 @@ class Form extends React.PureComponent {
<button type="submit"><Trans>Display</Trans></button>
<div className={ style.select }>
<select
data-testid="syntax-select"
name="syntax"
value={ syntax }
onChange={ this.handleChange } >

View File

@ -1,5 +1,9 @@
jest.mock('react-feather/dist/icons/chevrons-down', () =>
require('__mocks__/component-mock')(
'react-feather/dist/icons/chevrons-down'));
import React from 'react';
import { shallow } from 'enzyme';
import { render, fireEvent } from 'react-testing-library';
import { mockT } from 'i18n';
import { Form } from 'components/Form';
@ -12,76 +16,66 @@ const commonProps = { syntaxList, t: mockT };
describe('Form', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<Form onSubmit={ jest.fn() } { ...commonProps }>
Actions
</Form>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
describe('submitting expression', () => {
test('submitting form', () => {
const onSubmit = jest.fn();
const component = shallow(
const { getByTestId } = render(
<Form onSubmit={ onSubmit } { ...commonProps } />
);
const exprInput = component.find('[name="expr"]');
const syntaxInput = component.find('[name="syntax"]');
exprInput.simulate('change', {
target: {
name: 'expr',
value: 'Test expression'
}
fireEvent.change(getByTestId('expr-input'), {
target: { value: 'Test expression' }
});
syntaxInput.simulate('change', {
target: {
name: 'syntax',
value: 'test'
}
fireEvent.change(getByTestId('syntax-select'), {
target: { value: 'other' }
});
const eventObj = { preventDefault: jest.fn() };
component.find('form').simulate('submit', eventObj);
const event = new Event('submit');
jest.spyOn(event, 'preventDefault');
expect(eventObj.preventDefault).toHaveBeenCalled();
fireEvent(getByTestId('form'), event);
expect(event.preventDefault).toHaveBeenCalled();
expect(onSubmit).toHaveBeenCalledWith({
expr: 'Test expression',
syntax: 'test'
syntax: 'other'
});
});
test('submitting form with Shift+Enter', () => {
const component = shallow(
<Form onSubmit={ jest.fn() } { ...commonProps } />
const onSubmit = jest.fn();
const { getByTestId } = render(
<Form onSubmit={ onSubmit } { ...commonProps } />
);
const form = component.instance();
const eventObj = {
preventDefault: Function.prototype,
fireEvent.keyPress(getByTestId('expr-input'), {
charCode: 13,
shiftKey: true
};
jest.spyOn(form, 'handleSubmit');
component.find('textarea').simulate('keypress', eventObj);
});
expect(form.handleSubmit).toHaveBeenCalled();
expect(onSubmit).toHaveBeenCalled();
});
test('not submitting with just Enter', () => {
const component = shallow(
<Form onSubmit={ jest.fn() } { ...commonProps } />
const onSubmit = jest.fn();
const { getByTestId } = render(
<Form onSubmit={ onSubmit } { ...commonProps } />
);
const form = component.instance();
const eventObj = {
preventDefault: Function.prototype,
fireEvent.keyPress(getByTestId('expr-input'), {
charCode: 13,
shiftKey: false
};
jest.spyOn(form, 'handleSubmit');
component.find('textarea').simulate('keypress', eventObj);
});
expect(form.handleSubmit).not.toHaveBeenCalled();
expect(onSubmit).not.toHaveBeenCalled();
});
});
});

View File

@ -1,172 +1,196 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FormActions rendering 1`] = `
<ul
className="actions"
/>
<DocumentFragment>
<ul
class="actions"
/>
</DocumentFragment>
`;
exports[`FormActions rendering download links 1`] = `
<ul
className="actions"
>
<li>
<a
download="image.png"
href="http://example.com/image.png"
type="image/png"
>
<Download
color="currentColor"
size="24"
/>
TRANSLATE(Example PNG Link)
</a>
</li>
<li>
<a
download="image.svg"
href="http://example.com/image.svg"
type="image/svg+xml"
>
<Download
color="currentColor"
size="24"
/>
TRANSLATE(Example SVG Link)
</a>
</li>
</ul>
<DocumentFragment>
<ul
class="actions"
>
<li>
<a
download="image.png"
href="http://example.com/image.png"
type="image/png"
>
<span
data-component="Download"
data-props="{}"
/>
TRANSLATE(Example PNG Link)
</a>
</li>
<li>
<a
download="image.svg"
href="http://example.com/image.svg"
type="image/svg+xml"
>
<span
data-component="Download"
data-props="{}"
/>
TRANSLATE(Example SVG Link)
</a>
</li>
</ul>
</DocumentFragment>
`;
exports[`FormActions rendering download links with data after mounting 1`] = `
<ul
className="actions"
>
<li>
<a
href="http://example.com"
>
<Link
color="currentColor"
size="24"
/>
<Trans>
Permalink
</Trans>
</a>
</li>
</ul>
<DocumentFragment>
<ul
class="actions"
>
<li>
<a
href="http://example.com"
>
<span
data-component="Link"
data-props="{}"
/>
<span
data-component="Trans"
data-props="{}"
>
Permalink
</span>
</a>
</li>
</ul>
</DocumentFragment>
`;
exports[`FormActions rendering download links with data after mounting 2`] = `
<ul
className="actions"
>
<li>
<a
download="image.png"
href="http://example.com/image.png"
type="image/png"
>
<Download
color="currentColor"
size="24"
/>
TRANSLATE(Example PNG Link)
</a>
</li>
<li>
<a
download="image.svg"
href="http://example.com/image.svg"
type="image/svg+xml"
>
<Download
color="currentColor"
size="24"
/>
TRANSLATE(Example SVG Link)
</a>
</li>
<li>
<a
href="http://example.com"
>
<Link
color="currentColor"
size="24"
/>
<Trans>
Permalink
</Trans>
</a>
</li>
</ul>
<DocumentFragment>
<ul
class="actions"
>
<li>
<a
download="image.png"
href="http://example.com/image.png"
type="image/png"
>
<span
data-component="Download"
data-props="{}"
/>
TRANSLATE(Example PNG Link)
</a>
</li>
<li>
<a
download="image.svg"
href="http://example.com/image.svg"
type="image/svg+xml"
>
<span
data-component="Download"
data-props="{}"
/>
TRANSLATE(Example SVG Link)
</a>
</li>
<li>
<a
href="http://example.com"
>
<span
data-component="Link"
data-props="{}"
/>
<span
data-component="Trans"
data-props="{}"
>
Permalink
</span>
</a>
</li>
</ul>
</DocumentFragment>
`;
exports[`FormActions rendering download links with data after mounting 3`] = `
<ul
className="actions"
>
<li>
<a
download="image.png"
href="http://example.com/image.png"
type="image/png"
>
<Download
color="currentColor"
size="24"
/>
TRANSLATE(Example PNG Link)
</a>
</li>
<li>
<a
download="image.svg"
href="http://example.com/image.svg"
type="image/svg+xml"
>
<Download
color="currentColor"
size="24"
/>
TRANSLATE(Example SVG Link)
</a>
</li>
<li>
<a
href="http://example.com"
>
<Link
color="currentColor"
size="24"
/>
<Trans>
Permalink
</Trans>
</a>
</li>
</ul>
<DocumentFragment>
<ul
class="actions"
>
<li>
<a
download="image.png"
href="http://example.com/image.png"
type="image/png"
>
<span
data-component="Download"
data-props="{}"
/>
TRANSLATE(Example PNG Link)
</a>
</li>
<li>
<a
download="image.svg"
href="http://example.com/image.svg"
type="image/svg+xml"
>
<span
data-component="Download"
data-props="{}"
/>
TRANSLATE(Example SVG Link)
</a>
</li>
<li>
<a
href="http://example.com"
>
<span
data-component="Link"
data-props="{}"
/>
<span
data-component="Trans"
data-props="{}"
>
Permalink
</span>
</a>
</li>
</ul>
</DocumentFragment>
`;
exports[`FormActions rendering with a permalink 1`] = `
<ul
className="actions"
>
<li>
<a
href="http://example.com"
>
<Link
color="currentColor"
size="24"
/>
<Trans>
Permalink
</Trans>
</a>
</li>
</ul>
<DocumentFragment>
<ul
class="actions"
>
<li>
<a
href="http://example.com"
>
<span
data-component="Link"
data-props="{}"
/>
<span
data-component="Trans"
data-props="{}"
>
Permalink
</span>
</a>
</li>
</ul>
</DocumentFragment>
`;

View File

@ -1,7 +1,13 @@
jest.mock('./links');
jest.mock('react-feather/dist/icons/download', () =>
require('__mocks__/component-mock')(
'react-feather/dist/icons/download'));
jest.mock('react-feather/dist/icons/link', () =>
require('__mocks__/component-mock')(
'react-feather/dist/icons/link'));
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import { mockT } from 'i18n';
import { FormActions } from 'components/FormActions';
@ -22,17 +28,17 @@ createSvgLink.mockResolvedValue({
describe('FormActions', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<FormActions t={ mockT } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with a permalink', () => {
const component = shallow(
const { asFragment } = render(
<FormActions permalinkUrl="http://example.com" t={ mockT } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering download links', async () => {
@ -42,47 +48,49 @@ describe('FormActions', () => {
height: 20
};
const component = shallow(
const { asFragment } = render(
<FormActions imageDetails={ imageDetails } t={ mockT } />
);
// Give a beat for mocked promises to resolve
await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering download links with data after mounting', async () => {
const component = shallow(
const { asFragment, rerender } = render(
<FormActions t={ mockT } />
);
component.setProps({ permalinkUrl: 'http://example.com' });
rerender(
<FormActions permalinkUrl="http://example.com" t={ mockT } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
component.setProps({
imageDetails: {
svg: 'test image'
}
});
rerender(
<FormActions
permalinkUrl="http://example.com"
imageDetails={ { svg: 'test-image' } }
t={ mockT } />
);
// Give a beat for mocked promises to resolve
await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
component.setProps({
imageDetails: {
svg: 'test image',
width: 10,
height: 20
}
});
rerender(
<FormActions
permalinkUrl="http://example.com"
imageDetails={ { svg: 'test-image', width: 10, height: 20 } }
t={ mockT } />
);
// Give a beat for mocked promises to resolve
await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,182 +1,30 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Header closing the Privacy Policy modal 1`] = `
<Fragment>
<Modal
ariaHideApp={true}
bodyOpenClassName="ReactModal__Body--open"
closeTimeoutMS={0}
isOpen={true}
onRequestClose={[Function]}
parentSelector={[Function]}
portalClassName="ReactModalPortal"
role="dialog"
shouldCloseOnEsc={true}
shouldCloseOnOverlayClick={true}
shouldFocusAfterRender={true}
shouldReturnFocusAfterClose={true}
>
<withI18nextTranslation(PrivacyPolicy)
onClose={[Function]}
/>
</Modal>
<header
className="header"
data-banner={null}
>
<h1>
<mockConstructor
to="/"
>
Regexper
</mockConstructor>
</h1>
<ul
className="list"
>
<li>
<a
href="https://gitlab.com/javallone/regexper-static"
rel="external noopener noreferrer"
target="_blank"
>
<Gitlab
color="currentColor"
size="24"
/>
<Trans>
Source on GitLab
</Trans>
</a>
</li>
<li>
<mockConstructor
onClick={[Function]}
to="/privacy"
>
<Trans>
Privacy Policy
</Trans>
</mockConstructor>
</li>
<li>
<withI18nextTranslation(InstallPrompt) />
</li>
<li
data-requires-js={true}
>
<withI18nextTranslation(LocaleSwitcher) />
</li>
</ul>
</header>
</Fragment>
`;
exports[`Header closing the Privacy Policy modal 2`] = `
<Fragment>
<Modal
ariaHideApp={true}
bodyOpenClassName="ReactModal__Body--open"
closeTimeoutMS={0}
isOpen={false}
onRequestClose={[Function]}
parentSelector={[Function]}
portalClassName="ReactModalPortal"
role="dialog"
shouldCloseOnEsc={true}
shouldCloseOnOverlayClick={true}
shouldFocusAfterRender={true}
shouldReturnFocusAfterClose={true}
>
<withI18nextTranslation(PrivacyPolicy)
onClose={[Function]}
/>
</Modal>
<header
className="header"
data-banner={null}
>
<h1>
<mockConstructor
to="/"
>
Regexper
</mockConstructor>
</h1>
<ul
className="list"
>
<li>
<a
href="https://gitlab.com/javallone/regexper-static"
rel="external noopener noreferrer"
target="_blank"
>
<Gitlab
color="currentColor"
size="24"
/>
<Trans>
Source on GitLab
</Trans>
</a>
</li>
<li>
<mockConstructor
onClick={[Function]}
to="/privacy"
>
<Trans>
Privacy Policy
</Trans>
</mockConstructor>
</li>
<li>
<withI18nextTranslation(InstallPrompt) />
</li>
<li
data-requires-js={true}
>
<withI18nextTranslation(LocaleSwitcher) />
</li>
</ul>
</header>
</Fragment>
`;
exports[`Header opening the Privacy Policy modal 1`] = `
<Fragment>
<Modal
ariaHideApp={true}
bodyOpenClassName="ReactModal__Body--open"
closeTimeoutMS={0}
isOpen={true}
onRequestClose={[Function]}
parentSelector={[Function]}
portalClassName="ReactModalPortal"
role="dialog"
shouldCloseOnEsc={true}
shouldCloseOnOverlayClick={true}
shouldFocusAfterRender={true}
shouldReturnFocusAfterClose={true}
<DocumentFragment>
<span
data-component="Modal"
data-props="{
\\"isOpen\\": true
}"
>
<withI18nextTranslation(PrivacyPolicy)
onClose={[Function]}
<span
data-component="withI18nextTranslation(PrivacyPolicy)"
data-props="{}"
/>
</Modal>
</span>
<header
className="header"
data-banner={null}
class="header"
>
<h1>
<mockConstructor
to="/"
<a
href="/"
>
Regexper
</mockConstructor>
</a>
</h1>
<ul
className="list"
class="list"
>
<li>
<a
@ -184,71 +32,380 @@ exports[`Header opening the Privacy Policy modal 1`] = `
rel="external noopener noreferrer"
target="_blank"
>
<Gitlab
color="currentColor"
size="24"
<span
data-component="Gitlab"
data-props="{}"
/>
<Trans>
<span
data-component="Trans"
data-props="{}"
>
Source on GitLab
</Trans>
</span>
</a>
</li>
<li>
<mockConstructor
onClick={[Function]}
to="/privacy"
<a
data-testid="privacy-link"
href="/privacy"
>
<Trans>
<span
data-component="Trans"
data-props="{}"
>
Privacy Policy
</Trans>
</mockConstructor>
</span>
</a>
</li>
<li>
<withI18nextTranslation(InstallPrompt) />
<span
data-component="withI18nextTranslation(InstallPrompt)"
data-props="{}"
/>
</li>
<li
data-requires-js={true}
data-requires-js="true"
>
<withI18nextTranslation(LocaleSwitcher) />
<span
data-component="withI18nextTranslation(LocaleSwitcher)"
data-props="{}"
/>
</li>
</ul>
</header>
</Fragment>
</DocumentFragment>
`;
exports[`Header opening the Privacy Policy modal while holding alt key 1`] = `
<DocumentFragment>
<span
data-component="Modal"
data-props="{
\\"isOpen\\": false
}"
>
<span
data-component="withI18nextTranslation(PrivacyPolicy)"
data-props="{}"
/>
</span>
<header
class="header"
>
<h1>
<a
href="/"
>
Regexper
</a>
</h1>
<ul
class="list"
>
<li>
<a
href="https://gitlab.com/javallone/regexper-static"
rel="external noopener noreferrer"
target="_blank"
>
<span
data-component="Gitlab"
data-props="{}"
/>
<span
data-component="Trans"
data-props="{}"
>
Source on GitLab
</span>
</a>
</li>
<li>
<a
data-testid="privacy-link"
href="/privacy"
>
<span
data-component="Trans"
data-props="{}"
>
Privacy Policy
</span>
</a>
</li>
<li>
<span
data-component="withI18nextTranslation(InstallPrompt)"
data-props="{}"
/>
</li>
<li
data-requires-js="true"
>
<span
data-component="withI18nextTranslation(LocaleSwitcher)"
data-props="{}"
/>
</li>
</ul>
</header>
</DocumentFragment>
`;
exports[`Header opening the Privacy Policy modal while holding ctrl key 1`] = `
<DocumentFragment>
<span
data-component="Modal"
data-props="{
\\"isOpen\\": false
}"
>
<span
data-component="withI18nextTranslation(PrivacyPolicy)"
data-props="{}"
/>
</span>
<header
class="header"
>
<h1>
<a
href="/"
>
Regexper
</a>
</h1>
<ul
class="list"
>
<li>
<a
href="https://gitlab.com/javallone/regexper-static"
rel="external noopener noreferrer"
target="_blank"
>
<span
data-component="Gitlab"
data-props="{}"
/>
<span
data-component="Trans"
data-props="{}"
>
Source on GitLab
</span>
</a>
</li>
<li>
<a
data-testid="privacy-link"
href="/privacy"
>
<span
data-component="Trans"
data-props="{}"
>
Privacy Policy
</span>
</a>
</li>
<li>
<span
data-component="withI18nextTranslation(InstallPrompt)"
data-props="{}"
/>
</li>
<li
data-requires-js="true"
>
<span
data-component="withI18nextTranslation(LocaleSwitcher)"
data-props="{}"
/>
</li>
</ul>
</header>
</DocumentFragment>
`;
exports[`Header opening the Privacy Policy modal while holding meta key 1`] = `
<DocumentFragment>
<span
data-component="Modal"
data-props="{
\\"isOpen\\": false
}"
>
<span
data-component="withI18nextTranslation(PrivacyPolicy)"
data-props="{}"
/>
</span>
<header
class="header"
>
<h1>
<a
href="/"
>
Regexper
</a>
</h1>
<ul
class="list"
>
<li>
<a
href="https://gitlab.com/javallone/regexper-static"
rel="external noopener noreferrer"
target="_blank"
>
<span
data-component="Gitlab"
data-props="{}"
/>
<span
data-component="Trans"
data-props="{}"
>
Source on GitLab
</span>
</a>
</li>
<li>
<a
data-testid="privacy-link"
href="/privacy"
>
<span
data-component="Trans"
data-props="{}"
>
Privacy Policy
</span>
</a>
</li>
<li>
<span
data-component="withI18nextTranslation(InstallPrompt)"
data-props="{}"
/>
</li>
<li
data-requires-js="true"
>
<span
data-component="withI18nextTranslation(LocaleSwitcher)"
data-props="{}"
/>
</li>
</ul>
</header>
</DocumentFragment>
`;
exports[`Header opening the Privacy Policy modal while holding shift key 1`] = `
<DocumentFragment>
<span
data-component="Modal"
data-props="{
\\"isOpen\\": false
}"
>
<span
data-component="withI18nextTranslation(PrivacyPolicy)"
data-props="{}"
/>
</span>
<header
class="header"
>
<h1>
<a
href="/"
>
Regexper
</a>
</h1>
<ul
class="list"
>
<li>
<a
href="https://gitlab.com/javallone/regexper-static"
rel="external noopener noreferrer"
target="_blank"
>
<span
data-component="Gitlab"
data-props="{}"
/>
<span
data-component="Trans"
data-props="{}"
>
Source on GitLab
</span>
</a>
</li>
<li>
<a
data-testid="privacy-link"
href="/privacy"
>
<span
data-component="Trans"
data-props="{}"
>
Privacy Policy
</span>
</a>
</li>
<li>
<span
data-component="withI18nextTranslation(InstallPrompt)"
data-props="{}"
/>
</li>
<li
data-requires-js="true"
>
<span
data-component="withI18nextTranslation(LocaleSwitcher)"
data-props="{}"
/>
</li>
</ul>
</header>
</DocumentFragment>
`;
exports[`Header rendering 1`] = `
<Fragment>
<Modal
ariaHideApp={true}
bodyOpenClassName="ReactModal__Body--open"
closeTimeoutMS={0}
isOpen={false}
onRequestClose={[Function]}
parentSelector={[Function]}
portalClassName="ReactModalPortal"
role="dialog"
shouldCloseOnEsc={true}
shouldCloseOnOverlayClick={true}
shouldFocusAfterRender={true}
shouldReturnFocusAfterClose={true}
<DocumentFragment>
<span
data-component="Modal"
data-props="{
\\"isOpen\\": false
}"
>
<withI18nextTranslation(PrivacyPolicy)
onClose={[Function]}
<span
data-component="withI18nextTranslation(PrivacyPolicy)"
data-props="{}"
/>
</Modal>
</span>
<header
className="header"
class="header"
data-banner="testing"
>
<h1>
<mockConstructor
to="/"
<a
href="/"
>
Regexper
</mockConstructor>
</a>
</h1>
<ul
className="list"
class="list"
>
<li>
<a
@ -256,71 +413,75 @@ exports[`Header rendering 1`] = `
rel="external noopener noreferrer"
target="_blank"
>
<Gitlab
color="currentColor"
size="24"
<span
data-component="Gitlab"
data-props="{}"
/>
<Trans>
<span
data-component="Trans"
data-props="{}"
>
Source on GitLab
</Trans>
</span>
</a>
</li>
<li>
<mockConstructor
onClick={[Function]}
to="/privacy"
<a
data-testid="privacy-link"
href="/privacy"
>
<Trans>
<span
data-component="Trans"
data-props="{}"
>
Privacy Policy
</Trans>
</mockConstructor>
</span>
</a>
</li>
<li>
<withI18nextTranslation(InstallPrompt) />
<span
data-component="withI18nextTranslation(InstallPrompt)"
data-props="{}"
/>
</li>
<li
data-requires-js={true}
data-requires-js="true"
>
<withI18nextTranslation(LocaleSwitcher) />
<span
data-component="withI18nextTranslation(LocaleSwitcher)"
data-props="{}"
/>
</li>
</ul>
</header>
</Fragment>
</DocumentFragment>
`;
exports[`Header rendering with no banner 1`] = `
<Fragment>
<Modal
ariaHideApp={true}
bodyOpenClassName="ReactModal__Body--open"
closeTimeoutMS={0}
isOpen={false}
onRequestClose={[Function]}
parentSelector={[Function]}
portalClassName="ReactModalPortal"
role="dialog"
shouldCloseOnEsc={true}
shouldCloseOnOverlayClick={true}
shouldFocusAfterRender={true}
shouldReturnFocusAfterClose={true}
<DocumentFragment>
<span
data-component="Modal"
data-props="{
\\"isOpen\\": false
}"
>
<withI18nextTranslation(PrivacyPolicy)
onClose={[Function]}
<span
data-component="withI18nextTranslation(PrivacyPolicy)"
data-props="{}"
/>
</Modal>
</span>
<header
className="header"
data-banner={null}
class="header"
>
<h1>
<mockConstructor
to="/"
<a
href="/"
>
Regexper
</mockConstructor>
</a>
</h1>
<ul
className="list"
class="list"
>
<li>
<a
@ -328,34 +489,46 @@ exports[`Header rendering with no banner 1`] = `
rel="external noopener noreferrer"
target="_blank"
>
<Gitlab
color="currentColor"
size="24"
<span
data-component="Gitlab"
data-props="{}"
/>
<Trans>
<span
data-component="Trans"
data-props="{}"
>
Source on GitLab
</Trans>
</span>
</a>
</li>
<li>
<mockConstructor
onClick={[Function]}
to="/privacy"
<a
data-testid="privacy-link"
href="/privacy"
>
<Trans>
<span
data-component="Trans"
data-props="{}"
>
Privacy Policy
</Trans>
</mockConstructor>
</span>
</a>
</li>
<li>
<withI18nextTranslation(InstallPrompt) />
<span
data-component="withI18nextTranslation(InstallPrompt)"
data-props="{}"
/>
</li>
<li
data-requires-js={true}
data-requires-js="true"
>
<withI18nextTranslation(LocaleSwitcher) />
<span
data-component="withI18nextTranslation(LocaleSwitcher)"
data-props="{}"
/>
</li>
</ul>
</header>
</Fragment>
</DocumentFragment>
`;

View File

@ -64,7 +64,10 @@ class Header extends React.PureComponent {
</a>
</li>
<li>
<Link to="/privacy" onClick={ this.handleOpen }>
<Link to="/privacy"
data-testid="privacy-link"
onClick={ this.handleOpen }
>
<Trans>Privacy Policy</Trans>
</Link>
</li>

View File

@ -1,60 +1,62 @@
jest.mock('react-modal', () =>
require('__mocks__/component-mock')('react-modal'));
jest.mock('react-feather/dist/icons/gitlab', () =>
require('__mocks__/component-mock')('react-feather/dist/icons/gitlab'));
jest.mock('components/LocaleSwitcher', () =>
require('__mocks__/component-mock')('components/LocaleSwitcher'));
jest.mock('components/InstallPrompt', () =>
require('__mocks__/component-mock')('components/InstallPrompt'));
jest.mock('components/PrivacyPolicy', () =>
require('__mocks__/component-mock')('components/PrivacyPolicy'));
import React from 'react';
import { shallow } from 'enzyme';
import { render, fireEvent } from 'react-testing-library';
import { Header } from 'components/Header';
describe('Header', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<Header banner="testing" />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with no banner', () => {
const component = shallow(
const { asFragment } = render(
<Header banner={ false } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('opening the Privacy Policy modal', () => {
const component = shallow(
const { asFragment, getByTestId } = render(
<Header banner={ false } />
);
const eventObj = { preventDefault: jest.fn() };
const event = new MouseEvent('click', { bubbles: true });
jest.spyOn(event, 'preventDefault');
component.instance().handleOpen(eventObj);
fireEvent(getByTestId('privacy-link'), event);
expect(eventObj.preventDefault).toHaveBeenCalled();
expect(component).toMatchSnapshot();
expect(event.preventDefault).toHaveBeenCalled();
expect(asFragment()).toMatchSnapshot();
});
['shift', 'ctrl', 'alt', 'meta'].forEach(key => {
test(`opening the Privacy Policy modal while holding ${ key } key`, () => {
const component = shallow(
const { asFragment, getByTestId } = render(
<Header banner={ false } />
);
const eventObj = { preventDefault: jest.fn() };
const event = new MouseEvent('click', {
bubbles: true,
[key + 'Key']: true
});
jest.spyOn(event, 'preventDefault');
component.instance().handleOpen({ [key + 'Key']: true, ...eventObj });
fireEvent(getByTestId('privacy-link'), event);
expect(eventObj.preventDefault).not.toHaveBeenCalled();
expect(component.state('showModal')).toEqual(false);
expect(event.preventDefault).not.toHaveBeenCalled();
expect(asFragment()).toMatchSnapshot();
});
});
test('closing the Privacy Policy modal', () => {
const component = shallow(
<Header banner={ false } />
);
component.setState({ showModal: true });
expect(component).toMatchSnapshot();
component.instance().handleClose();
expect(component).toMatchSnapshot();
});
});

View File

@ -1,16 +1,57 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`InstallPrompt rendering 1`] = `""`;
exports[`InstallPrompt accepting install prompt 1`] = `
<DocumentFragment>
<a
data-testid="install"
href="#install"
>
<span
data-component="Trans"
data-props="{}"
>
Add to Home Screen
</span>
</a>
</DocumentFragment>
`;
exports[`InstallPrompt rendering after an install prompt has been requested 1`] = `""`;
exports[`InstallPrompt accepting install prompt 2`] = `<DocumentFragment />`;
exports[`InstallPrompt rejecting install prompt 1`] = `
<DocumentFragment>
<a
data-testid="install"
href="#install"
>
<span
data-component="Trans"
data-props="{}"
>
Add to Home Screen
</span>
</a>
</DocumentFragment>
`;
exports[`InstallPrompt rejecting install prompt 2`] = `<DocumentFragment />`;
exports[`InstallPrompt rendering 1`] = `<DocumentFragment />`;
exports[`InstallPrompt rendering after an install prompt has been requested 1`] = `<DocumentFragment />`;
exports[`InstallPrompt rendering after an install prompt has been requested 2`] = `
<a
href="#install"
onClick={[Function]}
>
<Trans>
Add to Home Screen
</Trans>
</a>
<DocumentFragment>
<a
data-testid="install"
href="#install"
>
<span
data-component="Trans"
data-props="{}"
>
Add to Home Screen
</span>
</a>
</DocumentFragment>
`;

View File

@ -43,7 +43,10 @@ class InstallPrompt extends React.PureComponent {
return null;
}
return <a href="#install" onClick={ this.handleInstall }>
return <a href="#install"
data-testid="install"
onClick={ this.handleInstall }
>
<Trans>Add to Home Screen</Trans>
</a>;
}

View File

@ -1,88 +1,86 @@
import React from 'react';
import { shallow } from 'enzyme';
import { render, fireEvent } from 'react-testing-library';
import { InstallPrompt } from 'components/InstallPrompt';
describe('InstallPrompt', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<InstallPrompt />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering after an install prompt has been requested', () => {
const component = shallow(
const { asFragment } = render(
<InstallPrompt />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
component.instance().handleInstallPrompt({
const event = new Event('beforeinstallprompt', {
prompt: jest.fn()
});
fireEvent(window, event);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('adding and removing event listener', () => {
test('removing event listener', () => {
jest.spyOn(window, 'addEventListener');
jest.spyOn(window, 'removeEventListener');
const component = shallow(
const { unmount } = render(
<InstallPrompt />
);
const handleInstallPrompt = component.instance().handleInstallPrompt;
expect(window.addEventListener).toHaveBeenCalledWith(
'beforeinstallprompt',
handleInstallPrompt);
component.unmount();
unmount();
expect(window.removeEventListener).toHaveBeenCalledWith(
'beforeinstallprompt',
handleInstallPrompt);
expect.any(Function));
});
test('accepting install prompt', async () => {
const component = shallow(
const { asFragment, getByTestId } = render(
<InstallPrompt />
);
const promptObj = {
prompt: jest.fn(),
userChoice: Promise.resolve()
};
const eventObj = { preventDefault: jest.fn() };
const promptEvent = new Event('beforeinstallprompt');
promptEvent.prompt = jest.fn();
promptEvent.userChoice = Promise.resolve();
const clickEvent = new MouseEvent('click', { bubbles: true });
jest.spyOn(clickEvent, 'preventDefault');
component.instance().handleInstallPrompt(promptObj);
component.find('a').simulate('click', eventObj);
fireEvent(window, promptEvent);
expect(asFragment()).toMatchSnapshot();
fireEvent(getByTestId('install'), clickEvent);
// Allow async code to run
await new Promise(resolve => setTimeout(resolve));
expect(eventObj.preventDefault).toHaveBeenCalled();
expect(promptObj.prompt).toHaveBeenCalled();
expect(component.state('installPrompt')).toBeNull();
expect(clickEvent.preventDefault).toHaveBeenCalled();
expect(promptEvent.prompt).toHaveBeenCalled();
expect(asFragment()).toMatchSnapshot();
});
test('rejecting install prompt', async () => {
const component = shallow(
const { asFragment, getByTestId } = render(
<InstallPrompt />
);
const promptObj = {
prompt: jest.fn(),
userChoice: Promise.reject()
};
const eventObj = { preventDefault: jest.fn() };
const promptEvent = new Event('beforeinstallprompt');
promptEvent.prompt = jest.fn();
promptEvent.userChoice = Promise.reject();
const clickEvent = new MouseEvent('click', { bubbles: true });
jest.spyOn(clickEvent, 'preventDefault');
component.instance().handleInstallPrompt(promptObj);
component.find('a').simulate('click', eventObj);
fireEvent(window, promptEvent);
expect(asFragment()).toMatchSnapshot();
fireEvent(getByTestId('install'), clickEvent);
// Allow async code to run
await new Promise(resolve => setTimeout(resolve));
expect(eventObj.preventDefault).toHaveBeenCalled();
expect(promptObj.prompt).toHaveBeenCalled();
expect(component.state('installPrompt')).toBeNull();
expect(clickEvent.preventDefault).toHaveBeenCalled();
expect(promptEvent.prompt).toHaveBeenCalled();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,26 +1,30 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Layout rendering 1`] = `
<SentryBoundary>
<noscript>
<style
type="text/css"
<DocumentFragment>
<span
data-component="SentryBoundary"
data-props="{}"
>
<noscript />
<span
data-component="withI18nextTranslation(Header)"
data-props="{
\\"banner\\": \\"Test Banner\\"
}"
/>
<span
data-component="SentryBoundary"
data-props="{}"
>
[data-requires-js] {
display: none !important;
}
</style>
</noscript>
<withI18nextTranslation(Header)
banner="Test Banner"
/>
<SentryBoundary>
Example content
</SentryBoundary>
<withI18nextTranslation(Footer)
buildId="test-buildid"
/>
</SentryBoundary>
Example content
</span>
<span
data-component="withI18nextTranslation(Footer)"
data-props="{
\\"buildId\\": \\"test-buildid\\"
}"
/>
</span>
</DocumentFragment>
`;

View File

@ -1,15 +1,22 @@
jest.mock('components/SentryBoundary', () =>
require('__mocks__/component-mock')('components/SentryBoundary'));
jest.mock('components/Header', () =>
require('__mocks__/component-mock')('components/Header'));
jest.mock('components/Footer', () =>
require('__mocks__/component-mock')('components/Footer'));
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import { Layout } from 'components/Layout';
describe('Layout', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<Layout banner="Test Banner" buildId="test-buildid">
Example content
</Layout>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,82 +1,75 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Loader rendering 1`] = `
<Loader
t={[Function]}
>
<DocumentFragment>
<div
className="loader"
class="loader"
>
<Loader
color="currentColor"
size="24"
<svg
fill="none"
height="24"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<svg
fill="none"
height="24"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<line
x1="12"
x2="12"
y1="2"
y2="6"
/>
<line
x1="12"
x2="12"
y1="18"
y2="22"
/>
<line
x1="4.93"
x2="7.76"
y1="4.93"
y2="7.76"
/>
<line
x1="16.24"
x2="19.07"
y1="16.24"
y2="19.07"
/>
<line
x1="2"
x2="6"
y1="12"
y2="12"
/>
<line
x1="18"
x2="22"
y1="12"
y2="12"
/>
<line
x1="4.93"
x2="7.76"
y1="19.07"
y2="16.24"
/>
<line
x1="16.24"
x2="19.07"
y1="7.76"
y2="4.93"
/>
</svg>
</Loader>
<line
x1="12"
x2="12"
y1="2"
y2="6"
/>
<line
x1="12"
x2="12"
y1="18"
y2="22"
/>
<line
x1="4.93"
x2="7.76"
y1="4.93"
y2="7.76"
/>
<line
x1="16.24"
x2="19.07"
y1="16.24"
y2="19.07"
/>
<line
x1="2"
x2="6"
y1="12"
y2="12"
/>
<line
x1="18"
x2="22"
y1="12"
y2="12"
/>
<line
x1="4.93"
x2="7.76"
y1="19.07"
y2="16.24"
/>
<line
x1="16.24"
x2="19.07"
y1="7.76"
y2="4.93"
/>
</svg>
<div
className="message"
class="message"
>
TRANSLATE(Loading...)
</div>
</div>
</Loader>
</DocumentFragment>
`;

View File

@ -1,5 +1,5 @@
import React from 'react';
import { mount } from 'enzyme';
import { render } from 'react-testing-library';
import { mockT } from 'i18n';
import { Loader } from 'components/Loader';
@ -8,9 +8,9 @@ describe('Loader', () => {
test('rendering', () => {
// Using full rendering here since styles for this depend on the structure
// of the SVG.
const component = mount(
const { asFragment } = render(
<Loader t={ mockT } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,34 +1,36 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LocaleSwitcher rendering 1`] = `
<label>
<Trans>
Language
</Trans>
<div
className="switcher"
>
<select
onChange={[Function]}
value="en"
<DocumentFragment>
<label>
<span
data-component="Trans"
data-props="{}"
>
<option
key="en"
value="en"
Language
</span>
<div
class="switcher"
>
<select
data-testid="language-select"
>
English
</option>
<option
key="other"
value="other"
>
Other
</option>
</select>
<ChevronsDown
color="currentColor"
size="24"
/>
</div>
</label>
<option
value="en"
>
English
</option>
<option
value="other"
>
Other
</option>
</select>
<span
data-component="ChevronsDown"
data-props="{}"
/>
</div>
</label>
</DocumentFragment>
`;

View File

@ -38,7 +38,10 @@ export class LocaleSwitcher extends React.PureComponent {
return <label>
<Trans>Language</Trans>
<div className={ style.switcher }>
<select value={ current } onChange={ this.handleSelectChange }>
<select data-testid="language-select"
value={ current }
onChange={ this.handleSelectChange }
>
{ locales.map(locale => (
<option value={ locale.code } key={ locale.code }>
{ locale.name }

View File

@ -1,5 +1,9 @@
jest.mock('react-feather/dist/icons/chevrons-down', () =>
require('__mocks__/component-mock')(
'react-feather/dist/icons/chevrons-down'));
import React from 'react';
import { shallow } from 'enzyme';
import { render, fireEvent } from 'react-testing-library';
import i18n from 'i18n';
import { LocaleSwitcher } from 'components/LocaleSwitcher';
@ -9,44 +13,47 @@ jest.mock('./locale-to-available', () => jest.fn(() => 'en'));
describe('LocaleSwitcher', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<LocaleSwitcher />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('changing language', () => {
jest.spyOn(i18n, 'changeLanguage');
const component = shallow(
const { getByTestId } = render(
<LocaleSwitcher />
);
const selectInput = component.find('select');
selectInput.value = 'other';
selectInput.simulate('change', { target: { value: 'other' } });
const event = new Event('change', { bubbles: true });
const select = getByTestId('language-select');
select.value = 'other';
fireEvent(select, event);
expect(i18n.changeLanguage).toHaveBeenCalledWith('other');
});
test('interface update from language change', () => {
const component = shallow(
const { getByTestId } = render(
<LocaleSwitcher />
);
expect(component.find('select').prop('value')).toEqual('en');
expect(getByTestId('language-select').value).toEqual('en');
i18n.emit('languageChanged', 'other');
expect(component.find('select').prop('value')).toEqual('other');
expect(getByTestId('language-select').value).toEqual('other');
});
test('disconnecting event handler on unmount', () => {
const component = shallow(
const { unmount } = render(
<LocaleSwitcher />
);
jest.spyOn(component, 'setState');
jest.spyOn(i18n, 'off');
component.unmount();
i18n.emit('languageChanged', 'other');
expect(component.setState).not.toHaveBeenCalled();
unmount();
expect(i18n.off).toHaveBeenCalledWith(
'languageChanged',
expect.any(Function));
});
});

View File

@ -1,99 +1,105 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Message rendering 1`] = `
<div
className="message"
>
<DocumentFragment>
<div
className="header"
class="message"
>
<h2>
Testing
</h2>
<div
class="header"
>
<h2>
Testing
</h2>
</div>
<div
class="content"
>
<p>
Message content
</p>
</div>
</div>
<div
className="content"
>
<p>
Message content
</p>
</div>
</div>
</DocumentFragment>
`;
exports[`Message rendering with a close button 1`] = `
<div
className="message"
>
<DocumentFragment>
<div
className="header"
class="message"
>
<h2>
Testing
</h2>
<button
onClick={[MockFunction]}
<div
class="header"
>
<XSquare
color="currentColor"
size="24"
/>
Close
</button>
<h2>
Testing
</h2>
<button>
<span
data-component="XSquare"
data-props="{}"
/>
Close
</button>
</div>
<div
class="content"
>
<p>
Message content
</p>
</div>
</div>
<div
className="content"
>
<p>
Message content
</p>
</div>
</div>
</DocumentFragment>
`;
exports[`Message rendering with icon 1`] = `
<div
className="message"
>
<DocumentFragment>
<div
className="header"
class="message"
>
<Icon />
<h2>
Testing
</h2>
<div
class="header"
>
Sample icon SVG
<h2>
Testing
</h2>
</div>
<div
class="content"
>
<p>
Message content
</p>
</div>
</div>
<div
className="content"
>
<p>
Message content
</p>
</div>
</div>
</DocumentFragment>
`;
exports[`Message rendering with type 1`] = `
<div
className="message error"
>
<DocumentFragment>
<div
className="header"
class="message error"
>
<AlertOctagon
color="currentColor"
size="24"
/>
<h2>
Testing
</h2>
<div
class="header"
>
<span
data-component="AlertOctagon"
data-props="{}"
/>
<h2>
Testing
</h2>
</div>
<div
class="content"
>
<p>
Message content
</p>
</div>
</div>
<div
className="content"
>
<p>
Message content
</p>
</div>
</div>
</DocumentFragment>
`;

View File

@ -1,43 +1,56 @@
jest.mock('react-feather/dist/icons/info', () =>
require('__mocks__/component-mock')('react-feather/dist/icons/info'));
jest.mock('react-feather/dist/icons/alert-octagon', () =>
require('__mocks__/component-mock')(
'react-feather/dist/icons/alert-octagon'
));
jest.mock('react-feather/dist/icons/alert-triangle', () =>
require('__mocks__/component-mock')(
'react-feather/dist/icons/alert-triangle'
));
jest.mock('react-feather/dist/icons/x-square', () =>
require('__mocks__/component-mock')('react-feather/dist/icons/x-square'));
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import Message from 'components/Message';
describe('Message', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<Message heading="Testing">
<p>Message content</p>
</Message>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with icon', () => {
const Icon = () => 'Sample icon SVG';
const component = shallow(
const { asFragment } = render(
<Message heading="Testing" icon={ Icon }>
<p>Message content</p>
</Message>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with type', () => {
const component = shallow(
const { asFragment } = render(
<Message heading="Testing" type="error">
<p>Message content</p>
</Message>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with a close button', () => {
const component = shallow(
const { asFragment } = render(
<Message heading="Testing" onClose={ jest.fn() }>
<p>Message content</p>
</Message>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,37 +1,39 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Metadata rendering 1`] = `
<HelmetWrapper
defer={true}
encodeSpecialCharacters={true}
htmlAttributes={
Object {
"lang": "test-lang",
}
<DocumentFragment>
<span
data-component="HelmetWrapper"
data-props="{
\\"htmlAttributes\\": {
\\"lang\\": \\"test-lang\\"
}
>
<title>
Regexper
</title>
</HelmetWrapper>
}"
>
<title>
Regexper
</title>
</span>
</DocumentFragment>
`;
exports[`Metadata rendering with a title and description 1`] = `
<HelmetWrapper
defer={true}
encodeSpecialCharacters={true}
htmlAttributes={
Object {
"lang": "test-lang",
}
<DocumentFragment>
<span
data-component="HelmetWrapper"
data-props="{
\\"htmlAttributes\\": {
\\"lang\\": \\"test-lang\\"
}
>
<title>
Regexper - Testing
</title>
<meta
content="Test description"
name="description"
/>
</HelmetWrapper>
}"
>
<title>
Regexper - Testing
</title>
<meta
content="Test description"
name="description"
/>
</span>
</DocumentFragment>
`;

View File

@ -1,5 +1,13 @@
jest.mock('react-helmet', () => {
const helmet = jest.requireActual('react-helmet');
return {
...helmet,
Helmet: require('__mocks__/component-mock').buildMock(helmet.Helmet)
};
});
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import { Metadata } from 'components/Metadata';
@ -9,19 +17,19 @@ const commonProps = {
describe('Metadata', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<Metadata { ...commonProps } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with a title and description', () => {
const component = shallow(
const { asFragment } = render(
<Metadata
title="Testing"
description="Test description"
{ ...commonProps } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,56 +1,63 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PrivacyPolicy rendering 1`] = `
<Message
heading="TRANSLATE(Privacy Policy)"
onClose={[MockFunction]}
type="info"
>
<Trans
i18nKey="Privacy policy copy"
<DocumentFragment>
<span
data-component="Message"
data-props="{
\\"type\\": \\"info\\",
\\"heading\\": \\"TRANSLATE(Privacy Policy)\\"
}"
>
<p>
Regexper and the tools used to create it are all open source. If you are concerned that the JavaScript being delivered is in any way malicious, please inspect the source in the
<a
href="https://gitlab.com/javallone/regexper-static"
rel="external noopener noreferrer"
target="_blank"
>
GitLab repository
</a>
.
</p>
<p>
There are two data collection tools integrated in the app. These tools are not used to collect personal information:
</p>
<ul>
<li>
<span
data-component="Trans"
data-props="{
\\"i18nKey\\": \\"Privacy policy copy\\"
}"
>
<p>
Regexper and the tools used to create it are all open source. If you are concerned that the JavaScript being delivered is in any way malicious, please inspect the source in the
<a
href="https://gitlab.com/javallone/regexper-static"
rel="external noopener noreferrer"
target="_blank"
>
GitLab repository
</a>
.
</p>
<p>
There are two data collection tools integrated in the app. These tools are not used to collect personal information:
</p>
<ul>
<li>
<b>
Google Analytics
</b>
is used to track browser usage data and application performance. It is configured to anonymize the client IP address.
</li>
<li>
<b>
Sentry.io
</b>
is a tool used to capture and report client-side JavaScript errors. It is configured to not store the client IP address.
</li>
</ul>
<p>
Regexper honors the browser
<b>
Google Analytics
“Do Not Track”
</b>
is used to track browser usage data and application performance. It is configured to anonymize the client IP address.
</li>
<li>
setting and will not enable these data collection tools if that setting is enabled. Also, most popular ad blockers will prevent these tools from sending any tracking data. Disabling or blocking these data collection tools will
<b>
Sentry.io
not
</b>
is a tool used to capture and report client-side JavaScript errors. It is configured to not store the client IP address.
</li>
</ul>
<p>
Regexper honors the browser
<b>
“Do Not Track”
</b>
setting and will not enable these data collection tools if that setting is enabled. Also, most popular ad blockers will prevent these tools from sending any tracking data. Disabling or blocking these data collection tools will
<b>
not
</b>
impact the performance of this app. The information collected by these tools is used to monitor application performance, determine browser support, and collect error reports.
</p>
<p>
Regexper is not supported by ad revenue or sales of any kind.
</p>
</Trans>
</Message>
impact the performance of this app. The information collected by these tools is used to monitor application performance, determine browser support, and collect error reports.
</p>
<p>
Regexper is not supported by ad revenue or sales of any kind.
</p>
</span>
</span>
</DocumentFragment>
`;

View File

@ -1,14 +1,17 @@
jest.mock('components/Message', () =>
require('__mocks__/component-mock')('components/Message'));
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import { mockT } from 'i18n';
import { PrivacyPolicy } from 'components/PrivacyPolicy';
describe('PrivacyPolicy', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<PrivacyPolicy onClose={ jest.fn() } t={ mockT } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,155 +1,510 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Render debugging 1`] = `
<div
className="render"
>
<SVG
onReflow={[Function]}
<DocumentFragment>
<div
class="render"
>
<Text>
Example
</Text>
<rect
height={50}
style={
Object {
"fill": "transparent",
"opacity": 0.5,
"stroke": "red",
"strokeDasharray": "2,2",
"strokeWidth": "1px",
}
}
width={100}
/>
<circle
cx={5}
cy={10}
r="3"
style={
Object {
"fill": "red",
"opacity": 0.5,
}
}
/>
<circle
cx={95}
cy={10}
r="3"
style={
Object {
"fill": "red",
"opacity": 0.5,
}
}
/>
</SVG>
</div>
<svg
style="background-color: rgb(255, 255, 255);"
viewBox="0 0 "
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>
<metadata>
<rdf:rdf>
<cc:license
rdf:about="http://creativecommons.org/licenses/by/3.0/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:license>
</rdf:rdf>
</metadata>
<g
transform="translate(10 10)"
>
<span
data-component="Text"
data-props="{}"
>
Example
</span>
<rect
height="50"
style="fill: transparent; stroke: red; stroke-width: 1px; stroke-dasharray: 2,2; opacity: 0.5;"
width="100"
/>
<circle
cx="5"
cy="10"
r="3"
style="fill: red; opacity: 0.5;"
/>
<circle
cx="95"
cy="10"
r="3"
style="fill: red; opacity: 0.5;"
/>
</g>
</svg>
</div>
</DocumentFragment>
`;
exports[`Render types Box 1`] = `
<div
className="render"
>
<SVG
onReflow={[Function]}
<DocumentFragment>
<div
class="render"
>
<Box
padding={5}
radius={3}
<svg
style="background-color: rgb(255, 255, 255);"
viewBox="0 0 "
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>
<Text>
Example
</Text>
</Box>
</SVG>
</div>
<metadata>
<rdf:rdf>
<cc:license
rdf:about="http://creativecommons.org/licenses/by/3.0/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:license>
</rdf:rdf>
</metadata>
<g
transform="translate(10 10)"
>
<span
data-component="Box"
data-props="{}"
>
<span
data-component="Text"
data-props="{}"
>
Example
</span>
</span>
</g>
</svg>
</div>
</DocumentFragment>
`;
exports[`Render types HorizontalLayout 1`] = `
<div
className="render"
>
<SVG
onReflow={[Function]}
<DocumentFragment>
<div
class="render"
>
<HorizontalLayout
spacing={10}
withConnectors={false}
<svg
style="background-color: rgb(255, 255, 255);"
viewBox="0 0 "
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>
<Text>
Example
</Text>
<Text>
Another Example
</Text>
</HorizontalLayout>
</SVG>
</div>
<metadata>
<rdf:rdf>
<cc:license
rdf:about="http://creativecommons.org/licenses/by/3.0/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:license>
</rdf:rdf>
</metadata>
<g
transform="translate(10 10)"
>
<span
data-component="HorizontalLayout"
data-props="{}"
>
<span
data-component="Text"
data-props="{}"
>
Example
</span>
<span
data-component="Text"
data-props="{}"
>
Another Example
</span>
</span>
</g>
</svg>
</div>
</DocumentFragment>
`;
exports[`Render types Loop 1`] = `
<div
className="render"
>
<SVG
onReflow={[Function]}
<DocumentFragment>
<div
class="render"
>
<Loop>
<Text>
Example
</Text>
</Loop>
</SVG>
</div>
<svg
style="background-color: rgb(255, 255, 255);"
viewBox="0 0 "
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>
<metadata>
<rdf:rdf>
<cc:license
rdf:about="http://creativecommons.org/licenses/by/3.0/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:license>
</rdf:rdf>
</metadata>
<g
transform="translate(10 10)"
>
<span
data-component="Loop"
data-props="{}"
>
<span
data-component="Text"
data-props="{}"
>
Example
</span>
</span>
</g>
</svg>
</div>
</DocumentFragment>
`;
exports[`Render types Pin 1`] = `
<div
className="render"
>
<SVG
onReflow={[Function]}
<DocumentFragment>
<div
class="render"
>
<Pin />
</SVG>
</div>
<svg
style="background-color: rgb(255, 255, 255);"
viewBox="0 0 "
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>
<metadata>
<rdf:rdf>
<cc:license
rdf:about="http://creativecommons.org/licenses/by/3.0/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:license>
</rdf:rdf>
</metadata>
<g
transform="translate(10 10)"
>
<span
data-component="Pin"
data-props="{}"
/>
</g>
</svg>
</div>
</DocumentFragment>
`;
exports[`Render types Text 1`] = `
<div
className="render"
>
<SVG
onReflow={[Function]}
<DocumentFragment>
<div
class="render"
>
<Text>
Example
</Text>
</SVG>
</div>
<svg
style="background-color: rgb(255, 255, 255);"
viewBox="0 0 "
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>
<metadata>
<rdf:rdf>
<cc:license
rdf:about="http://creativecommons.org/licenses/by/3.0/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:license>
</rdf:rdf>
</metadata>
<g
transform="translate(10 10)"
>
<span
data-component="Text"
data-props="{}"
>
Example
</span>
</g>
</svg>
</div>
</DocumentFragment>
`;
exports[`Render types VerticalLayout 1`] = `
<div
className="render"
>
<SVG
onReflow={[Function]}
<DocumentFragment>
<div
class="render"
>
<VerticalLayout
spacing={10}
withConnectors={false}
<svg
style="background-color: rgb(255, 255, 255);"
viewBox="0 0 "
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>
<Text>
Example
</Text>
<Text>
Another Example
</Text>
</VerticalLayout>
</SVG>
</div>
<metadata>
<rdf:rdf>
<cc:license
rdf:about="http://creativecommons.org/licenses/by/3.0/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:license>
</rdf:rdf>
</metadata>
<g
transform="translate(10 10)"
>
<span
data-component="VerticalLayout"
data-props="{}"
>
<span
data-component="Text"
data-props="{}"
>
Example
</span>
<span
data-component="Text"
data-props="{}"
>
Another Example
</span>
</span>
</g>
</svg>
</div>
</DocumentFragment>
`;

View File

@ -1,15 +1,28 @@
jest.mock('rendering/Box', () =>
require('__mocks__/component-mock')('rendering/Box'));
jest.mock('rendering/HorizontalLayout', () =>
require('__mocks__/component-mock')('rendering/HorizontalLayout'));
jest.mock('rendering/Loop', () =>
require('__mocks__/component-mock')('rendering/Loop'));
jest.mock('rendering/Pin', () =>
require('__mocks__/component-mock')('rendering/Pin'));
jest.mock('rendering/Text', () =>
require('__mocks__/component-mock')('rendering/Text'));
jest.mock('rendering/VerticalLayout', () =>
require('__mocks__/component-mock')('rendering/VerticalLayout'));
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import Render from 'components/Render';
const testType = (name, item) => {
test(name, () => {
const data = { type: 'SVG', children: [item] };
const component = shallow(
const { asFragment } = render(
<Render data={ data } onRender={ jest.fn() }/>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
};
@ -34,10 +47,10 @@ describe('Render', () => {
}
]
};
const component = shallow(
const { asFragment } = render(
<Render data={ data } onRender={ jest.fn() }/>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
describe('types', () => {

View File

@ -1,7 +1,22 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SentryBoundary error handling 1`] = `<Child />`;
exports[`SentryBoundary error handling 1`] = `
<DocumentFragment>
Example content
</DocumentFragment>
`;
exports[`SentryBoundary error handling 2`] = `<withI18nextTranslation(SentryError) />`;
exports[`SentryBoundary error handling 2`] = `
<DocumentFragment>
<span
data-component="withI18nextTranslation(SentryError)"
data-props="{}"
/>
</DocumentFragment>
`;
exports[`SentryBoundary rendering 1`] = `"Example content"`;
exports[`SentryBoundary rendering 1`] = `
<DocumentFragment>
Example content
</DocumentFragment>
`;

View File

@ -1,41 +1,53 @@
jest.mock('@sentry/browser');
jest.mock('components/SentryError', () =>
require('__mocks__/component-mock')('components/SentryError'));
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import * as Sentry from '@sentry/browser';
import SentryBoundary from 'components/SentryBoundary';
describe('SentryBoundary', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<SentryBoundary>
Example content
</SentryBoundary>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('error handling', () => {
const Child = () => 'Example content';
const component = shallow(
// Hide React's console logging about the error
jest.spyOn(console, 'error').mockImplementation(() => {});
const error =new Error('Example error');
const Child = ({ shouldThrow }) => {
if (shouldThrow) {
throw error;
}
return 'Example content';
};
const { asFragment, rerender } = render(
<SentryBoundary>
<Child />
<Child shouldThrow={ false } />
</SentryBoundary>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
const error = new Error('Example error');
component.find('Child').simulateError(error);
// NOTE: Enzyme doesn't call getDerivedStateFromError yet, so we have to
// set the state manually
component.setState(SentryBoundary.getDerivedStateFromError(error));
rerender(
<SentryBoundary>
<Child shouldThrow={ true } />
</SentryBoundary>
);
const scope = { setExtra: jest.fn() };
expect(Sentry.withScope).toHaveBeenCalled();
Sentry.withScope.mock.calls[0][0](scope);
expect(Sentry.captureException).toHaveBeenCalledWith(error);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,21 +1,29 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SentryError rendering 1`] = `
<Message
heading="TRANSLATE(An error has occurred)"
type="error"
>
<p>
<Trans>
This error has been logged. You may also
<a
href="#error-report"
onClick={[Function]}
<DocumentFragment>
<span
data-component="Message"
data-props="{
\\"type\\": \\"error\\",
\\"heading\\": \\"TRANSLATE(An error has occurred)\\"
}"
>
<p>
<span
data-component="Trans"
data-props="{}"
>
fill out a report
</a>
.
</Trans>
</p>
</Message>
This error has been logged. You may also
<a
data-testid="error-report"
href="#error-report"
>
fill out a report
</a>
.
</span>
</p>
</span>
</DocumentFragment>
`;

View File

@ -16,7 +16,9 @@ const reportError = event => {
export const SentryError = ({ t }) => (
<Message type="error" heading={ t('An error has occurred') }>
<p>
<Trans>This error has been logged. You may also <a href="#error-report"
<Trans>This error has been logged. You may also <a
href="#error-report"
data-testid="error-report"
onClick={ reportError }>fill out a report</a>.</Trans>
</p>
</Message>

View File

@ -1,7 +1,10 @@
jest.mock('@sentry/browser');
jest.mock('components/Message', () =>
require('__mocks__/component-mock')('components/Message'));
import React from 'react';
import { shallow } from 'enzyme';
import { render, fireEvent } from 'react-testing-library';
import * as Sentry from '@sentry/browser';
import { mockT } from 'i18n';
@ -9,34 +12,36 @@ import { SentryError } from 'components/SentryError';
describe('SentryError', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<SentryError t={ mockT }/>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
describe('error reporting', () => {
test('fill out a report when an event has been logged', () => {
Sentry.lastEventId.mockReturnValue(1);
const component = shallow(
const { getByTestId } = render(
<SentryError t={ mockT } />
);
const eventObj = { preventDefault: jest.fn() };
component.find('a').simulate('click', eventObj);
const event = new MouseEvent('click', { bubbles: true });
jest.spyOn(event, 'preventDefault');
fireEvent(getByTestId('error-report'), event);
expect(eventObj.preventDefault).toHaveBeenCalled();
expect(event.preventDefault).toHaveBeenCalled();
expect(Sentry.showReportDialog).toHaveBeenCalled();
});
test('fill out a report when an event has not been logged', () => {
Sentry.lastEventId.mockReturnValue(false);
const component = shallow(
const { getByTestId } = render(
<SentryError t={ mockT } />
);
const eventObj = { preventDefault: jest.fn() };
component.find('a').simulate('click', eventObj);
const event = new MouseEvent('click', { bubbles: true });
jest.spyOn(event, 'preventDefault');
fireEvent(getByTestId('error-report'), event);
expect(eventObj.preventDefault).toHaveBeenCalled();
expect(event.preventDefault).toHaveBeenCalled();
expect(Sentry.showReportDialog).not.toHaveBeenCalled();
});
});

View File

@ -1,14 +1,19 @@
jest.mock('components/Metadata', () =>
require('__mocks__/component-mock')('components/Metadata'));
jest.mock('components/Message', () =>
require('__mocks__/component-mock')('components/Message'));
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import { mockT } from 'i18n';
import { ErrorPage } from 'pages/404';
describe('Error Page', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<ErrorPage t={ mockT } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,19 +1,28 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Error Page rendering 1`] = `
<Fragment>
<withI18nextTranslation(Metadata)
title="TRANSLATE(Page Not Found)"
<DocumentFragment>
<span
data-component="withI18nextTranslation(Metadata)"
data-props="{
\\"title\\": \\"TRANSLATE(Page Not Found)\\"
}"
/>
<Message
heading="TRANSLATE(404 Page Not Found)"
type="error"
<span
data-component="Message"
data-props="{
\\"type\\": \\"error\\",
\\"heading\\": \\"TRANSLATE(404 Page Not Found)\\"
}"
>
<p>
<Trans>
<span
data-component="Trans"
data-props="{}"
>
The page you have requested could not be found.
</Trans>
</span>
</p>
</Message>
</Fragment>
</span>
</DocumentFragment>
`;

View File

@ -1,89 +1,61 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Index Page rendering 1`] = `
<Fragment>
<withI18nextTranslation(Metadata)
description="Test description"
<DocumentFragment>
<span
data-component="withI18nextTranslation(Metadata)"
data-props="{
\\"description\\": \\"Test description\\"
}"
/>
<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>
<withI18nextTranslation(App)
expr=""
permalinkUrl={null}
syntax="testJs"
syntaxList={
Array [
Object {
"id": "testJS",
"name": "Testing JS",
},
Object {
"id": "other",
"name": "Other",
},
]
<noscript />
<span
data-component="withI18nextTranslation(App)"
data-props="{
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"name\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"name\\": \\"Other\\"
}
],
\\"syntax\\": \\"testJs\\",
\\"expr\\": \\"\\",
\\"permalinkUrl\\": null
}"
/>
</Fragment>
</DocumentFragment>
`;
exports[`Index Page rendering with an expression on the URL 1`] = `
<Fragment>
<withI18nextTranslation(Metadata)
description="Test description"
<DocumentFragment>
<span
data-component="withI18nextTranslation(Metadata)"
data-props="{
\\"description\\": \\"Test description\\"
}"
/>
<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>
<withI18nextTranslation(App)
expr="testing"
permalinkUrl="http://example.com"
syntax="test"
syntaxList={
Array [
Object {
"id": "testJS",
"name": "Testing JS",
},
Object {
"id": "other",
"name": "Other",
},
]
<noscript />
<span
data-component="withI18nextTranslation(App)"
data-props="{
\\"syntaxList\\": [
{
\\"id\\": \\"testJS\\",
\\"name\\": \\"Testing JS\\"
},
{
\\"id\\": \\"other\\",
\\"name\\": \\"Other\\"
}
],
\\"syntax\\": \\"test\\",
\\"expr\\": \\"testing\\",
\\"permalinkUrl\\": \\"http://example.com\\"
}"
/>
</Fragment>
</DocumentFragment>
`;

View File

@ -1,10 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Privacy Page rendering 1`] = `
<Fragment>
<withI18nextTranslation(Metadata)
title="TRANSLATE(Privacy Policy)"
<DocumentFragment>
<span
data-component="withI18nextTranslation(Metadata)"
data-props="{
\\"title\\": \\"TRANSLATE(Privacy Policy)\\"
}"
/>
<withI18nextTranslation(PrivacyPolicy) />
</Fragment>
<span
data-component="withI18nextTranslation(PrivacyPolicy)"
data-props="{}"
/>
</DocumentFragment>
`;

View File

@ -1,5 +1,12 @@
jest.mock('components/Metadata', () =>
require('__mocks__/component-mock')('components/Metadata'));
jest.mock('components/Message', () =>
require('__mocks__/component-mock')('components/Message'));
jest.mock('components/App', () =>
require('__mocks__/component-mock')('components/App'));
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import { IndexPage } from 'pages/index';
@ -18,19 +25,19 @@ const queryResult = {
describe('Index Page', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<IndexPage location={{ hash: '' }} data={ queryResult } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with an expression on the URL', () => {
const component = shallow(
const { asFragment } = render(
<IndexPage location={{
hash: '#syntax=test&expr=testing',
href: 'http://example.com'
}} data={ queryResult } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -1,14 +1,19 @@
jest.mock('components/Metadata', () =>
require('__mocks__/component-mock')('components/Metadata'));
jest.mock('components/PrivacyPolicy', () =>
require('__mocks__/component-mock')('components/PrivacyPolicy'));
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import { mockT } from 'i18n';
import { PrivacyPage } from 'pages/privacy';
describe('Privacy Page', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<PrivacyPage t={ mockT } />
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -156,174 +156,149 @@ Object {
`;
exports[`Box rendering 1`] = `
<Fragment>
<rect
rx={3}
ry={3}
/>
<g>
Example
</g>
</Fragment>
<DocumentFragment>
<svg>
<rect
rx="3"
ry="3"
/>
<g>
Example
</g>
</svg>
</DocumentFragment>
`;
exports[`Box rendering with a corner radius 1`] = `
<Fragment>
<rect
rx={5}
ry={5}
/>
<g>
Example
</g>
</Fragment>
<DocumentFragment>
<svg>
<rect
rx="5"
ry="5"
/>
<g>
Example
</g>
</svg>
</DocumentFragment>
`;
exports[`Box rendering with a label 1`] = `
<Fragment>
<rect
rx={3}
ry={3}
/>
<text
style={
Object {
"fontFamily": "Arial",
"fontSize": "12px",
}
}
>
Test box
</text>
<g>
Example
</g>
</Fragment>
<DocumentFragment>
<svg>
<rect
rx="3"
ry="3"
/>
<text
style="font-size: 12px; font-family: Arial;"
>
Test box
</text>
<g>
Example
</g>
</svg>
</DocumentFragment>
`;
exports[`Box rendering with props from layout 1`] = `
<Fragment>
<rect
height={50}
rx={3}
ry={3}
style={
Object {
"fill": "#dae9e5",
"stroke": "#6b6659",
"strokeWidth": "1px",
}
}
transform="RECT TRANSFORM"
width={100}
/>
<text
style={
Object {
"fontFamily": "Arial",
"fontSize": "12px",
}
}
transform="LABEL TRANSFORM"
>
Test box
</text>
<g
transform="CONTENT TRANSFORM"
>
Example
</g>
</Fragment>
<DocumentFragment>
<svg>
<rect
height="50"
rx="3"
ry="3"
style="fill: #dae9e5; stroke-width: 1px; stroke: #6b6659;"
transform="RECT TRANSFORM"
width="100"
/>
<text
style="font-size: 12px; font-family: Arial;"
transform="LABEL TRANSFORM"
>
Test box
</text>
<g
transform="CONTENT TRANSFORM"
>
Example
</g>
</svg>
</DocumentFragment>
`;
exports[`Box themes rendering a "anchor" Box 1`] = `
<Fragment>
<rect
rx={3}
ry={3}
style={
Object {
"fill": "#6b6659",
}
}
/>
<g>
Example
</g>
</Fragment>
<DocumentFragment>
<svg>
<rect
rx="3"
ry="3"
style="fill: #6b6659;"
/>
<g>
Example
</g>
</svg>
</DocumentFragment>
`;
exports[`Box themes rendering a "capture" Box 1`] = `
<Fragment>
<rect
rx={3}
ry={3}
style={
Object {
"fillOpacity": 0,
"stroke": "#908c83",
"strokeDasharray": "6,2",
"strokeWidth": "2px",
}
}
/>
<g>
Example
</g>
</Fragment>
<DocumentFragment>
<svg>
<rect
rx="3"
ry="3"
style="fill-opacity: 0; stroke-width: 2px; stroke: #908c83; stroke-dasharray: 6,2;"
/>
<g>
Example
</g>
</svg>
</DocumentFragment>
`;
exports[`Box themes rendering a "charClass" Box 1`] = `
<Fragment>
<rect
rx={3}
ry={3}
style={
Object {
"fill": "#cbcbba",
}
}
/>
<g>
Example
</g>
</Fragment>
<DocumentFragment>
<svg>
<rect
rx="3"
ry="3"
style="fill: #cbcbba;"
/>
<g>
Example
</g>
</svg>
</DocumentFragment>
`;
exports[`Box themes rendering a "escape" Box 1`] = `
<Fragment>
<rect
rx={3}
ry={3}
style={
Object {
"fill": "#bada55",
"stroke": "#6b6659",
"strokeWidth": "1px",
}
}
/>
<g>
Example
</g>
</Fragment>
<DocumentFragment>
<svg>
<rect
rx="3"
ry="3"
style="fill: #bada55; stroke-width: 1px; stroke: #6b6659;"
/>
<g>
Example
</g>
</svg>
</DocumentFragment>
`;
exports[`Box themes rendering a "literal" Box 1`] = `
<Fragment>
<rect
rx={3}
ry={3}
style={
Object {
"fill": "#dae9e5",
"stroke": "#6b6659",
"strokeWidth": "1px",
}
}
/>
<g>
Example
</g>
</Fragment>
<DocumentFragment>
<svg>
<rect
rx="3"
ry="3"
style="fill: #dae9e5; stroke-width: 1px; stroke: #6b6659;"
/>
<g>
Example
</g>
</svg>
</DocumentFragment>
`;

View File

@ -1,7 +1,7 @@
jest.mock('rendering/getbbox', () => jest.fn());
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import getBBox from 'rendering/getbbox';
@ -9,24 +9,30 @@ import Box, { layout } from 'rendering/Box';
describe('Box', () => {
test('rendering', () => {
const component = shallow(
<Box>Example</Box>
const { asFragment } = render(
<svg>
<Box>Example</Box>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with a corner radius', () => {
const component = shallow(
<Box radius={ 5 }>Example</Box>
const { asFragment } = render(
<svg>
<Box radius={ 5 }>Example</Box>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with a label', () => {
const component = shallow(
<Box label="Test box">Example</Box>
const { asFragment } = render(
<svg>
<Box label="Test box">Example</Box>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with props from layout', () => {
@ -39,46 +45,58 @@ describe('Box', () => {
labelTransform: 'LABEL TRANSFORM',
contentTransform: 'CONTENT TRANSFORM'
};
const component = shallow(
<Box { ...props }>Example</Box>
const { asFragment } = render(
<svg>
<Box { ...props }>Example</Box>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
describe('themes', () => {
test('rendering a "literal" Box', () => {
const component = shallow(
<Box theme="literal">Example</Box>
const { asFragment } = render(
<svg>
<Box theme="literal">Example</Box>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering a "escape" Box', () => {
const component = shallow(
<Box theme="escape">Example</Box>
const { asFragment } = render(
<svg>
<Box theme="escape">Example</Box>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering a "charClass" Box', () => {
const component = shallow(
<Box theme="charClass">Example</Box>
const { asFragment } = render(
<svg>
<Box theme="charClass">Example</Box>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering a "capture" Box', () => {
const component = shallow(
<Box theme="capture">Example</Box>
const { asFragment } = render(
<svg>
<Box theme="capture">Example</Box>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering a "anchor" Box', () => {
const component = shallow(
<Box theme="anchor">Example</Box>
const { asFragment } = render(
<svg>
<Box theme="anchor">Example</Box>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
});

View File

@ -11,15 +11,13 @@ Object {
`;
exports[`Pin rendering 1`] = `
<circle
r={5}
style={
Object {
"fill": "#6b6659",
"stroke": "#000",
"strokeWidth": "2px",
}
}
transform="translate(5 5)"
/>
<DocumentFragment>
<svg>
<circle
r="5"
style="fill: #6b6659; stroke-width: 2px; stroke: #000;"
transform="translate(5 5)"
/>
</svg>
</DocumentFragment>
`;

View File

@ -1,14 +1,16 @@
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import Pin, { layout } from 'rendering/Pin';
describe('Pin', () => {
test('rendering', () => {
const component = shallow(
<Pin/>
const { asFragment } = render(
<svg>
<Pin/>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('layout', () => {

View File

@ -24,38 +24,60 @@ Object {
`;
exports[`SVG rendering 1`] = `
<svg
height={20}
style={
Object {
"backgroundColor": "#fff",
}
}
viewBox="0 0 100 20"
width={100}
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>
<metadata
dangerouslySetInnerHTML={
Object {
"__html": "<rdf:rdf>
<cc:license rdf:about=\\"http://creativecommons.org/licenses/by/3.0/\\">
<cc:permits rdf:resource=\\"http://creativecommons.org/ns#Reproduction\\"></cc:permits>
<cc:permits rdf:resource=\\"http://creativecommons.org/ns#Distribution\\"></cc:permits>
<cc:requires rdf:resource=\\"http://creativecommons.org/ns#Notice\\"></cc:requires>
<cc:requires rdf:resource=\\"http://creativecommons.org/ns#Attribution\\"></cc:requires>
<cc:permits rdf:resource=\\"http://creativecommons.org/ns#DerivativeWorks\\"></cc:permits>
</cc:license>
</rdf:rdf>",
}
}
/>
<g
transform="translate(10 10)"
<DocumentFragment>
<svg
height="20"
style="background-color: rgb(255, 255, 255);"
viewBox="0 0 100 20"
width="100"
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
>
Content
</g>
</svg>
<metadata>
<rdf:rdf>
<cc:license
rdf:about="http://creativecommons.org/licenses/by/3.0/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Notice"
/>
<cc:requires
rdf:resource="http://creativecommons.org/ns#Attribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:license>
</rdf:rdf>
</metadata>
<g
transform="translate(10 10)"
>
Content
</g>
</svg>
</DocumentFragment>
`;

View File

@ -1,14 +1,14 @@
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import SVG, { layout } from 'rendering/SVG';
describe('SVG', () => {
test('rendering', () => {
const component = shallow(
const { asFragment } = render(
<SVG width={ 100 } height={ 20 }>Content</SVG>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('layout', () => {

View File

@ -18,75 +18,62 @@ Object {
`;
exports[`Text positioning text 1`] = `
<text
style={
Object {
"fontFamily": "Arial",
"fontSize": "16px",
}
}
transform="translate(1 2)"
>
Example
</text>
<DocumentFragment>
<svg>
<text
style="font-size: 16px; font-family: Arial;"
transform="translate(1 2)"
>
Example
</text>
</svg>
</DocumentFragment>
`;
exports[`Text rendering 1`] = `
<text
style={
Object {
"fontFamily": "Arial",
"fontSize": "16px",
}
}
>
Example
</text>
<DocumentFragment>
<svg>
<text
style="font-size: 16px; font-family: Arial;"
>
Example
</text>
</svg>
</DocumentFragment>
`;
exports[`Text rendering quoted text 1`] = `
<text
style={
Object {
"fontFamily": "Arial",
"fontSize": "16px",
}
}
>
<tspan
style={
Object {
"fill": "#908c83",
}
}
>
</tspan>
<tspan>
Example
</tspan>
<tspan
style={
Object {
"fill": "#908c83",
}
}
>
</tspan>
</text>
<DocumentFragment>
<svg>
<text
style="font-size: 16px; font-family: Arial;"
>
<tspan
style="fill: #908c83;"
>
</tspan>
<tspan>
Example
</tspan>
<tspan
style="fill: #908c83;"
>
</tspan>
</text>
</svg>
</DocumentFragment>
`;
exports[`Text rendering with a theme 1`] = `
<text
style={
Object {
"fill": "#fff",
"fontFamily": "Arial",
"fontSize": "16px",
}
}
>
Example
</text>
<DocumentFragment>
<svg>
<text
style="font-size: 16px; font-family: Arial; fill: #fff;"
>
Example
</text>
</svg>
</DocumentFragment>
`;

View File

@ -1,35 +1,43 @@
import React from 'react';
import { shallow } from 'enzyme';
import { render } from 'react-testing-library';
import Text, { layout } from 'rendering/Text';
describe('Text', () => {
test('rendering', () => {
const component = shallow(
<Text>Example</Text>
const { asFragment } = render(
<svg>
<Text>Example</Text>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('positioning text', () => {
const component = shallow(
<Text transform="translate(1 2)">Example</Text>
const { asFragment } = render(
<svg>
<Text transform="translate(1 2)">Example</Text>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering with a theme', () => {
const component = shallow(
<Text theme="anchor">Example</Text>
const { asFragment } = render(
<svg>
<Text theme="anchor">Example</Text>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('rendering quoted text', () => {
const component = shallow(
<Text quoted={ true }>Example</Text>
const { asFragment } = render(
<svg>
<Text quoted={ true }>Example</Text>
</svg>
);
expect(component).toMatchSnapshot();
expect(asFragment()).toMatchSnapshot();
});
test('layout', () => {

244
yarn.lock
View File

@ -700,7 +700,7 @@
"@babel/plugin-transform-react-jsx-self" "^7.0.0"
"@babel/plugin-transform-react-jsx-source" "^7.0.0"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2":
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.4":
version "7.4.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.2.tgz#f5ab6897320f16decd855eed70b705908a313fe8"
integrity sha512-7Bl2rALb7HpvXFL7TETNzKSAeBVCPHELzc0C//9FCxN8nsiueWSJBqaF+2oIJScyILStASR/Cx5WMkXGYTiJFA==
@ -1077,6 +1077,11 @@
"@sentry/types" "4.5.3"
tslib "^1.9.3"
"@sheerun/mutationobserver-shim@^0.3.2":
version "0.3.2"
resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#8013f2af54a2b7d735f71560ff360d3a8176a87b"
integrity sha512-vTCdPp/T/Q3oSqwHmZ5Kpa9oI7iLtGl3RQaA/NyLHikvcrPxACkkKVr/XzkSPJWXHRhKGzVvb0urJsbMlRxi1Q==
"@sindresorhus/is@^0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd"
@ -1655,11 +1660,6 @@ array-equal@^1.0.0:
resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=
array-filter@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83"
integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=
array-filter@~0.0.0:
version "0.0.1"
resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec"
@ -1720,15 +1720,6 @@ 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.flat@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz#812db8f02cad24d3fab65dd67eabe3b8903494a4"
integrity sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==
dependencies:
define-properties "^1.1.2"
es-abstract "^1.10.0"
function-bind "^1.1.1"
arraybuffer.slice@~0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
@ -3923,11 +3914,6 @@ diffie-hellman@^5.0.0:
miller-rabin "^4.0.0"
randombytes "^2.0.0"
discontinuous-range@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
integrity sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=
dns-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
@ -3992,6 +3978,16 @@ dom-serializer@0, dom-serializer@~0.1.0:
domelementtype "^1.3.0"
entities "^1.1.1"
dom-testing-library@^3.13.1:
version "3.18.2"
resolved "https://registry.yarnpkg.com/dom-testing-library/-/dom-testing-library-3.18.2.tgz#07d65166743ad3299b7bee5b488e9622c31241bc"
integrity sha512-+nYUgGhHarrCY8kLVmyHlgM+IGwBXXrYsWIJB6vpAx2ne9WFgKfwMGcOkkTKQhuAro0sP6RIuRGfm5NF3+ccmQ==
dependencies:
"@babel/runtime" "^7.3.4"
"@sheerun/mutationobserver-shim" "^0.3.2"
pretty-format "^24.5.0"
wait-for-expect "^1.1.0"
dom-walk@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
@ -4210,64 +4206,6 @@ envinfo@^5.8.1:
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-5.12.1.tgz#83068c33e0972eb657d6bc69a6df30badefb46ef"
integrity sha512-pwdo0/G3CIkQ0y6PCXq4RdkvId2elvtPCJMG0konqlrfkWQbf1DWeH9K2b/cvu2YgGvPPTOnonZxXM1gikFu1w==
enzyme-adapter-react-16@^1.7.1:
version "1.11.2"
resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.11.2.tgz#8efeafb27e96873a5492fdef3f423693182eb9d4"
integrity sha512-2ruTTCPRb0lPuw/vKTXGVZVBZqh83MNDnakMhzxhpJcIbneEwNy2Cv0KvL97pl57/GOazJHflWNLjwWhex5AAA==
dependencies:
enzyme-adapter-utils "^1.10.1"
object.assign "^4.1.0"
object.values "^1.1.0"
prop-types "^15.7.2"
react-is "^16.8.4"
react-test-renderer "^16.0.0-0"
semver "^5.6.0"
enzyme-adapter-utils@^1.10.1:
version "1.10.1"
resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.10.1.tgz#58264efa19a7befdbf964fb7981a108a5452ac96"
integrity sha512-oasinhhLoBuZsIkTe8mx0HiudtfErUtG0Ooe1FOplu/t4c9rOmyG5gtrBASK6u4whHIRWvv0cbZMElzNTR21SA==
dependencies:
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.5:
version "3.3.5"
resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.3.5.tgz#f8eb82bd3d5941c9d8bc6fd9140030777d17d0af"
integrity sha512-DmH1wJ68HyPqKSYXdQqB33ZotwfUhwQZW3IGXaNXgR69Iodaoj8TF/D9RjLdz4pEhGq2Tx2zwNUIjBuqoZeTgA==
dependencies:
lodash "^4.17.4"
enzyme@^3.8.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/enzyme/-/enzyme-3.9.0.tgz#2b491f06ca966eb56b6510068c7894a7e0be3909"
integrity sha512-JqxI2BRFHbmiP7/UFqvsjxTirWoM1HfeaJrmVSZ9a1EADKkZgdPcAuISPMpoUiHlac9J4dYt81MC5BBIrbJGMg==
dependencies:
array.prototype.flat "^1.2.1"
cheerio "^1.0.0-rc.2"
function.prototype.name "^1.1.0"
has "^1.0.3"
html-element-map "^1.0.0"
is-boolean-object "^1.0.0"
is-callable "^1.1.4"
is-number-object "^1.0.3"
is-regex "^1.0.4"
is-string "^1.0.4"
is-subset "^0.1.1"
lodash.escape "^4.0.1"
lodash.isequal "^4.5.0"
object-inspect "^1.6.0"
object-is "^1.0.1"
object.assign "^4.1.0"
object.entries "^1.0.4"
object.values "^1.0.4"
raf "^3.4.0"
rst-selector-parser "^2.2.3"
string.prototype.trim "^1.1.2"
eol@^0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/eol/-/eol-0.8.1.tgz#defc3224990c7eca73bb34461a56cf9dc24761d0"
@ -4294,7 +4232,7 @@ error-stack-parser@^2.0.0:
dependencies:
stackframe "^1.0.4"
es-abstract@^1.10.0, es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.5.0, es-abstract@^1.5.1, es-abstract@^1.7.0:
es-abstract@^1.11.0, es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.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==
@ -5341,20 +5279,11 @@ fsevents@^1.2.7:
nan "^2.9.2"
node-pre-gyp "^0.10.0"
function-bind@^1.0.2, function-bind@^1.1.1:
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
function.prototype.name@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.0.tgz#8bd763cc0af860a859cc5d49384d74b932cd2327"
integrity sha512-Bs0VRrTz4ghD8pTmbJQD1mZ8A/mN0ur/jGz+A6FBxPDUPkm1tNfF6bhTYPA7i7aF4lZJVr+OXTNNrnnIl58Wfg==
dependencies:
define-properties "^1.1.2"
function-bind "^1.1.1"
is-callable "^1.1.3"
functional-red-black-tree@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
@ -6239,13 +6168,6 @@ html-comment-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7"
integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==
html-element-map@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.0.0.tgz#19a41940225153ecdfead74f8509154ff1cdc18b"
integrity sha512-/SP6aOiM5Ai9zALvCxDubIeez0LvG3qP7R9GcRDnJEP/HBmv0A8A9K0o8+HFudcFt46+i921ANjzKsjPjb7Enw==
dependencies:
array-filter "^1.0.0"
html-encoding-sniffer@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8"
@ -6701,11 +6623,6 @@ is-binary-path@^1.0.0:
dependencies:
binary-extensions "^1.0.0"
is-boolean-object@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93"
integrity sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M=
is-buffer@^1.1.5, is-buffer@~1.1.1:
version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
@ -6723,7 +6640,7 @@ is-builtin-module@^3.0.0:
dependencies:
builtin-modules "^3.0.0"
is-callable@^1.1.3, is-callable@^1.1.4:
is-callable@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
@ -6857,11 +6774,6 @@ is-npm@^1.0.0:
resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ=
is-number-object@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.3.tgz#f265ab89a9f445034ef6aff15a8f00b00f551799"
integrity sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=
is-number@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
@ -6971,16 +6883,6 @@ is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
is-string@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.4.tgz#cc3a9b69857d621e963725a24caeec873b826e64"
integrity sha1-zDqbaYV9Yh6WNyWiTK7shzuCbmQ=
is-subset@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6"
integrity sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=
is-svg@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75"
@ -7963,11 +7865,6 @@ lodash._shimkeys@~2.4.1:
dependencies:
lodash._objecttypes "~2.4.1"
lodash.escape@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98"
integrity sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=
lodash.every@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.every/-/lodash.every-4.6.0.tgz#eb89984bebc4364279bb3aefbbd1ca19bfa6c6a7"
@ -8008,11 +7905,6 @@ lodash.isboolean@^3.0.3:
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
lodash.isinteger@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
@ -8552,11 +8444,6 @@ moment@^2.21.0:
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
moo@^0.4.3:
version "0.4.3"
resolved "https://registry.yarnpkg.com/moo/-/moo-0.4.3.tgz#3f847a26f31cf625a956a87f2b10fbc013bfd10e"
integrity sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw==
morgan@^1.8.2:
version "1.9.1"
resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.9.1.tgz#0a8d16734a1d9afbc824b99df87e738e58e2da59"
@ -8670,17 +8557,6 @@ ncp@1.0.x:
resolved "https://registry.yarnpkg.com/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246"
integrity sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=
nearley@^2.7.10:
version "2.16.0"
resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.16.0.tgz#77c297d041941d268290ec84b739d0ee297e83a7"
integrity sha512-Tr9XD3Vt/EujXbZBv6UAHYoLUSMQAxSsTnm9K3koXzjzNWY195NqALeyrzLZBKzAkL3gl92BcSogqrHjD8QuUg==
dependencies:
commander "^2.19.0"
moo "^0.4.3"
railroad-diagrams "^1.0.0"
randexp "0.4.6"
semver "^5.4.1"
needle@^2.2.1:
version "2.2.4"
resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e"
@ -8987,16 +8863,6 @@ object-hash@^1.1.4:
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df"
integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==
object-inspect@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b"
integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==
object-is@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6"
integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=
object-keys@^1.0.11, object-keys@^1.0.12:
version "1.1.0"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032"
@ -9024,16 +8890,6 @@ object.assign@^4.1.0:
has-symbols "^1.0.0"
object-keys "^1.0.11"
object.entries@^1.0.4:
version "1.1.0"
resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.0.tgz#2024fc6d6ba246aee38bdb0ffd5cfbcf371b7519"
integrity sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==
dependencies:
define-properties "^1.1.3"
es-abstract "^1.12.0"
function-bind "^1.1.1"
has "^1.0.3"
object.fromentries@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.0.tgz#49a543d92151f8277b3ac9600f1e930b189d30ab"
@ -9059,7 +8915,7 @@ object.pick@^1.3.0:
dependencies:
isobject "^3.0.1"
object.values@^1.0.4, object.values@^1.1.0:
object.values@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9"
integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==
@ -10405,7 +10261,7 @@ prop-types@^15.5.10, prop-types@^15.5.4:
loose-envify "^1.3.1"
object-assign "^4.1.1"
prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
prop-types@^15.6.1, prop-types@^15.6.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@ -10541,26 +10397,6 @@ querystringify@^2.0.0:
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
raf@^3.4.0:
version "3.4.1"
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
dependencies:
performance-now "^2.1.0"
railroad-diagrams@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e"
integrity sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=
randexp@0.4.6:
version "0.4.6"
resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3"
integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==
dependencies:
discontinuous-range "1.0.0"
ret "~0.1.10"
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
@ -10683,7 +10519,7 @@ react-i18next@^10.5.3:
"@babel/runtime" "^7.3.1"
html-parse-stringify2 "2.0.1"
react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.5:
react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4:
version "16.8.5"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.5.tgz#c54ac229dd66b5afe0de5acbe47647c3da692ff8"
integrity sha512-sudt2uq5P/2TznPV4Wtdi+Lnq3yaYW8LfvPKLM9BKD8jJNBkxMVyB0C9/GmVhLw7Jbdmndk/73n7XQGeN9A3QQ==
@ -10711,15 +10547,13 @@ react-side-effect@^1.1.0:
exenv "^1.2.1"
shallowequal "^1.0.1"
react-test-renderer@^16.0.0-0:
version "16.8.5"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.5.tgz#4cba7a8aad73f7e8a0bc4379a0fe21632886a563"
integrity sha512-/pFpHYQH4f35OqOae/DgOCXJDxBqD3K3akVfDhLgR0qYHoHjnICI/XS9QDwIhbrOFHWL7okVW9kKMaHuKvt2ng==
react-testing-library@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/react-testing-library/-/react-testing-library-6.0.2.tgz#afd7ddaa174e21cf672605e4e4f6f8156c4c9ef9"
integrity sha512-hWJIixR/jxJBnemcWI5O2JCMXlwoIpgF1IEUF8EYNEADORSZ9fs8rEJu4ygqyC53l3QOowkNb8D+eF5kGT3srg==
dependencies:
object-assign "^4.1.1"
prop-types "^15.6.2"
react-is "^16.8.5"
scheduler "^0.13.5"
"@babel/runtime" "^7.3.1"
dom-testing-library "^3.13.1"
react@^16.7.0:
version "16.8.5"
@ -11254,14 +11088,6 @@ router@^1.3.1:
setprototypeof "1.1.0"
utils-merge "1.0.1"
rst-selector-parser@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91"
integrity sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=
dependencies:
lodash.flattendeep "^4.4.0"
nearley "^2.7.10"
rsvp@^3.6.2:
version "3.6.2"
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a"
@ -12073,15 +11899,6 @@ string-width@^3.0.0:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"
string.prototype.trim@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea"
integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=
dependencies:
define-properties "^1.1.2"
es-abstract "^1.5.0"
function-bind "^1.0.2"
string_decoder@^1.0.0, string_decoder@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
@ -12948,6 +12765,11 @@ w3c-hr-time@^1.0.1:
dependencies:
browser-process-hrtime "^0.1.2"
wait-for-expect@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/wait-for-expect/-/wait-for-expect-1.1.0.tgz#6607375c3f79d32add35cd2c87ce13f351a3d453"
integrity sha512-vQDokqxyMyknfX3luCDn16bSaRcOyH6gGuUXMIbxBLeTo6nWuEWYqMTT9a+44FmW8c2m6TRWBdNvBBjA1hwEKg==
walker@~1.0.5:
version "1.0.7"
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"