]> source.dussan.org Git - sonarqube.git/commitdiff
[NO-JIRA] Improve ButtonToggle accessibility
authorPhilippe Perrin <philippe.perrin@sonarsource.com>
Tue, 12 Jul 2022 12:44:50 +0000 (14:44 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 18 Jul 2022 20:03:26 +0000 (20:03 +0000)
47 files changed:
server/sonar-web/src/main/js/apps/code/components/Search.tsx
server/sonar-web/src/main/js/apps/code/components/__tests__/__snapshots__/Search-test.tsx.snap
server/sonar-web/src/main/js/apps/coding-rules/__tests__/CodingRules-it.ts
server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx
server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx
server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesApp-test.tsx.snap
server/sonar-web/src/main/js/apps/marketplace/Search.tsx
server/sonar-web/src/main/js/apps/permissions/shared/components/SearchForm.tsx
server/sonar-web/src/main/js/apps/projects/components/FavoriteFilter.tsx
server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/App-it.tsx
server/sonar-web/src/main/js/apps/security-hotspots/components/FilterBar.tsx
server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/FilterBar-test.tsx.snap
server/sonar-web/src/main/js/apps/settings/components/almIntegration/BitbucketForm.tsx
server/sonar-web/src/main/js/apps/settings/components/almIntegration/__tests__/__snapshots__/BitbucketForm-test.tsx.snap
server/sonar-web/src/main/js/components/controls/ButtonToggle.css
server/sonar-web/src/main/js/components/controls/ButtonToggle.tsx
server/sonar-web/src/main/js/components/controls/SelectList.tsx
server/sonar-web/src/main/js/components/controls/__tests__/ButtonToggle-test.tsx
server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ButtonToggle-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SelectList-test.tsx.snap
server/sonar-web/src/main/js/components/controls/buttons.css
server/sonar-web/src/main/js/components/rules/RuleDescription.tsx
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/BranchAnalysisStepContent.tsx
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/__tests__/__snapshots__/BranchAnalysisStepContent-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/ClangGCC.tsx
server/sonar-web/src/main/js/components/tutorials/azure-pipelines/commands/__tests__/__snapshots__/ClangGCC-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/components/RenderOptions.tsx
server/sonar-web/src/main/js/components/tutorials/components/YamlFileStep.tsx
server/sonar-web/src/main/js/components/tutorials/components/__tests__/RenderOptions-test.tsx
server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/RenderOptions-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/YamlFileStep-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/github-action/commands/CFamily.tsx
server/sonar-web/src/main/js/components/tutorials/github-action/commands/__tests__/__snapshots__/CFamily-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/gitlabci/ProjectKeyStep.tsx
server/sonar-web/src/main/js/components/tutorials/gitlabci/__tests__/__snapshots__/ProjectKeyStep-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/SelectAlmStep.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/SelectAlmStep-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/CFamilly.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/DotNet.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/CFamilly-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/jenkins/buildtool-steps/__tests__/__snapshots__/DotNet-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/other/BuildToolForm.tsx
server/sonar-web/src/main/js/components/tutorials/other/__tests__/__snapshots__/BuildToolForm-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/other/commands/DotNet.tsx
server/sonar-web/src/main/js/components/tutorials/other/commands/__tests__/__snapshots__/DotNet-test.tsx.snap

index 8fee9b154cca6a4accdeb4fc2f908e0842063a60..67c80e5c85ff622ae50b6d3df6cee56b9d58de07 100644 (file)
@@ -140,24 +140,23 @@ export class Search extends React.PureComponent<Props, State> {
     return (
       <div className="code-search" id="code-search">
         {isPortfolio && (
-          <ButtonToggle
-            name="portfolio-scope"
-            className="big-spacer-right"
-            options={[
-              {
-                value: true,
-                label: translate('projects.view.new_code'),
-                disabled: !isEmpty(query)
-              },
-              {
-                value: false,
-                label: translate('projects.view.overall_code'),
-                disabled: !isEmpty(query)
-              }
-            ]}
-            value={newCodeSelected}
-            onCheck={this.props.onNewCodeToggle}
-          />
+          <span className="big-spacer-right">
+            <ButtonToggle
+              disabled={!isEmpty(query)}
+              options={[
+                {
+                  value: true,
+                  label: translate('projects.view.new_code')
+                },
+                {
+                  value: false,
+                  label: translate('projects.view.overall_code')
+                }
+              ]}
+              value={newCodeSelected}
+              onCheck={this.props.onNewCodeToggle}
+            />
+          </span>
         )}
         <SearchBox
           minLength={3}
index 3c526b8b107d82660fa3e48d5b4e40d25dd3146b..9fa3873195fafe94d2694bad9638368ee478040a 100644 (file)
@@ -24,27 +24,27 @@ exports[`should render correcly: new code toggle for portfolio 1`] = `
   className="code-search"
   id="code-search"
 >
-  <ButtonToggle
+  <span
     className="big-spacer-right"
-    disabled={false}
-    name="portfolio-scope"
-    onCheck={[MockFunction]}
-    options={
-      Array [
-        Object {
-          "disabled": false,
-          "label": "projects.view.new_code",
-          "value": true,
-        },
-        Object {
-          "disabled": false,
-          "label": "projects.view.overall_code",
-          "value": false,
-        },
-      ]
-    }
-    value={false}
-  />
+  >
+    <ButtonToggle
+      disabled={false}
+      onCheck={[MockFunction]}
+      options={
+        Array [
+          Object {
+            "label": "projects.view.new_code",
+            "value": true,
+          },
+          Object {
+            "label": "projects.view.overall_code",
+            "value": false,
+          },
+        ]
+      }
+      value={false}
+    />
+  </span>
   <SearchBox
     minLength={3}
     onChange={[Function]}
@@ -64,27 +64,27 @@ exports[`should render correcly: new code toggle for portfolio disabled 1`] = `
   className="code-search"
   id="code-search"
 >
-  <ButtonToggle
+  <span
     className="big-spacer-right"
-    disabled={false}
-    name="portfolio-scope"
-    onCheck={[MockFunction]}
-    options={
-      Array [
-        Object {
-          "disabled": true,
-          "label": "projects.view.new_code",
-          "value": true,
-        },
-        Object {
-          "disabled": true,
-          "label": "projects.view.overall_code",
-          "value": false,
-        },
-      ]
-    }
-    value={false}
-  />
+  >
+    <ButtonToggle
+      disabled={true}
+      onCheck={[MockFunction]}
+      options={
+        Array [
+          Object {
+            "label": "projects.view.new_code",
+            "value": true,
+          },
+          Object {
+            "label": "projects.view.overall_code",
+            "value": false,
+          },
+        ]
+      }
+      value={false}
+    />
+  </span>
   <SearchBox
     minLength={3}
     onChange={[Function]}
index b159a3d56933d0114912f0af2163f9e3f1b94540..4b98d0ba8c8e53789f854a87914b99156278bedb 100644 (file)
@@ -153,21 +153,21 @@ it('should show rule advanced section with context', async () => {
       name: 'coding_rules.description_section.title.how_to_fix'
     })
   );
-  expect(screen.getByRole('radio', { name: 'Spring' })).toBeInTheDocument();
-  expect(screen.getByRole('radio', { name: 'Spring boot' })).toBeInTheDocument();
+  expect(screen.getByRole('button', { name: 'Spring' })).toBeInTheDocument();
+  expect(screen.getByRole('button', { name: 'Spring boot' })).toBeInTheDocument();
   expect(
-    screen.getByRole('radio', { name: 'coding_rules.description_context.other' })
+    screen.getByRole('button', { name: 'coding_rules.description_context.other' })
   ).toBeInTheDocument();
   expect(screen.getByText('coding_rules.description_context.sub_title.Spring')).toBeInTheDocument();
   expect(screen.getByText('This is how to fix for spring')).toBeInTheDocument();
 
-  await user.click(screen.getByRole('radio', { name: 'Spring boot' }));
+  await user.click(screen.getByRole('button', { name: 'Spring boot' }));
   expect(
     screen.getByText('coding_rules.description_context.sub_title.Spring boot')
   ).toBeInTheDocument();
   expect(screen.getByText('This is how to fix for spring boot')).toBeInTheDocument();
 
-  await user.click(screen.getByRole('radio', { name: 'coding_rules.description_context.other' }));
+  await user.click(screen.getByRole('button', { name: 'coding_rules.description_context.other' }));
   expect(
     screen.queryByText(
       'coding_rules.description_context.sub_title.coding_rules.description_context.other'
index aa9052cba31f951f9dbf791589e56f05dc26ce37..c3184867fb90eaa396c089c5ee8ea44a0aeaa85b 100644 (file)
@@ -69,20 +69,20 @@ it('should open issue and navigate', async () => {
   await user.click(screen.getByRole('button', { name: `issue.tabs.how_to_fix` }));
 
   // Is the context selector present with the expected values and default selection?
-  expect(screen.getByRole('radio', { name: 'Context 2' })).toBeInTheDocument();
-  expect(screen.getByRole('radio', { name: 'Context 3' })).toBeInTheDocument();
-  expect(screen.getByRole('radio', { name: 'Spring' })).toBeInTheDocument();
+  expect(screen.getByRole('button', { name: 'Context 2' })).toBeInTheDocument();
+  expect(screen.getByRole('button', { name: 'Context 3' })).toBeInTheDocument();
+  expect(screen.getByRole('button', { name: 'Spring' })).toBeInTheDocument();
   expect(
-    screen.getByRole('radio', { name: 'coding_rules.description_context.other' })
+    screen.getByRole('button', { name: 'coding_rules.description_context.other' })
   ).toBeInTheDocument();
-  expect(screen.getByRole('radio', { name: 'Spring' })).toBeChecked();
+  expect(screen.getByRole('button', { name: 'Spring' })).toHaveClass('selected');
 
   // Select context 2 and check tab content
-  await user.click(screen.getByRole('radio', { name: 'Context 2' }));
+  await user.click(screen.getByRole('button', { name: 'Context 2' }));
   expect(screen.getByText('Context 2 content')).toBeInTheDocument();
 
   // Select the "other" context and check tab content
-  await user.click(screen.getByRole('radio', { name: 'coding_rules.description_context.other' }));
+  await user.click(screen.getByRole('button', { name: 'coding_rules.description_context.other' }));
   expect(screen.getByText('coding_rules.context.others.title')).toBeInTheDocument();
   expect(screen.getByText('coding_rules.context.others.description.first')).toBeInTheDocument();
   expect(screen.getByText('coding_rules.context.others.description.second')).toBeInTheDocument();
index f17301ba6a42c3105f5c6884aebdd628c1342b17..99d36dbfc4d8b0b5f6a084b1f7824910b692c5fe 100644 (file)
@@ -886,7 +886,6 @@ export class App extends React.PureComponent<Props, State> {
         {currentUser.isLoggedIn && (
           <div className="display-flex-justify-center big-spacer-bottom">
             <ButtonToggle
-              name="my-issue-filter"
               options={[
                 { value: true, label: translate('issues.my_issues') },
                 { value: false, label: translate('all') }
index 420babbff3c79b832573531337652952a36a3c1c..65ca848f341cd92bcb5620c767fb0bd0b0097d20 100644 (file)
@@ -61,8 +61,6 @@ exports[`should show warnning when not all projects are accessible 1`] = `
           className="display-flex-justify-center big-spacer-bottom"
         >
           <ButtonToggle
-            disabled={false}
-            name="my-issue-filter"
             onCheck={[Function]}
             options={
               Array [
index 2c9544b506bd725bbc3c4a8cf7a33e9179c8e339..8adefc03bb3b60f7c804c0cbc0e9423fcb86ce2c 100644 (file)
@@ -52,7 +52,6 @@ export default class Search extends React.PureComponent<Props> {
       <div className="big-spacer-bottom" id="marketplace-search">
         <div className="display-inline-block text-top nowrap abs-width-240 spacer-right">
           <ButtonToggle
-            name="marketplace-filter"
             onCheck={this.handleFilterChange}
             options={radioOptions}
             value={query.filter}
index 7c9b91b6ede50385a982e71a048236af65a07a91..05473328be1cf2133c76a6628e2740421851fd3f 100644 (file)
@@ -38,12 +38,7 @@ export default function SearchForm(props: Props) {
 
   return (
     <div className="display-flex-row">
-      <ButtonToggle
-        name="users-or-groups"
-        onCheck={props.onFilter}
-        options={filterOptions}
-        value={props.filter}
-      />
+      <ButtonToggle onCheck={props.onFilter} options={filterOptions} value={props.filter} />
 
       <div className="flex-1 spacer-left">
         <SearchBox
index 66b337a674e170533fed5315132273d4f2d55d04..008d4380449d4e44449818ddb384b4a0327be38e 100644 (file)
@@ -64,7 +64,6 @@ export class FavoriteFilter extends React.PureComponent<Props> {
     return (
       <div className="page-header text-center">
         <ButtonToggle
-          name="favorite-filter"
           options={[
             { value: true, label: translate('my_favorites') },
             { value: false, label: translate('all') }
index a376ce36407fece9cbe3dc104638ae6326a6cb19..46ee39cc0cce93b4640ce9d41af9d6066ac8e682 100644 (file)
@@ -285,16 +285,22 @@ describe('The Project section', () => {
     const notDefaultQualityGate = await screen.findByText('SonarSource way - CFamily');
 
     await user.click(notDefaultQualityGate);
+
+    const projectSelectList = screen.getByRole('group');
     // by default it shows "selected" values
-    expect(screen.getAllByRole('radio')).toHaveLength(3);
+    expect(within(projectSelectList).getAllByRole('button')).toHaveLength(3);
     expect(screen.getAllByRole('checkbox')).toHaveLength(2);
 
     // change tabs to show deselected projects
-    await user.click(screen.getByRole('radio', { name: 'quality_gates.projects.without' }));
+    await user.click(
+      within(projectSelectList).getByRole('button', { name: 'quality_gates.projects.without' })
+    );
     expect(screen.getAllByRole('checkbox')).toHaveLength(2);
 
     // change tabs to show all projects
-    await user.click(screen.getByRole('radio', { name: 'quality_gates.projects.all' }));
+    await user.click(
+      within(projectSelectList).getByRole('button', { name: 'quality_gates.projects.all' })
+    );
     expect(screen.getAllByRole('checkbox')).toHaveLength(4);
   });
 
@@ -304,8 +310,10 @@ describe('The Project section', () => {
     renderQualityGateApp();
 
     const notDefaultQualityGate = await screen.findByText('SonarSource way - CFamily');
+
     await user.click(notDefaultQualityGate);
 
+    const projectSelectList = screen.getByRole('group');
     const checkedProjects = screen.getAllByRole('checkbox')[0];
     expect(screen.getAllByRole('checkbox')).toHaveLength(2);
     await user.click(checkedProjects);
@@ -315,7 +323,7 @@ describe('The Project section', () => {
     expect(screen.getAllByRole('checkbox')).toHaveLength(1);
 
     // change tabs to show deselected projects
-    await user.click(screen.getAllByRole('radio')[1]);
+    await user.click(within(projectSelectList).getAllByRole('button')[1]);
 
     const uncheckedProjects = screen.getAllByRole('checkbox')[0];
     expect(screen.getAllByRole('checkbox')).toHaveLength(3);
index d31590984bfa40d58c75bfd64da75a86800c1049..91409b6441aa094d0f34bda9c5fdc059fc1a452e 100644 (file)
@@ -98,17 +98,17 @@ export function FilterBar(props: FilterBarProps) {
                 <h3 className="huge-spacer-right">{translate('hotspot.filters.title')}</h3>
 
                 {isLoggedIn(currentUser) && (
-                  <ButtonToggle
-                    className="huge-spacer-right"
-                    name="assignee-filter"
-                    onCheck={(value: AssigneeFilterOption) =>
-                      props.onChangeFilters({ assignedToMe: value === AssigneeFilterOption.ME })
-                    }
-                    options={assigneeFilterOptions}
-                    value={
-                      filters.assignedToMe ? AssigneeFilterOption.ME : AssigneeFilterOption.ALL
-                    }
-                  />
+                  <span className="huge-spacer-right">
+                    <ButtonToggle
+                      onCheck={(value: AssigneeFilterOption) =>
+                        props.onChangeFilters({ assignedToMe: value === AssigneeFilterOption.ME })
+                      }
+                      options={assigneeFilterOptions}
+                      value={
+                        filters.assignedToMe ? AssigneeFilterOption.ME : AssigneeFilterOption.ALL
+                      }
+                    />
+                  </span>
                 )}
 
                 <span className="spacer-right"> {translate('status')} </span>
index ab5a9d2636cd0576086e5b8fa6ecdc4b7f1b4861..b65d1ace7516f9e23ee78c61b029a7fc3bc5daf9 100644 (file)
@@ -157,25 +157,26 @@ exports[`should render correctly: logged-in 1`] = `
           >
             hotspot.filters.title
           </h3>
-          <ButtonToggle
+          <span
             className="huge-spacer-right"
-            disabled={false}
-            name="assignee-filter"
-            onCheck={[Function]}
-            options={
-              Array [
-                Object {
-                  "label": "hotspot.filters.assignee.assigned_to_me",
-                  "value": "me",
-                },
-                Object {
-                  "label": "hotspot.filters.assignee.all",
-                  "value": "all",
-                },
-              ]
-            }
-            value="all"
-          />
+          >
+            <ButtonToggle
+              onCheck={[Function]}
+              options={
+                Array [
+                  Object {
+                    "label": "hotspot.filters.assignee.assigned_to_me",
+                    "value": "me",
+                  },
+                  Object {
+                    "label": "hotspot.filters.assignee.all",
+                    "value": "all",
+                  },
+                ]
+              }
+              value="all"
+            />
+          </span>
           <span
             className="spacer-right"
           >
@@ -289,25 +290,26 @@ exports[`should render correctly: non-project 1`] = `
           >
             hotspot.filters.title
           </h3>
-          <ButtonToggle
+          <span
             className="huge-spacer-right"
-            disabled={false}
-            name="assignee-filter"
-            onCheck={[Function]}
-            options={
-              Array [
-                Object {
-                  "label": "hotspot.filters.assignee.assigned_to_me",
-                  "value": "me",
-                },
-                Object {
-                  "label": "hotspot.filters.assignee.all",
-                  "value": "all",
-                },
-              ]
-            }
-            value="all"
-          />
+          >
+            <ButtonToggle
+              onCheck={[Function]}
+              options={
+                Array [
+                  Object {
+                    "label": "hotspot.filters.assignee.assigned_to_me",
+                    "value": "me",
+                  },
+                  Object {
+                    "label": "hotspot.filters.assignee.all",
+                    "value": "all",
+                  },
+                ]
+              }
+              value="all"
+            />
+          </span>
           <span
             className="spacer-right"
           >
index d1dbc68b56cb2d7ea2e488f4976d9cfde56216b4..7b1c7c94e50f36e5aff8442b5575af4c05d243ac 100644 (file)
@@ -47,19 +47,20 @@ export default function BitbucketForm(props: BitbucketFormProps) {
       {!isUpdate && (
         <div className="display-flex-column">
           <strong>{translate('settings.almintegration.form.choose_bitbucket_variant')}</strong>
-          <ButtonToggle
-            className="little-spacer-top big-spacer-bottom"
-            name="variant"
-            onCheck={props.onVariantChange}
-            options={[
-              {
-                label: 'Bitbucket Server',
-                value: AlmKeys.BitbucketServer
-              },
-              { label: 'Bitbucket Cloud', value: AlmKeys.BitbucketCloud }
-            ]}
-            value={variant}
-          />
+          <div className="little-spacer-top big-spacer-bottom">
+            <ButtonToggle
+              label={translate('settings.almintegration.form.choose_bitbucket_variant')}
+              onCheck={props.onVariantChange}
+              options={[
+                {
+                  label: 'Bitbucket Server',
+                  value: AlmKeys.BitbucketServer
+                },
+                { label: 'Bitbucket Cloud', value: AlmKeys.BitbucketCloud }
+              ]}
+              value={variant}
+            />
+          </div>
         </div>
       )}
 
index 4d07a4d823016c4e2a4434301cb1231093accd33..f5be3549dad460ecfd05fc60845093484df086d4 100644 (file)
@@ -8,25 +8,27 @@ exports[`should render correctly: bbc 1`] = `
     <strong>
       settings.almintegration.form.choose_bitbucket_variant
     </strong>
-    <ButtonToggle
+    <div
       className="little-spacer-top big-spacer-bottom"
-      disabled={false}
-      name="variant"
-      onCheck={[MockFunction]}
-      options={
-        Array [
-          Object {
-            "label": "Bitbucket Server",
-            "value": "bitbucket",
-          },
-          Object {
-            "label": "Bitbucket Cloud",
-            "value": "bitbucketcloud",
-          },
-        ]
-      }
-      value="bitbucketcloud"
-    />
+    >
+      <ButtonToggle
+        label="settings.almintegration.form.choose_bitbucket_variant"
+        onCheck={[MockFunction]}
+        options={
+          Array [
+            Object {
+              "label": "Bitbucket Server",
+              "value": "bitbucket",
+            },
+            Object {
+              "label": "Bitbucket Cloud",
+              "value": "bitbucketcloud",
+            },
+          ]
+        }
+        value="bitbucketcloud"
+      />
+    </div>
   </div>
   <BitbucketCloudForm
     formData={
@@ -50,25 +52,27 @@ exports[`should render correctly: bbs 1`] = `
     <strong>
       settings.almintegration.form.choose_bitbucket_variant
     </strong>
-    <ButtonToggle
+    <div
       className="little-spacer-top big-spacer-bottom"
-      disabled={false}
-      name="variant"
-      onCheck={[MockFunction]}
-      options={
-        Array [
-          Object {
-            "label": "Bitbucket Server",
-            "value": "bitbucket",
-          },
-          Object {
-            "label": "Bitbucket Cloud",
-            "value": "bitbucketcloud",
-          },
-        ]
-      }
-      value="bitbucket"
-    />
+    >
+      <ButtonToggle
+        label="settings.almintegration.form.choose_bitbucket_variant"
+        onCheck={[MockFunction]}
+        options={
+          Array [
+            Object {
+              "label": "Bitbucket Server",
+              "value": "bitbucket",
+            },
+            Object {
+              "label": "Bitbucket Cloud",
+              "value": "bitbucketcloud",
+            },
+          ]
+        }
+        value="bitbucket"
+      />
+    </div>
   </div>
   <BitbucketServerForm
     formData={
index a225399c83c52dd17381f42d3e62d618c9f2d097..f899481d479477c2d012ad1ff0e7e96ed43803fd 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.
  */
-.radio-toggle {
-  display: inline-block;
-  vertical-align: middle;
-  font-size: 0;
-  white-space: nowrap;
-}
-
-.radio-toggle > li {
-  display: inline-block;
-  vertical-align: middle;
-  font-size: var(--smallFontSize);
-}
-
-.radio-toggle > li:first-child > label {
-  border-top-left-radius: 2px;
-  border-bottom-left-radius: 2px;
-}
-
-.radio-toggle > li:last-child > label {
-  border-top-right-radius: 2px;
-  border-bottom-right-radius: 2px;
-}
-
-.radio-toggle > li + li > label {
-  border-left: none;
-}
-
-.radio-toggle > li > label {
-  display: inline-block;
-  padding: 0 12px;
-  margin: 0;
-  border: 1px solid var(--darkBlue);
-  color: var(--darkBlue);
-  height: calc(var(--controlHeight) - 2px);
-  line-height: calc(var(--controlHeight) - 2px);
-  cursor: pointer;
-  font-weight: 600;
-}
-
-.radio-toggle input[type='radio'] {
-  display: none;
-}
-
-.radio-toggle input[type='radio']:checked + label {
-  background-color: var(--darkBlue);
-  color: #fff;
-}
 
-.radio-toggle input[type='radio']:disabled + label {
-  color: var(--disableGrayText);
-  border-color: var(--disableGrayBorder);
-  background: var(--disableGrayBg);
-  cursor: not-allowed;
+.button-toggle button:not(:first-child) {
+  margin-left: -1px;
 }
index 8b7eaff8e1e433aff8f1928c6af612e9e2a25ded..6289a172d12c7542efbda88757627473adf42125 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 * as React from 'react';
+import { Button } from './buttons';
 import './ButtonToggle.css';
-import Tooltip from './Tooltip';
 
 export type ButtonToggleValueType = string | number | boolean;
 
 export interface ButtonToggleOption {
-  disabled?: boolean;
   label: string;
-  tooltip?: string;
   value: ButtonToggleValueType;
 }
 
-interface Props {
-  className?: string;
-  name: string;
-  onCheck: (value: ButtonToggleValueType) => void;
+export interface ButtonToggleProps {
+  label?: string;
+  disabled?: boolean;
   options: ButtonToggleOption[];
   value?: ButtonToggleValueType;
+  onCheck: (value: ButtonToggleValueType) => void;
 }
 
-export default class ButtonToggle extends React.PureComponent<Props> {
-  static defaultProps = {
-    disabled: false,
-    value: null
-  };
-
-  renderOption = (option: ButtonToggleOption) => {
-    const checked = option.value === this.props.value;
-    const htmlId = `${this.props.name}__${option.value}`;
-    return (
-      <li key={option.value.toString()}>
-        <input
-          checked={checked}
-          disabled={option.disabled}
-          id={htmlId}
-          name={this.props.name}
-          onChange={() => this.props.onCheck(option.value)}
-          type="radio"
-        />
-        <Tooltip overlay={option.tooltip || undefined}>
-          <label htmlFor={htmlId}>{option.label}</label>
-        </Tooltip>
-      </li>
-    );
-  };
+export default function ButtonToggle(props: ButtonToggleProps) {
+  const { disabled, label, options, value } = props;
 
-  render() {
-    return (
-      <ul className={classNames('radio-toggle', this.props.className)}>
-        {this.props.options.map(this.renderOption)}
-      </ul>
-    );
-  }
+  return (
+    <span aria-label={label} role="group" className="button-toggle">
+      {options.map(option => (
+        <Button
+          key={option.value.toString()}
+          onClick={() => option.value !== value && props.onCheck(option.value)}
+          disabled={disabled}
+          data-value={option.value}
+          className={classNames({ selected: option.value === value })}>
+          {option.label}
+        </Button>
+      ))}
+    </span>
+  );
 }
index 439d32b9d70414ddcea6f48e3c802aa0ec97304d..367e6b499cc6567a9fc9f50bc5a5a97acbbe6d84 100644 (file)
@@ -144,17 +144,18 @@ export default class SelectList extends React.PureComponent<Props, State> {
     return (
       <div className="select-list">
         <div className="display-flex-center">
-          <ButtonToggle
-            className="select-list-filter spacer-right"
-            name="filter"
-            onCheck={this.changeFilter}
-            options={[
-              { disabled, label: labelSelected, value: SelectListFilter.Selected },
-              { disabled, label: labelUnselected, value: SelectListFilter.Unselected },
-              { disabled, label: labelAll, value: SelectListFilter.All }
-            ]}
-            value={filter}
-          />
+          <span className="select-list-filter spacer-right">
+            <ButtonToggle
+              onCheck={this.changeFilter}
+              disabled={disabled}
+              options={[
+                { label: labelSelected, value: SelectListFilter.Selected },
+                { label: labelUnselected, value: SelectListFilter.Unselected },
+                { label: labelAll, value: SelectListFilter.All }
+              ]}
+              value={filter}
+            />
+          </span>
           <SearchBox
             autoFocus={true}
             loading={this.state.loading}
index 96c6e63595acd679df8ecd21d3d394ead6a79cc9..0c0727c20dbdde8b186ae2988d09e6e6f26c7452 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 { shallow } from 'enzyme';
+import { screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
 import * as React from 'react';
-import { change } from '../../../helpers/testUtils';
-import ButtonToggle from '../ButtonToggle';
+import { renderComponent } from '../../../helpers/testReactTestingUtils';
+import ButtonToggle, { ButtonToggleProps } from '../ButtonToggle';
 
-it('renders', () => {
-  expect(shallowRender()).toMatchSnapshot();
-});
-
-it('calls onCheck', () => {
+it('should behave properly', async () => {
   const onCheck = jest.fn();
-  const wrapper = shallowRender({ onCheck });
-  change(wrapper.find('input[id="sample__two"]'), '');
-  expect(onCheck).toBeCalledWith('two');
-});
+  const user = userEvent.setup();
 
-it('handles numeric values', () => {
-  const onCheck = jest.fn();
-  const wrapper = shallowRender({
-    onCheck,
-    options: [
-      { value: 1, label: 'first', tooltip: 'foo' },
-      { value: 2, label: 'second', tooltip: 'bar' }
-    ],
-    value: 1
-  });
-  change(wrapper.find('input[id="sample__2"]'), '');
-  expect(onCheck).toBeCalledWith(2);
-});
+  render({ onCheck });
+  expect(screen.getAllByRole('button')).toHaveLength(3);
 
-it('handles boolean values', () => {
-  const onCheck = jest.fn();
-  const wrapper = shallowRender({
-    onCheck,
-    options: [
-      { value: true, label: 'yes', tooltip: 'foo' },
-      { value: false, label: 'no', tooltip: 'bar' }
-    ],
-    value: true
-  });
-  change(wrapper.find('input[id="sample__false"]'), '');
-  expect(onCheck).toBeCalledWith(false);
+  await user.click(screen.getByRole('button', { name: 'first' }));
+  expect(onCheck).toHaveBeenCalledWith('one');
+
+  await user.click(screen.getByRole('button', { name: 'second' }));
+  expect(onCheck).not.toHaveBeenLastCalledWith('two');
 });
 
-it('initialize value', () => {
+it('should behave properly when disabled', async () => {
   const onCheck = jest.fn();
-  const wrapper = shallowRender({
-    onCheck,
-    options: [
-      { value: 1, label: 'first', tooltip: 'foo' },
-      { value: 2, label: 'second', tooltip: 'bar', disabled: true }
-    ],
-    value: 2
-  });
-  expect(wrapper.find('input[checked=true]').prop('id')).toBe('sample__2');
-});
+  const user = userEvent.setup();
+
+  render({ disabled: true, onCheck });
 
-it('accepts advanced options fields', () => {
-  expect(
-    shallowRender({
-      options: [
-        { value: 'one', label: 'first', tooltip: 'foo' },
-        { value: 'two', label: 'second', tooltip: 'bar', disabled: true }
-      ]
-    })
-  ).toMatchSnapshot();
+  await user.click(screen.getByRole('button', { name: 'first' }));
+  expect(onCheck).not.toHaveBeenCalled();
 });
 
-function shallowRender(props?: Partial<ButtonToggle['props']>) {
-  const options = [
-    { value: 'one', label: 'first' },
-    { value: 'two', label: 'second' }
-  ];
-  return shallow(<ButtonToggle name="sample" onCheck={() => true} options={options} {...props} />);
+function render(props?: Partial<ButtonToggleProps>) {
+  renderComponent(
+    <ButtonToggle
+      label="test-label"
+      onCheck={jest.fn()}
+      disabled={false}
+      options={[
+        { value: 'one', label: 'first' },
+        { value: 'two', label: 'second' },
+        { value: 'tree', label: 'third' }
+      ]}
+      value="two"
+      {...props}
+    />
+  );
 }
diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ButtonToggle-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/ButtonToggle-test.tsx.snap
deleted file mode 100644 (file)
index 791d312..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`accepts advanced options fields 1`] = `
-<ul
-  className="radio-toggle"
->
-  <li
-    key="one"
-  >
-    <input
-      checked={false}
-      id="sample__one"
-      name="sample"
-      onChange={[Function]}
-      type="radio"
-    />
-    <Tooltip
-      overlay="foo"
-    >
-      <label
-        htmlFor="sample__one"
-      >
-        first
-      </label>
-    </Tooltip>
-  </li>
-  <li
-    key="two"
-  >
-    <input
-      checked={false}
-      disabled={true}
-      id="sample__two"
-      name="sample"
-      onChange={[Function]}
-      type="radio"
-    />
-    <Tooltip
-      overlay="bar"
-    >
-      <label
-        htmlFor="sample__two"
-      >
-        second
-      </label>
-    </Tooltip>
-  </li>
-</ul>
-`;
-
-exports[`renders 1`] = `
-<ul
-  className="radio-toggle"
->
-  <li
-    key="one"
-  >
-    <input
-      checked={false}
-      id="sample__one"
-      name="sample"
-      onChange={[Function]}
-      type="radio"
-    />
-    <Tooltip>
-      <label
-        htmlFor="sample__one"
-      >
-        first
-      </label>
-    </Tooltip>
-  </li>
-  <li
-    key="two"
-  >
-    <input
-      checked={false}
-      id="sample__two"
-      name="sample"
-      onChange={[Function]}
-      type="radio"
-    />
-    <Tooltip>
-      <label
-        htmlFor="sample__two"
-      >
-        second
-      </label>
-    </Tooltip>
-  </li>
-</ul>
-`;
index edb8439bce767c5a78c9d3065665f0794410bda1..a2480c6b0495cf2c519764cee5a6d5172d50c90b 100644 (file)
@@ -7,32 +7,31 @@ exports[`should cancel filter selection when search is active 1`] = `
   <div
     className="display-flex-center"
   >
-    <ButtonToggle
+    <span
       className="select-list-filter spacer-right"
-      disabled={false}
-      name="filter"
-      onCheck={[Function]}
-      options={
-        Array [
-          Object {
-            "disabled": false,
-            "label": "selected",
-            "value": "selected",
-          },
-          Object {
-            "disabled": false,
-            "label": "unselected",
-            "value": "deselected",
-          },
-          Object {
-            "disabled": false,
-            "label": "all",
-            "value": "all",
-          },
-        ]
-      }
-      value="deselected"
-    />
+    >
+      <ButtonToggle
+        disabled={false}
+        onCheck={[Function]}
+        options={
+          Array [
+            Object {
+              "label": "selected",
+              "value": "selected",
+            },
+            Object {
+              "label": "unselected",
+              "value": "deselected",
+            },
+            Object {
+              "label": "all",
+              "value": "all",
+            },
+          ]
+        }
+        value="deselected"
+      />
+    </span>
     <SearchBox
       autoFocus={true}
       loading={false}
@@ -74,32 +73,31 @@ exports[`should cancel filter selection when search is active 2`] = `
   <div
     className="display-flex-center"
   >
-    <ButtonToggle
+    <span
       className="select-list-filter spacer-right"
-      disabled={false}
-      name="filter"
-      onCheck={[Function]}
-      options={
-        Array [
-          Object {
-            "disabled": true,
-            "label": "selected",
-            "value": "selected",
-          },
-          Object {
-            "disabled": true,
-            "label": "unselected",
-            "value": "deselected",
-          },
-          Object {
-            "disabled": true,
-            "label": "all",
-            "value": "all",
-          },
-        ]
-      }
-      value="deselected"
-    />
+    >
+      <ButtonToggle
+        disabled={true}
+        onCheck={[Function]}
+        options={
+          Array [
+            Object {
+              "label": "selected",
+              "value": "selected",
+            },
+            Object {
+              "label": "unselected",
+              "value": "deselected",
+            },
+            Object {
+              "label": "all",
+              "value": "all",
+            },
+          ]
+        }
+        value="deselected"
+      />
+    </span>
     <SearchBox
       autoFocus={true}
       loading={false}
@@ -141,32 +139,31 @@ exports[`should cancel filter selection when search is active 3`] = `
   <div
     className="display-flex-center"
   >
-    <ButtonToggle
+    <span
       className="select-list-filter spacer-right"
-      disabled={false}
-      name="filter"
-      onCheck={[Function]}
-      options={
-        Array [
-          Object {
-            "disabled": false,
-            "label": "selected",
-            "value": "selected",
-          },
-          Object {
-            "disabled": false,
-            "label": "unselected",
-            "value": "deselected",
-          },
-          Object {
-            "disabled": false,
-            "label": "all",
-            "value": "all",
-          },
-        ]
-      }
-      value="deselected"
-    />
+    >
+      <ButtonToggle
+        disabled={false}
+        onCheck={[Function]}
+        options={
+          Array [
+            Object {
+              "label": "selected",
+              "value": "selected",
+            },
+            Object {
+              "label": "unselected",
+              "value": "deselected",
+            },
+            Object {
+              "label": "all",
+              "value": "all",
+            },
+          ]
+        }
+        value="deselected"
+      />
+    </span>
     <SearchBox
       autoFocus={true}
       loading={false}
@@ -208,32 +205,31 @@ exports[`should display a loader when searching 1`] = `
   <div
     className="display-flex-center"
   >
-    <ButtonToggle
+    <span
       className="select-list-filter spacer-right"
-      disabled={false}
-      name="filter"
-      onCheck={[Function]}
-      options={
-        Array [
-          Object {
-            "disabled": false,
-            "label": "selected",
-            "value": "selected",
-          },
-          Object {
-            "disabled": false,
-            "label": "unselected",
-            "value": "deselected",
-          },
-          Object {
-            "disabled": false,
-            "label": "all",
-            "value": "all",
-          },
-        ]
-      }
-      value="selected"
-    />
+    >
+      <ButtonToggle
+        disabled={false}
+        onCheck={[Function]}
+        options={
+          Array [
+            Object {
+              "label": "selected",
+              "value": "selected",
+            },
+            Object {
+              "label": "unselected",
+              "value": "deselected",
+            },
+            Object {
+              "label": "all",
+              "value": "all",
+            },
+          ]
+        }
+        value="selected"
+      />
+    </span>
     <SearchBox
       autoFocus={true}
       loading={true}
@@ -275,32 +271,31 @@ exports[`should display pagination element properly and call search method with
   <div
     className="display-flex-center"
   >
-    <ButtonToggle
+    <span
       className="select-list-filter spacer-right"
-      disabled={false}
-      name="filter"
-      onCheck={[Function]}
-      options={
-        Array [
-          Object {
-            "disabled": false,
-            "label": "selected",
-            "value": "selected",
-          },
-          Object {
-            "disabled": false,
-            "label": "unselected",
-            "value": "deselected",
-          },
-          Object {
-            "disabled": false,
-            "label": "all",
-            "value": "all",
-          },
-        ]
-      }
-      value="selected"
-    />
+    >
+      <ButtonToggle
+        disabled={false}
+        onCheck={[Function]}
+        options={
+          Array [
+            Object {
+              "label": "selected",
+              "value": "selected",
+            },
+            Object {
+              "label": "unselected",
+              "value": "deselected",
+            },
+            Object {
+              "label": "all",
+              "value": "all",
+            },
+          ]
+        }
+        value="selected"
+      />
+    </span>
     <SearchBox
       autoFocus={true}
       loading={true}
@@ -348,32 +343,31 @@ exports[`should display pagination element properly and call search method with
   <div
     className="display-flex-center"
   >
-    <ButtonToggle
+    <span
       className="select-list-filter spacer-right"
-      disabled={false}
-      name="filter"
-      onCheck={[Function]}
-      options={
-        Array [
-          Object {
-            "disabled": false,
-            "label": "selected",
-            "value": "selected",
-          },
-          Object {
-            "disabled": false,
-            "label": "unselected",
-            "value": "deselected",
-          },
-          Object {
-            "disabled": false,
-            "label": "all",
-            "value": "all",
-          },
-        ]
-      }
-      value="selected"
-    />
+    >
+      <ButtonToggle
+        disabled={false}
+        onCheck={[Function]}
+        options={
+          Array [
+            Object {
+              "label": "selected",
+              "value": "selected",
+            },
+            Object {
+              "label": "unselected",
+              "value": "deselected",
+            },
+            Object {
+              "label": "all",
+              "value": "all",
+            },
+          ]
+        }
+        value="selected"
+      />
+    </span>
     <SearchBox
       autoFocus={true}
       loading={true}
@@ -422,32 +416,31 @@ exports[`should display properly with advanced features 1`] = `
   <div
     className="display-flex-center"
   >
-    <ButtonToggle
+    <span
       className="select-list-filter spacer-right"
-      disabled={false}
-      name="filter"
-      onCheck={[Function]}
-      options={
-        Array [
-          Object {
-            "disabled": false,
-            "label": "selected",
-            "value": "selected",
-          },
-          Object {
-            "disabled": false,
-            "label": "unselected",
-            "value": "deselected",
-          },
-          Object {
-            "disabled": false,
-            "label": "all",
-            "value": "all",
-          },
-        ]
-      }
-      value="selected"
-    />
+    >
+      <ButtonToggle
+        disabled={false}
+        onCheck={[Function]}
+        options={
+          Array [
+            Object {
+              "label": "selected",
+              "value": "selected",
+            },
+            Object {
+              "label": "unselected",
+              "value": "deselected",
+            },
+            Object {
+              "label": "all",
+              "value": "all",
+            },
+          ]
+        }
+        value="selected"
+      />
+    </span>
     <SearchBox
       autoFocus={true}
       loading={false}
@@ -497,32 +490,31 @@ exports[`should display properly with basics features 1`] = `
   <div
     className="display-flex-center"
   >
-    <ButtonToggle
+    <span
       className="select-list-filter spacer-right"
-      disabled={false}
-      name="filter"
-      onCheck={[Function]}
-      options={
-        Array [
-          Object {
-            "disabled": false,
-            "label": "selected",
-            "value": "selected",
-          },
-          Object {
-            "disabled": false,
-            "label": "unselected",
-            "value": "deselected",
-          },
-          Object {
-            "disabled": false,
-            "label": "all",
-            "value": "all",
-          },
-        ]
-      }
-      value="selected"
-    />
+    >
+      <ButtonToggle
+        disabled={false}
+        onCheck={[Function]}
+        options={
+          Array [
+            Object {
+              "label": "selected",
+              "value": "selected",
+            },
+            Object {
+              "label": "unselected",
+              "value": "deselected",
+            },
+            Object {
+              "label": "all",
+              "value": "all",
+            },
+          ]
+        }
+        value="selected"
+      />
+    </span>
     <SearchBox
       autoFocus={true}
       loading={false}
index 506173cb063485790b4b9548132783722c1136b7..2a78bdffbac75dbfa3eb9f115acd4e5986954575 100644 (file)
@@ -38,7 +38,8 @@
   transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
 }
 
-.button:hover {
+.button:hover,
+.button.selected {
   background: var(--darkBlue);
   color: var(--white);
 }
index d3eae2237cfea3271d2b030c9b5b519fb5332cb3..e4d317a528798668c4bfa49f706f7288950dfc0e 100644 (file)
@@ -135,10 +135,9 @@ export default class RuleDescription extends React.PureComponent<Props, State> {
                 )}
               </Alert>
             )}
-            <div>
+            <div className="big-spacer-bottom">
               <ButtonToggle
-                className="big-spacer-bottom"
-                name="filter"
+                label={translate('coding_rules.description_context.title')}
                 onCheck={this.handleToggleContext}
                 options={options}
                 value={selectedContext.displayName}
index 2a05bd465d57d92805ec05755a82e3306e5f7281..70200e4d080fb0287f31a2e399427dbca217b836 100644 (file)
@@ -52,8 +52,8 @@ export function BranchAnalysisStepContent(props: BranchesAnalysisStepProps) {
     <>
       <span>{translate('onboarding.build')}</span>
       <RenderOptions
+        label={translate('onboarding.build')}
         checked={buildTechnology}
-        name="buildTechnology"
         onCheck={value => setBuildTechnology(value as BuildTools)}
         optionLabelKey="onboarding.build"
         options={buildToolsList}
index ab69a5c3830f90fbaeb3c15a6cb72cb6688a25a0..1baea0c61c856c1334d962110a8e761bbfcdee64 100644 (file)
@@ -6,7 +6,7 @@ exports[`should render correctly 1`] = `
     onboarding.build
   </span>
   <RenderOptions
-    name="buildTechnology"
+    label="onboarding.build"
     onCheck={[Function]}
     optionLabelKey="onboarding.build"
     options={
@@ -33,7 +33,7 @@ exports[`should render correctly: dotnet 1`] = `
   </span>
   <RenderOptions
     checked="dotnet"
-    name="buildTechnology"
+    label="onboarding.build"
     onCheck={[Function]}
     optionLabelKey="onboarding.build"
     options={
@@ -61,7 +61,7 @@ exports[`should render correctly: gradle 1`] = `
   </span>
   <RenderOptions
     checked="gradle"
-    name="buildTechnology"
+    label="onboarding.build"
     onCheck={[Function]}
     optionLabelKey="onboarding.build"
     options={
@@ -89,7 +89,7 @@ exports[`should render correctly: maven 1`] = `
   </span>
   <RenderOptions
     checked="maven"
-    name="buildTechnology"
+    label="onboarding.build"
     onCheck={[Function]}
     optionLabelKey="onboarding.build"
     options={
@@ -117,7 +117,7 @@ exports[`should render correctly: other 1`] = `
   </span>
   <RenderOptions
     checked="other"
-    name="buildTechnology"
+    label="onboarding.build"
     onCheck={[Function]}
     optionLabelKey="onboarding.build"
     options={
@@ -144,7 +144,7 @@ exports[`should render correctly: without C 1`] = `
     onboarding.build
   </span>
   <RenderOptions
-    name="buildTechnology"
+    label="onboarding.build"
     onCheck={[Function]}
     optionLabelKey="onboarding.build"
     options={
index da7c2b6a56959c162779d5c52621049a7db1c408..49073dfef022a3e7f306974bd5f5e00542bbc6a4 100644 (file)
@@ -93,8 +93,8 @@ unzip build-wrapper.zip`,
         {translate('onboarding.tutorial.with.azure_pipelines.os')}
       </span>
       <RenderOptions
+        label={translate('onboarding.tutorial.with.azure_pipelines.os')}
         checked={os}
-        name="os"
         onCheck={handlOsChange}
         optionLabelKey="onboarding.build.other.os"
         options={Object.values(OSs)}
index 2b40b0cdf5fa7c2c739b9c8986bef19063045022..7c5167fafd649fb029980b036531a8a9dec16697 100644 (file)
@@ -9,7 +9,7 @@ exports[`should render correctly for "linux" 1`] = `
   </span>
   <RenderOptions
     checked="linux"
-    name="os"
+    label="onboarding.tutorial.with.azure_pipelines.os"
     onCheck={[Function]}
     optionLabelKey="onboarding.build.other.os"
     options={
@@ -131,7 +131,7 @@ exports[`should render correctly for "mac" 1`] = `
   </span>
   <RenderOptions
     checked="mac"
-    name="os"
+    label="onboarding.tutorial.with.azure_pipelines.os"
     onCheck={[Function]}
     optionLabelKey="onboarding.build.other.os"
     options={
@@ -253,7 +253,7 @@ exports[`should render correctly for "win" 1`] = `
   </span>
   <RenderOptions
     checked="win"
-    name="os"
+    label="onboarding.tutorial.with.azure_pipelines.os"
     onCheck={[Function]}
     optionLabelKey="onboarding.build.other.os"
     options={
index 73468d8ea4480f57110bcec7ae185f8893791f8d..44e23a9d26dcc53f4db57b2b3db8be2fbb7df0be 100644 (file)
@@ -23,7 +23,7 @@ import ButtonToggle from '../../controls/ButtonToggle';
 
 export interface RenderOptionsProps {
   checked: string | undefined;
-  name: string;
+  label?: string;
   onCheck: (checked: string) => void;
   optionLabelKey: string;
   options: string[];
@@ -32,7 +32,7 @@ export interface RenderOptionsProps {
 
 export default function RenderOptions({
   checked,
-  name,
+  label,
   onCheck,
   optionLabelKey,
   options,
@@ -43,7 +43,7 @@ export default function RenderOptions({
       {titleLabelKey && <h4 className="spacer-bottom">{translate(titleLabelKey)}</h4>}
 
       <ButtonToggle
-        name={name}
+        label={label}
         onCheck={onCheck}
         options={options.map(build => ({
           label: translate(optionLabelKey, build),
index da4a875ee8455c7ac07e0f7fcaf687433e9caa5d..f310794296d29a1ad2a38c10c27fd5a2366404d2 100644 (file)
@@ -44,8 +44,8 @@ export function YamlFileStep(props: YamlFileStepProps) {
       <li className="abs-width-600">
         {translate('onboarding.build')}
         <RenderOptions
+          label={translate('onboarding.build')}
           checked={buildToolSelected}
-          name="language"
           onCheck={value => setBuildToolSelected(value as BuildTools)}
           options={buildTools}
           optionLabelKey="onboarding.build"
index 2a3a7e312d5fe6907cc946fda407ebcfd2e48382..b45fda8cdf8623ec5a5b38de7d458d804c19f2e7 100644 (file)
@@ -30,8 +30,8 @@ it('should render correctly', () => {
 function shallowRender(props: Partial<RenderOptionsProps> = {}) {
   return shallow<RenderOptionsProps>(
     <RenderOptions
+      label="test-label"
       checked={undefined}
-      name="bar"
       onCheck={jest.fn()}
       optionLabelKey="foo.bar"
       options={['foo', 'baz']}
index 4c0915326989d96b8aac8107670686033dbad394..c985d3645751f534a9ecdcbfadbc1acc94e7d8a3 100644 (file)
@@ -5,8 +5,7 @@ exports[`should render correctly: default 1`] = `
   className="big-spacer-top"
 >
   <ButtonToggle
-    disabled={false}
-    name="bar"
+    label="test-label"
     onCheck={[MockFunction]}
     options={
       Array [
@@ -20,7 +19,6 @@ exports[`should render correctly: default 1`] = `
         },
       ]
     }
-    value={null}
   />
 </div>
 `;
@@ -30,8 +28,7 @@ exports[`should render correctly: option checked 1`] = `
   className="big-spacer-top"
 >
   <ButtonToggle
-    disabled={false}
-    name="bar"
+    label="test-label"
     onCheck={[MockFunction]}
     options={
       Array [
@@ -60,8 +57,7 @@ exports[`should render correctly: with title 1`] = `
     title.key
   </h4>
   <ButtonToggle
-    disabled={false}
-    name="bar"
+    label="test-label"
     onCheck={[MockFunction]}
     options={
       Array [
@@ -75,7 +71,6 @@ exports[`should render correctly: with title 1`] = `
         },
       ]
     }
-    value={null}
   />
 </div>
 `;
index 3f8c491c2534786c4a319ce7eef857892dc45834..2c88601539803d0c5ace92b9562c58818ca8d74b 100644 (file)
@@ -9,7 +9,7 @@ exports[`should render child correctly: C unavailable 1`] = `
   >
     onboarding.build
     <RenderOptions
-      name="language"
+      label="onboarding.build"
       onCheck={[Function]}
       optionLabelKey="onboarding.build"
       options={
@@ -34,7 +34,7 @@ exports[`should render correctly: C available 1`] = `
   >
     onboarding.build
     <RenderOptions
-      name="language"
+      label="onboarding.build"
       onCheck={[Function]}
       optionLabelKey="onboarding.build"
       options={
@@ -60,7 +60,7 @@ exports[`should render correctly: C unavailable 1`] = `
   >
     onboarding.build
     <RenderOptions
-      name="language"
+      label="onboarding.build"
       onCheck={[Function]}
       optionLabelKey="onboarding.build"
       options={
index 4e4c0422e900930c5cfd8d2188f4e80505272021..c6e3e5bd27fe60ae9b16f00b439a7b6ce9760566 100644 (file)
@@ -152,8 +152,8 @@ export default function CFamily(props: CFamilyProps) {
       <li className="abs-width-600">
         <span>{translate('onboarding.build.other.os')}</span>
         <RenderOptions
+          label={translate('onboarding.build.other.os')}
           checked={os}
-          name="os"
           onCheck={(value: OSs) => setOs(value)}
           optionLabelKey="onboarding.build.other.os"
           options={Object.values(OSs)}
index 8db7aead8273b97dc03e963b834a7c83f8233c8a..0bb3b8961db293d9464133554ce3b89f0afe39c0 100644 (file)
@@ -33,7 +33,7 @@ exports[`should render correctly 1`] = `
       onboarding.build.other.os
     </span>
     <RenderOptions
-      name="os"
+      label="onboarding.build.other.os"
       onCheck={[Function]}
       optionLabelKey="onboarding.build.other.os"
       options={
@@ -82,7 +82,7 @@ exports[`should render correctly for linux: branches disabled 1`] = `
     </span>
     <RenderOptions
       checked="linux"
-      name="os"
+      label="onboarding.build.other.os"
       onCheck={[Function]}
       optionLabelKey="onboarding.build.other.os"
       options={
@@ -185,7 +185,7 @@ exports[`should render correctly for mac: branches enabled 1`] = `
     </span>
     <RenderOptions
       checked="mac"
-      name="os"
+      label="onboarding.build.other.os"
       onCheck={[Function]}
       optionLabelKey="onboarding.build.other.os"
       options={
@@ -287,7 +287,7 @@ exports[`should render correctly for win: branches enabled 1`] = `
     </span>
     <RenderOptions
       checked="win"
-      name="os"
+      label="onboarding.build.other.os"
       onCheck={[Function]}
       optionLabelKey="onboarding.build.other.os"
       options={
index 377e1bddcdf9d4e57e0708f3cc59b4ffc0dbe98a..df7bcb7b2de63a6b36f6f7fe6bff8d95e6a80c3c 100644 (file)
@@ -95,8 +95,8 @@ export function ProjectKeyStep(props: ProjectKeyStepProps) {
         <li>
           {translate('onboarding.build')}
           <RenderOptions
+            label={translate('onboarding.build')}
             checked={buildTool}
-            name="buildtool"
             onCheck={buildToolSelect}
             optionLabelKey="onboarding.build"
             options={buildTools}
index 532a86250014994b4674086cfd4bfdd4c4d11e10..b6e01193cae2c42a3711f80e534855adc978f9f7 100644 (file)
@@ -11,7 +11,7 @@ exports[`should render correctly for build tool cfamily 1`] = `
       onboarding.build
       <RenderOptions
         checked="cfamily"
-        name="buildtool"
+        label="onboarding.build"
         onCheck={[Function]}
         optionLabelKey="onboarding.build"
         options={
@@ -73,7 +73,7 @@ exports[`should render correctly for build tool dotnet 1`] = `
       onboarding.build
       <RenderOptions
         checked="dotnet"
-        name="buildtool"
+        label="onboarding.build"
         onCheck={[Function]}
         optionLabelKey="onboarding.build"
         options={
@@ -107,7 +107,7 @@ exports[`should render correctly for build tool gradle 1`] = `
       onboarding.build
       <RenderOptions
         checked="gradle"
-        name="buildtool"
+        label="onboarding.build"
         onCheck={[Function]}
         optionLabelKey="onboarding.build"
         options={
@@ -176,7 +176,7 @@ exports[`should render correctly for build tool maven 1`] = `
       onboarding.build
       <RenderOptions
         checked="maven"
-        name="buildtool"
+        label="onboarding.build"
         onCheck={[Function]}
         optionLabelKey="onboarding.build"
         options={
@@ -238,7 +238,7 @@ exports[`should render correctly for build tool other 1`] = `
       onboarding.build
       <RenderOptions
         checked="other"
-        name="buildtool"
+        label="onboarding.build"
         onCheck={[Function]}
         optionLabelKey="onboarding.build"
         options={
@@ -299,7 +299,7 @@ exports[`should render correctly if C is not available 1`] = `
     <li>
       onboarding.build
       <RenderOptions
-        name="buildtool"
+        label="onboarding.build"
         onCheck={[Function]}
         optionLabelKey="onboarding.build"
         options={
@@ -337,7 +337,7 @@ exports[`should render correctly: initial content 1`] = `
     <li>
       onboarding.build
       <RenderOptions
-        name="buildtool"
+        label="onboarding.build"
         onCheck={[Function]}
         optionLabelKey="onboarding.build"
         options={
index 159d4af296eafc626c1ad4d9cb61d857f9f6574e..318c935d0d1a447cb4dea3d02dc0d7a13f403e77 100644 (file)
@@ -75,8 +75,8 @@ export function JenkinsfileStep(props: JenkinsfileStepProps) {
             <li>
               {translate('onboarding.build')}
               <RenderOptions
+                label={translate('onboarding.build')}
                 checked={buildTool}
-                name="buildtool"
                 onCheck={value => setBuildTool(value as BuildTools)}
                 optionLabelKey="onboarding.build"
                 options={buildToolOrder}
index a340071bdcb1160e1b34406c2040c45a0c6e20da..c7812fba08ed41a2ecd4212324ceeb8aeb9e09bc 100644 (file)
@@ -45,7 +45,7 @@ export default function SelectAlmStep(props: SelectAlmStepProps) {
       renderForm={() => (
         <div className="boxed-group-inner">
           <ButtonToggle
-            name="alm"
+            label={translate('onboarding.tutorial.with.jenkins.alm_selection.title')}
             onCheck={props.onCheck}
             options={[
               AlmKeys.BitbucketCloud,
index f99f6e725271c55b54d32a4b2999547502c544e4..35eed831440f19ae702a9ac23366e1a6920d7362 100644 (file)
@@ -11,7 +11,7 @@ exports[`should render correctly for .NET 1`] = `
       onboarding.build
       <RenderOptions
         checked="dotnet"
-        name="buildtool"
+        label="onboarding.build"
         onCheck={[Function]}
         optionLabelKey="onboarding.build"
         options={
@@ -65,7 +65,7 @@ exports[`should render correctly for Gradle 1`] = `
       onboarding.build
       <RenderOptions
         checked="gradle"
-        name="buildtool"
+        label="onboarding.build"
         onCheck={[Function]}
         optionLabelKey="onboarding.build"
         options={
@@ -119,7 +119,7 @@ exports[`should render correctly for Maven 1`] = `
       onboarding.build
       <RenderOptions
         checked="maven"
-        name="buildtool"
+        label="onboarding.build"
         onCheck={[Function]}
         optionLabelKey="onboarding.build"
         options={
@@ -173,7 +173,7 @@ exports[`should render correctly for Other 1`] = `
       onboarding.build
       <RenderOptions
         checked="other"
-        name="buildtool"
+        label="onboarding.build"
         onCheck={[Function]}
         optionLabelKey="onboarding.build"
         options={
@@ -248,7 +248,7 @@ exports[`should render correctly: initial content 1`] = `
     <li>
       onboarding.build
       <RenderOptions
-        name="buildtool"
+        label="onboarding.build"
         onCheck={[Function]}
         optionLabelKey="onboarding.build"
         options={
index 399edf832def61ef85f3453f3bfa7e6bca9e2da0..087ba3fe6084e52ba8a65783182ca663263aebb9 100644 (file)
@@ -16,8 +16,7 @@ exports[`should render correctly: form, default 1`] = `
   className="boxed-group-inner"
 >
   <ButtonToggle
-    disabled={false}
-    name="alm"
+    label="onboarding.tutorial.with.jenkins.alm_selection.title"
     onCheck={[MockFunction]}
     options={
       Array [
@@ -39,7 +38,6 @@ exports[`should render correctly: form, default 1`] = `
         },
       ]
     }
-    value={null}
   />
 </div>
 `;
@@ -49,8 +47,7 @@ exports[`should render correctly: form, with alm 1`] = `
   className="boxed-group-inner"
 >
   <ButtonToggle
-    disabled={false}
-    name="alm"
+    label="onboarding.tutorial.with.jenkins.alm_selection.title"
     onCheck={[MockFunction]}
     options={
       Array [
index 9959f7965762a6d4ed026d529a9922a1d99491bb..6f2c0c610cc3e9e1557cea62676e2b58952b4566 100644 (file)
@@ -111,8 +111,8 @@ export default function CFamilly(props: LanguageProps) {
       <li className="abs-width-600">
         {translate('onboarding.build.other.os')}
         <RenderOptions
+          label={translate('onboarding.build.other.os')}
           checked={os}
-          name="flavorComponent"
           optionLabelKey="onboarding.build.other.os"
           onCheck={value => setOs(value as OSs)}
           options={Object.values(OSs)}
index e2d75bf48e48f8c07b3531d660b06b7c74ea590b..0dcb38afd7133942e516ec4180008c9042abcdc2 100644 (file)
@@ -50,8 +50,8 @@ export default function DotNet(props: LanguageProps) {
       <li>
         {translate('onboarding.tutorial.with.jenkins.jenkinsfile.dotnet.build_agent')}
         <RenderOptions
+          label={translate('onboarding.tutorial.with.jenkins.jenkinsfile.dotnet.build_agent')}
           checked={flavorComponent}
-          name="flavorComponent"
           optionLabelKey="onboarding.build.dotnet"
           onCheck={value => setFlavorComponet(value as keyof typeof DotNetFlavor)}
           options={Object.keys(DotNetFlavor)}
index 3a258621fc0ce7511b66234272543fe960552570..a35dc65c26dcababd1c93b7b5c034e544979662d 100644 (file)
@@ -31,7 +31,7 @@ exports[`should render correctly for 1`] = `
   >
     onboarding.build.other.os
     <RenderOptions
-      name="flavorComponent"
+      label="onboarding.build.other.os"
       onCheck={[Function]}
       optionLabelKey="onboarding.build.other.os"
       options={
@@ -78,7 +78,7 @@ exports[`should render correctly for linux: linux 1`] = `
     onboarding.build.other.os
     <RenderOptions
       checked="linux"
-      name="flavorComponent"
+      label="onboarding.build.other.os"
       onCheck={[Function]}
       optionLabelKey="onboarding.build.other.os"
       options={
@@ -157,7 +157,7 @@ exports[`should render correctly for mac: mac 1`] = `
     onboarding.build.other.os
     <RenderOptions
       checked="mac"
-      name="flavorComponent"
+      label="onboarding.build.other.os"
       onCheck={[Function]}
       optionLabelKey="onboarding.build.other.os"
       options={
@@ -240,7 +240,7 @@ exports[`should render correctly for win: win 1`] = `
     onboarding.build.other.os
     <RenderOptions
       checked="win"
-      name="flavorComponent"
+      label="onboarding.build.other.os"
       onCheck={[Function]}
       optionLabelKey="onboarding.build.other.os"
       options={
index 60d9bf011b9b1ecdc005093bba4d59218ebc44ae..34b0cd7f07b9c9f09515aadcc4d7b6ff4c13dc5c 100644 (file)
@@ -5,7 +5,7 @@ exports[`should render correctly 1`] = `
   <li>
     onboarding.tutorial.with.jenkins.jenkinsfile.dotnet.build_agent
     <RenderOptions
-      name="flavorComponent"
+      label="onboarding.tutorial.with.jenkins.jenkinsfile.dotnet.build_agent"
       onCheck={[Function]}
       optionLabelKey="onboarding.build.dotnet"
       options={
index 304d55f335a99cd992f79f8be98380c8837f3e87..6bff4777b5828b81cec4f10b995809b73ce68613 100644 (file)
@@ -72,7 +72,7 @@ export class BuildToolForm extends React.PureComponent<Props, State> {
         <div>
           <h4 className="spacer-bottom">{translate('onboarding.build')}</h4>
           <ButtonToggle
-            name="language"
+            label={translate('onboarding.build')}
             onCheck={this.handleBuildToolChange}
             options={buildTools.map(tool => ({
               label: translate('onboarding.build', tool),
@@ -84,8 +84,8 @@ export class BuildToolForm extends React.PureComponent<Props, State> {
 
         {(config.buildTool === BuildTools.Other || config.buildTool === BuildTools.CFamily) && (
           <RenderOptions
+            label={translate('onboarding.build.other.os')}
             checked={config.os}
-            name="os"
             onCheck={this.handleOSChange}
             optionLabelKey="onboarding.build.other.os"
             options={[OSs.Linux, OSs.Windows, OSs.MacOS]}
index d2da6bd3dea9c8d9b66426135b7af72233208631..5af117d2d8e40a0fd10daac4a02e696ba4115d3b 100644 (file)
@@ -9,8 +9,7 @@ exports[`renders correctly: default 1`] = `
       onboarding.build
     </h4>
     <ButtonToggle
-      disabled={false}
-      name="language"
+      label="onboarding.build"
       onCheck={[Function]}
       options={
         Array [
@@ -36,7 +35,6 @@ exports[`renders correctly: default 1`] = `
           },
         ]
       }
-      value={null}
     />
   </div>
 </Fragment>
@@ -51,8 +49,7 @@ exports[`renders correctly: with "maven" selected 1`] = `
       onboarding.build
     </h4>
     <ButtonToggle
-      disabled={false}
-      name="language"
+      label="onboarding.build"
       onCheck={[Function]}
       options={
         Array [
@@ -93,8 +90,7 @@ exports[`renders correctly: with "other" selected 1`] = `
       onboarding.build
     </h4>
     <ButtonToggle
-      disabled={false}
-      name="language"
+      label="onboarding.build"
       onCheck={[Function]}
       options={
         Array [
@@ -124,7 +120,7 @@ exports[`renders correctly: with "other" selected 1`] = `
     />
   </div>
   <RenderOptions
-    name="os"
+    label="onboarding.build.other.os"
     onCheck={[Function]}
     optionLabelKey="onboarding.build.other.os"
     options={
@@ -148,8 +144,7 @@ exports[`renders correctly: without C 1`] = `
       onboarding.build
     </h4>
     <ButtonToggle
-      disabled={false}
-      name="language"
+      label="onboarding.build"
       onCheck={[Function]}
       options={
         Array [
@@ -171,7 +166,6 @@ exports[`renders correctly: without C 1`] = `
           },
         ]
       }
-      value={null}
     />
   </div>
 </Fragment>
index b0dfd6f743cd38a091cf13ce360e5e202f89be2b..e512f38cab2e067a4855e464199764bef43d3819 100644 (file)
@@ -18,6 +18,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
+import { translate } from '../../../../helpers/l10n';
 import { Component } from '../../../../types/types';
 import RenderOptions from '../../components/RenderOptions';
 import DotNetCore from './DotNetCore';
@@ -41,8 +42,8 @@ export default function DotNet(props: DotNetProps) {
   return (
     <>
       <RenderOptions
+        label={translate('onboarding.build.other.os')}
         checked={variant}
-        name="variant"
         onCheck={value => setVariant(value as Variant)}
         optionLabelKey="onboarding.build.dotnet.variant"
         options={['dotnet_core', 'dotnet_framework']}
index b88033c45f5e7cf1ebc8cd1ee79451406c283f6a..02c7e57d294960fcead604eb2c446db0e10cf18b 100644 (file)
@@ -4,7 +4,7 @@ exports[`should render correctly 1`] = `
 <Fragment>
   <RenderOptions
     checked="dotnet_core"
-    name="variant"
+    label="onboarding.build.other.os"
     onCheck={[Function]}
     optionLabelKey="onboarding.build.dotnet.variant"
     options={