diff --git a/packages/lib/src/accordion/Accordion.test.tsx b/packages/lib/src/accordion/Accordion.test.tsx index 4aab152c14..c121ceb984 100644 --- a/packages/lib/src/accordion/Accordion.test.tsx +++ b/packages/lib/src/accordion/Accordion.test.tsx @@ -131,4 +131,18 @@ describe("Accordion component tests", () => { fireEvent.click(getByText("Accordion")); expect(onChange).not.toHaveBeenCalled(); }); + test("Accordion does not trigger onSubmit when inside a form", () => { + const onSubmit = jest.fn(); + const { getByText } = render( +
+ + +
test-expanded
+
+
+
+ ); + fireEvent.click(getByText("Accordion")); + expect(onSubmit).not.toHaveBeenCalled(); + }); }); diff --git a/packages/lib/src/accordion/AccordionItem.tsx b/packages/lib/src/accordion/AccordionItem.tsx index cbae646b33..5d1b132128 100644 --- a/packages/lib/src/accordion/AccordionItem.tsx +++ b/packages/lib/src/accordion/AccordionItem.tsx @@ -174,6 +174,7 @@ const AccordionItem = ({ tabIndex={disabled ? -1 : tabIndex} aria-expanded={isItemExpanded} aria-controls={`accordion-panel-${id}`} + type="button" > diff --git a/packages/lib/src/date-input/Calendar.tsx b/packages/lib/src/date-input/Calendar.tsx index 6e27e6f398..3e2b61b387 100644 --- a/packages/lib/src/date-input/Calendar.tsx +++ b/packages/lib/src/date-input/Calendar.tsx @@ -283,6 +283,7 @@ const Calendar = ({ today.get("month") === date.month && today.get("year") === innerDate.get("year") } + type="button" > {date.day} diff --git a/packages/lib/src/date-input/DateInput.test.tsx b/packages/lib/src/date-input/DateInput.test.tsx index 8212575bf2..27655dcfa6 100644 --- a/packages/lib/src/date-input/DateInput.test.tsx +++ b/packages/lib/src/date-input/DateInput.test.tsx @@ -497,4 +497,20 @@ describe("DateInput component tests", () => { userEvent.click(calendarAction); expect(getByText("October 2080")).toBeTruthy(); }); + test("Form onSubmit is not called when interacting with the calendar and pressing enter", () => { + const onSubmit = jest.fn(); + const { getByRole, getAllByText } = render( +
+ + + ); + const calendarAction = getByRole("combobox"); + userEvent.click(calendarAction); + const day1 = getAllByText("1")[0]; + if (day1 != null) { + userEvent.click(day1); + } + userEvent.type(calendarAction, "{enter}"); + expect(onSubmit).not.toHaveBeenCalled(); + }); }); diff --git a/packages/lib/src/date-input/DatePicker.tsx b/packages/lib/src/date-input/DatePicker.tsx index fb5b8f45c4..723d8b4bd9 100644 --- a/packages/lib/src/date-input/DatePicker.tsx +++ b/packages/lib/src/date-input/DatePicker.tsx @@ -107,6 +107,7 @@ const DatePicker = ({ date, onDateSelect, id }: DatePickerPropsType): JSX.Elemen handleMonthChange(innerDate.set("month", innerDate.get("month") - 1))} + type="button" > @@ -114,6 +115,7 @@ const DatePicker = ({ date, onDateSelect, id }: DatePickerPropsType): JSX.Elemen setContent((currentContent) => (currentContent === "yearPicker" ? "calendar" : "yearPicker"))} + type="button" > {translatedLabels.calendar.months[innerDate.get("month")]} {innerDate.format("YYYY")} @@ -124,6 +126,7 @@ const DatePicker = ({ date, onDateSelect, id }: DatePickerPropsType): JSX.Elemen handleMonthChange(innerDate.set("month", innerDate.get("month") + 1))} + type="button" > diff --git a/packages/lib/src/date-input/YearPicker.tsx b/packages/lib/src/date-input/YearPicker.tsx index b08f0cd547..d32ecc103c 100644 --- a/packages/lib/src/date-input/YearPicker.tsx +++ b/packages/lib/src/date-input/YearPicker.tsx @@ -109,6 +109,7 @@ const YearPicker = ({ onYearSelect, selectedDate, today }: YearPickerPropsType): onYearSelect(year); }} role="option" + type="button" > {year} diff --git a/packages/lib/src/dropdown/Dropdown.test.tsx b/packages/lib/src/dropdown/Dropdown.test.tsx index ba2290eb71..de333c8ebe 100644 --- a/packages/lib/src/dropdown/Dropdown.test.tsx +++ b/packages/lib/src/dropdown/Dropdown.test.tsx @@ -411,4 +411,15 @@ describe("Dropdown component tests", () => { }); expect(queryByRole("menu")).toBeFalsy(); }); + test("Dropdown does not trigger form submission when inside a form", () => { + const onSubmit = jest.fn(); + const { getByRole } = render( +
+ {}} /> + + ); + const dropdown = getByRole("button"); + userEvent.click(dropdown); + expect(onSubmit).not.toHaveBeenCalled(); + }); }); diff --git a/packages/lib/src/dropdown/Dropdown.tsx b/packages/lib/src/dropdown/Dropdown.tsx index f9d75012a4..c67357e45b 100644 --- a/packages/lib/src/dropdown/Dropdown.tsx +++ b/packages/lib/src/dropdown/Dropdown.tsx @@ -283,6 +283,7 @@ const DxcDropdown = ({ aria-label="Show options" tabIndex={tabIndex} ref={triggerRef} + type="button" > {icon && ( diff --git a/packages/lib/src/tabs/Tabs.test.tsx b/packages/lib/src/tabs/Tabs.test.tsx index 66f4f4815c..430d3172d7 100644 --- a/packages/lib/src/tabs/Tabs.test.tsx +++ b/packages/lib/src/tabs/Tabs.test.tsx @@ -331,4 +331,29 @@ describe("Tabs component tests", () => { expect(tabs[1]?.getAttribute("aria-selected")).toBe("false"); expect(tabs[2]?.getAttribute("aria-selected")).toBe("true"); }); + test("Tabs should not trigger onSubmit inside a form", () => { + const onSubmit = jest.fn(); + const onTabClick = [jest.fn(), jest.fn(), jest.fn()]; + const { getAllByRole } = render( +
+ + + <> + + + <> + + + <> + + +
+ ); + const tabs = getAllByRole("tab"); + if (tabs[0]) { + fireEvent.click(tabs[0]); + } + expect(onTabClick[0]).toHaveBeenCalled(); + expect(onSubmit).not.toHaveBeenCalled(); + }); }); diff --git a/packages/lib/src/tabs/Tabs.tsx b/packages/lib/src/tabs/Tabs.tsx index 1d137cf0f4..4d96e056ba 100644 --- a/packages/lib/src/tabs/Tabs.tsx +++ b/packages/lib/src/tabs/Tabs.tsx @@ -208,6 +208,7 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs disabled={!scrollLeftEnabled} onClick={scrollLeft} tabIndex={scrollLeftEnabled ? tabIndex : -1} + type="button" > @@ -229,6 +230,7 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs disabled={!scrollRightEnabled} onClick={scrollRight} tabIndex={scrollRightEnabled ? tabIndex : -1} + type="button" > diff --git a/packages/lib/src/toggle-group/ToggleGroup.test.tsx b/packages/lib/src/toggle-group/ToggleGroup.test.tsx index 2aa58d02c2..88f916a7c8 100644 --- a/packages/lib/src/toggle-group/ToggleGroup.test.tsx +++ b/packages/lib/src/toggle-group/ToggleGroup.test.tsx @@ -160,4 +160,21 @@ describe("Toggle group component tests", () => { fireEvent.click(getByRole("button", { name: "Ebay" })); expect(handleChange).toHaveBeenCalledWith([1, 2]); }); + + test("Togglegroup should not trigger onSubmit when inside a form", () => { + const handleSubmit = jest.fn(); + const handleChange = jest.fn(); + const options = [ + { value: 1, label: "Amazon" }, + { value: 2, label: "Ebay" }, + ]; + const { getByRole } = render( +
+ + + ); + fireEvent.click(getByRole("button", { name: "Ebay" })); + expect(handleChange).toHaveBeenCalledWith([1, 2]); + expect(handleSubmit).not.toHaveBeenCalled(); + }); }); diff --git a/packages/lib/src/toggle-group/ToggleGroup.tsx b/packages/lib/src/toggle-group/ToggleGroup.tsx index db80c10de5..ec1ddd85f9 100644 --- a/packages/lib/src/toggle-group/ToggleGroup.tsx +++ b/packages/lib/src/toggle-group/ToggleGroup.tsx @@ -120,6 +120,7 @@ export default function DxcToggleGroup({ onlyIcon={!option.label && !!option.icon} selected={selected} tabIndex={!option.disabled ? tabIndex : -1} + type="button" > {option.icon && ( diff --git a/packages/lib/src/wizard/Wizard.test.tsx b/packages/lib/src/wizard/Wizard.test.tsx index 83d14e9777..cd2dce2113 100644 --- a/packages/lib/src/wizard/Wizard.test.tsx +++ b/packages/lib/src/wizard/Wizard.test.tsx @@ -140,4 +140,25 @@ describe("Wizard components tests", () => { expect(onClick).toHaveBeenNthCalledWith(1, 1); expect(onClick).toHaveBeenNthCalledWith(2, 0); }); + + test("Wizard should not trigger onSubmit when inside a form", () => { + const onSubmit = jest.fn(); + const { getByText } = render( +
+ + + ); + const step = getByText("second-step"); + fireEvent.click(step); + expect(onSubmit).not.toHaveBeenCalled(); + }); }); diff --git a/packages/lib/src/wizard/Wizard.tsx b/packages/lib/src/wizard/Wizard.tsx index aa15ebfb89..fb0799b368 100644 --- a/packages/lib/src/wizard/Wizard.tsx +++ b/packages/lib/src/wizard/Wizard.tsx @@ -190,6 +190,7 @@ export default function DxcWizard({ }} tabIndex={tabIndex} unvisited={i > (currentStep ?? innerCurrent)} + type="button" >