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 = { global.___loader = {
enqueue: jest.fn() enqueue: jest.fn()
}; };

View File

@ -56,11 +56,9 @@
"node_modules" "node_modules"
], ],
"setupFilesAfterEnv": [ "setupFilesAfterEnv": [
"react-testing-library/cleanup-after-each",
"<rootDir>/jest/setup.js" "<rootDir>/jest/setup.js"
], ],
"snapshotSerializers": [
"enzyme-to-json/serializer"
],
"testPathIgnorePatterns": [ "testPathIgnorePatterns": [
"node_modules", "node_modules",
".cache" ".cache"
@ -85,9 +83,6 @@
"babel-jest": "^24.5.0", "babel-jest": "^24.5.0",
"babel-plugin-dynamic-import-node": "^2.2.0", "babel-plugin-dynamic-import-node": "^2.2.0",
"babel-preset-gatsby": "^0.1.6", "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": "^5.11.1",
"eslint-plugin-jest": "^22.1.2", "eslint-plugin-jest": "^22.1.2",
"eslint-plugin-react": "^7.12.1", "eslint-plugin-react": "^7.12.1",
@ -114,6 +109,7 @@
"react-feather": "^1.1.5", "react-feather": "^1.1.5",
"react-helmet": "^5.2.0", "react-helmet": "^5.2.0",
"react-i18next": "^10.5.3", "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 // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`App removing rendered expression 1`] = ` exports[`App removing rendered expression 1`] = `
<Fragment> <DocumentFragment>
<withI18nextTranslation(Form) <span
expr="test expression" data-component="withI18nextTranslation(Form)"
onSubmit={[Function]} data-props="{
syntax="js" \\"syntax\\": \\"js\\",
syntaxList={ \\"expr\\": \\"test expression\\",
Array [ \\"syntaxList\\": [
Object { {
"id": "testJS", \\"id\\": \\"testJS\\",
"label": "Testing JS", \\"label\\": \\"Testing JS\\"
}, },
Object { {
"id": "other", \\"id\\": \\"other\\",
"label": "Other", \\"label\\": \\"Other\\"
},
]
} }
]
}"
> >
<withI18nextTranslation(FormActions) /> <span
</withI18nextTranslation(Form)> data-component="withI18nextTranslation(FormActions)"
<Render data-props="{}"
data="LAYOUT(PARSED(test expression))" />
onRender={[Function]} </span>
<span
data-component="Render"
data-props="{
\\"data\\": \\"LAYOUT(PARSED(test expression))\\"
}"
/> />
</Fragment> </DocumentFragment>
`; `;
exports[`App removing rendered expression 2`] = ` exports[`App removing rendered expression 2`] = `
<Fragment> <DocumentFragment>
<withI18nextTranslation(Form) <span
expr="" data-component="withI18nextTranslation(Form)"
onSubmit={[Function]} data-props="{
syntax="js" \\"syntax\\": \\"js\\",
syntaxList={ \\"expr\\": \\"\\",
Array [ \\"syntaxList\\": [
Object { {
"id": "testJS", \\"id\\": \\"testJS\\",
"label": "Testing JS", \\"label\\": \\"Testing JS\\"
}, },
Object { {
"id": "other", \\"id\\": \\"other\\",
"label": "Other", \\"label\\": \\"Other\\"
},
]
} }
]
}"
/> />
</Fragment> </DocumentFragment>
`; `;
exports[`App rendering 1`] = ` exports[`App rendering 1`] = `
<Fragment> <DocumentFragment>
<withI18nextTranslation(Form) <span
expr="" data-component="withI18nextTranslation(Form)"
onSubmit={[Function]} data-props="{
syntax="js" \\"syntax\\": \\"js\\",
syntaxList={ \\"expr\\": \\"\\",
Array [ \\"syntaxList\\": [
Object { {
"id": "testJS", \\"id\\": \\"testJS\\",
"label": "Testing JS", \\"label\\": \\"Testing JS\\"
}, },
Object { {
"id": "other", \\"id\\": \\"other\\",
"label": "Other", \\"label\\": \\"Other\\"
},
]
} }
]
}"
/> />
</Fragment> </DocumentFragment>
`; `;
exports[`App rendering an expression 1`] = ` exports[`App rendering an expression 1`] = `
<Fragment> <DocumentFragment>
<withI18nextTranslation(Form) <span
expr="" data-component="withI18nextTranslation(Form)"
onSubmit={[Function]} data-props="{
syntax="js" \\"syntax\\": \\"js\\",
syntaxList={ \\"expr\\": \\"\\",
Array [ \\"syntaxList\\": [
Object { {
"id": "testJS", \\"id\\": \\"testJS\\",
"label": "Testing JS", \\"label\\": \\"Testing JS\\"
}, },
Object { {
"id": "other", \\"id\\": \\"other\\",
"label": "Other", \\"label\\": \\"Other\\"
},
]
} }
]
}"
/> />
</Fragment> </DocumentFragment>
`; `;
exports[`App rendering an expression 2`] = ` exports[`App rendering an expression 2`] = `
<Fragment> <DocumentFragment>
<withI18nextTranslation(Form) <span
expr="test expression" data-component="withI18nextTranslation(Form)"
onSubmit={[Function]} data-props="{
syntax="js" \\"syntax\\": \\"js\\",
syntaxList={ \\"expr\\": \\"test expression\\",
Array [ \\"syntaxList\\": [
Object { {
"id": "testJS", \\"id\\": \\"testJS\\",
"label": "Testing JS", \\"label\\": \\"Testing JS\\"
}, },
Object { {
"id": "other", \\"id\\": \\"other\\",
"label": "Other", \\"label\\": \\"Other\\"
},
]
} }
]
}"
/> />
<withI18nextTranslation(Loader) /> <span
</Fragment> data-component="withI18nextTranslation(Loader)"
data-props="{}"
/>
</DocumentFragment>
`; `;
exports[`App rendering an expression 3`] = ` exports[`App rendering an expression 3`] = `
<Fragment> <DocumentFragment>
<withI18nextTranslation(Form) <span
expr="test expression" data-component="withI18nextTranslation(Form)"
onSubmit={[Function]} data-props="{
syntax="js" \\"syntax\\": \\"js\\",
syntaxList={ \\"expr\\": \\"test expression\\",
Array [ \\"syntaxList\\": [
Object { {
"id": "testJS", \\"id\\": \\"testJS\\",
"label": "Testing JS", \\"label\\": \\"Testing JS\\"
}, },
Object { {
"id": "other", \\"id\\": \\"other\\",
"label": "Other", \\"label\\": \\"Other\\"
},
]
} }
]
}"
> >
<withI18nextTranslation(FormActions) /> <span
</withI18nextTranslation(Form)> data-component="withI18nextTranslation(FormActions)"
<Render data-props="{}"
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",
}
}
/> />
</withI18nextTranslation(Form)> </span>
<Render <span
data="LAYOUT(PARSED(test expression))" data-component="Render"
onRender={[Function]} data-props="{
\\"data\\": \\"LAYOUT(PARSED(test expression))\\"
}"
/> />
</Fragment> </DocumentFragment>
`; `;
exports[`App rendering with an invalid syntax 1`] = ` exports[`App rendering with an invalid syntax 1`] = `
<Fragment> <DocumentFragment>
<withI18nextTranslation(Form) <span
expr="" data-component="withI18nextTranslation(Form)"
onSubmit={[Function]} data-props="{
syntax="invalid" \\"syntax\\": \\"invalid\\",
syntaxList={ \\"expr\\": \\"\\",
Array [ \\"syntaxList\\": [
Object { {
"id": "testJS", \\"id\\": \\"testJS\\",
"label": "Testing JS", \\"label\\": \\"Testing JS\\"
}, },
Object { {
"id": "other", \\"id\\": \\"other\\",
"label": "Other", \\"label\\": \\"Other\\"
},
]
} }
]
}"
/> />
</Fragment> </DocumentFragment>
`; `;
exports[`App rendering with an invalid syntax 2`] = ` exports[`App rendering with an invalid syntax 2`] = `
<Fragment> <DocumentFragment>
<withI18nextTranslation(Form) <span
expr="test expression" data-component="withI18nextTranslation(Form)"
onSubmit={[Function]} data-props="{
syntax="invalid" \\"syntax\\": \\"invalid\\",
syntaxList={ \\"expr\\": \\"test expression\\",
Array [ \\"syntaxList\\": [
Object { {
"id": "testJS", \\"id\\": \\"testJS\\",
"label": "Testing JS", \\"label\\": \\"Testing JS\\"
}, },
Object { {
"id": "other", \\"id\\": \\"other\\",
"label": "Other", \\"label\\": \\"Other\\"
},
]
} }
]
}"
/> />
<withI18nextTranslation(Loader) /> <span
</Fragment> data-component="withI18nextTranslation(Loader)"
data-props="{}"
/>
</DocumentFragment>
`; `;
exports[`App rendering with an invalid syntax 3`] = ` exports[`App rendering with an invalid syntax 3`] = `
<Fragment> <DocumentFragment>
<withI18nextTranslation(Form) <span
expr="test expression" data-component="withI18nextTranslation(Form)"
onSubmit={[Function]} data-props="{
syntax="invalid" \\"syntax\\": \\"invalid\\",
syntaxList={ \\"expr\\": \\"test expression\\",
Array [ \\"syntaxList\\": [
Object { {
"id": "testJS", \\"id\\": \\"testJS\\",
"label": "Testing JS", \\"label\\": \\"Testing JS\\"
}, },
Object { {
"id": "other", \\"id\\": \\"other\\",
"label": "Other", \\"label\\": \\"Other\\"
},
]
} }
]
}"
/> />
<Message <span
heading="TRANSLATE(Render Failure)" data-component="Message"
type="error" data-props="{
\\"type\\": \\"error\\",
\\"heading\\": \\"TRANSLATE(Render Failure)\\"
}"
> >
<p> <p>
<Trans> <span
data-component="Trans"
data-props="{}"
>
An error occurred while rendering the regular expression. An error occurred while rendering the regular expression.
</Trans> </span>
</p> </p>
<a <a
href="#retry" href="#retry"
onClick={[Function]}
> >
<Trans> <span
data-component="Trans"
data-props="{}"
>
Retry Retry
</Trans> </span>
</a> </a>
</Message> </span>
</Fragment> </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 React from 'react';
import { shallow } from 'enzyme'; import { render } from 'react-testing-library';
import { mockT } from 'i18n'; import { mockT } from 'i18n';
import { App } from 'components/App'; import { App } from 'components/App';
@ -7,7 +16,7 @@ import { App } from 'components/App';
jest.mock('syntax/js', () => ({ jest.mock('syntax/js', () => ({
parse: expr => `PARSED(${ expr })`, parse: expr => `PARSED(${ expr })`,
layout: parsed => `LAYOUT(${ parsed })`, layout: parsed => `LAYOUT(${ parsed })`,
Render: () => '' Render: require('__mocks__/component-mock').buildMock(function Render() {})
})); }));
const syntaxList = [ const syntaxList = [
@ -18,115 +27,64 @@ const commonProps = { syntaxList, t: mockT };
describe('App', () => { describe('App', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<App expr="" syntax="js" { ...commonProps } /> <App expr="" syntax="js" { ...commonProps } />
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering an expression', async () => { test('rendering an expression', async () => {
const component = shallow( const { asFragment, rerender } = render(
<App expr="" syntax="js" { ...commonProps } /> <App expr="" syntax="js" { ...commonProps } />
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
component.setProps({ rerender(
expr: 'test expression' <App expr="test expression" syntax="js" { ...commonProps } />
}); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
// Give a beat for module to load // Give a beat for module to load
await new Promise(resolve => setTimeout(resolve)); await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering with an invalid syntax', async () => { test('rendering with an invalid syntax', async () => {
jest.spyOn(console, 'error').mockImplementation(() => {}); jest.spyOn(console, 'error').mockImplementation(() => {});
const component = shallow( const { asFragment, rerender } = render(
<App expr="" syntax="invalid" { ...commonProps } /> <App expr="" syntax="invalid" { ...commonProps } />
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
component.setProps({ rerender(
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(
<App expr="test expression" syntax="invalid" { ...commonProps } /> <App expr="test expression" syntax="invalid" { ...commonProps } />
); );
const instance = component.instance(); expect(asFragment()).toMatchSnapshot();
const event = { preventDefault: jest.fn() };
jest.spyOn(instance, 'handleRender'); // Give a beat for module to load
await new Promise(resolve => setTimeout(resolve));
instance.handleRetry(event); expect(asFragment()).toMatchSnapshot();
expect(event.preventDefault).toHaveBeenCalled();
expect(instance.handleRender).toHaveBeenCalled();
}); });
test('submitting an expression to render', () => { test('removing rendered expression', async () => {
const component = shallow( 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 } /> <App expr="" syntax="js" { ...commonProps } />
); );
const instance = component.instance(); expect(asFragment()).toMatchSnapshot();
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');
}); });
}); });

View File

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

View File

@ -1,14 +1,14 @@
import React from 'react'; import React from 'react';
import { shallow } from 'enzyme'; import { render } from 'react-testing-library';
import { mockT } from 'i18n'; import { mockT } from 'i18n';
import { Footer } from 'components/Footer'; import { Footer } from 'components/Footer';
describe('Footer', () => { describe('Footer', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<Footer buildId="abc-123" t={ mockT } /> <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 // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Form rendering 1`] = ` exports[`Form rendering 1`] = `
<div <DocumentFragment>
className="form" <div
data-requires-js={true} class="form"
> data-requires-js="true"
<form
onSubmit={[Function]}
> >
<textarea <form
autoFocus={true} data-testid="form"
name="expr"
onChange={[Function]}
onKeyPress={[Function]}
placeholder="TRANSLATE(Enter regular expression to display)"
/>
<button
type="submit"
> >
<Trans> <textarea
Display data-testid="expr-input"
</Trans> name="expr"
</button> placeholder="TRANSLATE(Enter regular expression to display)"
<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"
/> />
</div> <button
Actions type="submit"
</form> >
</div> <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; const { expr, syntax } = this.state;
return <div className={ style.form } data-requires-js> return <div className={ style.form } data-requires-js>
<form onSubmit={ this.handleSubmit }> <form data-testid="form" onSubmit={ this.handleSubmit }>
<textarea <textarea
data-testid="expr-input"
name="expr" name="expr"
value={ expr } value={ expr }
onKeyPress={ this.handleKeyPress } onKeyPress={ this.handleKeyPress }
@ -65,6 +66,7 @@ class Form extends React.PureComponent {
<button type="submit"><Trans>Display</Trans></button> <button type="submit"><Trans>Display</Trans></button>
<div className={ style.select }> <div className={ style.select }>
<select <select
data-testid="syntax-select"
name="syntax" name="syntax"
value={ syntax } value={ syntax }
onChange={ this.handleChange } > 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 React from 'react';
import { shallow } from 'enzyme'; import { render, fireEvent } from 'react-testing-library';
import { mockT } from 'i18n'; import { mockT } from 'i18n';
import { Form } from 'components/Form'; import { Form } from 'components/Form';
@ -12,76 +16,66 @@ const commonProps = { syntaxList, t: mockT };
describe('Form', () => { describe('Form', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<Form onSubmit={ jest.fn() } { ...commonProps }> <Form onSubmit={ jest.fn() } { ...commonProps }>
Actions Actions
</Form> </Form>
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
describe('submitting expression', () => { describe('submitting expression', () => {
test('submitting form', () => { test('submitting form', () => {
const onSubmit = jest.fn(); const onSubmit = jest.fn();
const component = shallow( const { getByTestId } = render(
<Form onSubmit={ onSubmit } { ...commonProps } /> <Form onSubmit={ onSubmit } { ...commonProps } />
); );
const exprInput = component.find('[name="expr"]'); fireEvent.change(getByTestId('expr-input'), {
const syntaxInput = component.find('[name="syntax"]'); target: { value: 'Test expression' }
exprInput.simulate('change', {
target: {
name: 'expr',
value: 'Test expression'
}
}); });
syntaxInput.simulate('change', { fireEvent.change(getByTestId('syntax-select'), {
target: { target: { value: 'other' }
name: 'syntax',
value: 'test'
}
}); });
const eventObj = { preventDefault: jest.fn() }; const event = new Event('submit');
component.find('form').simulate('submit', eventObj); jest.spyOn(event, 'preventDefault');
expect(eventObj.preventDefault).toHaveBeenCalled(); fireEvent(getByTestId('form'), event);
expect(event.preventDefault).toHaveBeenCalled();
expect(onSubmit).toHaveBeenCalledWith({ expect(onSubmit).toHaveBeenCalledWith({
expr: 'Test expression', expr: 'Test expression',
syntax: 'test' syntax: 'other'
}); });
}); });
test('submitting form with Shift+Enter', () => { test('submitting form with Shift+Enter', () => {
const component = shallow( const onSubmit = jest.fn();
<Form onSubmit={ jest.fn() } { ...commonProps } /> const { getByTestId } = render(
<Form onSubmit={ onSubmit } { ...commonProps } />
); );
const form = component.instance();
const eventObj = { fireEvent.keyPress(getByTestId('expr-input'), {
preventDefault: Function.prototype,
charCode: 13, charCode: 13,
shiftKey: true 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', () => { test('not submitting with just Enter', () => {
const component = shallow( const onSubmit = jest.fn();
<Form onSubmit={ jest.fn() } { ...commonProps } /> const { getByTestId } = render(
<Form onSubmit={ onSubmit } { ...commonProps } />
); );
const form = component.instance();
const eventObj = { fireEvent.keyPress(getByTestId('expr-input'), {
preventDefault: Function.prototype,
charCode: 13, charCode: 13,
shiftKey: false 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 // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FormActions rendering 1`] = ` exports[`FormActions rendering 1`] = `
<ul <DocumentFragment>
className="actions" <ul
/> class="actions"
/>
</DocumentFragment>
`; `;
exports[`FormActions rendering download links 1`] = ` exports[`FormActions rendering download links 1`] = `
<ul <DocumentFragment>
className="actions" <ul
> class="actions"
<li> >
<a <li>
download="image.png" <a
href="http://example.com/image.png" download="image.png"
type="image/png" href="http://example.com/image.png"
> type="image/png"
<Download >
color="currentColor" <span
size="24" data-component="Download"
/> data-props="{}"
TRANSLATE(Example PNG Link) />
</a> TRANSLATE(Example PNG Link)
</li> </a>
<li> </li>
<a <li>
download="image.svg" <a
href="http://example.com/image.svg" download="image.svg"
type="image/svg+xml" href="http://example.com/image.svg"
> type="image/svg+xml"
<Download >
color="currentColor" <span
size="24" data-component="Download"
/> data-props="{}"
TRANSLATE(Example SVG Link) />
</a> TRANSLATE(Example SVG Link)
</li> </a>
</ul> </li>
</ul>
</DocumentFragment>
`; `;
exports[`FormActions rendering download links with data after mounting 1`] = ` exports[`FormActions rendering download links with data after mounting 1`] = `
<ul <DocumentFragment>
className="actions" <ul
> class="actions"
<li> >
<a <li>
href="http://example.com" <a
> href="http://example.com"
<Link >
color="currentColor" <span
size="24" data-component="Link"
/> data-props="{}"
<Trans> />
Permalink <span
</Trans> data-component="Trans"
</a> data-props="{}"
</li> >
</ul> Permalink
</span>
</a>
</li>
</ul>
</DocumentFragment>
`; `;
exports[`FormActions rendering download links with data after mounting 2`] = ` exports[`FormActions rendering download links with data after mounting 2`] = `
<ul <DocumentFragment>
className="actions" <ul
> class="actions"
<li> >
<a <li>
download="image.png" <a
href="http://example.com/image.png" download="image.png"
type="image/png" href="http://example.com/image.png"
> type="image/png"
<Download >
color="currentColor" <span
size="24" data-component="Download"
/> data-props="{}"
TRANSLATE(Example PNG Link) />
</a> TRANSLATE(Example PNG Link)
</li> </a>
<li> </li>
<a <li>
download="image.svg" <a
href="http://example.com/image.svg" download="image.svg"
type="image/svg+xml" href="http://example.com/image.svg"
> type="image/svg+xml"
<Download >
color="currentColor" <span
size="24" data-component="Download"
/> data-props="{}"
TRANSLATE(Example SVG Link) />
</a> TRANSLATE(Example SVG Link)
</li> </a>
<li> </li>
<a <li>
href="http://example.com" <a
> href="http://example.com"
<Link >
color="currentColor" <span
size="24" data-component="Link"
/> data-props="{}"
<Trans> />
Permalink <span
</Trans> data-component="Trans"
</a> data-props="{}"
</li> >
</ul> Permalink
</span>
</a>
</li>
</ul>
</DocumentFragment>
`; `;
exports[`FormActions rendering download links with data after mounting 3`] = ` exports[`FormActions rendering download links with data after mounting 3`] = `
<ul <DocumentFragment>
className="actions" <ul
> class="actions"
<li> >
<a <li>
download="image.png" <a
href="http://example.com/image.png" download="image.png"
type="image/png" href="http://example.com/image.png"
> type="image/png"
<Download >
color="currentColor" <span
size="24" data-component="Download"
/> data-props="{}"
TRANSLATE(Example PNG Link) />
</a> TRANSLATE(Example PNG Link)
</li> </a>
<li> </li>
<a <li>
download="image.svg" <a
href="http://example.com/image.svg" download="image.svg"
type="image/svg+xml" href="http://example.com/image.svg"
> type="image/svg+xml"
<Download >
color="currentColor" <span
size="24" data-component="Download"
/> data-props="{}"
TRANSLATE(Example SVG Link) />
</a> TRANSLATE(Example SVG Link)
</li> </a>
<li> </li>
<a <li>
href="http://example.com" <a
> href="http://example.com"
<Link >
color="currentColor" <span
size="24" data-component="Link"
/> data-props="{}"
<Trans> />
Permalink <span
</Trans> data-component="Trans"
</a> data-props="{}"
</li> >
</ul> Permalink
</span>
</a>
</li>
</ul>
</DocumentFragment>
`; `;
exports[`FormActions rendering with a permalink 1`] = ` exports[`FormActions rendering with a permalink 1`] = `
<ul <DocumentFragment>
className="actions" <ul
> class="actions"
<li> >
<a <li>
href="http://example.com" <a
> href="http://example.com"
<Link >
color="currentColor" <span
size="24" data-component="Link"
/> data-props="{}"
<Trans> />
Permalink <span
</Trans> data-component="Trans"
</a> data-props="{}"
</li> >
</ul> Permalink
</span>
</a>
</li>
</ul>
</DocumentFragment>
`; `;

View File

@ -1,7 +1,13 @@
jest.mock('./links'); 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 React from 'react';
import { shallow } from 'enzyme'; import { render } from 'react-testing-library';
import { mockT } from 'i18n'; import { mockT } from 'i18n';
import { FormActions } from 'components/FormActions'; import { FormActions } from 'components/FormActions';
@ -22,17 +28,17 @@ createSvgLink.mockResolvedValue({
describe('FormActions', () => { describe('FormActions', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<FormActions t={ mockT } /> <FormActions t={ mockT } />
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering with a permalink', () => { test('rendering with a permalink', () => {
const component = shallow( const { asFragment } = render(
<FormActions permalinkUrl="http://example.com" t={ mockT } /> <FormActions permalinkUrl="http://example.com" t={ mockT } />
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering download links', async () => { test('rendering download links', async () => {
@ -42,47 +48,49 @@ describe('FormActions', () => {
height: 20 height: 20
}; };
const component = shallow( const { asFragment } = render(
<FormActions imageDetails={ imageDetails } t={ mockT } /> <FormActions imageDetails={ imageDetails } t={ mockT } />
); );
// Give a beat for mocked promises to resolve // Give a beat for mocked promises to resolve
await new Promise(resolve => setTimeout(resolve)); await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering download links with data after mounting', async () => { test('rendering download links with data after mounting', async () => {
const component = shallow( const { asFragment, rerender } = render(
<FormActions t={ mockT } /> <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({ rerender(
imageDetails: { <FormActions
svg: 'test image' permalinkUrl="http://example.com"
} imageDetails={ { svg: 'test-image' } }
}); t={ mockT } />
);
// Give a beat for mocked promises to resolve // Give a beat for mocked promises to resolve
await new Promise(resolve => setTimeout(resolve)); await new Promise(resolve => setTimeout(resolve));
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
component.setProps({ rerender(
imageDetails: { <FormActions
svg: 'test image', permalinkUrl="http://example.com"
width: 10, imageDetails={ { svg: 'test-image', width: 10, height: 20 } }
height: 20 t={ mockT } />
} );
});
// Give a beat for mocked promises to resolve // Give a beat for mocked promises to resolve
await new Promise(resolve => setTimeout(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 // 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`] = ` exports[`Header opening the Privacy Policy modal 1`] = `
<Fragment> <DocumentFragment>
<Modal <span
ariaHideApp={true} data-component="Modal"
bodyOpenClassName="ReactModal__Body--open" data-props="{
closeTimeoutMS={0} \\"isOpen\\": true
isOpen={true} }"
onRequestClose={[Function]}
parentSelector={[Function]}
portalClassName="ReactModalPortal"
role="dialog"
shouldCloseOnEsc={true}
shouldCloseOnOverlayClick={true}
shouldFocusAfterRender={true}
shouldReturnFocusAfterClose={true}
> >
<withI18nextTranslation(PrivacyPolicy) <span
onClose={[Function]} data-component="withI18nextTranslation(PrivacyPolicy)"
data-props="{}"
/> />
</Modal> </span>
<header <header
className="header" class="header"
data-banner={null}
> >
<h1> <h1>
<mockConstructor <a
to="/" href="/"
> >
Regexper Regexper
</mockConstructor> </a>
</h1> </h1>
<ul <ul
className="list" class="list"
> >
<li> <li>
<a <a
@ -184,71 +32,380 @@ exports[`Header opening the Privacy Policy modal 1`] = `
rel="external noopener noreferrer" rel="external noopener noreferrer"
target="_blank" target="_blank"
> >
<Gitlab <span
color="currentColor" data-component="Gitlab"
size="24" data-props="{}"
/> />
<Trans> <span
data-component="Trans"
data-props="{}"
>
Source on GitLab Source on GitLab
</Trans> </span>
</a> </a>
</li> </li>
<li> <li>
<mockConstructor <a
onClick={[Function]} data-testid="privacy-link"
to="/privacy" href="/privacy"
> >
<Trans> <span
data-component="Trans"
data-props="{}"
>
Privacy Policy Privacy Policy
</Trans> </span>
</mockConstructor> </a>
</li> </li>
<li> <li>
<withI18nextTranslation(InstallPrompt) /> <span
data-component="withI18nextTranslation(InstallPrompt)"
data-props="{}"
/>
</li> </li>
<li <li
data-requires-js={true} data-requires-js="true"
> >
<withI18nextTranslation(LocaleSwitcher) /> <span
data-component="withI18nextTranslation(LocaleSwitcher)"
data-props="{}"
/>
</li> </li>
</ul> </ul>
</header> </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`] = ` exports[`Header rendering 1`] = `
<Fragment> <DocumentFragment>
<Modal <span
ariaHideApp={true} data-component="Modal"
bodyOpenClassName="ReactModal__Body--open" data-props="{
closeTimeoutMS={0} \\"isOpen\\": false
isOpen={false} }"
onRequestClose={[Function]}
parentSelector={[Function]}
portalClassName="ReactModalPortal"
role="dialog"
shouldCloseOnEsc={true}
shouldCloseOnOverlayClick={true}
shouldFocusAfterRender={true}
shouldReturnFocusAfterClose={true}
> >
<withI18nextTranslation(PrivacyPolicy) <span
onClose={[Function]} data-component="withI18nextTranslation(PrivacyPolicy)"
data-props="{}"
/> />
</Modal> </span>
<header <header
className="header" class="header"
data-banner="testing" data-banner="testing"
> >
<h1> <h1>
<mockConstructor <a
to="/" href="/"
> >
Regexper Regexper
</mockConstructor> </a>
</h1> </h1>
<ul <ul
className="list" class="list"
> >
<li> <li>
<a <a
@ -256,71 +413,75 @@ exports[`Header rendering 1`] = `
rel="external noopener noreferrer" rel="external noopener noreferrer"
target="_blank" target="_blank"
> >
<Gitlab <span
color="currentColor" data-component="Gitlab"
size="24" data-props="{}"
/> />
<Trans> <span
data-component="Trans"
data-props="{}"
>
Source on GitLab Source on GitLab
</Trans> </span>
</a> </a>
</li> </li>
<li> <li>
<mockConstructor <a
onClick={[Function]} data-testid="privacy-link"
to="/privacy" href="/privacy"
> >
<Trans> <span
data-component="Trans"
data-props="{}"
>
Privacy Policy Privacy Policy
</Trans> </span>
</mockConstructor> </a>
</li> </li>
<li> <li>
<withI18nextTranslation(InstallPrompt) /> <span
data-component="withI18nextTranslation(InstallPrompt)"
data-props="{}"
/>
</li> </li>
<li <li
data-requires-js={true} data-requires-js="true"
> >
<withI18nextTranslation(LocaleSwitcher) /> <span
data-component="withI18nextTranslation(LocaleSwitcher)"
data-props="{}"
/>
</li> </li>
</ul> </ul>
</header> </header>
</Fragment> </DocumentFragment>
`; `;
exports[`Header rendering with no banner 1`] = ` exports[`Header rendering with no banner 1`] = `
<Fragment> <DocumentFragment>
<Modal <span
ariaHideApp={true} data-component="Modal"
bodyOpenClassName="ReactModal__Body--open" data-props="{
closeTimeoutMS={0} \\"isOpen\\": false
isOpen={false} }"
onRequestClose={[Function]}
parentSelector={[Function]}
portalClassName="ReactModalPortal"
role="dialog"
shouldCloseOnEsc={true}
shouldCloseOnOverlayClick={true}
shouldFocusAfterRender={true}
shouldReturnFocusAfterClose={true}
> >
<withI18nextTranslation(PrivacyPolicy) <span
onClose={[Function]} data-component="withI18nextTranslation(PrivacyPolicy)"
data-props="{}"
/> />
</Modal> </span>
<header <header
className="header" class="header"
data-banner={null}
> >
<h1> <h1>
<mockConstructor <a
to="/" href="/"
> >
Regexper Regexper
</mockConstructor> </a>
</h1> </h1>
<ul <ul
className="list" class="list"
> >
<li> <li>
<a <a
@ -328,34 +489,46 @@ exports[`Header rendering with no banner 1`] = `
rel="external noopener noreferrer" rel="external noopener noreferrer"
target="_blank" target="_blank"
> >
<Gitlab <span
color="currentColor" data-component="Gitlab"
size="24" data-props="{}"
/> />
<Trans> <span
data-component="Trans"
data-props="{}"
>
Source on GitLab Source on GitLab
</Trans> </span>
</a> </a>
</li> </li>
<li> <li>
<mockConstructor <a
onClick={[Function]} data-testid="privacy-link"
to="/privacy" href="/privacy"
> >
<Trans> <span
data-component="Trans"
data-props="{}"
>
Privacy Policy Privacy Policy
</Trans> </span>
</mockConstructor> </a>
</li> </li>
<li> <li>
<withI18nextTranslation(InstallPrompt) /> <span
data-component="withI18nextTranslation(InstallPrompt)"
data-props="{}"
/>
</li> </li>
<li <li
data-requires-js={true} data-requires-js="true"
> >
<withI18nextTranslation(LocaleSwitcher) /> <span
data-component="withI18nextTranslation(LocaleSwitcher)"
data-props="{}"
/>
</li> </li>
</ul> </ul>
</header> </header>
</Fragment> </DocumentFragment>
`; `;

View File

@ -64,7 +64,10 @@ class Header extends React.PureComponent {
</a> </a>
</li> </li>
<li> <li>
<Link to="/privacy" onClick={ this.handleOpen }> <Link to="/privacy"
data-testid="privacy-link"
onClick={ this.handleOpen }
>
<Trans>Privacy Policy</Trans> <Trans>Privacy Policy</Trans>
</Link> </Link>
</li> </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 React from 'react';
import { shallow } from 'enzyme'; import { render, fireEvent } from 'react-testing-library';
import { Header } from 'components/Header'; import { Header } from 'components/Header';
describe('Header', () => { describe('Header', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<Header banner="testing" /> <Header banner="testing" />
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering with no banner', () => { test('rendering with no banner', () => {
const component = shallow( const { asFragment } = render(
<Header banner={ false } /> <Header banner={ false } />
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('opening the Privacy Policy modal', () => { test('opening the Privacy Policy modal', () => {
const component = shallow( const { asFragment, getByTestId } = render(
<Header banner={ false } /> <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(event.preventDefault).toHaveBeenCalled();
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
['shift', 'ctrl', 'alt', 'meta'].forEach(key => { ['shift', 'ctrl', 'alt', 'meta'].forEach(key => {
test(`opening the Privacy Policy modal while holding ${ key } key`, () => { test(`opening the Privacy Policy modal while holding ${ key } key`, () => {
const component = shallow( const { asFragment, getByTestId } = render(
<Header banner={ false } /> <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(event.preventDefault).not.toHaveBeenCalled();
expect(component.state('showModal')).toEqual(false); 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 // 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`] = ` exports[`InstallPrompt rendering after an install prompt has been requested 2`] = `
<a <DocumentFragment>
href="#install" <a
onClick={[Function]} data-testid="install"
> href="#install"
<Trans> >
Add to Home Screen <span
</Trans> data-component="Trans"
</a> data-props="{}"
>
Add to Home Screen
</span>
</a>
</DocumentFragment>
`; `;

View File

@ -43,7 +43,10 @@ class InstallPrompt extends React.PureComponent {
return null; 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> <Trans>Add to Home Screen</Trans>
</a>; </a>;
} }

View File

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

View File

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

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 React from 'react';
import { shallow } from 'enzyme'; import { render } from 'react-testing-library';
import { Layout } from 'components/Layout'; import { Layout } from 'components/Layout';
describe('Layout', () => { describe('Layout', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<Layout banner="Test Banner" buildId="test-buildid"> <Layout banner="Test Banner" buildId="test-buildid">
Example content Example content
</Layout> </Layout>
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
}); });

View File

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

View File

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

View File

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

View File

@ -38,7 +38,10 @@ export class LocaleSwitcher extends React.PureComponent {
return <label> return <label>
<Trans>Language</Trans> <Trans>Language</Trans>
<div className={ style.switcher }> <div className={ style.switcher }>
<select value={ current } onChange={ this.handleSelectChange }> <select data-testid="language-select"
value={ current }
onChange={ this.handleSelectChange }
>
{ locales.map(locale => ( { locales.map(locale => (
<option value={ locale.code } key={ locale.code }> <option value={ locale.code } key={ locale.code }>
{ locale.name } { 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 React from 'react';
import { shallow } from 'enzyme'; import { render, fireEvent } from 'react-testing-library';
import i18n from 'i18n'; import i18n from 'i18n';
import { LocaleSwitcher } from 'components/LocaleSwitcher'; import { LocaleSwitcher } from 'components/LocaleSwitcher';
@ -9,44 +13,47 @@ jest.mock('./locale-to-available', () => jest.fn(() => 'en'));
describe('LocaleSwitcher', () => { describe('LocaleSwitcher', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<LocaleSwitcher /> <LocaleSwitcher />
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('changing language', () => { test('changing language', () => {
jest.spyOn(i18n, 'changeLanguage'); jest.spyOn(i18n, 'changeLanguage');
const component = shallow( const { getByTestId } = render(
<LocaleSwitcher /> <LocaleSwitcher />
); );
const selectInput = component.find('select'); const event = new Event('change', { bubbles: true });
selectInput.value = 'other'; const select = getByTestId('language-select');
selectInput.simulate('change', { target: { value: 'other' } }); select.value = 'other';
fireEvent(select, event);
expect(i18n.changeLanguage).toHaveBeenCalledWith('other'); expect(i18n.changeLanguage).toHaveBeenCalledWith('other');
}); });
test('interface update from language change', () => { test('interface update from language change', () => {
const component = shallow( const { getByTestId } = render(
<LocaleSwitcher /> <LocaleSwitcher />
); );
expect(component.find('select').prop('value')).toEqual('en'); expect(getByTestId('language-select').value).toEqual('en');
i18n.emit('languageChanged', 'other'); 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', () => { test('disconnecting event handler on unmount', () => {
const component = shallow( const { unmount } = render(
<LocaleSwitcher /> <LocaleSwitcher />
); );
jest.spyOn(component, 'setState'); jest.spyOn(i18n, 'off');
component.unmount(); unmount();
i18n.emit('languageChanged', 'other'); expect(i18n.off).toHaveBeenCalledWith(
expect(component.setState).not.toHaveBeenCalled(); 'languageChanged',
expect.any(Function));
}); });
}); });

View File

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

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 React from 'react';
import { shallow } from 'enzyme'; import { render } from 'react-testing-library';
import Message from 'components/Message'; import Message from 'components/Message';
describe('Message', () => { describe('Message', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<Message heading="Testing"> <Message heading="Testing">
<p>Message content</p> <p>Message content</p>
</Message> </Message>
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering with icon', () => { test('rendering with icon', () => {
const Icon = () => 'Sample icon SVG'; const Icon = () => 'Sample icon SVG';
const component = shallow( const { asFragment } = render(
<Message heading="Testing" icon={ Icon }> <Message heading="Testing" icon={ Icon }>
<p>Message content</p> <p>Message content</p>
</Message> </Message>
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering with type', () => { test('rendering with type', () => {
const component = shallow( const { asFragment } = render(
<Message heading="Testing" type="error"> <Message heading="Testing" type="error">
<p>Message content</p> <p>Message content</p>
</Message> </Message>
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering with a close button', () => { test('rendering with a close button', () => {
const component = shallow( const { asFragment } = render(
<Message heading="Testing" onClose={ jest.fn() }> <Message heading="Testing" onClose={ jest.fn() }>
<p>Message content</p> <p>Message content</p>
</Message> </Message>
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
}); });

View File

@ -1,37 +1,39 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Metadata rendering 1`] = ` exports[`Metadata rendering 1`] = `
<HelmetWrapper <DocumentFragment>
defer={true} <span
encodeSpecialCharacters={true} data-component="HelmetWrapper"
htmlAttributes={ data-props="{
Object { \\"htmlAttributes\\": {
"lang": "test-lang", \\"lang\\": \\"test-lang\\"
}
} }
> }"
<title> >
Regexper <title>
</title> Regexper
</HelmetWrapper> </title>
</span>
</DocumentFragment>
`; `;
exports[`Metadata rendering with a title and description 1`] = ` exports[`Metadata rendering with a title and description 1`] = `
<HelmetWrapper <DocumentFragment>
defer={true} <span
encodeSpecialCharacters={true} data-component="HelmetWrapper"
htmlAttributes={ data-props="{
Object { \\"htmlAttributes\\": {
"lang": "test-lang", \\"lang\\": \\"test-lang\\"
}
} }
> }"
<title> >
Regexper - Testing <title>
</title> Regexper - Testing
<meta </title>
content="Test description" <meta
name="description" content="Test description"
/> name="description"
</HelmetWrapper> />
</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 React from 'react';
import { shallow } from 'enzyme'; import { render } from 'react-testing-library';
import { Metadata } from 'components/Metadata'; import { Metadata } from 'components/Metadata';
@ -9,19 +17,19 @@ const commonProps = {
describe('Metadata', () => { describe('Metadata', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<Metadata { ...commonProps } /> <Metadata { ...commonProps } />
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering with a title and description', () => { test('rendering with a title and description', () => {
const component = shallow( const { asFragment } = render(
<Metadata <Metadata
title="Testing" title="Testing"
description="Test description" description="Test description"
{ ...commonProps } /> { ...commonProps } />
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
}); });

View File

@ -1,56 +1,63 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PrivacyPolicy rendering 1`] = ` exports[`PrivacyPolicy rendering 1`] = `
<Message <DocumentFragment>
heading="TRANSLATE(Privacy Policy)" <span
onClose={[MockFunction]} data-component="Message"
type="info" data-props="{
> \\"type\\": \\"info\\",
<Trans \\"heading\\": \\"TRANSLATE(Privacy Policy)\\"
i18nKey="Privacy policy copy" }"
> >
<p> <span
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 data-component="Trans"
<a data-props="{
href="https://gitlab.com/javallone/regexper-static" \\"i18nKey\\": \\"Privacy policy copy\\"
rel="external noopener noreferrer" }"
target="_blank" >
> <p>
GitLab repository 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> <a
. href="https://gitlab.com/javallone/regexper-static"
</p> rel="external noopener noreferrer"
<p> target="_blank"
There are two data collection tools integrated in the app. These tools are not used to collect personal information: >
</p> GitLab repository
<ul> </a>
<li> .
</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> <b>
Google Analytics “Do Not Track”
</b> </b>
is used to track browser usage data and application performance. It is configured to anonymize the client IP address. 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
</li>
<li>
<b> <b>
Sentry.io not
</b> </b>
is a tool used to capture and report client-side JavaScript errors. It is configured to not store the client IP address. 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.
</li> </p>
</ul> <p>
<p> Regexper is not supported by ad revenue or sales of any kind.
Regexper honors the browser </p>
<b> </span>
“Do Not Track” </span>
</b> </DocumentFragment>
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>
`; `;

View File

@ -1,14 +1,17 @@
jest.mock('components/Message', () =>
require('__mocks__/component-mock')('components/Message'));
import React from 'react'; import React from 'react';
import { shallow } from 'enzyme'; import { render } from 'react-testing-library';
import { mockT } from 'i18n'; import { mockT } from 'i18n';
import { PrivacyPolicy } from 'components/PrivacyPolicy'; import { PrivacyPolicy } from 'components/PrivacyPolicy';
describe('PrivacyPolicy', () => { describe('PrivacyPolicy', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<PrivacyPolicy onClose={ jest.fn() } t={ mockT } /> <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 // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Render debugging 1`] = ` exports[`Render debugging 1`] = `
<div <DocumentFragment>
className="render" <div
> class="render"
<SVG
onReflow={[Function]}
> >
<Text> <svg
Example style="background-color: rgb(255, 255, 255);"
</Text> viewBox="0 0 "
<rect xmlns="http://www.w3.org/2000/svg"
height={50} xmlns:cc="http://creativecommons.org/ns#"
style={ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
Object { >
"fill": "transparent", <metadata>
"opacity": 0.5, <rdf:rdf>
"stroke": "red",
"strokeDasharray": "2,2",
"strokeWidth": "1px", <cc:license
} rdf:about="http://creativecommons.org/licenses/by/3.0/"
} >
width={100}
/>
<circle <cc:permits
cx={5} rdf:resource="http://creativecommons.org/ns#Reproduction"
cy={10} />
r="3"
style={
Object { <cc:permits
"fill": "red", rdf:resource="http://creativecommons.org/ns#Distribution"
"opacity": 0.5, />
}
}
/> <cc:requires
<circle rdf:resource="http://creativecommons.org/ns#Notice"
cx={95} />
cy={10}
r="3"
style={ <cc:requires
Object { rdf:resource="http://creativecommons.org/ns#Attribution"
"fill": "red", />
"opacity": 0.5,
}
} <cc:permits
/> rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
</SVG> />
</div>
</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`] = ` exports[`Render types Box 1`] = `
<div <DocumentFragment>
className="render" <div
> class="render"
<SVG
onReflow={[Function]}
> >
<Box <svg
padding={5} style="background-color: rgb(255, 255, 255);"
radius={3} 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> <metadata>
Example <rdf:rdf>
</Text>
</Box>
</SVG> <cc:license
</div> 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`] = ` exports[`Render types HorizontalLayout 1`] = `
<div <DocumentFragment>
className="render" <div
> class="render"
<SVG
onReflow={[Function]}
> >
<HorizontalLayout <svg
spacing={10} style="background-color: rgb(255, 255, 255);"
withConnectors={false} 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> <metadata>
Example <rdf:rdf>
</Text>
<Text>
Another Example <cc:license
</Text> rdf:about="http://creativecommons.org/licenses/by/3.0/"
</HorizontalLayout> >
</SVG>
</div>
<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`] = ` exports[`Render types Loop 1`] = `
<div <DocumentFragment>
className="render" <div
> class="render"
<SVG
onReflow={[Function]}
> >
<Loop> <svg
<Text> style="background-color: rgb(255, 255, 255);"
Example viewBox="0 0 "
</Text> xmlns="http://www.w3.org/2000/svg"
</Loop> xmlns:cc="http://creativecommons.org/ns#"
</SVG> xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
</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="Loop"
data-props="{}"
>
<span
data-component="Text"
data-props="{}"
>
Example
</span>
</span>
</g>
</svg>
</div>
</DocumentFragment>
`; `;
exports[`Render types Pin 1`] = ` exports[`Render types Pin 1`] = `
<div <DocumentFragment>
className="render" <div
> class="render"
<SVG
onReflow={[Function]}
> >
<Pin /> <svg
</SVG> style="background-color: rgb(255, 255, 255);"
</div> 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`] = ` exports[`Render types Text 1`] = `
<div <DocumentFragment>
className="render" <div
> class="render"
<SVG
onReflow={[Function]}
> >
<Text> <svg
Example style="background-color: rgb(255, 255, 255);"
</Text> viewBox="0 0 "
</SVG> xmlns="http://www.w3.org/2000/svg"
</div> 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`] = ` exports[`Render types VerticalLayout 1`] = `
<div <DocumentFragment>
className="render" <div
> class="render"
<SVG
onReflow={[Function]}
> >
<VerticalLayout <svg
spacing={10} style="background-color: rgb(255, 255, 255);"
withConnectors={false} 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> <metadata>
Example <rdf:rdf>
</Text>
<Text>
Another Example <cc:license
</Text> rdf:about="http://creativecommons.org/licenses/by/3.0/"
</VerticalLayout> >
</SVG>
</div>
<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 React from 'react';
import { shallow } from 'enzyme'; import { render } from 'react-testing-library';
import Render from 'components/Render'; import Render from 'components/Render';
const testType = (name, item) => { const testType = (name, item) => {
test(name, () => { test(name, () => {
const data = { type: 'SVG', children: [item] }; const data = { type: 'SVG', children: [item] };
const component = shallow( const { asFragment } = render(
<Render data={ data } onRender={ jest.fn() }/> <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() }/> <Render data={ data } onRender={ jest.fn() }/>
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
describe('types', () => { describe('types', () => {

View File

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

View File

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

View File

@ -16,7 +16,9 @@ const reportError = event => {
export const SentryError = ({ t }) => ( export const SentryError = ({ t }) => (
<Message type="error" heading={ t('An error has occurred') }> <Message type="error" heading={ t('An error has occurred') }>
<p> <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> onClick={ reportError }>fill out a report</a>.</Trans>
</p> </p>
</Message> </Message>

View File

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

View File

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

View File

@ -1,89 +1,61 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Index Page rendering 1`] = ` exports[`Index Page rendering 1`] = `
<Fragment> <DocumentFragment>
<withI18nextTranslation(Metadata) <span
description="Test description" data-component="withI18nextTranslation(Metadata)"
data-props="{
\\"description\\": \\"Test description\\"
}"
/> />
<noscript> <noscript />
<Message <span
heading="JavaScript Required" data-component="withI18nextTranslation(App)"
type="error" data-props="{
> \\"syntaxList\\": [
<p> {
You need JavaScript to use Regexper. \\"id\\": \\"testJS\\",
</p> \\"name\\": \\"Testing JS\\"
<p> },
If you have concerns regarding the use of tracking code on Regexper, please see the {
<mockConstructor \\"id\\": \\"other\\",
to="/privacy" \\"name\\": \\"Other\\"
>
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",
},
]
} }
],
\\"syntax\\": \\"testJs\\",
\\"expr\\": \\"\\",
\\"permalinkUrl\\": null
}"
/> />
</Fragment> </DocumentFragment>
`; `;
exports[`Index Page rendering with an expression on the URL 1`] = ` exports[`Index Page rendering with an expression on the URL 1`] = `
<Fragment> <DocumentFragment>
<withI18nextTranslation(Metadata) <span
description="Test description" data-component="withI18nextTranslation(Metadata)"
data-props="{
\\"description\\": \\"Test description\\"
}"
/> />
<noscript> <noscript />
<Message <span
heading="JavaScript Required" data-component="withI18nextTranslation(App)"
type="error" data-props="{
> \\"syntaxList\\": [
<p> {
You need JavaScript to use Regexper. \\"id\\": \\"testJS\\",
</p> \\"name\\": \\"Testing JS\\"
<p> },
If you have concerns regarding the use of tracking code on Regexper, please see the {
<mockConstructor \\"id\\": \\"other\\",
to="/privacy" \\"name\\": \\"Other\\"
>
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",
},
]
} }
],
\\"syntax\\": \\"test\\",
\\"expr\\": \\"testing\\",
\\"permalinkUrl\\": \\"http://example.com\\"
}"
/> />
</Fragment> </DocumentFragment>
`; `;

View File

@ -1,10 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Privacy Page rendering 1`] = ` exports[`Privacy Page rendering 1`] = `
<Fragment> <DocumentFragment>
<withI18nextTranslation(Metadata) <span
title="TRANSLATE(Privacy Policy)" data-component="withI18nextTranslation(Metadata)"
data-props="{
\\"title\\": \\"TRANSLATE(Privacy Policy)\\"
}"
/> />
<withI18nextTranslation(PrivacyPolicy) /> <span
</Fragment> 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 React from 'react';
import { shallow } from 'enzyme'; import { render } from 'react-testing-library';
import { IndexPage } from 'pages/index'; import { IndexPage } from 'pages/index';
@ -18,19 +25,19 @@ const queryResult = {
describe('Index Page', () => { describe('Index Page', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<IndexPage location={{ hash: '' }} data={ queryResult } /> <IndexPage location={{ hash: '' }} data={ queryResult } />
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering with an expression on the URL', () => { test('rendering with an expression on the URL', () => {
const component = shallow( const { asFragment } = render(
<IndexPage location={{ <IndexPage location={{
hash: '#syntax=test&expr=testing', hash: '#syntax=test&expr=testing',
href: 'http://example.com' href: 'http://example.com'
}} data={ queryResult } /> }} 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 React from 'react';
import { shallow } from 'enzyme'; import { render } from 'react-testing-library';
import { mockT } from 'i18n'; import { mockT } from 'i18n';
import { PrivacyPage } from 'pages/privacy'; import { PrivacyPage } from 'pages/privacy';
describe('Privacy Page', () => { describe('Privacy Page', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<PrivacyPage t={ mockT } /> <PrivacyPage t={ mockT } />
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
}); });

View File

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

View File

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

View File

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

View File

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

View File

@ -24,38 +24,60 @@ Object {
`; `;
exports[`SVG rendering 1`] = ` exports[`SVG rendering 1`] = `
<svg <DocumentFragment>
height={20} <svg
style={ height="20"
Object { style="background-color: rgb(255, 255, 255);"
"backgroundColor": "#fff", viewBox="0 0 100 20"
} width="100"
} xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 20" xmlns:cc="http://creativecommons.org/ns#"
width={100} xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
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)"
> >
Content <metadata>
</g> <rdf:rdf>
</svg>
<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 React from 'react';
import { shallow } from 'enzyme'; import { render } from 'react-testing-library';
import SVG, { layout } from 'rendering/SVG'; import SVG, { layout } from 'rendering/SVG';
describe('SVG', () => { describe('SVG', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<SVG width={ 100 } height={ 20 }>Content</SVG> <SVG width={ 100 } height={ 20 }>Content</SVG>
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('layout', () => { test('layout', () => {

View File

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

View File

@ -1,35 +1,43 @@
import React from 'react'; import React from 'react';
import { shallow } from 'enzyme'; import { render } from 'react-testing-library';
import Text, { layout } from 'rendering/Text'; import Text, { layout } from 'rendering/Text';
describe('Text', () => { describe('Text', () => {
test('rendering', () => { test('rendering', () => {
const component = shallow( const { asFragment } = render(
<Text>Example</Text> <svg>
<Text>Example</Text>
</svg>
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('positioning text', () => { test('positioning text', () => {
const component = shallow( const { asFragment } = render(
<Text transform="translate(1 2)">Example</Text> <svg>
<Text transform="translate(1 2)">Example</Text>
</svg>
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering with a theme', () => { test('rendering with a theme', () => {
const component = shallow( const { asFragment } = render(
<Text theme="anchor">Example</Text> <svg>
<Text theme="anchor">Example</Text>
</svg>
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('rendering quoted text', () => { test('rendering quoted text', () => {
const component = shallow( const { asFragment } = render(
<Text quoted={ true }>Example</Text> <svg>
<Text quoted={ true }>Example</Text>
</svg>
); );
expect(component).toMatchSnapshot(); expect(asFragment()).toMatchSnapshot();
}); });
test('layout', () => { 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-self" "^7.0.0"
"@babel/plugin-transform-react-jsx-source" "^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" version "7.4.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.2.tgz#f5ab6897320f16decd855eed70b705908a313fe8" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.2.tgz#f5ab6897320f16decd855eed70b705908a313fe8"
integrity sha512-7Bl2rALb7HpvXFL7TETNzKSAeBVCPHELzc0C//9FCxN8nsiueWSJBqaF+2oIJScyILStASR/Cx5WMkXGYTiJFA== integrity sha512-7Bl2rALb7HpvXFL7TETNzKSAeBVCPHELzc0C//9FCxN8nsiueWSJBqaF+2oIJScyILStASR/Cx5WMkXGYTiJFA==
@ -1077,6 +1077,11 @@
"@sentry/types" "4.5.3" "@sentry/types" "4.5.3"
tslib "^1.9.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": "@sindresorhus/is@^0.7.0":
version "0.7.0" version "0.7.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" 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" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93"
integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= 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: array-filter@~0.0.0:
version "0.0.1" version "0.0.1"
resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" 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" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= 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: arraybuffer.slice@~0.0.7:
version "0.0.7" version "0.0.7"
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" 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" miller-rabin "^4.0.0"
randombytes "^2.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: dns-equal@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" 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" domelementtype "^1.3.0"
entities "^1.1.1" 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: dom-walk@^0.1.0:
version "0.1.1" version "0.1.1"
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" 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" resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-5.12.1.tgz#83068c33e0972eb657d6bc69a6df30badefb46ef"
integrity sha512-pwdo0/G3CIkQ0y6PCXq4RdkvId2elvtPCJMG0konqlrfkWQbf1DWeH9K2b/cvu2YgGvPPTOnonZxXM1gikFu1w== 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: eol@^0.8.1:
version "0.8.1" version "0.8.1"
resolved "https://registry.yarnpkg.com/eol/-/eol-0.8.1.tgz#defc3224990c7eca73bb34461a56cf9dc24761d0" resolved "https://registry.yarnpkg.com/eol/-/eol-0.8.1.tgz#defc3224990c7eca73bb34461a56cf9dc24761d0"
@ -4294,7 +4232,7 @@ error-stack-parser@^2.0.0:
dependencies: dependencies:
stackframe "^1.0.4" 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" version "1.13.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9"
integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==
@ -5341,20 +5279,11 @@ fsevents@^1.2.7:
nan "^2.9.2" nan "^2.9.2"
node-pre-gyp "^0.10.0" 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" version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 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: functional-red-black-tree@^1.0.1:
version "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" 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" resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7"
integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== 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: html-encoding-sniffer@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" 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: dependencies:
binary-extensions "^1.0.0" 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: is-buffer@^1.1.5, is-buffer@~1.1.1:
version "1.1.6" version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" 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: dependencies:
builtin-modules "^3.0.0" builtin-modules "^3.0.0"
is-callable@^1.1.3, is-callable@^1.1.4: is-callable@^1.1.4:
version "1.1.4" version "1.1.4"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== 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" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= 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: is-number@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" 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" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= 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: is-svg@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75"
@ -7963,11 +7865,6 @@ lodash._shimkeys@~2.4.1:
dependencies: dependencies:
lodash._objecttypes "~2.4.1" 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: lodash.every@^4.6.0:
version "4.6.0" version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.every/-/lodash.every-4.6.0.tgz#eb89984bebc4364279bb3aefbbd1ca19bfa6c6a7" 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" resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= 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: lodash.isinteger@^4.0.4:
version "4.0.4" version "4.0.4"
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" 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" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== 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: morgan@^1.8.2:
version "1.9.1" version "1.9.1"
resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.9.1.tgz#0a8d16734a1d9afbc824b99df87e738e58e2da59" 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" resolved "https://registry.yarnpkg.com/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246"
integrity sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY= 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: needle@^2.2.1:
version "2.2.4" version "2.2.4"
resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" 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" resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df"
integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== 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: object-keys@^1.0.11, object-keys@^1.0.12:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" 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" has-symbols "^1.0.0"
object-keys "^1.0.11" 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: object.fromentries@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.0.tgz#49a543d92151f8277b3ac9600f1e930b189d30ab" resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.0.tgz#49a543d92151f8277b3ac9600f1e930b189d30ab"
@ -9059,7 +8915,7 @@ object.pick@^1.3.0:
dependencies: dependencies:
isobject "^3.0.1" isobject "^3.0.1"
object.values@^1.0.4, object.values@^1.1.0: object.values@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9"
integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==
@ -10405,7 +10261,7 @@ prop-types@^15.5.10, prop-types@^15.5.4:
loose-envify "^1.3.1" loose-envify "^1.3.1"
object-assign "^4.1.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" version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== 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" resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== 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: randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" 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" "@babel/runtime" "^7.3.1"
html-parse-stringify2 "2.0.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" version "16.8.5"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.5.tgz#c54ac229dd66b5afe0de5acbe47647c3da692ff8" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.5.tgz#c54ac229dd66b5afe0de5acbe47647c3da692ff8"
integrity sha512-sudt2uq5P/2TznPV4Wtdi+Lnq3yaYW8LfvPKLM9BKD8jJNBkxMVyB0C9/GmVhLw7Jbdmndk/73n7XQGeN9A3QQ== integrity sha512-sudt2uq5P/2TznPV4Wtdi+Lnq3yaYW8LfvPKLM9BKD8jJNBkxMVyB0C9/GmVhLw7Jbdmndk/73n7XQGeN9A3QQ==
@ -10711,15 +10547,13 @@ react-side-effect@^1.1.0:
exenv "^1.2.1" exenv "^1.2.1"
shallowequal "^1.0.1" shallowequal "^1.0.1"
react-test-renderer@^16.0.0-0: react-testing-library@^6.0.2:
version "16.8.5" version "6.0.2"
resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.5.tgz#4cba7a8aad73f7e8a0bc4379a0fe21632886a563" resolved "https://registry.yarnpkg.com/react-testing-library/-/react-testing-library-6.0.2.tgz#afd7ddaa174e21cf672605e4e4f6f8156c4c9ef9"
integrity sha512-/pFpHYQH4f35OqOae/DgOCXJDxBqD3K3akVfDhLgR0qYHoHjnICI/XS9QDwIhbrOFHWL7okVW9kKMaHuKvt2ng== integrity sha512-hWJIixR/jxJBnemcWI5O2JCMXlwoIpgF1IEUF8EYNEADORSZ9fs8rEJu4ygqyC53l3QOowkNb8D+eF5kGT3srg==
dependencies: dependencies:
object-assign "^4.1.1" "@babel/runtime" "^7.3.1"
prop-types "^15.6.2" dom-testing-library "^3.13.1"
react-is "^16.8.5"
scheduler "^0.13.5"
react@^16.7.0: react@^16.7.0:
version "16.8.5" version "16.8.5"
@ -11254,14 +11088,6 @@ router@^1.3.1:
setprototypeof "1.1.0" setprototypeof "1.1.0"
utils-merge "1.0.1" 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: rsvp@^3.6.2:
version "3.6.2" version "3.6.2"
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" 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" is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.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: string_decoder@^1.0.0, string_decoder@^1.1.1:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" 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: dependencies:
browser-process-hrtime "^0.1.2" 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: walker@~1.0.5:
version "1.0.7" version "1.0.7"
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"