From 2d0873e027ff54dbb470c46b76b04f98caa48384 Mon Sep 17 00:00:00 2001 From: Wouter Admiraal Date: Thu, 19 Aug 2021 15:03:11 +0200 Subject: [PATCH] SONAR-15297 Remove all sonar-ui-common initialization logic --- .../config/jest/SetupTestEnvironment.ts | 4 - .../embed-docs-modal/EmbedDocsPopup.tsx | 2 +- .../nav/global/GlobalNavBranding.tsx | 2 +- .../components/nav/global/GlobalNavUser.tsx | 2 +- .../components/nav/settings/SettingsNav.tsx | 2 +- server/sonar-web/src/main/js/app/index.ts | 3 - .../apps/about/components/AboutScanners.tsx | 2 +- .../account/profile/UserExternalIdentity.tsx | 2 +- .../project/AzureProjectCreateRenderer.tsx | 2 +- .../BitbucketCloudProjectCreateRender.tsx | 2 +- .../BitbucketProjectCreateRenderer.tsx | 2 +- .../project/CreateProjectModeSelection.tsx | 2 +- .../project/GitlabProjectCreateRenderer.tsx | 2 +- .../project/PersonalAccessTokenForm.tsx | 2 +- .../js/apps/maintenance/components/App.tsx | 4 +- .../branches/MeasuresPanelNoNewCode.tsx | 2 +- .../apps/permissions/__tests__/utils-test.ts | 10 +- .../components/ProjectCreationMenuItem.tsx | 2 +- .../__tests__/Header-test.tsx | 5 +- .../components/EmptyHotspotsPage.tsx | 2 +- .../js/apps/sessions/components/LoginForm.tsx | 2 +- .../js/apps/sessions/components/Logout.tsx | 2 +- .../sessions/components/OAuthProviders.tsx | 2 +- .../apps/sessions/components/Unauthorized.tsx | 2 +- .../almIntegration/AlmIntegrationRenderer.tsx | 2 +- .../js/apps/system/components/PageActions.tsx | 2 +- .../users/components/UserListItemIdentity.tsx | 2 +- .../SourceViewer/SourceViewerHeader.tsx | 2 +- .../activity-graph/GraphsHistory.tsx | 2 +- .../controls/IdentityProviderLink.tsx | 2 +- .../src/main/js/components/controls/Modal.tsx | 2 +- .../src/main/js/components/docs/DocImg.tsx | 2 +- .../main/js/components/lazyLoadComponent.tsx | 2 +- .../tutorials/TutorialSelectionRenderer.tsx | 2 +- .../tutorials/components/AllSet.tsx | 2 +- .../manual/commands/DownloadBuildWrapper.tsx | 2 +- .../main/js/helpers/__tests__/init-test.ts | 91 ------------------- .../main/js/helpers/__tests__/l10n-test.ts | 52 ++++------- .../js/helpers/__tests__/measures-test.ts | 6 +- .../main/js/helpers/__tests__/urls-test.ts | 12 --- .../sonar-web/src/main/js/helpers/browser.ts | 2 + .../src/main/js/helpers/extensions.ts | 2 +- .../src/main/js/helpers/getHistory.ts | 4 +- server/sonar-web/src/main/js/helpers/init.ts | 88 ------------------ server/sonar-web/src/main/js/helpers/l10n.ts | 42 ++++++++- .../sonar-web/src/main/js/helpers/request.ts | 4 +- .../sonar-web/src/main/js/helpers/system.ts | 4 + server/sonar-web/src/main/js/helpers/urls.ts | 7 +- 48 files changed, 115 insertions(+), 287 deletions(-) delete mode 100644 server/sonar-web/src/main/js/helpers/__tests__/init-test.ts delete mode 100644 server/sonar-web/src/main/js/helpers/init.ts diff --git a/server/sonar-web/config/jest/SetupTestEnvironment.ts b/server/sonar-web/config/jest/SetupTestEnvironment.ts index 9e3b4e53f86..e82edbb84a7 100644 --- a/server/sonar-web/config/jest/SetupTestEnvironment.ts +++ b/server/sonar-web/config/jest/SetupTestEnvironment.ts @@ -19,7 +19,6 @@ */ import * as theme from '../../src/main/js/app/theme'; import ThemeContext from '../../src/main/js/components/theme'; -import SonarUiCommonInitializer, { DEFAULT_LOCALE } from '../../src/main/js/helpers/init'; const content = document.createElement('div'); content.id = 'content'; @@ -27,9 +26,6 @@ document.documentElement.appendChild(content); const baseUrl = ''; (window as any).baseUrl = baseUrl; -SonarUiCommonInitializer.setLocale(DEFAULT_LOCALE) - .setMessages({}) - .setUrlContext(baseUrl); // Hack : override the default value of the context used for theme by emotion // This allows tests to get the theme value without specifiying a theme provider diff --git a/server/sonar-web/src/main/js/app/components/embed-docs-modal/EmbedDocsPopup.tsx b/server/sonar-web/src/main/js/app/components/embed-docs-modal/EmbedDocsPopup.tsx index 41d40dac55e..d924b95db37 100644 --- a/server/sonar-web/src/main/js/app/components/embed-docs-modal/EmbedDocsPopup.tsx +++ b/server/sonar-web/src/main/js/app/components/embed-docs-modal/EmbedDocsPopup.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { Link } from 'react-router'; import { DropdownOverlay } from '../../../components/controls/Dropdown'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import { SuggestionsContext } from './SuggestionsContext'; interface Props { diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.tsx b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.tsx index 1bd360c6a73..0e6ba57077e 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { connect } from 'react-redux'; import { Link } from 'react-router'; import { translate } from '../../../../helpers/l10n'; -import { getBaseUrl } from '../../../../helpers/urls'; +import { getBaseUrl } from '../../../../helpers/system'; import { getGlobalSettingValue, Store } from '../../../../store/rootReducer'; interface StateProps { diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.tsx b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.tsx index 95a148fb1ee..8d808a68ac4 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.tsx @@ -23,7 +23,7 @@ import Dropdown from '../../../../components/controls/Dropdown'; import { Router, withRouter } from '../../../../components/hoc/withRouter'; import Avatar from '../../../../components/ui/Avatar'; import { translate } from '../../../../helpers/l10n'; -import { getBaseUrl } from '../../../../helpers/urls'; +import { getBaseUrl } from '../../../../helpers/system'; import { isLoggedIn } from '../../../../helpers/users'; import { rawSizes } from '../../../theme'; diff --git a/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.tsx b/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.tsx index 0712fd67280..71bc8cc6b3b 100644 --- a/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.tsx @@ -25,7 +25,7 @@ import DropdownIcon from '../../../../components/icons/DropdownIcon'; import ContextNavBar from '../../../../components/ui/ContextNavBar'; import NavBarTabs from '../../../../components/ui/NavBarTabs'; import { translate } from '../../../../helpers/l10n'; -import { getBaseUrl } from '../../../../helpers/urls'; +import { getBaseUrl } from '../../../../helpers/system'; import { AdminPageExtension } from '../../../../types/extension'; import { PendingPluginResult } from '../../../../types/plugins'; import { rawSizes } from '../../../theme'; diff --git a/server/sonar-web/src/main/js/app/index.ts b/server/sonar-web/src/main/js/app/index.ts index cd7c28a8d01..8ceaf92f55f 100644 --- a/server/sonar-web/src/main/js/app/index.ts +++ b/server/sonar-web/src/main/js/app/index.ts @@ -18,14 +18,11 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { installExtensionsHandler, installWebAnalyticsHandler } from '../helpers/extensionsHandler'; -import SonarUiCommonInitializer from '../helpers/init'; import { loadL10nBundle } from '../helpers/l10n'; import { parseJSON, request } from '../helpers/request'; import { getBaseUrl, getSystemStatus } from '../helpers/system'; import './styles/sonar.css'; -SonarUiCommonInitializer.setUrlContext(getBaseUrl()); - installWebAnalyticsHandler(); if (isMainApp()) { diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutScanners.tsx b/server/sonar-web/src/main/js/apps/about/components/AboutScanners.tsx index bcbd9f92f57..f557b7966e3 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutScanners.tsx +++ b/server/sonar-web/src/main/js/apps/about/components/AboutScanners.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import { Link } from 'react-router'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; const scanners = [ { diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.tsx b/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.tsx index 822785ab572..096ec5c4382 100644 --- a/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.tsx +++ b/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { getIdentityProviders } from '../../../api/users'; import { colors } from '../../../app/theme'; import { getTextColor } from '../../../helpers/colors'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; export interface UserExternalIdentityProps { user: T.LoggedInUser; diff --git a/server/sonar-web/src/main/js/apps/create/project/AzureProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/AzureProjectCreateRenderer.tsx index b68f7eadd96..3c954c02665 100644 --- a/server/sonar-web/src/main/js/apps/create/project/AzureProjectCreateRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/AzureProjectCreateRenderer.tsx @@ -22,7 +22,7 @@ import { Button } from '../../../components/controls/buttons'; import SearchBox from '../../../components/controls/SearchBox'; import DeferredSpinner from '../../../components/ui/DeferredSpinner'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import { AzureProject, AzureRepository } from '../../../types/alm-integration'; import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings'; import AzurePersonalAccessTokenForm from './AzurePersonalAccessTokenForm'; diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx index 33de2a91863..744b6df114d 100644 --- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloudProjectCreateRender.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import { BitbucketCloudRepository } from '../../../types/alm-integration'; import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings'; import BitbucketCloudSearchForm from './BitbucketCloudSearchForm'; diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx index 118753f0ad2..972b367aabb 100644 --- a/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { Button } from '../../../components/controls/buttons'; import DeferredSpinner from '../../../components/ui/DeferredSpinner'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import { BitbucketProject, BitbucketProjectRepositories, diff --git a/server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx b/server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx index f3193c44ce8..6601bb02b5e 100644 --- a/server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/CreateProjectModeSelection.tsx @@ -23,7 +23,7 @@ import { withAppState } from '../../../components/hoc/withAppState'; import ChevronsIcon from '../../../components/icons/ChevronsIcon'; import { Alert } from '../../../components/ui/Alert'; import { translate, translateWithParameters } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import { AlmKeys } from '../../../types/alm-settings'; import { CreateProjectModes } from './types'; diff --git a/server/sonar-web/src/main/js/apps/create/project/GitlabProjectCreateRenderer.tsx b/server/sonar-web/src/main/js/apps/create/project/GitlabProjectCreateRenderer.tsx index cc63fc2a66a..2b2e761a9d1 100644 --- a/server/sonar-web/src/main/js/apps/create/project/GitlabProjectCreateRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/GitlabProjectCreateRenderer.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import { GitlabProject } from '../../../types/alm-integration'; import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings'; import CreateProjectPageHeader from './CreateProjectPageHeader'; diff --git a/server/sonar-web/src/main/js/apps/create/project/PersonalAccessTokenForm.tsx b/server/sonar-web/src/main/js/apps/create/project/PersonalAccessTokenForm.tsx index b452c0f096e..114698ed515 100644 --- a/server/sonar-web/src/main/js/apps/create/project/PersonalAccessTokenForm.tsx +++ b/server/sonar-web/src/main/js/apps/create/project/PersonalAccessTokenForm.tsx @@ -29,7 +29,7 @@ import ValidationInput from '../../../components/controls/ValidationInput'; import { Alert } from '../../../components/ui/Alert'; import DeferredSpinner from '../../../components/ui/DeferredSpinner'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import { AlmKeys, AlmSettingsInstance } from '../../../types/alm-settings'; interface Props { diff --git a/server/sonar-web/src/main/js/apps/maintenance/components/App.tsx b/server/sonar-web/src/main/js/apps/maintenance/components/App.tsx index 82b66453860..a676f7e2b5c 100644 --- a/server/sonar-web/src/main/js/apps/maintenance/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/maintenance/components/App.tsx @@ -27,8 +27,8 @@ import { Button } from '../../../components/controls/buttons'; import DateFromNow from '../../../components/intl/DateFromNow'; import TimeFormatter from '../../../components/intl/TimeFormatter'; import { translate } from '../../../helpers/l10n'; -import { isSonarCloud } from '../../../helpers/system'; -import { getBaseUrl, getReturnUrl } from '../../../helpers/urls'; +import { getBaseUrl, isSonarCloud } from '../../../helpers/system'; +import { getReturnUrl } from '../../../helpers/urls'; import '../styles.css'; interface Props { diff --git a/server/sonar-web/src/main/js/apps/overview/branches/MeasuresPanelNoNewCode.tsx b/server/sonar-web/src/main/js/apps/overview/branches/MeasuresPanelNoNewCode.tsx index e02240a9760..a6eaf3cf941 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/MeasuresPanelNoNewCode.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/MeasuresPanelNoNewCode.tsx @@ -22,7 +22,7 @@ import { FormattedMessage } from 'react-intl'; import { Link } from 'react-router'; import { getBranchLikeQuery } from '../../../helpers/branch-like'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import { Branch } from '../../../types/branch-like'; import { ComponentQualifier } from '../../../types/component'; diff --git a/server/sonar-web/src/main/js/apps/permissions/__tests__/utils-test.ts b/server/sonar-web/src/main/js/apps/permissions/__tests__/utils-test.ts index 5c6a1f128a9..a0f55b0bf91 100644 --- a/server/sonar-web/src/main/js/apps/permissions/__tests__/utils-test.ts +++ b/server/sonar-web/src/main/js/apps/permissions/__tests__/utils-test.ts @@ -17,21 +17,21 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import SonarUiCommonInitializer from '../../../helpers/init'; +import { resetMessages } from '../../../helpers/l10n'; import { isSonarCloud } from '../../../helpers/system'; import { convertToPermissionDefinitions } from '../utils'; jest.mock('../../../helpers/system', () => ({ isSonarCloud: jest.fn() })); afterEach(() => { - SonarUiCommonInitializer.setMessages({}); + resetMessages({}); }); describe('convertToPermissionDefinitions', () => { it('should convert and translate a permission definition', () => { (isSonarCloud as jest.Mock).mockImplementation(() => false); - SonarUiCommonInitializer.setMessages({ + resetMessages({ 'global_permissions.admin': 'Administer System' }); @@ -46,7 +46,7 @@ describe('convertToPermissionDefinitions', () => { it('should convert and translate a permission definition for SonarCloud', () => { (isSonarCloud as jest.Mock).mockImplementation(() => true); - SonarUiCommonInitializer.setMessages({ + resetMessages({ 'global_permissions.admin': 'Administer System', 'global_permissions.admin.sonarcloud': 'Administer Organization' }); @@ -66,7 +66,7 @@ describe('convertToPermissionDefinitions', () => { it('should fallback to basic message when SonarCloud version does not exist', () => { (isSonarCloud as jest.Mock).mockImplementation(() => true); - SonarUiCommonInitializer.setMessages({ + resetMessages({ 'global_permissions.admin': 'Administer System' }); diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCreationMenuItem.tsx b/server/sonar-web/src/main/js/apps/projects/components/ProjectCreationMenuItem.tsx index c34b94152d2..d750b387f97 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCreationMenuItem.tsx +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCreationMenuItem.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { Link } from 'react-router'; import ChevronsIcon from '../../../components/icons/ChevronsIcon'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import { AlmKeys } from '../../../types/alm-settings'; export interface ProjectCreationMenuItemProps { diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Header-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Header-test.tsx index c67e81e0cf6..19774442b90 100644 --- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Header-test.tsx +++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/Header-test.tsx @@ -22,7 +22,10 @@ import * as React from 'react'; import { click } from '../../../helpers/testUtils'; import Header, { Props } from '../Header'; -jest.mock('../../../helpers/system', () => ({ isSonarCloud: jest.fn().mockReturnValue(false) })); +jest.mock('../../../helpers/system', () => ({ + getReactDomContainerSelector: jest.fn(() => '#content'), + isSonarCloud: jest.fn().mockReturnValue(false) +})); it('renders', () => { expect(shallowRender()).toMatchSnapshot('default'); diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/EmptyHotspotsPage.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/EmptyHotspotsPage.tsx index ab115bb0128..6a3776756b7 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/components/EmptyHotspotsPage.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/EmptyHotspotsPage.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import { Link } from 'react-router'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; export interface EmptyHotspotsPageProps { filtered: boolean; diff --git a/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.tsx b/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.tsx index 4268892d492..0e607bc59ec 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { SubmitButton } from '../../../components/controls/buttons'; import DeferredSpinner from '../../../components/ui/DeferredSpinner'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import './LoginForm.css'; interface Props { diff --git a/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx b/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx index 8b240308f7e..48c984df959 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/Logout.tsx @@ -22,7 +22,7 @@ import { connect } from 'react-redux'; import GlobalMessagesContainer from '../../../app/components/GlobalMessagesContainer'; import RecentHistory from '../../../app/components/RecentHistory'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import { doLogout } from '../../../store/rootActions'; interface Props { diff --git a/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.tsx b/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.tsx index 85d3ce9cf53..8e8ee8f8303 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/OAuthProviders.tsx @@ -22,7 +22,7 @@ import * as React from 'react'; import HelpTooltip from '../../../components/controls/HelpTooltip'; import IdentityProviderLink from '../../../components/controls/IdentityProviderLink'; import { translateWithParameters } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import './OAuthProviders.css'; interface Props { diff --git a/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.tsx b/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.tsx index c6c7b573e87..e6da089ba73 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import { getCookie } from '../../../helpers/cookies'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; export default function Unauthorized() { const message = decodeURIComponent(getCookie('AUTHENTICATION-ERROR') || ''); diff --git a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationRenderer.tsx b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationRenderer.tsx index 094c1214e8b..04bd555a4be 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/settings/components/almIntegration/AlmIntegrationRenderer.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import BoxedTabs from '../../../../components/controls/BoxedTabs'; import { translate } from '../../../../helpers/l10n'; -import { getBaseUrl } from '../../../../helpers/urls'; +import { getBaseUrl } from '../../../../helpers/system'; import { AlmKeys, AlmSettingsBindingDefinitions, diff --git a/server/sonar-web/src/main/js/apps/system/components/PageActions.tsx b/server/sonar-web/src/main/js/apps/system/components/PageActions.tsx index 5f3e0887fe9..8554c67f874 100644 --- a/server/sonar-web/src/main/js/apps/system/components/PageActions.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/PageActions.tsx @@ -24,7 +24,7 @@ import { Button, EditButton } from '../../../components/controls/buttons'; import Dropdown from '../../../components/controls/Dropdown'; import DropdownIcon from '../../../components/icons/DropdownIcon'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import { getFileNameSuffix } from '../utils'; import ChangeLogLevelForm from './ChangeLogLevelForm'; diff --git a/server/sonar-web/src/main/js/apps/users/components/UserListItemIdentity.tsx b/server/sonar-web/src/main/js/apps/users/components/UserListItemIdentity.tsx index 14ba55b04b2..7ad86650cb6 100644 --- a/server/sonar-web/src/main/js/apps/users/components/UserListItemIdentity.tsx +++ b/server/sonar-web/src/main/js/apps/users/components/UserListItemIdentity.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import { colors } from '../../../app/theme'; import { getTextColor } from '../../../helpers/colors'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; export interface Props { identityProvider?: T.IdentityProvider; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.tsx b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.tsx index cbe62d3d085..95172b76ee5 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.tsx +++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.tsx @@ -33,8 +33,8 @@ import { translate } from '../../helpers/l10n'; import { formatMeasure } from '../../helpers/measures'; import { collapsedDirFromPath, fileFromPath } from '../../helpers/path'; import { omitNil } from '../../helpers/request'; +import { getBaseUrl } from '../../helpers/system'; import { - getBaseUrl, getBranchLikeUrl, getCodeUrl, getComponentIssuesUrl, diff --git a/server/sonar-web/src/main/js/components/activity-graph/GraphsHistory.tsx b/server/sonar-web/src/main/js/components/activity-graph/GraphsHistory.tsx index 8da9f418f94..29d351983c5 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/GraphsHistory.tsx +++ b/server/sonar-web/src/main/js/components/activity-graph/GraphsHistory.tsx @@ -21,7 +21,7 @@ import { isEqual } from 'lodash'; import * as React from 'react'; import DeferredSpinner from '../../components/ui/DeferredSpinner'; import { translate } from '../../helpers/l10n'; -import { getBaseUrl } from '../../helpers/urls'; +import { getBaseUrl } from '../../helpers/system'; import { GraphType, MeasureHistory, Serie } from '../../types/project-activity'; import GraphHistory from './GraphHistory'; import './styles.css'; diff --git a/server/sonar-web/src/main/js/components/controls/IdentityProviderLink.tsx b/server/sonar-web/src/main/js/components/controls/IdentityProviderLink.tsx index 31dd2da7e00..383a344b6ce 100644 --- a/server/sonar-web/src/main/js/components/controls/IdentityProviderLink.tsx +++ b/server/sonar-web/src/main/js/components/controls/IdentityProviderLink.tsx @@ -20,7 +20,7 @@ import * as classNames from 'classnames'; import * as React from 'react'; import { isDarkColor } from '../../helpers/colors'; -import { getBaseUrl } from '../../helpers/urls'; +import { getBaseUrl } from '../../helpers/system'; import './IdentityProviderLink.css'; interface Props { diff --git a/server/sonar-web/src/main/js/components/controls/Modal.tsx b/server/sonar-web/src/main/js/components/controls/Modal.tsx index d97d9e1522b..b7181e25e1f 100644 --- a/server/sonar-web/src/main/js/components/controls/Modal.tsx +++ b/server/sonar-web/src/main/js/components/controls/Modal.tsx @@ -20,7 +20,7 @@ import * as classNames from 'classnames'; import * as React from 'react'; import * as ReactModal from 'react-modal'; -import { getReactDomContainerSelector } from '../../helpers/init'; +import { getReactDomContainerSelector } from '../../helpers/system'; import './Modal.css'; ReactModal.setAppElement(getReactDomContainerSelector()); diff --git a/server/sonar-web/src/main/js/components/docs/DocImg.tsx b/server/sonar-web/src/main/js/components/docs/DocImg.tsx index d8baf103eab..67ff35adfeb 100644 --- a/server/sonar-web/src/main/js/components/docs/DocImg.tsx +++ b/server/sonar-web/src/main/js/components/docs/DocImg.tsx @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { getBaseUrl } from '../../helpers/urls'; +import { getBaseUrl } from '../../helpers/system'; export default function DocImg(props: React.ImgHTMLAttributes) { const { alt, src, ...other } = props; diff --git a/server/sonar-web/src/main/js/components/lazyLoadComponent.tsx b/server/sonar-web/src/main/js/components/lazyLoadComponent.tsx index d45577895dc..2d6a13f2fc0 100644 --- a/server/sonar-web/src/main/js/components/lazyLoadComponent.tsx +++ b/server/sonar-web/src/main/js/components/lazyLoadComponent.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { Alert } from '../components/ui/Alert'; -import { IS_SSR } from '../helpers/init'; +import { IS_SSR } from '../helpers/browser'; import { translate } from '../helpers/l10n'; import { requestTryAndRepeatUntil } from '../helpers/request'; diff --git a/server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx b/server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx index 39b7a6449ed..795f1ffbdd1 100644 --- a/server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import EllipsisIcon from '../../components/icons/EllipsisIcon'; import { translate } from '../../helpers/l10n'; -import { getBaseUrl } from '../../helpers/urls'; +import { getBaseUrl } from '../../helpers/system'; import { AlmKeys, AlmSettingsInstance, ProjectAlmBindingResponse } from '../../types/alm-settings'; import AzurePipelinesTutorial from './azure-pipelines/AzurePipelinesTutorial'; import BitbucketPipelinesTutorial from './bitbucket-pipelines/BitbucketPipelinesTutorial'; diff --git a/server/sonar-web/src/main/js/components/tutorials/components/AllSet.tsx b/server/sonar-web/src/main/js/components/tutorials/components/AllSet.tsx index 806d1e4215c..fa744dacabd 100644 --- a/server/sonar-web/src/main/js/components/tutorials/components/AllSet.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/components/AllSet.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/urls'; +import { getBaseUrl } from '../../../helpers/system'; import { AlmKeys } from '../../../types/alm-settings'; import { withAppState } from '../../hoc/withAppState'; import SentenceWithHighlights from './SentenceWithHighlights'; diff --git a/server/sonar-web/src/main/js/components/tutorials/manual/commands/DownloadBuildWrapper.tsx b/server/sonar-web/src/main/js/components/tutorials/manual/commands/DownloadBuildWrapper.tsx index 7f53c2048fe..2012d5f095c 100644 --- a/server/sonar-web/src/main/js/components/tutorials/manual/commands/DownloadBuildWrapper.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/manual/commands/DownloadBuildWrapper.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import { FormattedMessage } from 'react-intl'; import { translate } from '../../../../helpers/l10n'; -import { getBaseUrl } from '../../../../helpers/urls'; +import { getBaseUrl } from '../../../../helpers/system'; import { OSs } from '../../types'; export interface DownloadBuildWrapperProps { diff --git a/server/sonar-web/src/main/js/helpers/__tests__/init-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/init-test.ts deleted file mode 100644 index d1251f06697..00000000000 --- a/server/sonar-web/src/main/js/helpers/__tests__/init-test.ts +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -/* eslint-disable no-console */ -import Initializer, { - DEFAULT_LOCALE, - DEFAULT_MESSAGES, - getLocale, - getMessages, - getReactDomContainerSelector, - getUrlContext -} from '../init'; - -const originalConsoleWarn = console.warn; -console.warn = jest.fn(); - -beforeEach(() => { - (console.warn as jest.Mock).mockClear(); -}); - -afterAll(() => { - Initializer.setLocale('en') - .setMessages({}) - .setUrlContext(''); - // @ts-ignore: initialize everything to undefined, not possible by respecting types - Initializer.setReactDomContainer(undefined); - console.warn = originalConsoleWarn; -}); - -it('should throw when trying to get a value without initializing first', () => { - // @ts-ignore: initialize react dom container to undefined, not possible by respecting types - Initializer.setLocale(undefined) - .setMessages(undefined) - .setUrlContext(undefined); - - expect(getLocale()).toBe(DEFAULT_LOCALE); - expect(console.warn).toHaveBeenLastCalledWith( - expect.stringContaining('L10n locale is not initialized') - ); - - expect(getMessages()).toBe(DEFAULT_MESSAGES); - expect(console.warn).toHaveBeenLastCalledWith( - expect.stringContaining('L10n messages are not initialized') - ); - - expect(getUrlContext).toThrowErrorMatchingInlineSnapshot( - `"sonar-ui-common init: web context needs to be initialized by Initializer.setUrlContext before being used"` - ); -}); - -it('should return the initialized values', () => { - const locale = 'ru'; - const messages = { any: 'Any' }; - const urlContext = '/context'; - const reactDomContainerSelector = '#custom'; - - Initializer.setLocale(locale) - .setMessages(messages) - .setUrlContext(urlContext) - .setReactDomContainer(reactDomContainerSelector); - - expect(getLocale()).toBe(locale); - expect(getMessages()).toBe(messages); - expect(getUrlContext()).toBe(urlContext); - expect(getReactDomContainerSelector()).toBe(reactDomContainerSelector); - expect(console.warn).not.toBeCalled(); -}); - -it('should have a default react dom container selector without warning', () => { - // @ts-ignore: initialize react dom container to undefined, not possible by respecting types - Initializer.setReactDomContainer(undefined); - - expect(getReactDomContainerSelector()).toBe('#content'); - expect(console.warn).not.toBeCalled(); -}); diff --git a/server/sonar-web/src/main/js/helpers/__tests__/l10n-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/l10n-test.ts index 2c4e48221af..54378d58b3b 100644 --- a/server/sonar-web/src/main/js/helpers/__tests__/l10n-test.ts +++ b/server/sonar-web/src/main/js/helpers/__tests__/l10n-test.ts @@ -17,18 +17,18 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import * as reactIntl from 'react-intl'; import { fetchL10nBundle } from '../../api/l10n'; -import SonarUiCommonInitializer, { getMessages } from '../init'; import { getLocalizedCategoryMetricName, getLocalizedMetricDomain, getLocalizedMetricName, + getMessages, getShortMonthName, getShortWeekDayName, getWeekDayName, hasMessage, loadL10nBundle, + resetMessages, translate, translateWithParameters } from '../l10n'; @@ -86,35 +86,23 @@ describe('#loadL10nBundle', () => { expect.objectContaining({ locale: cachedBundle.locale, messages: cachedBundle.messages }) ); }); - - it('should init react-intl & sonar-ui-common', async () => { - jest.spyOn(SonarUiCommonInitializer, 'setLocale'); - jest.spyOn(SonarUiCommonInitializer, 'setMessages'); - jest.spyOn(reactIntl, 'addLocaleData'); - - await loadL10nBundle(); - - expect(SonarUiCommonInitializer.setLocale).toHaveBeenCalledWith('de'); - expect(SonarUiCommonInitializer.setMessages).toHaveBeenCalledWith({ test_message: 'test' }); - expect(reactIntl.addLocaleData).toHaveBeenCalled(); - }); }); const originalMessages = getMessages(); const MSG = 'my_message'; afterEach(() => { - SonarUiCommonInitializer.setMessages(originalMessages); + resetMessages(originalMessages); }); describe('translate', () => { it('should translate simple message', () => { - SonarUiCommonInitializer.setMessages({ my_key: MSG }); + resetMessages({ my_key: MSG }); expect(translate('my_key')).toBe(MSG); }); it('should translate message with composite key', () => { - SonarUiCommonInitializer.setMessages({ 'my.composite.message': MSG }); + resetMessages({ 'my.composite.message': MSG }); expect(translate('my', 'composite', 'message')).toBe(MSG); expect(translate('my.composite', 'message')).toBe(MSG); expect(translate('my', 'composite.message')).toBe(MSG); @@ -130,22 +118,22 @@ describe('translate', () => { describe('translateWithParameters', () => { it('should translate message with one parameter in the beginning', () => { - SonarUiCommonInitializer.setMessages({ x_apples: '{0} apples' }); + resetMessages({ x_apples: '{0} apples' }); expect(translateWithParameters('x_apples', 5)).toBe('5 apples'); }); it('should translate message with one parameter in the middle', () => { - SonarUiCommonInitializer.setMessages({ x_apples: 'I have {0} apples' }); + resetMessages({ x_apples: 'I have {0} apples' }); expect(translateWithParameters('x_apples', 5)).toBe('I have 5 apples'); }); it('should translate message with one parameter in the end', () => { - SonarUiCommonInitializer.setMessages({ x_apples: 'Apples: {0}' }); + resetMessages({ x_apples: 'Apples: {0}' }); expect(translateWithParameters('x_apples', 5)).toBe('Apples: 5'); }); it('should translate message with several parameters', () => { - SonarUiCommonInitializer.setMessages({ + resetMessages({ x_apples: '{0}: I have {2} apples in my {1} baskets - {3}' }); expect(translateWithParameters('x_apples', 1, 2, 3, 4)).toBe( @@ -154,7 +142,7 @@ describe('translateWithParameters', () => { }); it('should not be affected by replacement pattern XSS vulnerability of String.replace', () => { - SonarUiCommonInitializer.setMessages({ x_apples: 'I have {0} apples' }); + resetMessages({ x_apples: 'I have {0} apples' }); expect(translateWithParameters('x_apples', '$`')).toBe('I have $` apples'); }); @@ -167,7 +155,7 @@ describe('translateWithParameters', () => { describe('hasMessage', () => { it('should return that the message exists', () => { - SonarUiCommonInitializer.setMessages({ foo: 'Foo', 'foo.bar': 'Foo Bar' }); + resetMessages({ foo: 'Foo', 'foo.bar': 'Foo Bar' }); expect(hasMessage('foo')).toBe(true); expect(hasMessage('foo', 'bar')).toBe(true); }); @@ -182,19 +170,19 @@ describe('getLocalizedMetricName', () => { const metric = { key: 'new_code', name: 'new_code_metric_name' }; it('should return the metric name translation', () => { - SonarUiCommonInitializer.setMessages({ 'metric.new_code.name': 'metric.new_code.name_t' }); + resetMessages({ 'metric.new_code.name': 'metric.new_code.name_t' }); expect(getLocalizedMetricName(metric)).toBe('metric.new_code.name_t'); }); it('should return the metric short name', () => { - SonarUiCommonInitializer.setMessages({ + resetMessages({ 'metric.new_code.short_name': 'metric.new_code.short_name_t' }); expect(getLocalizedMetricName(metric, true)).toBe('metric.new_code.short_name_t'); }); it('should fallback on name if short name is absent', () => { - SonarUiCommonInitializer.setMessages({ 'metric.new_code.name': 'metric.new_code.name_t' }); + resetMessages({ 'metric.new_code.name': 'metric.new_code.name_t' }); expect(getLocalizedMetricName(metric, true)).toBe('metric.new_code.name_t'); }); @@ -209,7 +197,7 @@ describe('getLocalizedMetricName', () => { describe('getLocalizedCategoryMetricName', () => { it('should return metric category name translation', () => { - SonarUiCommonInitializer.setMessages({ + resetMessages({ 'metric.new_code.extra_short_name': 'metric.new_code.extra_short_name_t' }); expect(getLocalizedCategoryMetricName({ key: 'new_code' })).toBe( @@ -218,14 +206,14 @@ describe('getLocalizedCategoryMetricName', () => { }); it('should fallback on metric name if extra_short_name is absent', () => { - SonarUiCommonInitializer.setMessages({ 'metric.new_code.name': 'metric.new_code.name_t' }); + resetMessages({ 'metric.new_code.name': 'metric.new_code.name_t' }); expect(getLocalizedCategoryMetricName({ key: 'new_code' })).toBe('metric.new_code.name_t'); }); }); describe('getLocalizedMetricDomain', () => { it('should return metric domain name translation', () => { - SonarUiCommonInitializer.setMessages({ 'metric_domain.domain': 'metric_domain.domain_t' }); + resetMessages({ 'metric_domain.domain': 'metric_domain.domain_t' }); expect(getLocalizedMetricDomain('domain')).toBe('metric_domain.domain_t'); }); @@ -236,21 +224,21 @@ describe('getLocalizedMetricDomain', () => { describe('getShortMonthName', () => { it('should properly translation months', () => { - SonarUiCommonInitializer.setMessages({ Jan: 'Jan_t' }); + resetMessages({ Jan: 'Jan_t' }); expect(getShortMonthName(0)).toBe('Jan_t'); }); }); describe('getWeekDayName', () => { it('should properly translation weekday', () => { - SonarUiCommonInitializer.setMessages({ Sunday: 'Sunday_t' }); + resetMessages({ Sunday: 'Sunday_t' }); expect(getWeekDayName(0)).toBe('Sunday_t'); }); }); describe('getShortWeekDayName', () => { it('should properly translation short weekday', () => { - SonarUiCommonInitializer.setMessages({ Sun: 'Sun_t' }); + resetMessages({ Sun: 'Sun_t' }); expect(getShortWeekDayName(0)).toBe('Sun_t'); }); }); diff --git a/server/sonar-web/src/main/js/helpers/__tests__/measures-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/measures-test.ts index 2bc23d79bec..7671fc99a0c 100644 --- a/server/sonar-web/src/main/js/helpers/__tests__/measures-test.ts +++ b/server/sonar-web/src/main/js/helpers/__tests__/measures-test.ts @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import SonarUiCommonInitializer from '../init'; +import { resetMessages } from '../l10n'; import { enhanceConditionWithMeasure, formatMeasure, @@ -77,7 +77,7 @@ const ONE_HOUR = ONE_MINUTE * 60; const ONE_DAY = HOURS_IN_DAY * ONE_HOUR; beforeAll(() => { - SonarUiCommonInitializer.setMessages({ + resetMessages({ 'work_duration.x_days': '{0}d', 'work_duration.x_hours': '{0}h', 'work_duration.x_minutes': '{0}min', @@ -92,7 +92,7 @@ beforeAll(() => { }); afterAll(() => { - SonarUiCommonInitializer.setMessages({}); + resetMessages({}); }); describe('#formatMeasure()', () => { diff --git a/server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts index 79e986cb913..7e067b7aa9e 100644 --- a/server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts +++ b/server/sonar-web/src/main/js/helpers/__tests__/urls-test.ts @@ -20,7 +20,6 @@ import { AlmKeys } from '../../types/alm-settings'; import { ComponentQualifier } from '../../types/component'; import { IssueType } from '../../types/issues'; -import SonarUICommonInitializer from '../init'; import { convertGithubApiUrlToLink, getComponentDrilldownUrl, @@ -186,10 +185,6 @@ describe('#getProjectSettingsUrl', () => { }); }); -afterEach(() => { - SonarUICommonInitializer.setUrlContext(''); -}); - describe('#getPathUrlAsString', () => { it('should return component url', () => { expect( @@ -202,13 +197,6 @@ describe('#getPathUrlAsString', () => { getPathUrlAsString({ pathname: '/dashboard', query: { id: COMPLEX_COMPONENT_KEY } }) ).toBe('/dashboard?id=' + COMPLEX_COMPONENT_KEY_ENCODED); }); - - it('should take baseUrl into account', () => { - SonarUICommonInitializer.setUrlContext('/context'); - expect( - getPathUrlAsString({ pathname: '/dashboard', query: { id: COMPLEX_COMPONENT_KEY } }) - ).toBe('/context/dashboard?id=' + COMPLEX_COMPONENT_KEY_ENCODED); - }); }); describe('#getReturnUrl', () => { diff --git a/server/sonar-web/src/main/js/helpers/browser.ts b/server/sonar-web/src/main/js/helpers/browser.ts index e9a8fe5221f..9ae20d2657e 100644 --- a/server/sonar-web/src/main/js/helpers/browser.ts +++ b/server/sonar-web/src/main/js/helpers/browser.ts @@ -19,6 +19,8 @@ */ import { EnhancedWindow } from '../types/browser'; +export const IS_SSR = typeof window === 'undefined'; + export function getEnhancedWindow() { return (window as unknown) as EnhancedWindow; } diff --git a/server/sonar-web/src/main/js/helpers/extensions.ts b/server/sonar-web/src/main/js/helpers/extensions.ts index 484a085bc94..7b1ef7286d0 100644 --- a/server/sonar-web/src/main/js/helpers/extensions.ts +++ b/server/sonar-web/src/main/js/helpers/extensions.ts @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { getBaseUrl } from '../helpers/urls'; +import { getBaseUrl } from '../helpers/system'; import { getExtensionFromCache } from './extensionsHandler'; let librariesExposed = false; diff --git a/server/sonar-web/src/main/js/helpers/getHistory.ts b/server/sonar-web/src/main/js/helpers/getHistory.ts index ea76f47a724..16a66d584a2 100644 --- a/server/sonar-web/src/main/js/helpers/getHistory.ts +++ b/server/sonar-web/src/main/js/helpers/getHistory.ts @@ -19,14 +19,14 @@ */ import { createHistory, History } from 'history'; import { useRouterHistory } from 'react-router'; -import { getUrlContext } from './init'; +import { getBaseUrl } from './system'; let history: History; function ensureHistory() { // eslint-disable-next-line react-hooks/rules-of-hooks history = useRouterHistory(createHistory)({ - basename: getUrlContext() + basename: getBaseUrl() }); return history; } diff --git a/server/sonar-web/src/main/js/helpers/init.ts b/server/sonar-web/src/main/js/helpers/init.ts deleted file mode 100644 index fd9ab571dd6..00000000000 --- a/server/sonar-web/src/main/js/helpers/init.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2021 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -import { Messages } from './l10n'; - -let urlContext: string | undefined; // Is the base path (web context) in SQ -let messages: Messages | undefined; -let locale: string | undefined; -let reactDomContainerSelector: string | undefined; // CSS selector of the DOM node where the React App is attached - -export const IS_SSR = typeof window === 'undefined'; -export const DEFAULT_LOCALE = 'en'; -export const DEFAULT_MESSAGES = { - // eslint-disable-next-line camelcase - default_error_message: 'The request cannot be processed. Try again later.' -}; -const LOGGER_PREFIX = 'sonar-ui-common init:'; - -export default { - setUrlContext(newUrlContext?: string) { - urlContext = newUrlContext; - return this; - }, - setLocale(newLocale: string) { - locale = newLocale; - return this; - }, - setMessages(newMessages?: Messages) { - messages = newMessages; - return this; - }, - setReactDomContainer(nodeSelector: string) { - reactDomContainerSelector = nodeSelector; - return this; - } -}; - -export function getMessages() { - if (typeof messages === 'undefined') { - logWarning('L10n messages are not initialized. Use default messages.'); - return DEFAULT_MESSAGES; - } - return messages; -} - -export function getLocale() { - if (typeof locale === 'undefined') { - logWarning('L10n locale is not initialized. Use default locale.'); - return DEFAULT_LOCALE; - } - return locale; -} - -export function getReactDomContainerSelector() { - return reactDomContainerSelector || '#content'; -} - -export function getUrlContext() { - if (typeof urlContext === 'undefined') { - throw new Error( - `${LOGGER_PREFIX} web context needs to be initialized by Initializer.setUrlContext before being used` - ); - } - return urlContext; -} - -function logWarning(message: string) { - if (process.env.NODE_ENV !== 'production') { - // eslint-disable-next-line no-console - console.warn(`${LOGGER_PREFIX} ${message}`); - } -} diff --git a/server/sonar-web/src/main/js/helpers/l10n.ts b/server/sonar-web/src/main/js/helpers/l10n.ts index 01a93305912..a96f34682c2 100644 --- a/server/sonar-web/src/main/js/helpers/l10n.ts +++ b/server/sonar-web/src/main/js/helpers/l10n.ts @@ -20,11 +20,19 @@ import { fetchL10nBundle } from '../api/l10n'; import { L10nBundle, L10nBundleRequestParams } from '../types/l10n'; import { toNotSoISOString } from './dates'; -import SonarUiCommonInitializer, { DEFAULT_LOCALE, getLocale, getMessages } from './init'; import { get as loadFromLocalStorage, save as saveInLocalStorage } from './storage'; export type Messages = T.Dict; +export const DEFAULT_LOCALE = 'en'; +export const DEFAULT_MESSAGES = { + // eslint-disable-next-line camelcase + default_error_message: 'The request cannot be processed. Try again later.' +}; + +let allMessages: Messages = {}; +let locale: string | undefined; + export function translate(...keys: string[]): string { const messageKey = keys.join('.'); const l10nMessages = getMessages(); @@ -57,6 +65,18 @@ export function hasMessage(...keys: string[]): boolean { return getMessages()[messageKey] != null; } +export function getMessages() { + if (typeof allMessages === 'undefined') { + logWarning('L10n messages are not initialized. Use default messages.'); + return DEFAULT_MESSAGES; + } + return allMessages; +} + +export function resetMessages(newMessages: Messages) { + allMessages = newMessages; +} + export function getLocalizedMetricName( metric: { key: string; name?: string }, short = false @@ -81,7 +101,11 @@ export function getLocalizedMetricDomain(domainName: string) { } export function getCurrentLocale() { - return getLocale(); + return locale; +} + +export function resetCurrentLocale(newLocale: string) { + locale = newLocale; } export function getShortMonthName(index: number) { @@ -120,7 +144,9 @@ export async function loadL10nBundle() { messages: {} })); - SonarUiCommonInitializer.setLocale(bundle.locale).setMessages(bundle.messages); + resetCurrentLocale(bundle.locale); + resetMessages(bundle.messages); + // No need to load english (default) bundle, it's coming with react-intl if (bundle.locale !== DEFAULT_LOCALE) { const [intlBundle, intl] = await Promise.all([ @@ -159,9 +185,8 @@ export async function getLatestL10nBundle() { effectiveLocale: cachedBundle.locale || browserLocale || DEFAULT_LOCALE, messages: cachedBundle.messages ?? {} }; - } else { - throw new Error(`Unexpected status code: ${response.status}`); } + throw new Error(`Unexpected status code: ${response.status}`); }); const bundle = { @@ -198,3 +223,10 @@ function loadL10nBundleFromLocalStorage() { function saveL10nBundleToLocalStorage(bundle: L10nBundle) { saveInLocalStorage(L10N_BUNDLE_LS_KEY, JSON.stringify(bundle)); } + +function logWarning(message: string) { + if (process.env.NODE_ENV !== 'production') { + // eslint-disable-next-line no-console + console.warn(message); + } +} diff --git a/server/sonar-web/src/main/js/helpers/request.ts b/server/sonar-web/src/main/js/helpers/request.ts index e3ede0d9843..686ea3a218c 100644 --- a/server/sonar-web/src/main/js/helpers/request.ts +++ b/server/sonar-web/src/main/js/helpers/request.ts @@ -20,8 +20,8 @@ import { isNil, omitBy } from 'lodash'; import { stringify } from 'querystring'; import { getCookie } from './cookies'; -import { getUrlContext } from './init'; import { translate } from './l10n'; +import { getBaseUrl } from './system'; export function getCSRFTokenName(): string { return 'X-XSRF-TOKEN'; @@ -110,7 +110,7 @@ class Request { submit(): Promise { const { url, options } = this.getSubmitData({ ...getCSRFToken() }); - return window.fetch(getUrlContext() + url, options); + return window.fetch(getBaseUrl() + url, options); } setMethod(method: string): Request { diff --git a/server/sonar-web/src/main/js/helpers/system.ts b/server/sonar-web/src/main/js/helpers/system.ts index e7e53e5b966..f93cf592ead 100644 --- a/server/sonar-web/src/main/js/helpers/system.ts +++ b/server/sonar-web/src/main/js/helpers/system.ts @@ -39,3 +39,7 @@ export function isOfficial() { export function isSonarCloud() { return getInstance() === InstanceType.SonarCloud; } + +export function getReactDomContainerSelector() { + return '#content'; +} diff --git a/server/sonar-web/src/main/js/helpers/urls.ts b/server/sonar-web/src/main/js/helpers/urls.ts index 118b15f8a70..d0a95a62878 100644 --- a/server/sonar-web/src/main/js/helpers/urls.ts +++ b/server/sonar-web/src/main/js/helpers/urls.ts @@ -25,7 +25,8 @@ import { ComponentQualifier, isApplication, isPortfolioLike } from '../types/com import { GraphType } from '../types/project-activity'; import { SecurityStandard } from '../types/security'; import { getBranchLikeQuery, isBranch, isMainBranch, isPullRequest } from './branch-like'; -import { getUrlContext, IS_SSR } from './init'; +import { IS_SSR } from './browser'; +import { getBaseUrl } from './system'; export interface Location { pathname: string; @@ -315,10 +316,6 @@ export function stripTrailingSlash(url: string) { return url.replace(/\/$/, ''); } -export function getBaseUrl(): string { - return getUrlContext(); -} - export function getHostUrl(): string { if (IS_SSR) { throw new Error('No host url available on server side.'); -- 2.39.5