]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20337 Migrating quality gate header to MIUI
authorRevanshu Paliwal <revanshu.paliwal@sonarsource.com>
Thu, 14 Sep 2023 08:52:57 +0000 (10:52 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 19 Sep 2023 20:02:46 +0000 (20:02 +0000)
server/sonar-web/src/main/js/apps/quality-gates/components/BuiltInQualityGateBadge.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/CopyQualityGateForm.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/DeleteQualityGateForm.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/DetailsHeader.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/RenameQualityGateForm.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/QualityGate-it.tsx

index 341704ba7d32e7ae61f4db16a8e738d77c1805d7..b2c5203171b220fdf141e3bf9cd2f46eda988fc6 100644 (file)
@@ -17,7 +17,8 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import classNames from 'classnames';
+
+import { Badge } from 'design-system';
 import * as React from 'react';
 import Tooltip from '../../../components/controls/Tooltip';
 import { translate } from '../../../helpers/l10n';
@@ -29,7 +30,7 @@ interface Props {
 export default function BuiltInQualityGateBadge({ className }: Props) {
   return (
     <Tooltip overlay={translate('quality_gates.built_in.help')}>
-      <div className={classNames('badge', className)}>{translate('quality_gates.built_in')}</div>
+      <Badge className={className}>{translate('quality_gates.built_in')}</Badge>
     </Tooltip>
   );
 }
index f14b9ee6ea645544997a9ecff96ed8c764472bd4..13193152b680e3f84bc9428b50b8266432feaa94 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import { ButtonPrimary, FormField, InputField, Modal } from 'design-system';
 import * as React from 'react';
 import { copyQualityGate } from '../../../api/quality-gates';
-import ConfirmModal from '../../../components/controls/ConfirmModal';
 import { Router, withRouter } from '../../../components/hoc/withRouter';
-import MandatoryFieldMarker from '../../../components/ui/MandatoryFieldMarker';
 import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation';
 import { translate } from '../../../helpers/l10n';
 import { getQualityGateUrl } from '../../../helpers/urls';
@@ -38,6 +37,8 @@ interface State {
   name: string;
 }
 
+const FORM_ID = 'rename-quality-gate';
+
 export class CopyQualityGateForm extends React.PureComponent<Props, State> {
   constructor(props: Props) {
     super(props);
@@ -48,7 +49,9 @@ export class CopyQualityGateForm extends React.PureComponent<Props, State> {
     this.setState({ name: event.currentTarget.value });
   };
 
-  handleCopy = () => {
+  handleCopy = (event: React.FormEvent) => {
+    event.preventDefault();
+
     const { qualityGate } = this.props;
     const { name } = this.state;
 
@@ -61,35 +64,40 @@ export class CopyQualityGateForm extends React.PureComponent<Props, State> {
   render() {
     const { qualityGate } = this.props;
     const { name } = this.state;
-    const confirmDisable = !name || (qualityGate && qualityGate.name === name);
+    const buttonDisabled = !name || (qualityGate && qualityGate.name === name);
 
     return (
-      <ConfirmModal
-        confirmButtonText={translate('copy')}
-        confirmDisable={confirmDisable}
-        header={translate('quality_gates.copy')}
+      <Modal
+        headerTitle={translate('quality_gates.copy')}
         onClose={this.props.onClose}
-        onConfirm={this.handleCopy}
-        size="small"
-      >
-        <MandatoryFieldsExplanation className="modal-field" />
-        <div className="modal-field">
-          <label htmlFor="quality-gate-form-name">
-            {translate('name')}
-            <MandatoryFieldMarker />
-          </label>
-          <input
-            autoFocus
-            id="quality-gate-form-name"
-            maxLength={100}
-            onChange={this.handleNameChange}
-            required
-            size={50}
-            type="text"
-            value={name}
-          />
-        </div>
-      </ConfirmModal>
+        body={
+          <form id={FORM_ID} onSubmit={this.handleCopy}>
+            <MandatoryFieldsExplanation />
+            <FormField
+              label={translate('name')}
+              htmlFor="quality-gate-form-name"
+              required
+              className="sw-my-2"
+            >
+              <InputField
+                autoFocus
+                id="quality-gate-form-name"
+                maxLength={100}
+                onChange={this.handleNameChange}
+                size="auto"
+                type="text"
+                value={name}
+              />
+            </FormField>
+          </form>
+        }
+        primaryButton={
+          <ButtonPrimary autoFocus type="submit" disabled={buttonDisabled} form={FORM_ID}>
+            {translate('copy')}
+          </ButtonPrimary>
+        }
+        secondaryButtonLabel={translate('cancel')}
+      />
     );
   }
 }
index b58782e863438b8ad2ee33675a626f0abb505e7e..a022e1115540059bab230742c285d178affa3b42 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import { DangerButtonPrimary, Modal } from 'design-system';
 import * as React from 'react';
 import { deleteQualityGate } from '../../../api/quality-gates';
-import { Button } from '../../../components/controls/buttons';
-import ConfirmButton from '../../../components/controls/ConfirmButton';
 import { Router, withRouter } from '../../../components/hoc/withRouter';
 import { translate, translateWithParameters } from '../../../helpers/l10n';
 import { getQualityGatesUrl } from '../../../helpers/urls';
 import { QualityGate } from '../../../types/types';
 
 interface Props {
+  readonly onClose: () => void;
   onDelete: () => Promise<void>;
   qualityGate: QualityGate;
   router: Router;
@@ -46,26 +46,17 @@ export class DeleteQualityGateForm extends React.PureComponent<Props> {
     const { qualityGate } = this.props;
 
     return (
-      <ConfirmButton
-        confirmButtonText={translate('delete')}
-        isDestructive
-        modalBody={translateWithParameters(
-          'quality_gates.delete.confirm.message',
-          qualityGate.name,
-        )}
-        modalHeader={translate('quality_gates.delete')}
-        onConfirm={this.onDelete}
-      >
-        {({ onClick }) => (
-          <Button
-            className="little-spacer-left button-red"
-            id="quality-gate-delete"
-            onClick={onClick}
-          >
+      <Modal
+        headerTitle={translate('quality_gates.delete')}
+        onClose={this.props.onClose}
+        body={translateWithParameters('quality_gates.delete.confirm.message', qualityGate.name)}
+        primaryButton={
+          <DangerButtonPrimary autoFocus type="submit" onClick={this.onDelete}>
             {translate('delete')}
-          </Button>
-        )}
-      </ConfirmButton>
+          </DangerButtonPrimary>
+        }
+        secondaryButtonLabel={translate('cancel')}
+      />
     );
   }
 }
index 4aff608825cf653f35a47f053a73daebd2b19be6..ed02c326faa2b9f665d6ee4a98afda092230f7a8 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
+import {
+  ActionsDropdown,
+  Badge,
+  ButtonSecondary,
+  DangerButtonPrimary,
+  FlagWarningIcon,
+  ItemButton,
+  ItemDangerButton,
+  ItemDivider,
+  SubTitle,
+} from 'design-system';
+import { countBy } from 'lodash';
 import * as React from 'react';
 import { setQualityGateAsDefault } from '../../../api/quality-gates';
-import ModalButton from '../../../components/controls/ModalButton';
 import Tooltip from '../../../components/controls/Tooltip';
-import { Button } from '../../../components/controls/buttons';
-import AlertWarnIcon from '../../../components/icons/AlertWarnIcon';
 import { translate } from '../../../helpers/l10n';
 import { CaycStatus, QualityGate } from '../../../types/types';
 import BuiltInQualityGateBadge from './BuiltInQualityGateBadge';
@@ -40,122 +50,180 @@ interface Props {
 
 const TOOLTIP_MOUSE_LEAVE_DELAY = 0.3;
 
-export default class DetailsHeader extends React.PureComponent<Props> {
-  handleActionRefresh = () => {
-    const { refreshItem, refreshList } = this.props;
+export default function DetailsHeader({
+  refreshItem,
+  refreshList,
+  onSetDefault,
+  qualityGate,
+}: Props) {
+  const [isRenameFormOpen, setIsRenameFormOpen] = React.useState(false);
+  const [isCopyFormOpen, setIsCopyFormOpen] = React.useState(false);
+  const [isRemoveFormOpen, setIsRemoveFormOpen] = React.useState(false);
+  const actions = qualityGate.actions ?? {};
+  const actionsCount = countBy([
+    actions.rename,
+    actions.copy,
+    actions.delete,
+    actions.setAsDefault,
+  ])['true'];
+  const canEdit = Boolean(actions?.manageConditions);
+
+  const handleActionRefresh = () => {
     return Promise.all([refreshItem(), refreshList()]).then(
       () => {},
       () => {},
     );
   };
 
-  handleSetAsDefaultClick = () => {
-    const { qualityGate } = this.props;
+  const handleSetAsDefaultClick = () => {
     if (!qualityGate.isDefault) {
       // Optimistic update
-      this.props.onSetDefault();
+      onSetDefault();
       setQualityGateAsDefault({ name: qualityGate.name }).then(
-        this.handleActionRefresh,
-        this.handleActionRefresh,
+        handleActionRefresh,
+        handleActionRefresh,
       );
     }
   };
 
-  render() {
-    const { qualityGate } = this.props;
-    const actions = qualityGate.actions || ({} as any);
-    const canEdit = Boolean(actions?.manageConditions);
-
-    return (
-      <div className="layout-page-header-panel layout-page-main-header issues-main-header">
-        <div className="layout-page-header-panel-inner layout-page-main-header-inner">
-          <div className="layout-page-main-inner">
-            <div className="pull-left display-flex-center">
-              <h2>{qualityGate.name}</h2>
-              {qualityGate.isBuiltIn && <BuiltInQualityGateBadge className="spacer-left" />}
-              {qualityGate.caycStatus === CaycStatus.NonCompliant && canEdit && (
-                <Tooltip overlay={<CaycBadgeTooltip />} mouseLeaveDelay={TOOLTIP_MOUSE_LEAVE_DELAY}>
-                  <AlertWarnIcon className="spacer-left" description={<CaycBadgeTooltip />} />
-                </Tooltip>
-              )}
-            </div>
-
-            <div className="pull-right">
-              {actions.rename && (
-                <ModalButton
-                  modal={({ onClose }) => (
-                    <RenameQualityGateForm
-                      onClose={onClose}
-                      onRename={this.props.refreshList}
-                      qualityGate={qualityGate}
-                    />
-                  )}
+  return (
+    <>
+      <div className="it__layout-page-main-header sw-flex sw-items-center sw-justify-between sw-mb-9">
+        <div className="sw-flex sw-flex-col">
+          <div className="sw-flex sw-items-center">
+            <SubTitle className="sw-m-0">{qualityGate.name}</SubTitle>
+            {qualityGate.caycStatus === CaycStatus.NonCompliant && canEdit && (
+              <Tooltip overlay={<CaycBadgeTooltip />} mouseLeaveDelay={TOOLTIP_MOUSE_LEAVE_DELAY}>
+                <FlagWarningIcon className="sw-ml-2" description={<CaycBadgeTooltip />} />
+              </Tooltip>
+            )}
+          </div>
+          <div className="sw-flex sw-gap-2 sw-mt-4">
+            {qualityGate.isDefault && <Badge>{translate('default')}</Badge>}
+            {qualityGate.isBuiltIn && <BuiltInQualityGateBadge />}
+          </div>
+        </div>
+        {actionsCount === 1 && (
+          <>
+            {actions.rename && (
+              <ButtonSecondary onClick={() => setIsRenameFormOpen(true)}>
+                {translate('rename')}
+              </ButtonSecondary>
+            )}
+            {actions.copy && (
+              <Tooltip
+                overlay={
+                  qualityGate.caycStatus === CaycStatus.NonCompliant
+                    ? translate('quality_gates.cannot_copy_no_cayc')
+                    : null
+                }
+              >
+                <ButtonSecondary
+                  disabled={qualityGate.caycStatus === CaycStatus.NonCompliant}
+                  onClick={() => setIsCopyFormOpen(true)}
                 >
-                  {({ onClick }) => (
-                    <Button id="quality-gate-rename" onClick={onClick}>
-                      {translate('rename')}
-                    </Button>
-                  )}
-                </ModalButton>
-              )}
-              {actions.copy && (
-                <ModalButton
-                  modal={({ onClose }) => (
-                    <CopyQualityGateForm
-                      onClose={onClose}
-                      onCopy={this.handleActionRefresh}
-                      qualityGate={qualityGate}
-                    />
-                  )}
+                  {translate('copy')}
+                </ButtonSecondary>
+              </Tooltip>
+            )}
+            {actions.setAsDefault && (
+              <Tooltip
+                overlay={
+                  qualityGate.caycStatus === CaycStatus.NonCompliant
+                    ? translate('quality_gates.cannot_set_default_no_cayc')
+                    : null
+                }
+              >
+                <ButtonSecondary
+                  disabled={qualityGate.caycStatus === CaycStatus.NonCompliant}
+                  onClick={handleSetAsDefaultClick}
                 >
-                  {({ onClick }) => (
-                    <Tooltip
-                      overlay={
-                        qualityGate.caycStatus === CaycStatus.NonCompliant
-                          ? translate('quality_gates.cannot_copy_no_cayc')
-                          : null
-                      }
-                    >
-                      <Button
-                        className="little-spacer-left"
-                        id="quality-gate-copy"
-                        onClick={onClick}
-                        disabled={qualityGate.caycStatus === CaycStatus.NonCompliant}
-                      >
-                        {translate('copy')}
-                      </Button>
-                    </Tooltip>
-                  )}
-                </ModalButton>
-              )}
-              {actions.setAsDefault && (
-                <Tooltip
-                  overlay={
-                    qualityGate.caycStatus === CaycStatus.NonCompliant
-                      ? translate('quality_gates.cannot_set_default_no_cayc')
-                      : null
-                  }
+                  {translate('set_as_default')}
+                </ButtonSecondary>
+              </Tooltip>
+            )}
+            {actions.delete && (
+              <DangerButtonPrimary onClick={() => setIsRemoveFormOpen(true)}>
+                {translate('delete')}
+              </DangerButtonPrimary>
+            )}
+          </>
+        )}
+
+        {actionsCount > 1 && (
+          <ActionsDropdown allowResizing id="quality-gate-actions">
+            {actions.rename && (
+              <ItemButton onClick={() => setIsRenameFormOpen(true)}>
+                {translate('rename')}
+              </ItemButton>
+            )}
+            {actions.copy && (
+              <Tooltip
+                overlay={
+                  qualityGate.caycStatus === CaycStatus.NonCompliant
+                    ? translate('quality_gates.cannot_copy_no_cayc')
+                    : null
+                }
+              >
+                <ItemButton
+                  disabled={qualityGate.caycStatus === CaycStatus.NonCompliant}
+                  onClick={() => setIsCopyFormOpen(true)}
                 >
-                  <Button
-                    className="little-spacer-left"
-                    disabled={qualityGate.caycStatus === CaycStatus.NonCompliant}
-                    id="quality-gate-toggle-default"
-                    onClick={this.handleSetAsDefaultClick}
-                  >
-                    {translate('set_as_default')}
-                  </Button>
-                </Tooltip>
-              )}
-              {actions.delete && (
-                <DeleteQualityGateForm
-                  onDelete={this.props.refreshList}
-                  qualityGate={qualityGate}
-                />
-              )}
-            </div>
-          </div>
-        </div>
+                  {translate('copy')}
+                </ItemButton>
+              </Tooltip>
+            )}
+            {actions.setAsDefault && (
+              <Tooltip
+                overlay={
+                  qualityGate.caycStatus === CaycStatus.NonCompliant
+                    ? translate('quality_gates.cannot_set_default_no_cayc')
+                    : null
+                }
+              >
+                <ItemButton
+                  disabled={qualityGate.caycStatus === CaycStatus.NonCompliant}
+                  onClick={handleSetAsDefaultClick}
+                >
+                  {translate('set_as_default')}
+                </ItemButton>
+              </Tooltip>
+            )}
+            {actions.delete && (
+              <>
+                <ItemDivider />
+                <ItemDangerButton onClick={() => setIsRemoveFormOpen(true)}>
+                  {translate('delete')}
+                </ItemDangerButton>
+              </>
+            )}
+          </ActionsDropdown>
+        )}
       </div>
-    );
-  }
+
+      {isRenameFormOpen && (
+        <RenameQualityGateForm
+          onClose={() => setIsRenameFormOpen(false)}
+          onRename={handleActionRefresh}
+          qualityGate={qualityGate}
+        />
+      )}
+
+      {isCopyFormOpen && (
+        <CopyQualityGateForm
+          onClose={() => setIsCopyFormOpen(false)}
+          onCopy={handleActionRefresh}
+          qualityGate={qualityGate}
+        />
+      )}
+
+      {isRemoveFormOpen && (
+        <DeleteQualityGateForm
+          onClose={() => setIsRemoveFormOpen(false)}
+          onDelete={refreshList}
+          qualityGate={qualityGate}
+        />
+      )}
+    </>
+  );
 }
index f1dc6dc79fabd03b45c0edfcf6c17bb61b4e0e04..9d2c26bf6629501f928df09364d2695a84a92312 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+import { ButtonPrimary, FormField, InputField, Modal } from 'design-system/lib';
 import * as React from 'react';
 import { renameQualityGate } from '../../../api/quality-gates';
-import ConfirmModal from '../../../components/controls/ConfirmModal';
-import { withRouter, WithRouterProps } from '../../../components/hoc/withRouter';
-import MandatoryFieldMarker from '../../../components/ui/MandatoryFieldMarker';
+import { WithRouterProps, withRouter } from '../../../components/hoc/withRouter';
 import MandatoryFieldsExplanation from '../../../components/ui/MandatoryFieldsExplanation';
 import { translate } from '../../../helpers/l10n';
 import { getQualityGateUrl } from '../../../helpers/urls';
@@ -37,6 +36,8 @@ interface State {
   name: string;
 }
 
+const FORM_ID = 'rename-quality-gate';
+
 class RenameQualityGateForm extends React.PureComponent<Props, State> {
   constructor(props: Props) {
     super(props);
@@ -47,13 +48,15 @@ class RenameQualityGateForm extends React.PureComponent<Props, State> {
     this.setState({ name: event.currentTarget.value });
   };
 
-  handleRename = () => {
+  handleRename = (event: React.FormEvent) => {
+    event.preventDefault();
+
     const { qualityGate, router } = this.props;
     const { name } = this.state;
 
     return renameQualityGate({ currentName: qualityGate.name, name }).then(() => {
-      this.props.onRename();
       router.push(getQualityGateUrl(name));
+      this.props.onRename();
     });
   };
 
@@ -63,32 +66,37 @@ class RenameQualityGateForm extends React.PureComponent<Props, State> {
     const confirmDisable = !name || (qualityGate && qualityGate.name === name);
 
     return (
-      <ConfirmModal
-        confirmButtonText={translate('rename')}
-        confirmDisable={confirmDisable}
-        header={translate('quality_gates.rename')}
+      <Modal
+        headerTitle={translate('quality_gates.rename')}
         onClose={this.props.onClose}
-        onConfirm={this.handleRename}
-        size="small"
-      >
-        <MandatoryFieldsExplanation className="modal-field" />
-        <div className="modal-field">
-          <label htmlFor="quality-gate-form-name">
-            {translate('name')}
-            <MandatoryFieldMarker />
-          </label>
-          <input
-            autoFocus
-            id="quality-gate-form-name"
-            maxLength={100}
-            onChange={this.handleNameChange}
-            required
-            size={50}
-            type="text"
-            value={name}
-          />
-        </div>
-      </ConfirmModal>
+        body={
+          <form id={FORM_ID} onSubmit={this.handleRename}>
+            <MandatoryFieldsExplanation />
+            <FormField
+              label={translate('name')}
+              htmlFor="quality-gate-form-name"
+              required
+              className="sw-my-2"
+            >
+              <InputField
+                autoFocus
+                id="quality-gate-form-name"
+                maxLength={100}
+                onChange={this.handleNameChange}
+                size="auto"
+                type="text"
+                value={name}
+              />
+            </FormField>
+          </form>
+        }
+        primaryButton={
+          <ButtonPrimary autoFocus type="submit" disabled={confirmDisable} form={FORM_ID}>
+            {translate('rename')}
+          </ButtonPrimary>
+        }
+        secondaryButtonLabel={translate('cancel')}
+      />
     );
   }
 }
index 8522ed7a4887e83c87d9786312a87c654d1ec1a8..ec15cdda3123dfbaa8baae7fe7c8b0d39fbe365f 100644 (file)
@@ -96,7 +96,9 @@ it('should be able to create a quality gate then delete it', async () => {
 
   // Delete the quality gate
   await user.click(newQG);
-  const deleteButton = await screen.findByRole('button', { name: 'delete' });
+
+  await user.click(screen.getByLabelText('menu'));
+  const deleteButton = screen.getByRole('menuitem', { name: 'delete' });
   await user.click(deleteButton);
   const popup = screen.getByRole('dialog');
   const dialogDeleteButton = within(popup).getByRole('button', { name: 'delete' });
@@ -114,7 +116,8 @@ it('should be able to copy a quality gate which is CAYC compliant', async () =>
 
   const notDefaultQualityGate = await screen.findByText('Sonar way');
   await user.click(notDefaultQualityGate);
-  const copyButton = await screen.findByRole('button', { name: 'copy' });
+  await user.click(screen.getByLabelText('menu'));
+  const copyButton = screen.getByRole('menuitem', { name: 'copy' });
 
   await user.click(copyButton);
   const nameInput = screen.getByRole('textbox', { name: /name.*/ });
@@ -133,8 +136,8 @@ it('should not be able to copy a quality gate which is not CAYC compliant', asyn
 
   const notDefaultQualityGate = await screen.findByText('SonarSource way - CFamily');
   await user.click(notDefaultQualityGate);
-
-  const copyButton = await screen.findByRole('button', { name: 'copy' });
+  await user.click(screen.getByLabelText('menu'));
+  const copyButton = screen.getByRole('menuitem', { name: 'copy' });
 
   expect(copyButton).toBeDisabled();
 });
@@ -143,8 +146,8 @@ it('should be able to rename a quality gate', async () => {
   const user = userEvent.setup();
   handler.setIsAdmin(true);
   renderQualityGateApp();
-
-  const renameButton = await screen.findByRole('button', { name: 'rename' });
+  await user.click(await screen.findByLabelText('menu'));
+  const renameButton = screen.getByRole('menuitem', { name: 'rename' });
 
   await user.click(renameButton);
   const nameInput = screen.getByRole('textbox', { name: /name.*/ });
@@ -162,7 +165,8 @@ it('should not be able to set as default a quality gate which is not CAYC compli
 
   const notDefaultQualityGate = await screen.findByText('SonarSource way - CFamily');
   await user.click(notDefaultQualityGate);
-  const setAsDefaultButton = screen.getByRole('button', { name: 'set_as_default' });
+  await user.click(screen.getByLabelText('menu'));
+  const setAsDefaultButton = screen.getByRole('menuitem', { name: 'set_as_default' });
   expect(setAsDefaultButton).toBeDisabled();
 });
 
@@ -173,7 +177,8 @@ it('should be able to set as default a quality gate which is CAYC compliant', as
 
   const notDefaultQualityGate = await screen.findByRole('button', { name: /Sonar way/ });
   await user.click(notDefaultQualityGate);
-  const setAsDefaultButton = screen.getByRole('button', { name: 'set_as_default' });
+  await user.click(screen.getByLabelText('menu'));
+  const setAsDefaultButton = screen.getByRole('menuitem', { name: 'set_as_default' });
   await user.click(setAsDefaultButton);
   expect(screen.getByRole('button', { name: /Sonar way default/ })).toBeInTheDocument();
 });