Skip to content

Commit 54d4fe0

Browse files
committed
Merge remote-tracking branch 'remotes/upstream/develop' into copyable_prevNav
# Conflicts: # translations/locales/es-419/translations.json
2 parents 46b17db + af1a5cc commit 54d4fe0

File tree

10 files changed

+88
-37
lines changed

10 files changed

+88
-37
lines changed

client/i18n-test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import i18n from 'i18next';
2+
import { initReactI18next } from 'react-i18next';
3+
4+
import translations from '../translations/locales/en-US/translations.json';
5+
6+
i18n
7+
.use(initReactI18next)
8+
.init({
9+
lng: 'en-US',
10+
fallbackLng: 'en-US',
11+
12+
// have a common namespace used around the full app
13+
ns: ['translations'],
14+
defaultNS: 'translations',
15+
16+
debug: false,
17+
18+
interpolation: {
19+
escapeValue: false, // not needed for react!!
20+
},
21+
22+
resources: { 'en-US': { translations } },
23+
});
24+
25+
26+
export default i18n;

client/jest.setup.js

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,3 @@ import '@babel/polyfill';
33
// See: https://github.com/testing-library/jest-dom
44
// eslint-disable-next-line import/no-extraneous-dependencies
55
import '@testing-library/jest-dom';
6-
7-
import lodash from 'lodash';
8-
9-
// For testing, we use en-US and provide a mock implementation
10-
// of t() that finds the correct translation
11-
import translations from '../translations/locales/en-US/translations.json';
12-
13-
// This function name needs to be prefixed with "mock" so that Jest doesn't
14-
// complain that it's out-of-scope in the mock below
15-
const mockTranslate = key => lodash.get(translations, key);
16-
17-
jest.mock('react-i18next', () => ({
18-
// this mock makes sure any components using the translate HoC receive the t function as a prop
19-
withTranslation: () => (Component) => {
20-
Component.defaultProps = { ...Component.defaultProps, t: mockTranslate };
21-
return Component;
22-
},
23-
}));

client/modules/IDE/components/FileNode.jsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ FileName.propTypes = {
6767
name: PropTypes.string.isRequired
6868
};
6969

