]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20086 - Migrating Bitbucket server page
authorKevin Silva <kevin.silva@sonarsource.com>
Thu, 10 Aug 2023 13:12:23 +0000 (15:12 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 14 Aug 2023 20:02:57 +0000 (20:02 +0000)
server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketImportRepositoryForm.tsx
server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectAccordion.tsx
server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectCreate.tsx
server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketProjectCreateRenderer.tsx
server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketRepositories.tsx
server/sonar-web/src/main/js/apps/create/project/BitbucketServer/BitbucketSearchResults.tsx
server/sonar-web/src/main/js/apps/create/project/__tests__/Bitbucket-it.tsx
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index bee7ea6a447ade7e04124dd9a01b5c544f9c505f..8ea8ca5afda269275ea0764457c714ce8de9ef21 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 { FlagMessage, InputSearch, Link } from 'design-system';
 import * as React from 'react';
 import { FormattedMessage } from 'react-intl';
-import Link from '../../../../components/common/Link';
-import SearchBox from '../../../../components/controls/SearchBox';
-import { Alert } from '../../../../components/ui/Alert';
 import { translate } from '../../../../helpers/l10n';
 import { queryToSearch } from '../../../../helpers/urls';
 import {
@@ -35,26 +33,19 @@ import BitbucketSearchResults from './BitbucketSearchResults';
 
 export interface BitbucketImportRepositoryFormProps {
   onSearch: (query: string) => void;
-  onSelectRepository: (repo: BitbucketRepository) => void;
+  onImportRepository: (repo: BitbucketRepository) => void;
   projects?: BitbucketProject[];
   projectRepositories?: BitbucketProjectRepositories;
   searching: boolean;
   searchResults?: BitbucketRepository[];
-  selectedRepository?: BitbucketRepository;
 }
 
 export default function BitbucketImportRepositoryForm(props: BitbucketImportRepositoryFormProps) {
-  const {
-    projects = [],
-    projectRepositories = {},
-    searchResults,
-    searching,
-    selectedRepository,
-  } = props;
+  const { projects = [], projectRepositories = {}, searchResults, searching } = props;
 
   if (projects.length === 0) {
     return (
-      <Alert className="spacer-top" variant="warning">
+      <FlagMessage variant="warning">
         <FormattedMessage
           defaultMessage={translate('onboarding.create_project.no_bbs_projects')}
           id="onboarding.create_project.no_bbs_projects"
@@ -71,31 +62,34 @@ export default function BitbucketImportRepositoryForm(props: BitbucketImportRepo
             ),
           }}
         />
-      </Alert>
+      </FlagMessage>
     );
   }
 
   return (
-    <div className="create-project-import-bbs">
-      <SearchBox
-        onChange={props.onSearch}
-        placeholder={translate('onboarding.create_project.search_repositories_by_name')}
-      />
+    <div>
+      <div className="sw-mb-10 sw-w-abs-400">
+        <InputSearch
+          searchInputAriaLabel={translate('onboarding.create_project.search_repositories_by_name')}
+          clearIconAriaLabel={translate('clear')}
+          onChange={props.onSearch}
+          placeholder={translate('onboarding.create_project.search_repositories_by_name')}
+          size="full"
+        />
+      </div>
 
       {searching || searchResults ? (
         <BitbucketSearchResults
-          onSelectRepository={props.onSelectRepository}
+          onImportRepository={props.onImportRepository}
           projects={projects}
           searchResults={searchResults}
           searching={searching}
-          selectedRepository={selectedRepository}
         />
       ) : (
         <BitbucketRepositories
-          onSelectRepository={props.onSelectRepository}
+          onImportRepository={props.onImportRepository}
           projectRepositories={projectRepositories}
           projects={projects}
-          selectedRepository={selectedRepository}
         />
       )}
     </div>
index d6dda0e868043e15742c46722c9101c0f92006ea..99c3291f515236104cb0fc986977593bd2671640 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 classNames from 'classnames';
+import { Accordion, FlagMessage, Link } from 'design-system';
 import * as React from 'react';
 import { FormattedMessage } from 'react-intl';
-import { colors } from '../../../../app/theme';
-import Link from '../../../../components/common/Link';
-import BoxedGroupAccordion from '../../../../components/controls/BoxedGroupAccordion';
-import Radio from '../../../../components/controls/Radio';
-import CheckIcon from '../../../../components/icons/CheckIcon';
-import { Alert } from '../../../../components/ui/Alert';
 import { translate, translateWithParameters } from '../../../../helpers/l10n';
-import { getProjectUrl, queryToSearch } from '../../../../helpers/urls';
+import { getBaseUrl } from '../../../../helpers/system';
+import { queryToSearch } from '../../../../helpers/urls';
 import { BitbucketProject, BitbucketRepository } from '../../../../types/alm-integration';
+import AlmRepoItem from '../components/AlmRepoItem';
 import { CreateProjectModes } from '../types';
 
 export interface BitbucketProjectAccordionProps {
   onClick?: () => void;
-  onSelectRepository: (repo: BitbucketRepository) => void;
+  onImportRepository: (repository: BitbucketRepository) => void;
   open: boolean;
   project?: BitbucketProject;
   repositories: BitbucketRepository[];
-  selectedRepository?: BitbucketRepository;
   showingAllRepositories: boolean;
 }
 
 export default function BitbucketProjectAccordion(props: BitbucketProjectAccordionProps) {
-  const { open, project, repositories, selectedRepository, showingAllRepositories } = props;
+  const { open, project, repositories, showingAllRepositories } = props;
 
   const repositoryCount = repositories.length;
 
   const title = project?.name ?? translate('search_results');
 
   return (
-    <BoxedGroupAccordion
-      className={classNames('big-spacer-bottom', {
-        open,
-        'not-clickable': !props.onClick,
-        'no-hover': !props.onClick,
-      })}
+    <Accordion
+      className="sw-mb-6"
       onClick={
         props.onClick
           ? props.onClick
@@ -63,13 +54,13 @@ export default function BitbucketProjectAccordion(props: BitbucketProjectAccordi
             }
       }
       open={open}
-      title={<h3>{title}</h3>}
+      header={title}
     >
       {open && (
         <>
-          <div className="display-flex-wrap">
+          <div className="sw-mb-4">
             {repositoryCount === 0 && (
-              <Alert variant="warning">
+              <FlagMessage variant="warning">
                 <FormattedMessage
                   defaultMessage={translate('onboarding.create_project.no_bbs_repos')}
                   id="onboarding.create_project.no_bbs_repos"
@@ -89,49 +80,33 @@ export default function BitbucketProjectAccordion(props: BitbucketProjectAccordi
                     ),
                   }}
                 />
-              </Alert>
+              </FlagMessage>
             )}
 
-            {repositories.map((repo) =>
-              repo.sqProjectKey ? (
-                <div
-                  className="display-flex-start spacer-right spacer-bottom create-project-import-bbs-repo"
-                  key={repo.id}
-                >
-                  <CheckIcon className="spacer-right" fill={colors.green} size={14} />
-                  <div className="overflow-hidden">
-                    <div className="little-spacer-bottom">
-                      <strong title={repo.name}>
-                        <Link to={getProjectUrl(repo.sqProjectKey)}>{repo.name}</Link>
-                      </strong>
-                    </div>
-                    <em>{translate('onboarding.create_project.repository_imported')}</em>
-                  </div>
-                </div>
-              ) : (
-                <Radio
-                  checked={selectedRepository?.id === repo.id}
-                  className="display-flex-start spacer-right spacer-bottom create-project-import-bbs-repo overflow-hidden"
-                  key={repo.id}
-                  onCheck={() => props.onSelectRepository(repo)}
-                  value={String(repo.id)}
-                >
-                  <strong title={repo.name}>{repo.name}</strong>
-                </Radio>
-              )
-            )}
+            <div className="sw-flex sw-flex-col sw-gap-3">
+              {repositories.map((r) => (
+                <AlmRepoItem
+                  key={r.name}
+                  almKey={r.name}
+                  almIconSrc={`${getBaseUrl()}/images/alm/bitbucket.svg`}
+                  sqProjectKey={r.sqProjectKey}
+                  onImport={() => props.onImportRepository(r)}
+                  primaryTextNode={<span>{r.name}</span>}
+                />
+              ))}
+            </div>
           </div>
 
           {!showingAllRepositories && repositoryCount > 0 && (
-            <Alert variant="warning">
+            <FlagMessage variant="warning">
               {translateWithParameters(
                 'onboarding.create_project.only_showing_X_first_repos',
                 repositoryCount
               )}
-            </Alert>
+            </FlagMessage>
           )}
         </>
       )}
-    </BoxedGroupAccordion>
+    </Accordion>
   );
 }
