Skip to content

Commit 60e51c4

Browse files
authored
Merge pull request #7359 from Sage/FE-7268
fix(date, date-range): ensure date format override returns correct formatted value
2 parents f95186c + f7baa71 commit 60e51c4

File tree

9 files changed

+453
-146
lines changed

9 files changed

+453
-146
lines changed

src/components/date-range/date-range.component.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ export const DateRange = ({
149149
endRef,
150150
required,
151151
isOptional,
152+
dateFormatOverride: dateFormatOverrideProp,
152153
datePickerStartAriaLabel,
153154
datePickerStartAriaLabelledBy,
154155
datePickerEndAriaLabel,
@@ -169,8 +170,12 @@ export const DateRange = ({
169170
const l = useLocale();
170171
const { dateFnsLocale, dateFormatOverride } = l.date;
171172
const { format } = useMemo(
172-
() => getFormatData(dateFnsLocale(), dateFormatOverride),
173-
[dateFnsLocale, dateFormatOverride],
173+
() =>
174+
getFormatData(
175+
dateFnsLocale(),
176+
dateFormatOverrideProp || dateFormatOverride,
177+
),
178+
[dateFnsLocale, dateFormatOverrideProp, dateFormatOverride],
174179
);
175180
const inlineLabelWidth = 40;
176181
const [lastChangedDate, setLastChangedDate] = useState("");

src/components/date-range/date-range.test.tsx

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React from "react";
22
import { render, screen, within } from "@testing-library/react";
33
import userEvent from "@testing-library/user-event";
44
import { enGB as enGBLocale } from "date-fns/locale/en-GB";
5-
import { de as deLocale } from "date-fns/locale/de";
65

76
import DateRange, { DateRangeChangeEvent } from "./date-range.component";
87
import { testStyledSystemMargin } from "../../__spec_helper__/__internal__/test-utils";
@@ -1219,17 +1218,17 @@ test("should have the default styling when the `labelsInline` prop is set and `v
12191218
});
12201219

12211220
describe("Locale formatting overrides", () => {
1222-
test("should render with the input value matching the expected format when `dateFormatOverride` is set and the language is `de-DE`", () => {
1221+
it("should render with the input value matching the expected format when `dateFormatOverride` is passed as a translation key", () => {
12231222
render(
12241223
<I18nProvider
12251224
locale={{
1226-
locale: () => "de-DE",
1225+
locale: () => "en-GB",
12271226
date: {
12281227
ariaLabels: {
12291228
nextMonthButton: () => "foo",
12301229
previousMonthButton: () => "foo",
12311230
},
1232-
dateFnsLocale: () => deLocale,
1231+
dateFnsLocale: () => enGBLocale,
12331232
dateFormatOverride: "y-m-ddd",
12341233
},
12351234
}}
@@ -1251,28 +1250,15 @@ describe("Locale formatting overrides", () => {
12511250
);
12521251
});
12531252

1254-
test("should render with the input value matching the expected format when `dateFormatOverride` is set and the language is `en-GB`", () => {
1253+
it("should render with the input value matching the expected format when `dateFormatOverride` is passed as a prop", () => {
12551254
render(
1256-
<I18nProvider
1257-
locale={{
1258-
locale: () => "en-GB",
1259-
date: {
1260-
ariaLabels: {
1261-
nextMonthButton: () => "foo",
1262-
previousMonthButton: () => "foo",
1263-
},
1264-
dateFnsLocale: () => enGBLocale,
1265-
dateFormatOverride: "y-m-ddd",
1266-
},
1267-
}}
1268-
>
1269-
<DateRange
1270-
startLabel="start"
1271-
endLabel="end"
1272-
value={["2016-10-10", "2016-11-11"]}
1273-
onChange={() => {}}
1274-
/>
1275-
</I18nProvider>,
1255+
<DateRange
1256+
startLabel="start"
1257+
endLabel="end"
1258+
value={["2016-10-10", "2016-11-11"]}
1259+
onChange={() => {}}
1260+
dateFormatOverride="y-m-ddd"
1261+
/>,
12761262
);
12771263

12781264
expect(screen.getByRole("textbox", { name: "start" })).toHaveValue(

src/components/date/__internal__/date-formats/date-formats.test.ts

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -511,39 +511,65 @@ test("should default to en-GB locale if no locale code string passed to `getForm
511511
});
512512

513513
describe("dateFormatOverride tests", () => {
514-
const localeCodes = [
515-
// handled locales
516-
"en-CA",
517-
"en-US",
518-
"en-ZA",
519-
"fr-CA",
520-
"ar-EG",
521-
// random locale to cover default switch scenario
522-
"zh-HK",
523-
];
524-
const dateFormatOverride = "dd Mo yyyy";
525-
526-
test.each(localeCodes)(
527-
"should support %s locale code string passed to `getFormatData` when dateFormatOverride is provided",
528-
(code: string) => {
529-
const { formats, format } = getFormatData({ code }, dateFormatOverride);
530-
531-
const expectedFormats = getExpectedFormatForLocale(code);
532-
533-
expect(
534-
expectedFormats.every((formatStr) => formats.includes(formatStr)) &&
535-
formats.length === expectedFormats.length,
536-
).toEqual(true);
537-
538-
expect(format).toEqual(dateFormatOverride);
539-
},
540-
);
514+
it("should return the expected formats when `dateFormatOverride` is passed as NA locale", () => {
515+
const dateFormatOverride = "MM/dd/yyyy";
516+
const { formats, format } = getFormatData(
517+
{ code: "en-GB" },
518+
dateFormatOverride,
519+
);
520+
521+
// since the dateFormatOverride starts with the month, it should be treated as a NA locale
522+
const expectedFormats = getExpectedFormatForLocale("en-US");
523+
524+
expect(
525+
expectedFormats.every((formatStr) => formats.includes(formatStr)) &&
526+
formats.length === expectedFormats.length,
527+
).toEqual(true);
528+
529+
expect(format).toEqual(dateFormatOverride);
530+
});
531+
532+
it("should return the expected formats when `dateFormatOverride` is passed as EU locale", () => {
533+
const dateFormatOverride = "dd/MM/yyyy";
534+
const { formats, format } = getFormatData(
535+
{ code: "en-US" },
536+
dateFormatOverride,
537+
);
538+
539+
// since the dateFormatOverride starts with the day, it should be treated as a EU locale
540+
const expectedFormats = getExpectedFormatForLocale("en-GB");
541+
542+
expect(
543+
expectedFormats.every((formatStr) => formats.includes(formatStr)) &&
544+
formats.length === expectedFormats.length,
545+
).toEqual(true);
546+
547+
expect(format).toEqual(dateFormatOverride);
548+
});
549+
550+
it("should return the expected formats when `dateFormatOverride` is passed as CN locale", () => {
551+
const dateFormatOverride = "yyyy/MM/dd";
552+
const { formats, format } = getFormatData(
553+
{ code: "en-GB" },
554+
dateFormatOverride,
555+
);
556+
557+
// since the dateFormatOverride starts with the year, it should be treated as a CN locale
558+
const expectedFormats = getExpectedFormatForLocale("zh");
559+
560+
expect(
561+
expectedFormats.every((formatStr) => formats.includes(formatStr)) &&
562+
formats.length === expectedFormats.length,
563+
).toEqual(true);
564+
565+
expect(format).toEqual(dateFormatOverride);
566+
});
541567
});
542568

543569
describe.each(euLocales)(
544570
"when EU locales are passed to `getFormatData`",
545571
(locale: string) => {
546-
test(`should return the expected object shape for ${locale} locale`, () => {
572+
it(`should return the expected object shape for ${locale} locale`, () => {
547573
const { formats } = getFormatData({ code: locale });
548574

549575
const expectedFormats = getExpectedFormatForLocale(locale);
@@ -559,7 +585,7 @@ describe.each(euLocales)(
559585
describe.each(naLocales)(
560586
"when NA locales are passed to `getFormatData`",
561587
(locale: string) => {
562-
test(`should return the expected object shape for ${locale} locale`, () => {
588+
it(`should return the expected object shape for ${locale} locale`, () => {
563589
const { formats } = getFormatData({ code: locale });
564590

565591
const expectedFormats = getExpectedFormatForLocale(locale);
@@ -575,7 +601,7 @@ describe.each(naLocales)(
575601
describe.each(cnLocales)(
576602
"when CN locales are passed to `getFormatData`",
577603
(locale: string) => {
578-
test(`should return the expected object shape for ${locale} locale`, () => {
604+
it(`should return the expected object shape for ${locale} locale`, () => {
579605
const { formats } = getFormatData({ code: locale });
580606

581607
const expectedFormats = getExpectedFormatForLocale(locale);

src/components/date/__internal__/date-formats/index.ts

Lines changed: 17 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -145,51 +145,30 @@ const getFormatData = (
145145
dateFormatOverride?: string,
146146
): LocaleFormats => {
147147
const code = locale?.code || "en-GB";
148-
if (dateFormatOverride) {
149-
const { format } = getOutputFormatForLocale(code);
150-
let formatFromLocale;
151-
152-
switch (code) {
153-
case "en-CA":
154-
case "en-US":
155-
formatFromLocale = "MM/dd/yyyy";
156-
break;
157-
case "ar-EG":
158-
case "en-ZA":
159-
case "fr-CA":
160-
formatFromLocale = "dd/MM/yyyy";
161-
break;
162-
default:
163-
formatFromLocale = format;
164-
}
165148

166-
const formatsForLocale = getInputFormatsArrayForLocale(formatFromLocale);
149+
const dateFnsFormatOverrides: Record<
150+
string,
151+
{ format: string; separator?: Separator }
152+
> = {
153+
"en-CA": { format: "MM/dd/yyyy", separator: "/" },
154+
"en-US": { format: "MM/dd/yyyy", separator: "/" },
155+
"fr-CA": { format: "dd/MM/yyyy" },
156+
"en-ZA": { format: "dd/MM/yyyy" },
157+
"ar-EG": { format: "dd/MM/yyyy" },
158+
};
167159

168-
return {
169-
format: dateFormatOverride,
170-
formats: generateFormats(formatsForLocale, "/"),
171-
};
172-
}
160+
const { format: defaultFormat, separator: defaultSeparator } =
161+
getOutputFormatForLocale(code);
173162

174-
if (["en-CA", "en-US"].includes(code)) {
175-
const format = "MM/dd/yyyy";
176-
const formats = getInputFormatsArrayForLocale(format);
177-
return {
178-
format,
179-
formats: generateFormats(formats, "/"),
180-
};
181-
}
163+
const override = dateFnsFormatOverrides[code] || {};
182164

183-
const { format, separator } = getOutputFormatForLocale(code);
184-
const outputFormat = ["fr-CA", "en-ZA", "ar-EG"].includes(code)
185-
? "dd/MM/yyyy"
186-
: format;
187-
const formatsForLocale = getInputFormatsArrayForLocale(outputFormat);
165+
const format = dateFormatOverride ?? override.format ?? defaultFormat;
166+
const separator = override.separator ?? defaultSeparator;
188167

189168
return {
190-
format: outputFormat,
169+
format,
191170
formats: generateFormats(
192-
formatsForLocale,
171+
getInputFormatsArrayForLocale(format),
193172
separator,
194173
getTrailingChar(format),
195174
),

0 commit comments

Comments
 (0)