diff --git a/app/components/inputs/suggestionInput/__test__/SuggestionInput.test.tsx b/app/components/inputs/suggestionInput/__test__/SuggestionInput.test.tsx index 77db25974..1308a0407 100644 --- a/app/components/inputs/suggestionInput/__test__/SuggestionInput.test.tsx +++ b/app/components/inputs/suggestionInput/__test__/SuggestionInput.test.tsx @@ -74,8 +74,8 @@ describe("SuggestionInput", () => { const { getByText, getByRole, container } = render(); fireEvent.change(getByRole("combobox"), { target: { value: "Berlin" } }); - await waitFor(() => getByText("Berlin Brandenburg Flughafen (BER)")); - fireEvent.click(getByText("Berlin Brandenburg Flughafen (BER)")); + await waitFor(() => getByText("Brandenburg Flughafen (BER)")); + fireEvent.click(getByText("Brandenburg Flughafen (BER)")); expect(mockedValidate).toHaveBeenCalledTimes(1); await waitFor(() => { expect( @@ -136,8 +136,8 @@ describe("SuggestionInput", () => { ); fireEvent.change(getByRole("combobox"), { target: { value: "Berlin" } }); - await waitFor(() => getByText("Berlin Brandenburg Flughafen (BER)")); - fireEvent.click(getByText("Berlin Brandenburg Flughafen (BER)")); + await waitFor(() => getByText("Brandenburg Flughafen (BER)")); + fireEvent.click(getByText("Brandenburg Flughafen (BER)")); await waitFor(() => { expect( @@ -181,8 +181,8 @@ describe("SuggestionInput", () => { ).not.toBeInTheDocument(); fireEvent.change(getByRole("combobox"), { target: { value: "Berlin" } }); - await waitFor(() => getByText("Berlin Brandenburg Flughafen (BER)")); - fireEvent.click(getByText("Berlin Brandenburg Flughafen (BER)")); + await waitFor(() => getByText("Brandenburg Flughafen (BER)")); + fireEvent.click(getByText("Brandenburg Flughafen (BER)")); await waitFor(() => expect( diff --git a/app/components/inputs/suggestionInput/customComponents/FormatOptionLabel.tsx b/app/components/inputs/suggestionInput/customComponents/FormatOptionLabel.tsx index 357257da6..497deea62 100644 --- a/app/components/inputs/suggestionInput/customComponents/FormatOptionLabel.tsx +++ b/app/components/inputs/suggestionInput/customComponents/FormatOptionLabel.tsx @@ -1,22 +1,65 @@ import { FormatOptionLabelMeta } from "react-select"; import { DataListOptions } from "../SuggestionInput"; +function splitHighlightWord( + text: string | undefined, + matchWord: string, +): string[] { + if (typeof text === "undefined") { + return []; + } + + return text.split(new RegExp(`(${matchWord})`, "gi")); +} + +const renderHighlightText = ( + wordParts: string[], + matchWord: string, + testId: string, +) => { + return wordParts.map((wordPart, index) => + wordPart.toLowerCase() === matchWord.toLowerCase() ? ( + + {wordPart} + + ) : ( + wordPart + ), + ); +}; + const FormatOptionLabel = ( { label, subDescription }: DataListOptions, - { context }: FormatOptionLabelMeta, + { context, inputValue }: FormatOptionLabelMeta, ) => { - if (context === "menu") { - return ( -
- {label} -
- {subDescription} -
-
- ); + if (context === "value") { + return {label}; } - return {label}; + const inputWithoutSpace = inputValue.trim(); + + const labelParts = splitHighlightWord(label, inputWithoutSpace); + const subDescriptionParts = splitHighlightWord( + subDescription, + inputWithoutSpace, + ); + + return ( +
+ {renderHighlightText( + labelParts, + inputWithoutSpace, + "suggestion-item-label-highlight", + )} +
+ {renderHighlightText( + subDescriptionParts, + inputWithoutSpace, + "suggestion-item-subDescription-highlight", + )} +
+
+ ); }; export default FormatOptionLabel; diff --git a/app/components/inputs/suggestionInput/customComponents/__test__/FormatOptionLabel.test.tsx b/app/components/inputs/suggestionInput/customComponents/__test__/FormatOptionLabel.test.tsx new file mode 100644 index 000000000..5df89161f --- /dev/null +++ b/app/components/inputs/suggestionInput/customComponents/__test__/FormatOptionLabel.test.tsx @@ -0,0 +1,109 @@ +import { render } from "@testing-library/react"; +import FormatOptionLabel from "../FormatOptionLabel"; + +describe("FormatOptionLabel", () => { + it("it should render the label if the context is a value", () => { + const dataListOption = [{ label: "Paris", value: " any value" }]; + + const { getByText } = render( + FormatOptionLabel(dataListOption[0], { + context: "value", + inputValue: "Paris", + selectValue: dataListOption, + }), + ); + + expect(getByText(dataListOption[0].label)).toBeInTheDocument(); + }); + + it("it should render the label and the subDescription without highlight if the context is a menu", () => { + const dataListOption = [ + { label: "Paris", subDescription: "Paris, France", value: " any value" }, + ]; + + const { queryByTestId } = render( + FormatOptionLabel(dataListOption[0], { + context: "menu", + inputValue: "any text", + selectValue: dataListOption, + }), + ); + + expect( + queryByTestId("suggestion-item-label-highlight"), + ).not.toBeInTheDocument(); + + expect( + queryByTestId("suggestion-item-subDescription-highlight"), + ).not.toBeInTheDocument(); + }); + + it("it should render the label and the subDescription with highlight if the context is a menu", () => { + const dataListOption = [ + { + label: "Paris Charles de Gaulle", + subDescription: "Paris, France", + value: " any value", + }, + ]; + + const mockInputValue = "Paris"; + + const { queryByTestId } = render( + FormatOptionLabel(dataListOption[0], { + context: "menu", + inputValue: mockInputValue, + selectValue: dataListOption, + }), + ); + + expect( + queryByTestId("suggestion-item-label-highlight"), + ).toBeInTheDocument(); + expect(queryByTestId("suggestion-item-label-highlight")?.innerHTML).toBe( + mockInputValue, + ); + + expect( + queryByTestId("suggestion-item-subDescription-highlight"), + ).toBeInTheDocument(); + expect( + queryByTestId("suggestion-item-subDescription-highlight")?.innerHTML, + ).toBe(mockInputValue); + }); + + it("it should render the label and the subDescription with highlight if the context is a menu even with empty space", () => { + const dataListOption = [ + { + label: "Paris Charles de Gaulle", + subDescription: "Paris, France", + value: " any value", + }, + ]; + + const mockInputValue = "Paris"; + const emptySpace = " "; + + const { queryByTestId } = render( + FormatOptionLabel(dataListOption[0], { + context: "menu", + inputValue: `${mockInputValue}${emptySpace}`, + selectValue: dataListOption, + }), + ); + + expect( + queryByTestId("suggestion-item-label-highlight"), + ).toBeInTheDocument(); + expect(queryByTestId("suggestion-item-label-highlight")?.innerHTML).toBe( + mockInputValue, + ); + + expect( + queryByTestId("suggestion-item-subDescription-highlight"), + ).toBeInTheDocument(); + expect( + queryByTestId("suggestion-item-subDescription-highlight")?.innerHTML, + ).toBe(mockInputValue); + }); +});