diff --git a/app/views/LanguageView/index.test.tsx b/app/views/LanguageView/index.test.tsx new file mode 100644 index 00000000000..ccb5d9c1c91 --- /dev/null +++ b/app/views/LanguageView/index.test.tsx @@ -0,0 +1,91 @@ +import React from 'react'; +import { render, fireEvent, waitFor } from '@testing-library/react-native'; + +import LanguageView from './index'; +import * as i18n from '../../i18n'; + +jest.mock('@react-navigation/native', () => ({ + useNavigation: () => ({ setOptions: jest.fn(), navigate: jest.fn() }) +})); + +jest.mock('../../lib/hooks/useAppSelector', () => ({ + useAppSelector: () => ({ languageDefault: 'en', id: 'user-id' }) +})); + +jest.mock('react-redux', () => ({ + useDispatch: () => jest.fn() +})); + +jest.mock('../../actions/app', () => ({ + appStart: jest.fn() +})); + +jest.mock('../../actions/login', () => ({ + setUser: jest.fn() +})); + +jest.mock('react-native-restart', () => ({ + Restart: { Restart: jest.fn() } +})); + +jest.mock('react-native', () => { + const rn = jest.requireActual('react-native'); + rn.FlatList = ({ data, renderItem }: any) => ( + <> + {data.map((item: any, index: number) => ( + {renderItem({ item, index })} + ))} + + ); + return rn; +}); + +jest.mock('../../lib/services/restApi', () => ({ + saveUserPreferences: jest.fn(() => Promise.resolve()) +})); + +jest.mock('../../lib/database', () => ({ + default: { + servers: { + write: jest.fn((fn: any) => fn()), + get: jest.fn(() => ({ + find: jest.fn(() => Promise.resolve({ update: jest.fn() })) + })) + } + } +})); + +jest.mock('../../i18n', () => { + const setLanguage = jest.fn(); + const i18nMock = { + t: (key: string) => key, + locale: 'en', + translations: { en: {} } + }; + return { + __esModule: true, + default: i18nMock, + setLanguage, + isRTL: jest.fn(() => false), + LANGUAGES: [ + { label: 'English', value: 'en', file: () => ({}) }, + { label: 'EspaƱol', value: 'es', file: () => ({}) } + ] + }; +}); + +describe('LanguageView language change', () => { + it('applies the selected language at runtime via setLanguage', async () => { + const { findByTestId } = render(); + + const spanishOption = await findByTestId('language-view-es', {}, { timeout: 5000 }); + fireEvent(spanishOption, 'onPress'); + + await waitFor( + () => { + expect((i18n as any).setLanguage).toHaveBeenCalledWith('es'); + }, + { timeout: 5000 } + ); + }); +}); diff --git a/app/views/LanguageView/index.tsx b/app/views/LanguageView/index.tsx index 8aec1f66cb4..850e53f6ff0 100644 --- a/app/views/LanguageView/index.tsx +++ b/app/views/LanguageView/index.tsx @@ -12,7 +12,7 @@ import { setUser } from '../../actions/login'; import * as List from '../../containers/List'; import SafeAreaView from '../../containers/SafeAreaView'; import { RootEnum } from '../../definitions'; -import I18n, { isRTL, LANGUAGES } from '../../i18n'; +import I18n, { isRTL, LANGUAGES, setLanguage } from '../../i18n'; import database from '../../lib/database'; import { getUserSelector } from '../../selectors/login'; import { type SettingsStackParamList } from '../../stacks/types'; @@ -46,7 +46,11 @@ const LanguageView = () => { dispatch(appStart({ root: RootEnum.ROOT_LOADING, text: I18n.t('Change_language_loading') })); // shows loading for at least 300ms - await Promise.all([changeLanguage(language), new Promise(resolve => setTimeout(resolve, 300))]); + const [changed] = await Promise.all([changeLanguage(language), new Promise(resolve => setTimeout(resolve, 300))]); + + if (changed) { + setLanguage(language); + } if (shouldRestart) { await RNRestart.Restart(); @@ -55,7 +59,7 @@ const LanguageView = () => { } }; - const changeLanguage = async (language: string) => { + const changeLanguage = async (language: string): Promise => { logEvent(events.LANG_SET_LANGUAGE); const params: { language?: string } = {}; @@ -72,19 +76,18 @@ const LanguageView = () => { const serversDB = database.servers; const usersCollection = serversDB.get('users'); await serversDB.write(async () => { - try { - const userRecord = await usersCollection.find(id); - await userRecord.update(record => { - record.language = params.language; - }); - } catch (e) { - logEvent(events.LANG_SET_LANGUAGE_F); - } + const userRecord = await usersCollection.find(id); + await userRecord.update(record => { + record.language = params.language; + }); }); + + return true; } catch (e) { logEvent(events.LANG_SET_LANGUAGE_F); showErrorAlert(I18n.t('There_was_an_error_while_action', { action: I18n.t('saving_preferences') })); log(e); + return false; } };