]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-18068 Incorrect semantic markup
authorMathieu Suen <mathieu.suen@sonarsource.com>
Wed, 1 Feb 2023 08:47:49 +0000 (09:47 +0100)
committersonartech <sonartech@sonarsource.com>
Fri, 3 Feb 2023 14:26:00 +0000 (14:26 +0000)
server/sonar-web/src/main/js/components/controls/DateInput.tsx
server/sonar-web/src/main/js/components/controls/__tests__/DateInput-test.tsx
server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap
server/sonar-web/src/main/js/helpers/l10n.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 80174673eff41cd7cb9917a1ddcd744f68d270c6..1c3766ea0d7bd1f7b32d387e0434cc5921fa282a 100644 (file)
@@ -29,6 +29,7 @@ import CalendarIcon from '../../components/icons/CalendarIcon';
 import ChevronLeftIcon from '../../components/icons/ChevronLeftIcon';
 import ChevronRightIcon from '../../components/icons/ChevronRightIcon';
 import {
+  getMonthName,
   getShortMonthName,
   getShortWeekDayName,
   getWeekDayName,
@@ -65,7 +66,7 @@ interface State {
 
 type Week = [string, string, string, string, string, string, string];
 
-const LAST_MONTH_INDEX = 11;
+const MONTH_IN_YEAR = 12;
 
 export default class DateInput extends React.PureComponent<Props, State> {
   input?: HTMLInputElement | null;
@@ -128,32 +129,25 @@ export default class DateInput extends React.PureComponent<Props, State> {
 
   getPreviousMonthAriaLabel = () => {
     const { currentMonth } = this.state;
-    return currentMonth.getMonth() === 0
-      ? translateWithParameters(
-          'show_month_x_of_year_y',
-          getShortMonthName(LAST_MONTH_INDEX),
-          currentMonth.getFullYear() - 1
-        )
-      : translateWithParameters(
-          'show_month_x_of_year_y',
-          getShortMonthName(currentMonth.getMonth() - 1),
-          currentMonth.getFullYear()
-        );
+    const previous = (currentMonth.getMonth() + MONTH_IN_YEAR - 1) % MONTH_IN_YEAR;
+
+    return translateWithParameters(
+      'show_month_x_of_year_y',
+      getMonthName(previous),
+      currentMonth.getFullYear() - Math.floor(previous / (MONTH_IN_YEAR - 1))
+    );
   };
 
   getNextMonthAriaLabel = () => {
     const { currentMonth } = this.state;
-    return currentMonth.getMonth() === LAST_MONTH_INDEX
-      ? translateWithParameters(
-          'show_month_x_of_year_y',
-          getShortMonthName(0),
-          currentMonth.getFullYear() + 1
-        )
-      : translateWithParameters(
-          'show_month_x_of_year_y',
-          getShortMonthName(currentMonth.getMonth() + 1),
-          currentMonth.getFullYear()
-        );
+
+    const next = (currentMonth.getMonth() + MONTH_IN_YEAR + 1) % MONTH_IN_YEAR;
+
+    return translateWithParameters(
+      'show_month_x_of_year_y',
+      getMonthName(next),
+      currentMonth.getFullYear() + 1 - Math.ceil(next / (MONTH_IN_YEAR - 1))
+    );
   };
 
   render() {
@@ -173,7 +167,7 @@ export default class DateInput extends React.PureComponent<Props, State> {
 
     const after = this.props.maxDate || new Date();
 
-    const months = range(12);
+    const months = range(MONTH_IN_YEAR);
     const years = range(new Date().getFullYear() - 10, new Date().getFullYear() + 1);
 
     const selectedDays: Modifier[] = value ? [value] : [];
@@ -226,8 +220,14 @@ export default class DateInput extends React.PureComponent<Props, State> {
                 />
               )}
               {open && (
-                <div className={classNames('date-input-calendar', { 'align-right': alignRight })}>
-                  <nav className="date-input-calendar-nav">
+                <form className={classNames('date-input-calendar', { 'align-right': alignRight })}>
+                  <fieldset
+                    className="date-input-calendar-nav"
+                    aria-label={translateWithParameters(
+                      'date.select_month_and_year_x',
+                      `${getMonthName(currentMonth.getMonth())}, ${currentMonth.getFullYear()}`
+                    )}
+                  >
                     <ButtonIcon
                       className="button-small"
                       aria-label={this.getPreviousMonthAriaLabel()}
@@ -262,7 +262,7 @@ export default class DateInput extends React.PureComponent<Props, State> {
                     >
                       <ChevronRightIcon />
                     </ButtonIcon>
-                  </nav>
+                  </fieldset>
                   <DayPicker
                     captionElement={<NullComponent />}
                     disabledDays={{ after, before: minDate }}
@@ -276,7 +276,7 @@ export default class DateInput extends React.PureComponent<Props, State> {
                     weekdaysLong={weekdaysLong}
                     weekdaysShort={weekdaysShort}
                   />
-                </div>
+                </form>
               )}
             </span>
           </EscKeydownHandler>
index 30bd6262f1136e80dfe622f789d6a36dfd0cd346..35067dd5e9394ac67c835a353b64b7f5ad8bb772 100644 (file)
@@ -106,12 +106,12 @@ it('should hightlightTo range', () => {
 it('should announce the proper month and year for next/previous buttons aria label', () => {
   const { wrapper, instance } = shallowRender();
   expect(wrapper.state().currentMonth).toEqual(dateA);
-  expect(instance.getPreviousMonthAriaLabel()).toEqual('show_month_x_of_year_y.Dec.2017');
-  expect(instance.getNextMonthAriaLabel()).toEqual('show_month_x_of_year_y.Feb.2018');
+  expect(instance.getPreviousMonthAriaLabel()).toEqual('show_month_x_of_year_y.December.2017');
+  expect(instance.getNextMonthAriaLabel()).toEqual('show_month_x_of_year_y.February.2018');
 
   instance.handleCurrentMonthChange({ value: 11 });
-  expect(instance.getPreviousMonthAriaLabel()).toEqual('show_month_x_of_year_y.Nov.2018');
-  expect(instance.getNextMonthAriaLabel()).toEqual('show_month_x_of_year_y.Jan.2019');
+  expect(instance.getPreviousMonthAriaLabel()).toEqual('show_month_x_of_year_y.November.2018');
+  expect(instance.getNextMonthAriaLabel()).toEqual('show_month_x_of_year_y.January.2019');
 });
 
 function shallowRender(props?: Partial<DateInput['props']>) {
index e6f37a0c6d7fefa2cdc6bad789dfd389236b27db..b6d12dc1f0917a127a91340472f27aa27117c1ab 100644 (file)
@@ -109,14 +109,15 @@ exports[`should render 3`] = `
           }
           onClick={[Function]}
         />
-        <div
+        <form
           className="date-input-calendar"
         >
-          <nav
+          <fieldset
+            aria-label="date.select_month_and_year_x.January, 2018"
             className="date-input-calendar-nav"
           >
             <ButtonIcon
-              aria-label="show_month_x_of_year_y.Dec.2017"
+              aria-label="show_month_x_of_year_y.December.2017"
               className="button-small"
               onClick={[Function]}
             >
@@ -249,13 +250,13 @@ exports[`should render 3`] = `
               />
             </div>
             <ButtonIcon
-              aria-label="show_month_x_of_year_y.Feb.2018"
+              aria-label="show_month_x_of_year_y.February.2018"
               className="button-small"
               onClick={[Function]}
             >
               <ChevronRightIcon />
             </ButtonIcon>
-          </nav>
+          </fieldset>
           <DayPicker
             canChangeMonth={true}
             captionElement={<NullComponent />}
@@ -362,7 +363,7 @@ exports[`should render 3`] = `
               ]
             }
           />
-        </div>
+        </form>
       </span>
     </EscKeydownHandler>
   </OutsideClickHandler>
index 0f4d35e40e7aa08fad26032dc5c8d4158d10778b..6065fdc3e5a951db368bcf7e53b2e61afd1b3658 100644 (file)
@@ -74,6 +74,24 @@ export function getLocalizedMetricDomain(domainName: string) {
   return hasMessage(bundleKey) ? translate(bundleKey) : domainName;
 }
 
+export function getMonthName(index: number) {
+  const months = [
+    'January',
+    'February',
+    'March',
+    'April',
+    'May',
+    'June',
+    'July',
+    'August',
+    'September',
+    'October',
+    'November',
+    'December',
+  ];
+  return translate(months[index]);
+}
+
 export function getShortMonthName(index: number) {
   const months = [
     'Jan',
index 058f5be8573323e5ff06482d2f44522cbea754b4..e188285828e61dfe45813186c435344ceb90cb2d 100644 (file)
@@ -371,6 +371,7 @@ Sa=Sa
 select_month=Select a month
 show_month_x_of_year_y=Show {0} of {1}
 select_year=Select a year
+date.select_month_and_year_x=Select the month and year, currently {0}
 
 #------------------------------------------------------------------------------
 #