From 37f4e3ddfaefd756af9bbf5399e0cd93ccb5e55c Mon Sep 17 00:00:00 2001 From: yauheni-deriv <103182683+yauheni-deriv@users.noreply.github.com> Date: Wed, 4 Oct 2023 13:55:27 +0300 Subject: [PATCH] refactor: evgeniy/92724/language settings improvements (#8176) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: evgeniy/92724/language settings improvements * fix: cursor button fix * feat: same language menu usage for responsive * fix: hide language icon while opening language menu * refactor: review change, adding types and dependencies * fix: changes from master missed * fix: reading undefined error * fix: duplicated properties * fix: types duplicate * chore: language-settings test * refactor: menu-link store separately * chore: menu-link test coverage * refactor: test code structure * refactor: link code * refactor: remove unused code * refactor: code readability * refactor: variable usage * refactor: variable usage * refactor: review comments incorporating * fix: test refactor with mockstore * fix: missing mock * fix: :art: incorporated deriv/util package * fix: :zap: refactored code * feat: resolved code smells * feat: resolved review comments * feat: resolved review comments * feat: resolved review comments * fix: failing testcase * fix: :bug: missing import * Trigger build * chore: trigger build * Merge branch 'master' into evgeniy/92724/language_settings_improvements * chore: review comments incorporate * refactor: types store alphabetically order * refactor: types store alphabetically order * refactor: menulink export fix * chore: remove unused variable * refactor: remove unused variable * chore: trigger build * fix: resolve conflicts * fix: repeated fields * chore: isExternalLink description * chore: bootstrap --------- Co-authored-by: “yauheni-kryzhyk-deriv” <“yauheni@deriv.me”> Co-authored-by: Likhith Kolayari <98398322+likhith-deriv@users.noreply.github.com> Co-authored-by: Matin shafiei Co-authored-by: Likhith Kolayari --- package-lock.json | 19 ++ .../__tests__/language-settings.spec.tsx | 83 ++++++ .../LanguageSettings/language-settings.tsx | 84 ++---- .../mobile-drawer/mobile-drawer-submenu.tsx | 6 +- packages/core/package.json | 1 + .../Header/Components/ToggleMenu/index.ts | 4 + .../Components/ToggleMenu/menu-title.tsx | 39 +++ .../ToggleMenu/mobile-language-menu.tsx | 50 ++++ .../Header/__tests__/menu-link.spec.tsx | 156 ++++++++++ .../Components/Layout/Header/menu-link.tsx | 174 ++++++++++++ .../Layout/Header/toggle-menu-drawer.jsx | 268 ++---------------- .../Routes/__tests__/language-link.spec.tsx | 1 - .../App/Components/Routes/language-link.tsx | 7 +- .../SettingsModal/settings-language.jsx | 2 +- packages/core/src/Stores/client-store.js | 2 +- packages/core/src/Stores/common-store.js | 90 +++--- packages/core/src/Stores/ui-store.js | 7 + .../_common/components/settings-language.scss | 52 ++-- .../src/utils/files/file-uploader-utils.ts | 2 +- packages/stores/src/mockStore.ts | 2 + packages/stores/types.ts | 2 + .../utils/src/__tests__/parse-url.spec.tsx | 13 + packages/utils/src/index.ts | 1 + packages/utils/src/parse-url.ts | 6 + 24 files changed, 683 insertions(+), 388 deletions(-) create mode 100644 packages/account/src/Sections/Profile/LanguageSettings/__tests__/language-settings.spec.tsx create mode 100644 packages/core/src/App/Components/Layout/Header/Components/ToggleMenu/index.ts create mode 100644 packages/core/src/App/Components/Layout/Header/Components/ToggleMenu/menu-title.tsx create mode 100644 packages/core/src/App/Components/Layout/Header/Components/ToggleMenu/mobile-language-menu.tsx create mode 100644 packages/core/src/App/Components/Layout/Header/__tests__/menu-link.spec.tsx create mode 100644 packages/core/src/App/Components/Layout/Header/menu-link.tsx create mode 100644 packages/utils/src/__tests__/parse-url.spec.tsx create mode 100644 packages/utils/src/parse-url.ts diff --git a/package-lock.json b/package-lock.json index fd94a06889b6..bbb98bc84e9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,6 +79,7 @@ "eslint-formatter-pretty": "^4.0.0", "eslint-import-resolver-webpack": "^0.13.0", "eslint-plugin-import": "^2.23.4", + "eslint-plugin-local-rules": "2.0.0", "eslint-plugin-prettier": "^3.3.1", "eslint-plugin-react": "^7.22.0", "eslint-plugin-react-hooks": "^4.2.0", @@ -25232,6 +25233,11 @@ "eslint-plugin-playwright": "^0.9.0" } }, + "node_modules/eslint-plugin-local-rules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-local-rules/-/eslint-plugin-local-rules-2.0.0.tgz", + "integrity": "sha512-sWueme0kUcP0JC1+6OBDQ9edBDVFJR92WJHSRbhiRExlenMEuUisdaVBPR+ItFBFXo2Pdw6FD2UfGZWkz8e93g==" + }, "node_modules/eslint-plugin-playwright": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-0.9.0.tgz", @@ -60888,6 +60894,19 @@ "use-sync-external-store": "^1.2.0" } }, + "@tanstack/react-table": { + "version": "8.10.3", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.10.3.tgz", + "integrity": "sha512-Qya1cJ+91arAlW7IRDWksRDnYw28O446jJ/ljkRSc663EaftJoBCAU10M+VV1K6MpCBLrXq1BD5IQc1zj/ZEjA==", + "requires": { + "@tanstack/table-core": "8.10.3" + } + }, + "@tanstack/table-core": { + "version": "8.10.3", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.10.3.tgz", + "integrity": "sha512-hJ55YfJlWbfzRROfcyA/kC1aZr/shsLA8XNAwN8jXylhYWGLnPmiJJISrUfj4dMMWRiFi0xBlnlC7MLH+zSrcw==" + }, "@tensorflow-models/face-detection": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@tensorflow-models/face-detection/-/face-detection-1.0.2.tgz", diff --git a/packages/account/src/Sections/Profile/LanguageSettings/__tests__/language-settings.spec.tsx b/packages/account/src/Sections/Profile/LanguageSettings/__tests__/language-settings.spec.tsx new file mode 100644 index 000000000000..4fbf68caa5c0 --- /dev/null +++ b/packages/account/src/Sections/Profile/LanguageSettings/__tests__/language-settings.spec.tsx @@ -0,0 +1,83 @@ +import React from 'react'; +import { screen, render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { isMobile, routes } from '@deriv/shared'; +import LanguageSettings from '../language-settings'; +import { mockStore, StoreProvider } from '@deriv/stores'; + +jest.mock('@deriv/shared', () => ({ + ...jest.requireActual('@deriv/shared'), + isMobile: jest.fn(() => false), +})); + +jest.mock('@deriv/translations', () => ({ + ...jest.requireActual('@deriv/translations'), + getAllowedLanguages: jest.fn(() => ({ lang_1: 'Test Lang 1', lang_2: 'Test Lang 2' })), +})); + +jest.mock('@deriv/components', () => ({ + ...jest.requireActual('@deriv/components'), + Icon: jest.fn(() =>
Flag Icon
), +})); + +jest.mock('react-i18next', () => ({ + ...jest.requireActual('react-i18next'), + useTranslation: jest.fn(() => ({ i18n: { changeLanguage: jest.fn() } })), +})); + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + Redirect: jest.fn(() =>
Redirect
), +})); + +describe('LanguageSettings', () => { + const mockRootStore = mockStore({ + common: { + current_language: 'lang_1', + }, + }); + + const renderLanguageSettings = () => { + render(, { + wrapper: ({ children }) => {children}, + }); + }; + + it('should render LanguageSettings', () => { + renderLanguageSettings(); + + expect(screen.getByText('Select Language')).toBeInTheDocument(); + + const flags_icons = screen.getAllByText('Flag Icon'); + const lang_1 = screen.getByText('Test Lang 1'); + const lang_2 = screen.getByText('Test Lang 2'); + + expect(flags_icons.length).toBe(2); + expect(lang_1).toBeInTheDocument(); + expect(/(active)/i.test(lang_1.className)).toBeTruthy(); + expect(lang_2).toBeInTheDocument(); + expect(/(active)/i.test(lang_2.className)).toBeFalsy(); + }); + + it('should trigger language change', () => { + renderLanguageSettings(); + + const lang_2 = screen.getByText('Test Lang 2'); + userEvent.click(lang_2); + + expect(mockRootStore.common.changeSelectedLanguage).toHaveBeenCalled(); + }); + + it('should redirect for mobile', () => { + (isMobile as jest.Mock).mockReturnValue(true); + Object.defineProperty(window, 'location', { + configurable: true, + value: { pathname: routes.languages }, + }); + + renderLanguageSettings(); + + expect(screen.queryByText('Select Language')).not.toBeInTheDocument(); + expect(screen.getByText('Redirect')).toBeInTheDocument(); + }); +}); diff --git a/packages/account/src/Sections/Profile/LanguageSettings/language-settings.tsx b/packages/account/src/Sections/Profile/LanguageSettings/language-settings.tsx index cb0b7eea8b27..fb8886034605 100644 --- a/packages/account/src/Sections/Profile/LanguageSettings/language-settings.tsx +++ b/packages/account/src/Sections/Profile/LanguageSettings/language-settings.tsx @@ -1,68 +1,40 @@ import React from 'react'; -import { useTranslation } from 'react-i18next'; -import { Button, DesktopWrapper } from '@deriv/components'; +import { Redirect } from 'react-router-dom'; import { localize, getAllowedLanguages } from '@deriv/translations'; +import { isMobile, routes } from '@deriv/shared'; +import { observer, useStore } from '@deriv/stores'; import FormSubHeader from 'Components/form-sub-header'; -import { Formik, FormikHandlers, FormikHelpers, FormikValues } from 'formik'; -import FormFooter from 'Components/form-footer'; import LanguageRadioButton from 'Components/language-settings'; -import { observer, useStore } from '@deriv/stores'; const LanguageSettings = observer(() => { const { common } = useStore(); - const { changeSelectedLanguage, current_language, isCurrentLanguage } = common; - const { i18n } = useTranslation(); + const { changeSelectedLanguage, current_language } = common; + + if (window.location.pathname === routes.languages && isMobile()) { + return ; + } + const allowed_language_keys: string[] = Object.keys(getAllowedLanguages()); - const initial_values = { language_code: current_language }; return ( - { - const { language_code } = values; - await changeSelectedLanguage(language_code); - await i18n.changeLanguage?.(language_code); - }} - > - {({ handleSubmit, setFieldValue, values }: FormikHandlers & FormikHelpers & FormikValues) => { - return ( -
-
- - - -
- {allowed_language_keys.map(language_key => { - return ( - ) => - setFieldValue('language_code', event.target.value) - } - /> - ); - })} -
-
- -