70-
export class FileNode extends React.Component {
70+
class FileNode extends React.Component {
7171
constructor(props) {
7272
super(props);
7373

@@ -419,4 +419,7 @@ const TranslatedFileNode = withTranslation()(FileNode);
419419

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

422-
export default ConnectedFileNode;
422+
export {
423+
TranslatedFileNode as FileNode,
424+
ConnectedFileNode as default
425+
};

client/modules/IDE/components/FileNode.test.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
2-
import { fireEvent, render, screen, waitFor, within } from '@testing-library/react';
2+
3+
import { fireEvent, render, screen, waitFor, within } from '../../../test-utils';
34
import { FileNode } from './FileNode';
45

56
describe('<FileNode />', () => {

client/modules/IDE/components/QuickAddList/QuickAddList.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Icons from './Icons';
88
const Item = ({
99
isAdded, onSelect, name, url, t
1010
}) => {
11-
const buttonLabel = isAdded ? 'Remove from collection' : 'Add to collection';
11+
const buttonLabel = isAdded ? t('QuickAddList.ButtonRemoveARIA') : t('QuickAddList.ButtonAddToCollectionARIA');
1212
return (
1313
<li className="quick-add__item" onClick={onSelect}> { /* eslint-disable-line */ }
1414
<button className="quick-add__item-toggle" onClick={onSelect} aria-label={buttonLabel}>

client/modules/IDE/components/Toolbar.jsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,23 +86,23 @@ class Toolbar extends React.Component {
8686
this.props.setTextOutput(true);
8787
this.props.setGridOutput(true);
8888
}}
89-
aria-label="Play sketch"
89+
aria-label={this.props.t('Toolbar.PlaySketchARIA')}
9090
disabled={this.props.infiniteLoop}
9191
>
9292
<PlayIcon focusable="false" aria-hidden="true" />
9393
</button>
9494
<button
9595
className={playButtonClass}
9696
onClick={this.props.startSketch}
97-
aria-label="Play only visual sketch"
97+
aria-label={this.props.t('Toolbar.PlayOnlyVisualSketchARIA')}
9898
disabled={this.props.infiniteLoop}
9999
>
100100
<PlayIcon focusable="false" aria-hidden="true" />
101101
</button>
102102
<button
103103
className={stopButtonClass}
104104
onClick={this.props.stopSketch}
105-
aria-label="Stop sketch"
105+
aria-label={this.props.t('Toolbar.StopSketchARIA')}
106106
>
107107
<StopIcon focusable="false" aria-hidden="true" />
108108
</button>
@@ -129,7 +129,7 @@ class Toolbar extends React.Component {
129129
}
130130
}}
131131
disabled={!canEditProjectName}
132-
aria-label="Edit sketch name"
132+
aria-label={this.props.t('Toolbar.EditSketchARIA')}
133133
>
134134
<span>{this.props.project.name}</span>
135135
{
@@ -145,7 +145,7 @@ class Toolbar extends React.Component {
145145
type="text"
146146
maxLength="128"
147147
className="toolbar__project-name-input"
148-
aria-label="New sketch name"
148+
aria-label={this.props.t('Toolbar.NewSketchNameARIA')}
149149
value={this.state.projectNameInputValue}
150150
onChange={this.handleProjectNameChange}
151151
ref={(element) => { this.projectNameInput = element; }}
@@ -165,7 +165,7 @@ class Toolbar extends React.Component {
165165
<button
166166
className={preferencesButtonClass}
167167
onClick={this.props.openPreferences}
168-
aria-label="Open Preferences"
168+
aria-label={this.props.t('Toolbar.OpenPreferencesARIA')}
169169
>
170170
<PreferencesIcon focusable="false" aria-hidden="true" />
171171
</button>
@@ -200,6 +200,7 @@ Toolbar.propTypes = {
200200
saveProject: PropTypes.func.isRequired,
201201
currentUser: PropTypes.string,
202202
t: PropTypes.func.isRequired
203+
203204
};
204205

205206
Toolbar.defaultProps = {
@@ -225,6 +226,5 @@ const mapDispatchToProps = {
225226
...projectActions,
226227
};
227228

228-
export const ToolbarComponent = Toolbar;
229-
// export default connect(mapStateToProps, mapDispatchToProps)(Toolbar);
230-
export default withTranslation()(connect(mapStateToProps, mapDispatchToProps)(Toolbar));
229+
export const ToolbarComponent = withTranslation()(Toolbar);
230+
export default connect(mapStateToProps, mapDispatchToProps)(ToolbarComponent);

client/modules/IDE/components/Toolbar.test.jsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import React from 'react';
2-
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
32
import lodash from 'lodash';
43

5-
4+
import { fireEvent, render, screen, waitFor } from '../../../test-utils';
65
import { ToolbarComponent } from './Toolbar';
76

87
const renderComponent = (extraProps = {}) => {

client/test-utils.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* This file re-exports @testing-library but ensures that
3+
* any calls to render have translations available.
4+
*
5+
* This means tested components will be able to call
6+
* `t()` and have the translations of the default
7+
* language
8+
*
9+
* See: https://react.i18next.com/misc/testing#testing-without-stubbing
10+
*/
11+
12+
// eslint-disable-next-line import/no-extraneous-dependencies
13+
import { render } from '@testing-library/react';
14+
import React from 'react';
15+
import PropTypes from 'prop-types';
16+
17+
18+
import { I18nextProvider } from 'react-i18next';
19+
import i18n from './i18n-test';
20+
21+
// re-export everything
22+
// eslint-disable-next-line import/no-extraneous-dependencies
23+
export * from '@testing-library/react';
24+
25+
const Providers = ({ children }) => (
26+
// eslint-disable-next-line react/jsx-filename-extension
27+
<I18nextProvider i18n={i18n}>
28+
{children}
29+
</I18nextProvider>
30+
);
31+
32+
Providers.propTypes = {
33+
children: PropTypes.element.isRequired,
34+
};
35+
36+
const customRender = (ui, options) =>
37+
render(ui, { wrapper: Providers, ...options });
38+
39+
// override render method
40+
export { customRender as render };

translations/locales/en-US/translations.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,8 @@
468468
"AriaLabel": "Close {{title}} overlay"
469469
},
470470
"QuickAddList":{
471-
"ButtonLabelRemove": "Remove from collection",
472-
"ButtonLabelAddToCollection": "Add to collection",
471+
"ButtonRemoveARIA": "Remove from collection",
472+
"ButtonAddToCollectionARIA": "Add to collection",
473473
"View": "View"
474474
},
475475
"SketchList": {

translations/locales/es-419/translations.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,8 +468,8 @@
468468
"AriaLabel": "Cerrar la capa {{title}}"
469469
},
470470
"QuickAddList":{
471-
"ButtonLabelRemove": "Remover de colección",
472-
"ButtonLabelAddToCollection": "Agregar a colección",
471+
"ButtonRemoveARIA": "Remover de colección",
472+
"ButtonAddToCollectionARIA": "Agregar a colección",
473473
"View": "Ver"
474474
},
475475
"SketchList": {

0 commit comments

Comments
 (0)