Repository: digitalservicebund/a2j-rechtsantragstelle
Pull request #1919: fix: special chars issue
Author: login: pgurusinga
Labels: name: ZOV
Created: 2025-04-01T13:19:47Z | Merged: 2025-04-02T15:09:32Z

https://app.asana.com/0/1207022303033556/1209855503144765/f


Diff:
diff --git a/app/components/inputs/autoSuggestInput/customComponents/FormatOptionLabel.tsx b/app/components/inputs/autoSuggestInput/customComponents/FormatOptionLabel.tsx
index c60f09e5e8..df1586c378 100644
--- a/app/components/inputs/autoSuggestInput/customComponents/FormatOptionLabel.tsx
+++ b/app/components/inputs/autoSuggestInput/customComponents/FormatOptionLabel.tsx
@@ -1,6 +1,10 @@
 import type { FormatOptionLabelMeta } from "react-select";
 import type { DataListOptions } from "~/services/dataListOptions/getDataListOptions";
 
+function escapeParentheses(string: string) {
+  return string.replace(/[\\()]/g, "\\$&");
+}
+
 function splitHighlightWord(
   text: string | undefined,
   matchWord: string,
@@ -9,7 +13,7 @@ function splitHighlightWord(
     return [];
   }
 
-  return text.split(new RegExp(`(${matchWord})`, "gi"));
+  return text.split(new RegExp(`(${escapeParentheses(matchWord)})`, "gi"));
 }
 
 const renderHighlightText = (
diff --git a/app/components/inputs/autoSuggestInput/customComponents/__test__/FormatOptionLabel.test.tsx b/app/components/inputs/autoSuggestInput/customComponents/__test__/FormatOptionLabel.test.tsx
index 5df89161f3..a12f96fcf5 100644
--- a/app/components/inputs/autoSuggestInput/customComponents/__test__/FormatOptionLabel.test.tsx
+++ b/app/components/inputs/autoSuggestInput/customComponents/__test__/FormatOptionLabel.test.tsx
@@ -106,4 +106,68 @@ describe("FormatOptionLabel", () => {
       queryByTestId("suggestion-item-subDescription-highlight")?.innerHTML,
     ).toBe(mockInputValue);
   });
+
+  describe("handling special characters in search input", () => {
+    const testCases = [
+      {
+        label: "Berlin (BER)",
+        input: "Berlin (BER)",
+      },
+      {
+        label: "Frankfurt (FRA)",
+        input: "(FRA)",
+      },
+      {
+        label: "Munich (MUC) Airport",
+        input: "(MUC)",
+      },
+      {
+        label: "Test Airport (XYZ)",
+        input: "Test Airport (",
+      },
+      {
+        label: "Test ((Double))",
+        input: "((Double))",
+      },
+      {
+        label: "Test\\Backslash",
+        input: "Test\\Backslash",
+      },
+      {
+        label: "Multiple\\\\Backslashes",
+        input: "Multiple\\\\",
+      },
+      {
+        label: "Mixed (Test)\\Case",
+        input: "(Test)\\Case",
+      },
+    ];
+
+    testCases.forEach(({ label, input }) => {
+      it(`should highlight "${input}" in "${label}"`, () => {
+        const dataListOption = [
+          {
+            label,
+            subDescription: label,
+            value: "TEST",
+          },
+        ];
+
+        const { queryByTestId } = render(
+          FormatOptionLabel(dataListOption[0], {
+            context: "menu",
+            inputValue: input,
+            selectValue: dataListOption,
+          }),
+        );
+
+        const highlightedElement = queryByTestId(
+          "suggestion-item-label-highlight",
+        );
+
+        expect(highlightedElement).toBeInTheDocument();
+        expect(highlightedElement?.innerHTML).toBe(input);
+      });
+    });
+  });
 });


Reviews:
user: login: aaschlote
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T09:43:27Z
user: login: github-advanced-security[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-02T12:25:09Z
user: login: aaschlote
body: LGTM!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T14:30:48Z

Review comments:
diff_hunk: @@ -1,6 +1,10 @@
 import type { FormatOptionLabelMeta } from "react-select";
 import type { DataListOptions } from "~/services/dataListOptions/getDataListOptions";
 
+function escapeSpecialCharacters(string: string) {
+  return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
path: app/components/inputs/autoSuggestInput/customComponents/FormatOptionLabel.tsx
user: login: aaschlote
body: the error only happens with parentheses, so we don't need to scape all the special characters besides the parentheses.

Please remember to rename the function! 
created_at: 2025-04-02T09:43:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,6 +1,10 @@
 import type { FormatOptionLabelMeta } from "react-select";
 import type { DataListOptions } from "~/services/dataListOptions/getDataListOptions";
 
+function escapeParentheses(string: string) {
+  return string.replace(/[()]/g, "\\$&");
path: app/components/inputs/autoSuggestInput/customComponents/FormatOptionLabel.tsx
user: login: github-advanced-security[bot]
body: ## Incomplete string escaping or encoding

This does not escape backslash characters in the input.

[Show more details](https://github.com/digitalservicebund/a2j-rechtsantragstelle/security/code-scanning/75)
created_at: 2025-04-02T12:25:09Z
author_association: NONE

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-04-02T15:04:29Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=digitalservicebund_a2j-rechtsantragstelle&pullRequest=1919) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=digitalservicebund_a2j-rechtsantragstelle&pullRequest=1919&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=digitalservicebund_a2j-rechtsantragstelle&pullRequest=1919&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=digitalservicebund_a2j-rechtsantragstelle&pullRequest=1919&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [100.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=digitalservicebund_a2j-rechtsantragstelle&pullRequest=1919&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=digitalservicebund_a2j-rechtsantragstelle&pullRequest=1919&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=digitalservicebund_a2j-rechtsantragstelle&pullRequest=1919)


author_association: NONE