user-settings: update to use new translation APIs

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-09-14 21:12:29 +02:00
parent 28dc3e56c3
commit 41b10267d7
5 changed files with 61 additions and 111 deletions
@@ -16,111 +16,66 @@
import React from 'react';
import { screen, fireEvent } from '@testing-library/react';
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
import { UserSettingsLanguageToggle } from './UserSettingsLanguageToggle';
import { renderInTestApp } from '@backstage/test-utils';
import { useTranslation } from 'react-i18next';
jest.mock('@backstage/core-plugin-api/alpha', () => ({
...jest.requireActual('@backstage/core-plugin-api/alpha'),
useTranslationRef: jest.fn(),
}));
jest.mock('react-i18next', () => ({
...jest.requireActual('react-i18next'),
useTranslation: jest.fn(),
}));
import { TestApiProvider, renderInTestApp } from '@backstage/test-utils';
import { appLanguageApiRef } from '@backstage/core-plugin-api/alpha';
describe('UserSettingsLanguageToggle', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('should render correctly with multiple supported languages', async () => {
const messages: Record<string, string> = {
en: 'English',
fr: 'French',
de: 'German',
language: 'language',
change_the_language: 'Change the language',
};
it('should not render with only one available language', async () => {
const rendered = await renderInTestApp(<UserSettingsLanguageToggle />);
const i18nMock = {
language: 'en',
options: {
supportedLngs: ['en', 'fr', 'de'],
},
changeLanguage: jest.fn(),
};
(useTranslation as jest.Mock).mockReturnValue({
i18n: i18nMock,
});
(useTranslationRef as jest.Mock).mockReturnValue(
(key: string, option: any) =>
messages[option?.language || key] || 'translatedValue',
);
await renderInTestApp(<UserSettingsLanguageToggle />);
expect(screen.getAllByText('Change the language')).toHaveLength(1);
expect(screen.getAllByText('English')).toHaveLength(1);
expect(screen.getAllByText('French')).toHaveLength(1);
expect(screen.getAllByText('German')).toHaveLength(1);
expect(rendered.container).toBeEmptyDOMElement();
});
it('should not render when only one supported language', async () => {
const tMock = jest.fn().mockReturnValue('translatedValue');
const i18nMock = {
language: 'en',
options: {
supportedLngs: ['en'],
},
changeLanguage: jest.fn(),
it('should render correctly with multiple available languages', async () => {
const mockLanguageApi: typeof appLanguageApiRef.T = {
getAvailableLanguages: jest
.fn()
.mockReturnValue({ languages: ['en', 'de'] }),
getLanguage: jest.fn().mockReturnValue({ language: 'en' }),
language$: jest.fn().mockReturnValue({
subscribe: jest.fn().mockReturnValue({ unsubscribe: jest.fn() }),
}),
setLanguage: jest.fn(),
};
(useTranslationRef as jest.Mock).mockReturnValue(tMock);
await renderInTestApp(
<TestApiProvider apis={[[appLanguageApiRef, mockLanguageApi]]}>
<UserSettingsLanguageToggle />
</TestApiProvider>,
);
(useTranslation as jest.Mock).mockReturnValue({
i18n: i18nMock,
});
await renderInTestApp(<UserSettingsLanguageToggle />);
expect(screen.queryByText('translatedValue')).toBeNull();
expect(screen.queryByText('English')).toBeNull();
expect(screen.getByText('Change the language')).toBeInTheDocument();
});
it('should handle language change', async () => {
const messages: Record<string, string> = {
en: 'English',
fr: 'French',
language: 'language',
change_the_language: 'Change the language',
const mockLanguageApi: typeof appLanguageApiRef.T = {
getAvailableLanguages: jest
.fn()
.mockReturnValue({ languages: ['en', 'de'] }),
getLanguage: jest.fn().mockReturnValue({ language: 'en' }),
language$: jest.fn().mockReturnValue({
subscribe: jest.fn().mockReturnValue({ unsubscribe: jest.fn() }),
}),
setLanguage: jest.fn(),
};
const i18nMock = {
language: 'en',
options: {
supportedLngs: ['en', 'fr'],
},
changeLanguage: jest.fn(),
};
(useTranslationRef as jest.Mock).mockReturnValue(
(key: string, option: any) =>
messages[option?.language || key] || 'translatedValue',
await renderInTestApp(
<TestApiProvider apis={[[appLanguageApiRef, mockLanguageApi]]}>
<UserSettingsLanguageToggle />
</TestApiProvider>,
);
(useTranslation as jest.Mock).mockReturnValue({
i18n: i18nMock,
});
expect(screen.getByText('Change the language')).toBeInTheDocument();
await renderInTestApp(<UserSettingsLanguageToggle />);
fireEvent.click(screen.getByText('French'));
fireEvent.click(screen.getByText('de'));
expect(i18nMock.changeLanguage).toHaveBeenCalledWith('fr');
expect(mockLanguageApi.setLanguage).toHaveBeenCalledWith('de');
});
});
@@ -14,8 +14,11 @@
* limitations under the License.
*/
import React, { useMemo } from 'react';
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
import React, { useState } from 'react';
import {
useTranslationRef,
appLanguageApiRef,
} from '@backstage/core-plugin-api/alpha';
import ToggleButton from '@material-ui/lab/ToggleButton';
import ToggleButtonGroup from '@material-ui/lab/ToggleButtonGroup';
import {
@@ -26,7 +29,8 @@ import {
makeStyles,
} from '@material-ui/core';
import { userSettingsTranslationRef } from '../../translation';
import { useTranslation } from 'react-i18next';
import { useApi } from '@backstage/core-plugin-api';
import useObservable from 'react-use/lib/useObservable';
type TooltipToggleButtonProps = {
children: JSX.Element;
@@ -85,15 +89,18 @@ const TooltipToggleButton = ({
/** @public */
export const UserSettingsLanguageToggle = () => {
const classes = useStyles();
const { i18n } = useTranslation();
const t = useTranslationRef(userSettingsTranslationRef);
const languageApi = useApi(appLanguageApiRef);
const { t } = useTranslationRef(userSettingsTranslationRef);
const supportedLngs = useMemo(
() => (i18n.options.supportedLngs || []).filter(lng => lng !== 'cimode'),
[i18n],
const [languageObservable] = useState(() => languageApi.language$());
const { language: currentLanguage } = useObservable(
languageObservable,
languageApi.getLanguage(),
);
if (supportedLngs.length <= 1) {
const { languages } = languageApi.getAvailableLanguages();
if (languages.length <= 1) {
return null;
}
@@ -101,11 +108,7 @@ export const UserSettingsLanguageToggle = () => {
_event: React.MouseEvent<HTMLElement>,
newLanguage: string | undefined,
) => {
if (supportedLngs.some(it => it === newLanguage)) {
i18n.changeLanguage(newLanguage);
} else {
i18n.changeLanguage(undefined);
}
languageApi.setLanguage(newLanguage);
};
return (
@@ -122,23 +125,17 @@ export const UserSettingsLanguageToggle = () => {
<ToggleButtonGroup
exclusive
size="small"
value={i18n.language}
value={currentLanguage}
onChange={handleSetLanguage}
>
{supportedLngs.map(lng => {
{languages.map(language => {
return (
<TooltipToggleButton
key={lng}
title={t('select_lng', {
language: lng,
})}
value={lng}
key={language}
title={t('select_lng', { language })}
value={language}
>
<>
{t('lng', {
language: lng,
})}
</>
<>{t('lng', { language })}</>
</TooltipToggleButton>
);
})}
@@ -110,7 +110,7 @@ export const UserSettingsThemeToggle = () => {
const themeIds = appThemeApi.getInstalledThemes();
const t = useTranslationRef(userSettingsTranslationRef);
const { t } = useTranslationRef(userSettingsTranslationRef);
const handleSetTheme = (
_event: React.MouseEvent<HTMLElement>,