Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions client/i18n-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

import translations from '../translations/locales/en-US/translations.json';

i18n
.use(initReactI18next)
.init({
lng: 'en-US',
fallbackLng: 'en-US',

// have a common namespace used around the full app
ns: ['translations'],
defaultNS: 'translations',

debug: false,

interpolation: {
escapeValue: false, // not needed for react!!
},

resources: { 'en-US': { translations } },
});


export default i18n;
18 changes: 0 additions & 18 deletions client/jest.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,3 @@ import '@babel/polyfill';
// See: https://github.com/testing-library/jest-dom
// eslint-disable-next-line import/no-extraneous-dependencies
import '@testing-library/jest-dom';

import lodash from 'lodash';

// For testing, we use en-US and provide a mock implementation
// of t() that finds the correct translation
import translations from '../translations/locales/en-US/translations.json';

// This function name needs to be prefixed with "mock" so that Jest doesn't
// complain that it's out-of-scope in the mock below
const mockTranslate = key => lodash.get(translations, key);

jest.mock('react-i18next', () => ({
// this mock makes sure any components using the translate HoC receive the t function as a prop
withTranslation: () => (Component) => {
Component.defaultProps = { ...Component.defaultProps, t: mockTranslate };
return Component;
},
}));
7 changes: 5 additions & 2 deletions client/modules/IDE/components/FileNode.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ FileName.propTypes = {
name: PropTypes.string.isRequired
};

export class FileNode extends React.Component {
class FileNode extends React.Component {
constructor(props) {
super(props);

Expand Down Expand Up @@ -419,4 +419,7 @@ const TranslatedFileNode = withTranslation()(FileNode);

const ConnectedFileNode = connect(mapStateToProps, mapDispatchToProps)(TranslatedFileNode);

export default ConnectedFileNode;
export {
TranslatedFileNode as FileNode,
ConnectedFileNode as default
};
3 changes: 2 additions & 1 deletion client/modules/IDE/components/FileNode.test.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react';

import { fireEvent, render, screen, waitFor, within } from '../../../test-utils';
import { FileNode } from './FileNode';

describe('<FileNode />', () => {
Expand Down
18 changes: 9 additions & 9 deletions client/modules/IDE/components/Toolbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,23 @@ class Toolbar extends React.Component {
this.props.setTextOutput(true);
this.props.setGridOutput(true);
}}
aria-label="Play sketch"
aria-label={this.props.t('Toolbar.PlaySketchARIA')}
disabled={this.props.infiniteLoop}
>
<PlayIcon focusable="false" aria-hidden="true" />
</button>
<button
className={playButtonClass}
onClick={this.props.startSketch}
aria-label="Play only visual sketch"
aria-label={this.props.t('Toolbar.PlayOnlyVisualSketchARIA')}
disabled={this.props.infiniteLoop}
>
<PlayIcon focusable="false" aria-hidden="true" />
</button>
<button
className={stopButtonClass}
onClick={this.props.stopSketch}
aria-label="Stop sketch"
aria-label={this.props.t('Toolbar.StopSketchARIA')}
>
<StopIcon focusable="false" aria-hidden="true" />
</button>
Expand All @@ -129,7 +129,7 @@ class Toolbar extends React.Component {
}
}}
disabled={!canEditProjectName}
aria-label="Edit sketch name"
aria-label={this.props.t('Toolbar.EditSketchARIA')}
>
<span>{this.props.project.name}</span>
{
Expand All @@ -145,7 +145,7 @@ class Toolbar extends React.Component {
type="text"
maxLength="128"
className="toolbar__project-name-input"
aria-label="New sketch name"
aria-label={this.props.t('Toolbar.NewSketchNameARIA')}
value={this.state.projectNameInputValue}
onChange={this.handleProjectNameChange}
ref={(element) => { this.projectNameInput = element; }}
Expand All @@ -165,7 +165,7 @@ class Toolbar extends React.Component {
<button
className={preferencesButtonClass}
onClick={this.props.openPreferences}
aria-label="Open Preferences"
aria-label={this.props.t('Toolbar.OpenPreferencesARIA')}
>
<PreferencesIcon focusable="false" aria-hidden="true" />
</button>
Expand Down Expand Up @@ -200,6 +200,7 @@ Toolbar.propTypes = {
saveProject: PropTypes.func.isRequired,
currentUser: PropTypes.string,
t: PropTypes.func.isRequired

};

Toolbar.defaultProps = {
Expand All @@ -225,6 +226,5 @@ const mapDispatchToProps = {
...projectActions,
};

export const ToolbarComponent = Toolbar;
// export default connect(mapStateToProps, mapDispatchToProps)(Toolbar);
export default withTranslation()(connect(mapStateToProps, mapDispatchToProps)(Toolbar));
export const ToolbarComponent = withTranslation()(Toolbar);
export default connect(mapStateToProps, mapDispatchToProps)(ToolbarComponent);
3 changes: 1 addition & 2 deletions client/modules/IDE/components/Toolbar.test.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React from 'react';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import lodash from 'lodash';


import { fireEvent, render, screen, waitFor } from '../../../test-utils';
import { ToolbarComponent } from './Toolbar';

const renderComponent = (extraProps = {}) => {
Expand Down
40 changes: 40 additions & 0 deletions client/test-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* This file re-exports @testing-library but ensures that
* any calls to render have translations available.
*
* This means tested components will be able to call
* `t()` and have the translations of the default
* language
*
* See: https://react.i18next.com/misc/testing#testing-without-stubbing
*/

// eslint-disable-next-line import/no-extraneous-dependencies
import { render } from '@testing-library/react';
import React from 'react';
import PropTypes from 'prop-types';


import { I18nextProvider } from 'react-i18next';
import i18n from './i18n-test';

// re-export everything
// eslint-disable-next-line import/no-extraneous-dependencies
export * from '@testing-library/react';

const Providers = ({ children }) => (
// eslint-disable-next-line react/jsx-filename-extension
<I18nextProvider i18n={i18n}>
{children}
</I18nextProvider>
);

Providers.propTypes = {
children: PropTypes.element.isRequired,
};

const customRender = (ui, options) =>
render(ui, { wrapper: Providers, ...options });

// override render method
export { customRender as render };