]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20023 Update intl for spotlight tour
authorstanislavh <stanislav.honcharov@sonarsource.com>
Wed, 16 Aug 2023 12:56:48 +0000 (14:56 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 18 Aug 2023 20:02:50 +0000 (20:02 +0000)
server/sonar-web/design-system/src/components/SpotlightTour.tsx
server/sonar-web/design-system/src/components/__tests__/SpotlightTour-test.tsx
server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-it.tsx
server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx
server/sonar-web/src/main/js/apps/issues/test-utils.tsx

index 562389f56c63f1e1d3324b4523a84674cb72ed86..36f47f1a9fd82114d143d41a47279603087514b6 100644 (file)
@@ -21,6 +21,7 @@
 import { keyframes } from '@emotion/react';
 import styled from '@emotion/styled';
 import React from 'react';
+import { useIntl } from 'react-intl';
 import ReactJoyride, {
   Props as JoyrideProps,
   Step as JoyrideStep,
@@ -28,7 +29,6 @@ import ReactJoyride, {
 } from 'react-joyride';
 import tw from 'twin.macro';
 import { GLOBAL_POPUP_Z_INDEX, PopupZLevel, themeColor } from '../helpers';
-import { translate, translateWithParameters } from '../helpers/l10n';
 import { ButtonLink, ButtonPrimary, WrapperButton } from './buttons';
 import { CloseIcon } from './icons';
 import { PopupWrapper } from './popups';
@@ -78,6 +78,7 @@ function TooltipComponent({
     ref.current = node;
   }, []);
   const placement = step.placement ?? DEFAULT_PLACEMENT;
+  const intl = useIntl();
 
   React.useEffect(() => {
     // We don't compute for "center"; "center" will simply not show any arrow.
@@ -85,11 +86,12 @@ function TooltipComponent({
       let left = 0;
       let top = 0;
       let rotate = '0deg';
+
       const rect = (ref.current.parentNode as HTMLDivElement).getBoundingClientRect();
-      const targetRect =
-        typeof step.target === 'string'
-          ? (document.querySelector(step.target) as HTMLElement).getBoundingClientRect()
-          : step.target.getBoundingClientRect();
+      // In case target is null for some reason we use mocking object
+      const targetRect = (typeof step.target === 'string'
+        ? document.querySelector(step.target)?.getBoundingClientRect()
+        : step.target.getBoundingClientRect()) ?? { height: 0, y: 0, x: 0, width: 0 };
 
       if (placement === 'right') {
         left = -ARROW_LENGTH - PULSE_SIZE;
@@ -140,7 +142,7 @@ function TooltipComponent({
         <strong>
           {stepXofYLabel
             ? stepXofYLabel(index + 1, size)
-            : translateWithParameters('guiding.step_x_of_y', index + 1, size)}
+            : intl.formatMessage({ id: 'guiding.step_x_of_y' }, { '0': index + 1, '1': size })}
         </strong>
         <div>
           {index > 0 && (
@@ -164,6 +166,8 @@ export function SpotlightTour(props: SpotlightTourProps) {
   const { steps, skipLabel, backLabel, closeLabel, nextLabel, stepXofYLabel, ...otherProps } =
     props;
 
+  const intl = useIntl();
+
   return (
     <ReactJoyride
       disableOverlay
@@ -177,10 +181,10 @@ export function SpotlightTour(props: SpotlightTourProps) {
         offset: 0,
       }}
       locale={{
-        skip: skipLabel ?? translate('skip'),
-        back: backLabel ?? translate('go_back'),
-        close: closeLabel ?? translate('close'),
-        next: nextLabel ?? translate('next'),
+        skip: skipLabel ?? intl.formatMessage({ id: 'skip' }),
+        back: backLabel ?? intl.formatMessage({ id: 'go_back' }),
+        close: closeLabel ?? intl.formatMessage({ id: 'close' }),
+        next: nextLabel ?? intl.formatMessage({ id: 'next' }),
       }}
       scrollDuration={0}
       scrollOffset={250}
index 4e606267eb78dabe55d031d62204c95d6f4cc619..1d14f358b7b1571d48796dbd343cc98db3a1c8d2 100644 (file)
@@ -18,8 +18,9 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-import { render, screen } from '@testing-library/react';
+import { screen } from '@testing-library/react';
 import userEvent from '@testing-library/user-event';
+import { renderWithContext } from '../../helpers/testUtils';
 import { SpotlightTour, SpotlightTourProps } from '../SpotlightTour';
 
 it('should display the spotlight tour', async () => {
@@ -102,7 +103,7 @@ it('should allow the customization of button labels', async () => {
 });
 
 function renderSpotlightTour(props: Partial<SpotlightTourProps> = {}) {
-  return render(
+  return renderWithContext(
     <div>
       <div id="step1">This is step 1</div>
       <div id="step2">This is step 2</div>
index 2c74b149a70694dafda8a652dacebd8468192e12..08cd336d4891abdcd4cc0fc518d19580c256fb0a 100644 (file)
@@ -260,7 +260,9 @@ describe('issues app', () => {
     // Improve this to include all the bulk change fonctionality
     it('should be able to bulk change', async () => {
       const user = userEvent.setup();
-      const currentUser = mockLoggedInUser();
+      const currentUser = mockLoggedInUser({
+        dismissedNotices: { [NoticeType.ISSUE_GUIDE]: true },
+      });
       issuesHandler.setIsAdmin(true);
       issuesHandler.setCurrentUser(currentUser);
       renderIssueApp(currentUser);
index a89cac0e8c85ac5c8cbd03e644deab14d7533c2a..dd60808c9682a5663b428072a43665a434319ba4 100644 (file)
@@ -1313,7 +1313,6 @@ export class App extends React.PureComponent<Props, State> {
           <PageContentFontWrapper className="sw-body-sm">
             <div className="sw-w-full sw-flex" id="issues-page">
               <Suggestions suggestions="issues" />
-              <IssueGuide run={!open && !component?.needIssueSync && issues.length > 0} />
 
               {openIssue ? (
                 <Helmet
@@ -1325,7 +1324,10 @@ export class App extends React.PureComponent<Props, State> {
                   )}
                 />
               ) : (
-                <Helmet defer={false} title={translate('issues.page')} />
+                <>
+                  <Helmet defer={false} title={translate('issues.page')} />
+                  <IssueGuide run={!open && !component?.needIssueSync && issues.length > 0} />
+                </>
               )}
 
               <h1 className="a11y-hidden">{translate('issues.page')}</h1>
index 0079ffca4b299c9cb8e50b682217a12f4be62702..a5e8d9e7ee3ba523d4deb0199aa7c8c470207383 100644 (file)
@@ -141,7 +141,7 @@ export async function waitOnDataLoaded() {
 export function renderIssueApp(
   currentUser = mockCurrentUser({ dismissedNotices: { [NoticeType.ISSUE_GUIDE]: true } })
 ) {
-  renderApp('project/issues', <IssuesApp />, { currentUser });
+  renderApp('issues', <IssuesApp />, { currentUser });
 }
 
 export function renderProjectIssuesApp(