diff --git a/__tests__/src/components/LanguageSettings.test.js b/__tests__/src/components/LanguageSettings.test.js index e38cbb8cdbdadd2c4f0b3a0b99fd6ea93f32a11a..8ae798ec89479cf348e61fa0a293d09b6ff7cd20 100644 --- a/__tests__/src/components/LanguageSettings.test.js +++ b/__tests__/src/components/LanguageSettings.test.js @@ -8,7 +8,6 @@ import LanguageSettings from '../../../src/components/LanguageSettings'; function createWrapper(props) { return shallow( <LanguageSettings - active={lang => lang === 'de'} handleClick={() => {}} languages={{}} {...props} @@ -18,10 +17,10 @@ function createWrapper(props) { describe('LanguageSettings', () => { let wrapper; - const languages = { - de: 'Deutsch', - en: 'English', - }; + const languages = [ + { locale: 'de', label: 'Deutsch', current: true }, + { locale: 'en', label: 'English', current: false }, + ]; it('renders a list with a list item for each language passed in props', () => { @@ -82,11 +81,4 @@ describe('LanguageSettings', () => { expect(mockHandleClick).toHaveBeenCalledTimes(1); expect(mockHandleClick).toHaveBeenCalledWith('en'); }); - - it('passes the language prop to the active prop function to determine if the given language is active', () => { - const mockActiveFn = jest.fn(); - wrapper = createWrapper({ active: mockActiveFn, languages: { en: 'English' } }); - - expect(mockActiveFn).toHaveBeenCalledWith('en'); - }); }); diff --git a/__tests__/src/selectors/index.test.js b/__tests__/src/selectors/index.test.js index f3f04a75fe416ca6898e2b79dcceae4866b885fd..34e3abb4d77ae7a4bad28a1720936133bdf33b61 100644 --- a/__tests__/src/selectors/index.test.js +++ b/__tests__/src/selectors/index.test.js @@ -7,6 +7,7 @@ import { getCanvasLabel, getCompanionWindowForPosition, getDestructuredMetadata, + getLanguagesFromConfigWithCurrent, getSelectedCanvas, getWindowManifest, getManifestLogo, @@ -347,3 +348,18 @@ describe('getCompanionWindowForPosition', () => { expect(received).toBeUndefined(); }); }); + +describe('getLanguagesFromConfigWithCurrent', () => { + it('returns an array of objects with locale, label, and current properties', () => { + const state = { + config: { language: 'epo', availableLanguages: { epo: 'Esparanto', tlh: 'Klingon' } }, + }; + + const expected = [ + { locale: 'epo', label: 'Esparanto', current: true }, + { locale: 'tlh', label: 'Klingon', current: false }, + ]; + + expect(getLanguagesFromConfigWithCurrent(state)).toEqual(expected); + }); +}); diff --git a/src/components/LanguageSettings.js b/src/components/LanguageSettings.js index bdfbe1348b2bfaba22ab7103d215e1266481bc97..ebe77d427f6a8803fec3b5e66a52635d4c034560 100644 --- a/src/components/LanguageSettings.js +++ b/src/components/LanguageSettings.js @@ -17,25 +17,25 @@ export default class LanguageSettings extends Component { */ render() { const { - handleClick, languages, active, + handleClick, languages, } = this.props; return ( <List> { - Object.keys(languages).map(language => ( + languages.map(language => ( <MenuItem - button={!(active(language))} - key={language} - onClick={() => { handleClick(language); }} + button={!language.current} + key={language.locale} + onClick={() => { handleClick(language.locale); }} > { - active(language) + language.current && <ListItemIcon><CheckIcon /></ListItemIcon> } <ListItemText inset> <Typography variant="inherit"> - {languages[language]} + {language.label} </Typography> </ListItemText> </MenuItem> @@ -47,7 +47,12 @@ export default class LanguageSettings extends Component { } LanguageSettings.propTypes = { - active: PropTypes.func.isRequired, handleClick: PropTypes.func.isRequired, - languages: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types + languages: PropTypes.arrayOf( + PropTypes.shape({ + current: PropTypes.bool.isRequired, + label: PropTypes.string.isRequired, + locale: PropTypes.string.isRequired, + }), + ).isRequired, }; diff --git a/src/containers/LanguageSettings.js b/src/containers/LanguageSettings.js index b3d543858b0ba6024c8e4336326e15abc797ae18..ffd9c2147e607ed7aa7cc45a69a43ac734d4ea7d 100644 --- a/src/containers/LanguageSettings.js +++ b/src/containers/LanguageSettings.js @@ -1,14 +1,13 @@ import { connect } from 'react-redux'; import * as actions from '../state/actions'; +import { getLanguagesFromConfigWithCurrent } from '../state/selectors'; import LanguageSettings from '../components/LanguageSettings'; /** * Map state to props for connect */ const mapStateToProps = state => ({ - languages: state.config.availableLanguages, - currentLanguage: state.config.language, - active: language => language === state.config.language, + languages: getLanguagesFromConfigWithCurrent(state), }); /** diff --git a/src/state/selectors/index.js b/src/state/selectors/index.js index e7b4565c634581f94ddc3ff0caf2e9f251c2dacd..adcaee87f3dff77bac6c604cbc24f7c4896c58d7 100644 --- a/src/state/selectors/index.js +++ b/src/state/selectors/index.js @@ -201,3 +201,18 @@ export function getCompanionWindowForPosition(state, windowId, position) { export function getCompantionWindowIds(state, windowId) { return state.windows[windowId].companionWindowIds; } + +/** +* Return languages from config (in state) and indicate which is currently set +* @param {object} state +* @return {Array} [ {locale: 'de', label: 'Deutsch', current: true}, ... ] +*/ +export function getLanguagesFromConfigWithCurrent(state) { + const { availableLanguages, language } = state.config; + + return Object.keys(availableLanguages).map(key => ({ + locale: key, + label: availableLanguages[key], + current: key === language, + })); +}