From c413a00d70f7f76376c4f3f30efeeca2053db013 Mon Sep 17 00:00:00 2001
From: Alexander Polyankin <alexander.polyankin@metabase.com>
Date: Mon, 18 Jul 2022 14:05:55 +0300
Subject: [PATCH] Fix font format parsing for URLs with query strings and hash
 (#23990)

---
 .../FontFilesWidget.unit.spec.tsx             | 58 +++++++++++++------
 .../components/FontFilesWidget/utils.ts       | 26 +++++----
 2 files changed, 54 insertions(+), 30 deletions(-)

diff --git a/enterprise/frontend/src/metabase-enterprise/whitelabel/components/FontFilesWidget/FontFilesWidget.unit.spec.tsx b/enterprise/frontend/src/metabase-enterprise/whitelabel/components/FontFilesWidget/FontFilesWidget.unit.spec.tsx
index e33330734a7..68729beaec7 100644
--- a/enterprise/frontend/src/metabase-enterprise/whitelabel/components/FontFilesWidget/FontFilesWidget.unit.spec.tsx
+++ b/enterprise/frontend/src/metabase-enterprise/whitelabel/components/FontFilesWidget/FontFilesWidget.unit.spec.tsx
@@ -1,26 +1,59 @@
 import React from "react";
 import { render, screen } from "@testing-library/react";
 import userEvent from "@testing-library/user-event";
-import { FontFile } from "metabase-types/api";
+import { createMockFontFile } from "metabase-types/api/mocks";
 import FontFilesWidget from "./FontFilesWidget";
 
 describe("FontFilesWidget", () => {
-  it("should add a font file", () => {
-    const files = getFontFiles();
+  it("should add a font file with a query string in the URL", () => {
+    const file = createMockFontFile({
+      src: "https://metabase.test/regular.ttf?raw=true",
+      fontWeight: 400,
+      fontFormat: "truetype",
+    });
     const setting = { value: [] };
     const onChange = jest.fn();
 
     render(<FontFilesWidget setting={setting} onChange={onChange} />);
 
     const input = screen.getByLabelText("Regular");
-    userEvent.type(input, files[0].src);
+    userEvent.type(input, file.src);
     userEvent.tab();
 
-    expect(onChange).toHaveBeenCalledWith([files[0]]);
+    expect(onChange).toHaveBeenCalledWith([file]);
+  });
+
+  it("should add a font file with an invalid URL", () => {
+    const file = createMockFontFile({
+      src: "invalid",
+      fontWeight: 400,
+      fontFormat: "woff2",
+    });
+    const setting = { value: [] };
+    const onChange = jest.fn();
+
+    render(<FontFilesWidget setting={setting} onChange={onChange} />);
+
+    const input = screen.getByLabelText("Regular");
+    userEvent.type(input, file.src);
+    userEvent.tab();
+
+    expect(onChange).toHaveBeenCalledWith([file]);
   });
 
   it("should remove a font file", () => {
-    const files = getFontFiles();
+    const files = [
+      createMockFontFile({
+        src: "https://metabase.test/regular.ttf?raw=true",
+        fontWeight: 400,
+        fontFormat: "truetype",
+      }),
+      createMockFontFile({
+        src: "https://metabase.test/bold.woff2",
+        fontWeight: 700,
+        fontFormat: "woff2",
+      }),
+    ];
     const setting = { value: files };
     const onChange = jest.fn();
 
@@ -33,16 +66,3 @@ describe("FontFilesWidget", () => {
     expect(onChange).toHaveBeenCalledWith([files[1]]);
   });
 });
-
-const getFontFiles = (): FontFile[] => [
-  {
-    src: "https://metabase.test/regular.ttf",
-    fontWeight: 400,
-    fontFormat: "truetype",
-  },
-  {
-    src: "https://metabase.test/bold.woff2",
-    fontWeight: 700,
-    fontFormat: "woff2",
-  },
-];
diff --git a/enterprise/frontend/src/metabase-enterprise/whitelabel/components/FontFilesWidget/utils.ts b/enterprise/frontend/src/metabase-enterprise/whitelabel/components/FontFilesWidget/utils.ts
index 62fbf4510ff..b7d7f05f10e 100644
--- a/enterprise/frontend/src/metabase-enterprise/whitelabel/components/FontFilesWidget/utils.ts
+++ b/enterprise/frontend/src/metabase-enterprise/whitelabel/components/FontFilesWidget/utils.ts
@@ -36,17 +36,21 @@ const getFontFile = (src: string, option: FontFileOption): FontFile => {
 };
 
 const getFontFormat = (src: string): FontFormat => {
-  const match = src.match(/.*\.(\w+)/);
-  const extension = match ? match[1] : null;
+  try {
+    const url = new URL(src);
+    const extension = url.pathname.substring(url.pathname.lastIndexOf("."));
 
-  switch (extension) {
-    case "woff":
-      return "woff";
-    case "woff2":
-      return "woff2";
-    case "ttf":
-      return "truetype";
-    default:
-      return "woff2";
+    switch (extension) {
+      case ".woff":
+        return "woff";
+      case ".woff2":
+        return "woff2";
+      case ".ttf":
+        return "truetype";
+      default:
+        return "woff2";
+    }
+  } catch {
+    return "woff2";
   }
 };
-- 
GitLab