Skip to content

Commit

Permalink
refactor: separate the test for lang seector
Browse files Browse the repository at this point in the history
  • Loading branch information
dcoa committed Jan 13, 2025
1 parent 4880068 commit 0ae49f6
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 48 deletions.
47 changes: 2 additions & 45 deletions src/components/Footer.test.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
/* eslint-disable react/prop-types */
import React, { useMemo } from 'react';
import renderer from 'react-test-renderer';
import { fireEvent, render, waitFor } from '@testing-library/react';
import { initializeMockApp } from '@edx/frontend-platform/testing';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { getCookies } from '@edx/frontend-platform/i18n/lib';
import { AppContext } from '@edx/frontend-platform/react';
import '@testing-library/jest-dom';
import { initializeMockApp } from '@edx/frontend-platform/testing';

import Footer from './Footer';
import { patchPreferences, postSetLang } from './LanguageSelector/data';

jest.mock('./LanguageSelector/data', () => ({
patchPreferences: jest.fn(),
postSetLang: jest.fn(),
}));

const FooterWithContext = ({ locale = 'es' }) => {
const contextValue = useMemo(() => ({
Expand Down Expand Up @@ -61,11 +52,6 @@ const FooterWithLanguageSelector = ({ authenticatedUser = null }) => {
};

describe('<Footer />', () => {
beforeEach(() => {
jest.clearAllMocks();
initializeMockApp();
});

describe('renders correctly', () => {
it('renders without a language selector', () => {
const tree = renderer
Expand All @@ -80,40 +66,11 @@ describe('<Footer />', () => {
expect(tree).toMatchSnapshot();
});
it('renders with a language selector', () => {
initializeMockApp();
const tree = renderer
.create(<FooterWithLanguageSelector />)
.toJSON();
expect(tree).toMatchSnapshot();
});
});

describe('handles language switching', () => {
it('calls publish with LOCALE_CHANGED when the language changed', () => {
const setSpy = jest.spyOn(getCookies(), 'set');
const component = render(<FooterWithLanguageSelector />);

expect(component.queryByRole('button')).toBeInTheDocument();

const langDropdown = component.queryByRole('button');
fireEvent.click(langDropdown);
fireEvent.click(component.queryByText('Español'));

expect(setSpy).toHaveBeenCalledWith(LANGUAGE_PREFERENCE_COOKIE_NAME, 'es');
});
it('update the lang preference for an autheticathed user', async () => {
const userData = { username: 'test-user' };
const component = render(<FooterWithLanguageSelector authenticatedUser={userData} />);

expect(component.queryByRole('button')).toBeInTheDocument();

const langDropdown = component.queryByRole('button');
fireEvent.click(langDropdown);
fireEvent.click(component.queryByText('Español'));

await waitFor(() => {
expect(patchPreferences).toHaveBeenCalledWith(userData.username, { prefLang: 'es' });
expect(postSetLang).toHaveBeenCalledWith('es');
});
});
});
});
2 changes: 0 additions & 2 deletions src/components/LanguageSelector/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ export async function patchPreferences(username, params) {
.patch(`${getConfig().LMS_BASE_URL}/api/user/v1/preferences/${username}`, processedParams, {
headers: { 'Content-Type': 'application/merge-patch+json' },
});

return params;
}

export async function postSetLang(code) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/LanguageSelector/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const LanguageSelector = ({

const currentLocaleLabel = useMemo(() => {
if (width < 576) {
return null;
return '';
}
if (width < 768) {
return getPrimaryLanguageSubtag(currentLocale).toUpperCase();
Expand Down
141 changes: 141 additions & 0 deletions src/components/LanguageSelector/index.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/* eslint-disable react/prop-types */
import React, { useMemo } from 'react';
import {
act, fireEvent, render, waitFor,
} from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { getCookies } from '@edx/frontend-platform/i18n/lib';
import { AppContext } from '@edx/frontend-platform/react';
import { initializeMockApp } from '@edx/frontend-platform/testing';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';

import '@testing-library/jest-dom';

import LanguageSelector from '.';

jest.mock('@edx/frontend-platform/auth', () => ({
...jest.requireActual('@edx/frontend-platform/auth'),
getAuthenticatedHttpClient: jest.fn(),
}));

jest.mock('@openedx/paragon/icons', () => ({
Language: () => <div>LanguageIcon</div>,
}));

const { LANGUAGE_PREFERENCE_COOKIE_NAME } = process.env;

const LanguageSelectorContext = ({ authenticatedUser = null }) => {
const contextValue = useMemo(() => ({
authenticatedUser,
config: {
LANGUAGE_PREFERENCE_COOKIE_NAME,
LOGO_TRADEMARK_URL: process.env.LOGO_TRADEMARK_URL,
LMS_BASE_URL: process.env.LMS_BASE_URL,
SITE_SUPPORTED_LANGUAGES: ['es', 'en'],
},
}), [authenticatedUser]);

return (
<IntlProvider locale="en">
<AppContext.Provider
value={contextValue}
>
<LanguageSelector
options={['es', 'en']}
username={authenticatedUser?.username}
langCookieName={LANGUAGE_PREFERENCE_COOKIE_NAME}
/>
</AppContext.Provider>
</IntlProvider>
);
};

describe('LanguageSelector', () => {
let initService;

beforeEach(() => {
jest.clearAllMocks();
initService = initializeMockApp();
});

it('change the language for a non authenticated user', () => {
const setSpy = jest.spyOn(getCookies(), 'set');
const component = render(<LanguageSelectorContext />);

expect(component.queryByRole('button')).toBeInTheDocument();

const langDropdown = component.queryByRole('button');
fireEvent.click(langDropdown);
fireEvent.click(component.queryByText('Español'));

expect(setSpy).toHaveBeenCalledWith(LANGUAGE_PREFERENCE_COOKIE_NAME, 'es');
});

it('update the lang preference for an autheticathed user', async () => {
const userData = { username: 'test-user' };
const processedParams = {
'pref-lang': 'es',
};
getAuthenticatedHttpClient.mockReturnValue({
patch: jest.fn(),
post: jest.fn(),
});
const formData = new FormData();
formData.append('language', 'es');

const component = render(<LanguageSelectorContext authenticatedUser={userData} />);

expect(component.queryByRole('button')).toBeInTheDocument();

const langDropdown = component.queryByRole('button');
fireEvent.click(langDropdown);
fireEvent.click(component.queryByText('Español'));

await waitFor(() => {
expect(getAuthenticatedHttpClient().patch)
.toHaveBeenCalledWith(`${process.env.LMS_BASE_URL}/api/user/v1/preferences/${userData.username}`, processedParams, {
headers: { 'Content-Type': 'application/merge-patch+json' },
});
expect(getAuthenticatedHttpClient().post)
.toHaveBeenCalledWith(
`${process.env.LMS_BASE_URL}/i18n/setlang/`,
formData,
{ headers: { Accept: 'application/json', 'X-Requested-With': 'XMLHttpRequest' } },
);
});
});

it('call logError if it can not update the user preference', async () => {
const { loggingService } = initService;
const userData = { username: 'test-user' };
const component = render(<LanguageSelectorContext authenticatedUser={userData} />);
getAuthenticatedHttpClient.mockReturnValue({
patch: jest.fn().mockRejectedValue(new Error('Error')),
});
expect(component.queryByRole('button')).toBeInTheDocument();

const langDropdown = component.queryByRole('button');
fireEvent.click(langDropdown);
fireEvent.click(component.queryByText('Español'));

await waitFor(() => {
expect(loggingService.logError).toHaveBeenCalled();
});
});

it('should disp,ay the language icon and modify the label according to the screen size', () => {
const component = render(<LanguageSelectorContext />);
expect(component.queryByRole('button').textContent).toBe('LanguageIconEnglish');

act(() => {
global.innerWidth = 700;
global.dispatchEvent(new Event('resize'));
});
expect(component.queryByRole('button').textContent).toBe('LanguageIconEN');
act(() => {
global.innerWidth = 500;
global.dispatchEvent(new Event('resize'));
});
expect(component.queryByRole('button').textContent).toBe('LanguageIcon');
});
});

0 comments on commit 0ae49f6

Please sign in to comment.