Skip to content

Commit 7ec5478

Browse files
committed
refactor: separate the test for lang seector
1 parent 1dd8994 commit 7ec5478

File tree

4 files changed

+144
-48
lines changed

4 files changed

+144
-48
lines changed

src/components/Footer.test.jsx

+2-45
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,11 @@
11
/* eslint-disable react/prop-types */
22
import React, { useMemo } from 'react';
33
import renderer from 'react-test-renderer';
4-
import { fireEvent, render, waitFor } from '@testing-library/react';
5-
import { initializeMockApp } from '@edx/frontend-platform/testing';
64
import { IntlProvider } from '@edx/frontend-platform/i18n';
7-
import { getCookies } from '@edx/frontend-platform/i18n/lib';
85
import { AppContext } from '@edx/frontend-platform/react';
9-
import '@testing-library/jest-dom';
6+
import { initializeMockApp } from '@edx/frontend-platform/testing';
107

118
import Footer from './Footer';
12-
import { patchPreferences, postSetLang } from './LanguageSelector/data';
13-
14-
jest.mock('./LanguageSelector/data', () => ({
15-
patchPreferences: jest.fn(),
16-
postSetLang: jest.fn(),
17-
}));
189

1910
const FooterWithContext = ({ locale = 'es' }) => {
2011
const contextValue = useMemo(() => ({
@@ -61,11 +52,6 @@ const FooterWithLanguageSelector = ({ authenticatedUser = null }) => {
6152
};
6253

6354
describe('<Footer />', () => {
64-
beforeEach(() => {
65-
jest.clearAllMocks();
66-
initializeMockApp();
67-
});
68-
6955
describe('renders correctly', () => {
7056
it('renders without a language selector', () => {
7157
const tree = renderer
@@ -80,40 +66,11 @@ describe('<Footer />', () => {
8066
expect(tree).toMatchSnapshot();
8167
});
8268
it('renders with a language selector', () => {
69+
initializeMockApp();
8370
const tree = renderer
8471
.create(<FooterWithLanguageSelector />)
8572
.toJSON();
8673
expect(tree).toMatchSnapshot();
8774
});
8875
});
89-
90-
describe('handles language switching', () => {
91-
it('calls publish with LOCALE_CHANGED when the language changed', () => {
92-
const setSpy = jest.spyOn(getCookies(), 'set');
93-
const component = render(<FooterWithLanguageSelector />);
94-
95-
expect(component.queryByRole('button')).toBeInTheDocument();
96-
97-
const langDropdown = component.queryByRole('button');
98-
fireEvent.click(langDropdown);
99-
fireEvent.click(component.queryByText('Español'));
100-
101-
expect(setSpy).toHaveBeenCalledWith(LANGUAGE_PREFERENCE_COOKIE_NAME, 'es');
102-
});
103-
it('update the lang preference for an autheticathed user', async () => {
104-
const userData = { username: 'test-user' };
105-
const component = render(<FooterWithLanguageSelector authenticatedUser={userData} />);
106-
107-
expect(component.queryByRole('button')).toBeInTheDocument();
108-
109-
const langDropdown = component.queryByRole('button');
110-
fireEvent.click(langDropdown);
111-
fireEvent.click(component.queryByText('Español'));
112-
113-
await waitFor(() => {
114-
expect(patchPreferences).toHaveBeenCalledWith(userData.username, { prefLang: 'es' });
115-
expect(postSetLang).toHaveBeenCalledWith('es');
116-
});
117-
});
118-
});
11976
});

src/components/LanguageSelector/data.js

-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ export async function patchPreferences(username, params) {
1212
.patch(`${getConfig().LMS_BASE_URL}/api/user/v1/preferences/${username}`, processedParams, {
1313
headers: { 'Content-Type': 'application/merge-patch+json' },
1414
});
15-
16-
return params;
1715
}
1816

1917
export async function postSetLang(code) {

src/components/LanguageSelector/index.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const LanguageSelector = ({
4444

4545
const currentLocaleLabel = useMemo(() => {
4646
if (width < 576) {
47-
return null;
47+
return '';
4848
}
4949
if (width < 768) {
5050
return getPrimaryLanguageSubtag(currentLocale).toUpperCase();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/* eslint-disable react/prop-types */
2+
import React, { useMemo } from 'react';
3+
import {
4+
act, fireEvent, render, waitFor,
5+
} from '@testing-library/react';
6+
import { IntlProvider } from '@edx/frontend-platform/i18n';
7+
import { getCookies } from '@edx/frontend-platform/i18n/lib';
8+
import { AppContext } from '@edx/frontend-platform/react';
9+
import { initializeMockApp } from '@edx/frontend-platform/testing';
10+
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
11+
12+
import '@testing-library/jest-dom';
13+
14+
import LanguageSelector from '.';
15+
16+
jest.mock('@edx/frontend-platform/auth', () => ({
17+
...jest.requireActual('@edx/frontend-platform/auth'),
18+
getAuthenticatedHttpClient: jest.fn(),
19+
}));
20+
21+
jest.mock('@openedx/paragon/icons', () => ({
22+
Language: () => <div>LanguageIcon</div>,
23+
}));
24+
25+
const { LANGUAGE_PREFERENCE_COOKIE_NAME } = process.env;
26+
27+
const LanguageSelectorContext = ({ authenticatedUser = null }) => {
28+
const contextValue = useMemo(() => ({
29+
authenticatedUser,
30+
config: {
31+
LANGUAGE_PREFERENCE_COOKIE_NAME,
32+
LOGO_TRADEMARK_URL: process.env.LOGO_TRADEMARK_URL,
33+
LMS_BASE_URL: process.env.LMS_BASE_URL,
34+
SITE_SUPPORTED_LANGUAGES: ['es', 'en'],
35+
},
36+
}), [authenticatedUser]);
37+
38+
return (
39+
<IntlProvider locale="en">
40+
<AppContext.Provider
41+
value={contextValue}
42+
>
43+
<LanguageSelector
44+
options={['es', 'en']}
45+
username={authenticatedUser?.username}
46+
langCookieName={LANGUAGE_PREFERENCE_COOKIE_NAME}
47+
/>
48+
</AppContext.Provider>
49+
</IntlProvider>
50+
);
51+
};
52+
53+
describe('LanguageSelector', () => {
54+
let initService;
55+
56+
beforeEach(() => {
57+
jest.clearAllMocks();
58+
initService = initializeMockApp();
59+
});
60+
61+
it('change the language for a non authenticated user', () => {
62+
const setSpy = jest.spyOn(getCookies(), 'set');
63+
const component = render(<LanguageSelectorContext />);
64+
65+
expect(component.queryByRole('button')).toBeInTheDocument();
66+
67+
const langDropdown = component.queryByRole('button');
68+
fireEvent.click(langDropdown);
69+
fireEvent.click(component.queryByText('Español'));
70+
71+
expect(setSpy).toHaveBeenCalledWith(LANGUAGE_PREFERENCE_COOKIE_NAME, 'es');
72+
});
73+
74+
it('update the lang preference for an autheticathed user', async () => {
75+
const userData = { username: 'test-user' };
76+
const processedParams = {
77+
'pref-lang': 'es',
78+
};
79+
getAuthenticatedHttpClient.mockReturnValue({
80+
patch: jest.fn(),
81+
post: jest.fn(),
82+
});
83+
const formData = new FormData();
84+
formData.append('language', 'es');
85+
86+
const component = render(<LanguageSelectorContext authenticatedUser={userData} />);
87+
88+
expect(component.queryByRole('button')).toBeInTheDocument();
89+
90+
const langDropdown = component.queryByRole('button');
91+
fireEvent.click(langDropdown);
92+
fireEvent.click(component.queryByText('Español'));
93+
94+
await waitFor(() => {
95+
expect(getAuthenticatedHttpClient().patch)
96+
.toHaveBeenCalledWith(`${process.env.LMS_BASE_URL}/api/user/v1/preferences/${userData.username}`, processedParams, {
97+
headers: { 'Content-Type': 'application/merge-patch+json' },
98+
});
99+
expect(getAuthenticatedHttpClient().post)
100+
.toHaveBeenCalledWith(
101+
`${process.env.LMS_BASE_URL}/i18n/setlang/`,
102+
formData,
103+
{ headers: { Accept: 'application/json', 'X-Requested-With': 'XMLHttpRequest' } },
104+
);
105+
});
106+
});
107+
108+
it('call logError if it can not update the user preference', async () => {
109+
const { loggingService } = initService;
110+
const userData = { username: 'test-user' };
111+
const component = render(<LanguageSelectorContext authenticatedUser={userData} />);
112+
getAuthenticatedHttpClient.mockReturnValue({
113+
patch: jest.fn().mockRejectedValue(new Error('Error')),
114+
});
115+
expect(component.queryByRole('button')).toBeInTheDocument();
116+
117+
const langDropdown = component.queryByRole('button');
118+
fireEvent.click(langDropdown);
119+
fireEvent.click(component.queryByText('Español'));
120+
121+
await waitFor(() => {
122+
expect(loggingService.logError).toHaveBeenCalled();
123+
});
124+
});
125+
126+
it('should disp,ay the language icon and modify the label according to the screen size', () => {
127+
const component = render(<LanguageSelectorContext />);
128+
expect(component.queryByRole('button').textContent).toBe('LanguageIconEnglish');
129+
130+
act(() => {
131+
global.innerWidth = 700;
132+
global.dispatchEvent(new Event('resize'));
133+
});
134+
expect(component.queryByRole('button').textContent).toBe('LanguageIconEN');
135+
act(() => {
136+
global.innerWidth = 500;
137+
global.dispatchEvent(new Event('resize'));
138+
});
139+
expect(component.queryByRole('button').textContent).toBe('LanguageIcon');
140+
});
141+
});

0 commit comments

Comments
 (0)