index 0613375131aa10bfc29fe16031cef91c41e604c6..87b2af6cc2f960a811e5b16e36c3707a49e61515 100644 (file)
@@ -51,7 +51,6 @@ interface State {
   projectRepositories?: BitbucketProjectRepositories;
   searching: boolean;
   searchResults?: BitbucketRepository[];
-  selectedRepository?: BitbucketRepository;
   showPersonalAccessTokenForm: boolean;
 }
 
@@ -181,10 +180,10 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
     await this.fetchInitialData();
   };
 
-  handleImportRepository = () => {
-    const { selectedAlmInstance, selectedRepository } = this.state;
+  handleImportRepository = (selectedRepository: BitbucketRepository) => {
+    const { selectedAlmInstance } = this.state;
 
-    if (selectedAlmInstance && selectedRepository) {
+    if (selectedAlmInstance) {
       this.props.onProjectSetupDone(
         setupBitbucketServerProjectCreation({
           almSetting: selectedAlmInstance.key,
@@ -203,11 +202,11 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
     }
 
     if (!query) {
-      this.setState({ searching: false, searchResults: undefined, selectedRepository: undefined });
+      this.setState({ searching: false, searchResults: undefined });
       return;
     }
 
-    this.setState({ searching: true, selectedRepository: undefined });
+    this.setState({ searching: true });
     searchForBitbucketServerRepositories(selectedAlmInstance.key, query)
       .then(({ repositories }) => {
         if (this.mounted) {
@@ -221,10 +220,6 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
       });
   };
 
-  handleSelectRepository = (selectedRepository: BitbucketRepository) => {
-    this.setState({ selectedRepository });
-  };
-
   onSelectedAlmInstanceChange = (instance: AlmSettingsInstance) => {
     this.setState({
       selectedAlmInstance: instance,
@@ -243,7 +238,6 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
       projects,
       searching,
       searchResults,
-      selectedRepository,
       showPersonalAccessTokenForm,
     } = this.state;
 
@@ -256,14 +250,12 @@ export default class BitbucketProjectCreate extends React.PureComponent<Props, S
         onImportRepository={this.handleImportRepository}
         onPersonalAccessTokenCreated={this.handlePersonalAccessTokenCreated}
         onSearch={this.handleSearch}
-        onSelectRepository={this.handleSelectRepository}
         onSelectedAlmInstanceChange={this.onSelectedAlmInstanceChange}
         projectRepositories={projectRepositories}
         projects={projects}
         resetPat={Boolean(location.query.resetPat)}
         searchResults={searchResults}
         searching={searching}
-        selectedRepository={selectedRepository}
         showPersonalAccessTokenForm={
           showPersonalAccessTokenForm || Boolean(location.query.resetPat)
         }
index 426079c2836dedbc4f33859658ac205340d4dc39..0b435d15b5dc0222bda460a9806c8b6a33742969 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 { DeferredSpinner, LightPrimary, PageContentFontWrapper, Title } from 'design-system';
 import * as React from 'react';
-import { Button } from '../../../../components/controls/buttons';
 import { translate } from '../../../../helpers/l10n';
-import { getBaseUrl } from '../../../../helpers/system';
 import {
   BitbucketProject,
   BitbucketProjectRepositories,
@@ -28,7 +27,6 @@ import {
 } from '../../../../types/alm-integration';
 import { AlmKeys, AlmSettingsInstance } from '../../../../types/alm-settings';
 import AlmSettingsInstanceDropdown from '../components/AlmSettingsInstanceDropdown';
-import CreateProjectPageHeader from '../components/CreateProjectPageHeader';
 import PersonalAccessTokenForm from '../components/PersonalAccessTokenForm';
 import WrongBindingCountAlert from '../components/WrongBindingCountAlert';
 import BitbucketImportRepositoryForm from './BitbucketImportRepositoryForm';
@@ -38,9 +36,8 @@ export interface BitbucketProjectCreateRendererProps {
   almInstances: AlmSettingsInstance[];
   canAdmin?: boolean;
   loading: boolean;
-  onImportRepository: () => void;
+  onImportRepository: (repository: BitbucketRepository) => void;
   onSearch: (query: string) => void;
-  onSelectRepository: (repo: BitbucketRepository) => void;
   onPersonalAccessTokenCreated: () => void;
   onSelectedAlmInstanceChange: (instance: AlmSettingsInstance) => void;
   projects?: BitbucketProject[];
@@ -48,7 +45,6 @@ export interface BitbucketProjectCreateRendererProps {
   resetPat: boolean;
   searching: boolean;
   searchResults?: BitbucketRepository[];
-  selectedRepository?: BitbucketRepository;
   showPersonalAccessTokenForm?: boolean;
 }
 
@@ -60,7 +56,7 @@ export default function BitbucketProjectCreateRenderer(props: BitbucketProjectCr
     loading,
     projects,
     projectRepositories,
-    selectedRepository,
+
     searching,
     searchResults,
     showPersonalAccessTokenForm,
@@ -68,33 +64,15 @@ export default function BitbucketProjectCreateRenderer(props: BitbucketProjectCr
   } = props;
 
   return (
-    <>
-      <CreateProjectPageHeader
-        additionalActions={
-          !showPersonalAccessTokenForm && (
-            <div className="display-flex-center pull-right">
-              <Button
-                className="button-large button-primary"
-                disabled={!selectedRepository}
-                onClick={props.onImportRepository}
-              >
-                {translate('onboarding.create_project.import_selected_repo')}
-              </Button>
-            </div>
-          )
-        }
-        title={
-          <span className="text-middle">
-            <img
-              alt="" // Should be ignored by screen readers
-              className="spacer-right"
-              height="24"
-              src={`${getBaseUrl()}/images/alm/bitbucket.svg`}
-            />
-            {translate('onboarding.create_project.from_bbs')}
-          </span>
-        }
-      />
+    <PageContentFontWrapper>
+      <header className="sw-mb-10">
+        <Title className="sw-mb-4">
+          {translate('onboarding.create_project.import_selected_repo')}
+        </Title>
+        <LightPrimary className="sw-body-sm">
+          {translate('onboarding.create_project.from_bbs')}
+        </LightPrimary>
+      </header>
 
       <AlmSettingsInstanceDropdown
         almKey={AlmKeys.BitbucketServer}
@@ -103,31 +81,29 @@ export default function BitbucketProjectCreateRenderer(props: BitbucketProjectCr
         onChangeConfig={props.onSelectedAlmInstanceChange}
       />
 
-      {loading && <i className="spinner" />}
+      <DeferredSpinner loading={loading}>
+        {!selectedAlmInstance && (
+          <WrongBindingCountAlert alm={AlmKeys.BitbucketServer} canAdmin={!!canAdmin} />
+        )}
 
-      {!loading && !selectedAlmInstance && (
-        <WrongBindingCountAlert alm={AlmKeys.BitbucketServer} canAdmin={!!canAdmin} />
-      )}
-
-      {!loading &&
-        selectedAlmInstance &&
-        (showPersonalAccessTokenForm ? (
-          <PersonalAccessTokenForm
-            almSetting={selectedAlmInstance}
-            onPersonalAccessTokenCreated={props.onPersonalAccessTokenCreated}
-            resetPat={resetPat}
-          />
-        ) : (
-          <BitbucketImportRepositoryForm
-            onSearch={props.onSearch}
-            onSelectRepository={props.onSelectRepository}
-            projectRepositories={projectRepositories}
-            projects={projects}
-            searchResults={searchResults}
-            searching={searching}
-            selectedRepository={selectedRepository}
-          />
-        ))}
-    </>
+        {selectedAlmInstance &&
+          (showPersonalAccessTokenForm ? (
+            <PersonalAccessTokenForm
+              almSetting={selectedAlmInstance}
+              onPersonalAccessTokenCreated={props.onPersonalAccessTokenCreated}
+              resetPat={resetPat}
+            />
+          ) : (
+            <BitbucketImportRepositoryForm
+              onSearch={props.onSearch}
+              projectRepositories={projectRepositories}
+              projects={projects}
+              searchResults={searchResults}
+              searching={searching}
+              onImportRepository={props.onImportRepository}
+            />
+          ))}
+      </DeferredSpinner>
+    </PageContentFontWrapper>
   );
 }
index ef53100e336a9e03144202bd0f5f9eb26e4d51ee..8caf9497501199dc57bb1184db6d4cdc723cce35 100644 (file)
@@ -19,8 +19,6 @@
  */
 import { uniq, without } from 'lodash';
 import * as React from 'react';
-import { ButtonLink } from '../../../../components/controls/buttons';
-import { translate } from '../../../../helpers/l10n';
 import {
   BitbucketProject,
   BitbucketProjectRepositories,
@@ -29,21 +27,18 @@ import {
 import BitbucketProjectAccordion from './BitbucketProjectAccordion';
 
 export interface BitbucketRepositoriesProps {
-  onSelectRepository: (repo: BitbucketRepository) => void;
+  onImportRepository: (repo: BitbucketRepository) => void;
   projects: BitbucketProject[];
   projectRepositories: BitbucketProjectRepositories;
-  selectedRepository?: BitbucketRepository;
 }
 
 export default function BitbucketRepositories(props: BitbucketRepositoriesProps) {
-  const { projects, projectRepositories, selectedRepository } = props;
+  const { projects, projectRepositories } = props;
 
   const [openProjectKeys, setOpenProjectKeys] = React.useState(
     projects.length > 0 ? [projects[0].key] : []
   );
 
-  const allAreExpanded = projects.length <= openProjectKeys.length;
-
   const handleClick = (isOpen: boolean, projectKey: string) => {
     setOpenProjectKeys(
       isOpen ? without(openProjectKeys, projectKey) : uniq([...openProjectKeys, projectKey])
@@ -52,15 +47,6 @@ export default function BitbucketRepositories(props: BitbucketRepositoriesProps)
 
   return (
     <>
-      <div className="overflow-hidden spacer-bottom">
-        <ButtonLink
-          className="pull-right"
-          onClick={() => setOpenProjectKeys(allAreExpanded ? [] : projects.map((p) => p.key))}
-        >
-          {allAreExpanded ? translate('collapse_all') : translate('expand_all')}
-        </ButtonLink>
-      </div>
-
       {projects.map((project) => {
         const isOpen = openProjectKeys.includes(project.key);
         const { allShown, repositories = [] } = projectRepositories[project.key] || {};
@@ -69,12 +55,11 @@ export default function BitbucketRepositories(props: BitbucketRepositoriesProps)
           <BitbucketProjectAccordion
             key={project.key}
             onClick={() => handleClick(isOpen, project.key)}
-            onSelectRepository={props.onSelectRepository}
             open={isOpen}
             project={project}
             repositories={repositories}
-            selectedRepository={selectedRepository}
             showingAllRepositories={allShown}
+            onImportRepository={props.onImportRepository}
           />
         );
       })}
index a72b1d95e502600dd0c3e540e3eed919c1b2321c..4afc74f2460441df106b23ba64691006c7070ee0 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 { DeferredSpinner, FlagMessage } from 'design-system';
 import * as React from 'react';
-import { Alert } from '../../../../components/ui/Alert';
-import DeferredSpinner from '../../../../components/ui/DeferredSpinner';
 import { translate } from '../../../../helpers/l10n';
 import { BitbucketProject, BitbucketRepository } from '../../../../types/alm-integration';
 import BitbucketProjectAccordion from './BitbucketProjectAccordion';
 
 export interface BitbucketSearchResultsProps {
-  onSelectRepository: (repo: BitbucketRepository) => void;
+  onImportRepository: (repo: BitbucketRepository) => void;
   projects: BitbucketProject[];
   searching: boolean;
   searchResults?: BitbucketRepository[];
-  selectedRepository?: BitbucketRepository;
 }
 
 export default function BitbucketSearchResults(props: BitbucketSearchResultsProps) {
-  const { projects, searching, searchResults = [], selectedRepository } = props;
+  const { projects, searching, searchResults = [] } = props;
 
   if (searchResults.length === 0 && !searching) {
     return (
-      <Alert className="big-spacer-top" variant="warning">
+      <FlagMessage variant="warning">
         {translate('onboarding.create_project.no_bbs_repos.filter')}
-      </Alert>
+      </FlagMessage>
     );
   }
 
@@ -52,34 +50,30 @@ export default function BitbucketSearchResults(props: BitbucketSearchResultsProp
   );
 
   return (
-    <div className="big-spacer-top">
-      <DeferredSpinner loading={searching}>
-        {filteredSearchResults.length > 0 && (
+    <DeferredSpinner loading={searching}>
+      {filteredSearchResults.length > 0 && (
+        <BitbucketProjectAccordion
+          onImportRepository={props.onImportRepository}
+          open
+          repositories={filteredSearchResults}
+          showingAllRepositories
+        />
+      )}
+
+      {filteredProjects.map((project) => {
+        const repositories = searchResults.filter((r) => r.projectKey === project.key);
+
+        return (
           <BitbucketProjectAccordion
-            onSelectRepository={props.onSelectRepository}
+            onImportRepository={props.onImportRepository}
+            key={project.key}
             open
-            repositories={filteredSearchResults}
-            selectedRepository={selectedRepository}
+            project={project}
+            repositories={repositories}
             showingAllRepositories
           />
-        )}
-
-        {filteredProjects.map((project) => {
-          const repositories = searchResults.filter((r) => r.projectKey === project.key);
-
-          return (
-            <BitbucketProjectAccordion
-              key={project.key}
-              onSelectRepository={props.onSelectRepository}
-              open
-              project={project}
-              repositories={repositories}
-              selectedRepository={selectedRepository}
-              showingAllRepositories
-            />
-          );
-        })}
-      </DeferredSpinner>
-    </div>
+        );
+      })}
+    </DeferredSpinner>
   );
 }
index a7916f10af82b04b15501e20b25a029e8365620a..6b807c894857da2fcd4c8610854ef064347c25b1 100644 (file)
@@ -108,10 +108,6 @@ it('should show import project feature when PAT is already set', async () => {
 
   expect(screen.getByText('Bitbucket Project 1')).toBeInTheDocument();
 
-  await user.click(screen.getByRole('button', { name: 'expand_all' }));
-
-  expect(screen.getByRole('button', { name: 'collapse_all' })).toBeInTheDocument();
-
   const projectItem = screen.getByRole('region', { name: /Bitbucket Project 1/ });
 
   expect(
@@ -125,15 +121,20 @@ it('should show import project feature when PAT is already set', async () => {
   );
 
   await user.click(projectItem);
-  const radioButton = within(projectItem).getByRole('radio', {
-    name: 'Bitbucket Repo 2',
-  });
-  const importButton = screen.getByText('onboarding.create_project.import_selected_repo');
 
-  expect(radioButton).toBeInTheDocument();
-  expect(importButton).toBeDisabled();
-  await user.click(radioButton);
-  expect(importButton).toBeEnabled();
+  expect(
+    screen.getByRole('row', {
+      name: 'Bitbucket Repo 1 onboarding.create_project.repository_imported',
+    })
+  ).toBeInTheDocument();
+
+  expect(
+    screen.getByRole('row', {
+      name: 'Bitbucket Repo 2 onboarding.create_project.import',
+    })
+  ).toBeInTheDocument();
+
+  const importButton = screen.getByText('onboarding.create_project.import');
   await user.click(importButton);
 
   expect(
index 1268881dd6584467ab06cf51d133c629c0ce9c61..e593a4af405c6f89396b1dad351b000907fa5e9d 100644 (file)
@@ -2402,7 +2402,7 @@ my_account.create_new.TRK=Add a project
 my_account.add_project=Add Project
 my_account.add_project.manual=Manually
 my_account.add_project.azure=From Azure DevOps
-my_account.add_project.bitbucket=from Bitbucket Server
+my_account.add_project.bitbucket=From Bitbucket Server
 my_account.add_project.bitbucketcloud=From Bitbucket Cloud
 my_account.add_project.github=From GitHub
 my_account.add_project.gitlab=From GitLab