From f113c72c10157ecb5ee4fbd4f5bf5b381f87cbf6 Mon Sep 17 00:00:00 2001 From: Adrian Rumpold Date: Tue, 29 Apr 2025 07:33:01 +0200 Subject: [PATCH] Switch to Axios, Panel component test --- frontend/eslint.config.js | 33 +++-- frontend/package-lock.json | 75 +++++------ frontend/package.json | 2 +- frontend/src/App.tsx | 4 - frontend/src/components/Panel/Panel.test.tsx | 128 +++++++++++++++++++ frontend/src/components/Panel/Panel.tsx | 18 +-- frontend/src/constants.ts | 3 + frontend/src/hooks/useArticle.ts | 15 +++ frontend/src/lib/api.ts | 24 ++-- 9 files changed, 226 insertions(+), 76 deletions(-) create mode 100644 frontend/src/components/Panel/Panel.test.tsx create mode 100644 frontend/src/constants.ts create mode 100644 frontend/src/hooks/useArticle.ts diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js index 092408a..82f22a0 100644 --- a/frontend/eslint.config.js +++ b/frontend/eslint.config.js @@ -1,28 +1,33 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' +import js from "@eslint/js"; +import pluginQuery from "@tanstack/eslint-plugin-query"; +import reactHooks from "eslint-plugin-react-hooks"; +import reactRefresh from "eslint-plugin-react-refresh"; +import globals from "globals"; +import tseslint from "typescript-eslint"; export default tseslint.config( - { ignores: ['dist'] }, + { ignores: ["dist"] }, { - extends: [js.configs.recommended, ...tseslint.configs.recommended], - files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + ...tseslint.configs.recommended, + ...pluginQuery.configs["flat/recommended"], + ], + files: ["**/*.{ts,tsx}"], languageOptions: { ecmaVersion: 2020, globals: globals.browser, }, plugins: { - 'react-hooks': reactHooks, - 'react-refresh': reactRefresh, + "react-hooks": reactHooks, + "react-refresh": reactRefresh, }, rules: { ...reactHooks.configs.recommended.rules, - 'react-refresh/only-export-components': [ - 'warn', + "react-refresh/only-export-components": [ + "warn", { allowConstantExport: true }, ], }, - }, -) + } +); diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 33c9c7c..73a6702 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@tanstack/react-query": "^5.74.4", "@tanstack/react-query-devtools": "^5.74.6", - "dompurify": "^3.2.5", + "axios": "^1.9.0", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.5.1", @@ -2921,13 +2921,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT", - "optional": true - }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -3334,9 +3327,19 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, "license": "MIT" }, + "node_modules/axios": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -3560,7 +3563,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -3734,7 +3736,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -3953,7 +3954,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -4034,15 +4034,6 @@ "node": ">=12" } }, - "node_modules/dompurify": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.5.tgz", - "integrity": "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, "node_modules/dotenv": { "version": "16.5.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", @@ -4060,7 +4051,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -4155,7 +4145,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -4165,7 +4154,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -4175,7 +4163,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -4188,7 +4175,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -4736,11 +4722,30 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/form-data": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", - "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -4778,7 +4783,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4808,7 +4812,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -4843,7 +4846,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -4942,7 +4944,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -4986,7 +4987,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -4999,7 +4999,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -5015,7 +5014,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -6734,7 +6732,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -6789,7 +6786,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -6799,7 +6795,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -7434,6 +7429,12 @@ "node": ">= 6" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 0638bb2..1630621 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,7 +13,7 @@ "dependencies": { "@tanstack/react-query": "^5.74.4", "@tanstack/react-query-devtools": "^5.74.6", - "dompurify": "^3.2.5", + "axios": "^1.9.0", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.5.1", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index beee352..6ad6f7c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4,7 +4,6 @@ import ArticleSelector from "./components/ArticleSelector/ArticleSelector"; import Panel from "./components/Panel/Panel"; import TOC from "./components/TOC/TOC"; -import useNavState from "./store/navStore"; import useUIStore from "./store/uiStore"; import styles from "./App.module.css"; @@ -13,7 +12,6 @@ import { useTOC } from "./hooks/toc"; function App() { const { numPanels, addPanel } = useUIStore(); - const { celexId, articleId } = useNavState(); const { data: toc, isPending, error } = useTOC(); if (isPending) { @@ -35,11 +33,9 @@ function App() { {Array.from({ length: numPanels }, (_, index) => ( ))} diff --git a/frontend/src/components/Panel/Panel.test.tsx b/frontend/src/components/Panel/Panel.test.tsx new file mode 100644 index 0000000..1232e82 --- /dev/null +++ b/frontend/src/components/Panel/Panel.test.tsx @@ -0,0 +1,128 @@ +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { fireEvent, render } from "@testing-library/react"; +import { getArticle } from "../../lib/api"; +import { Language } from "../../lib/types"; +import useNavState from "../../store/navStore"; +import useUIStore from "../../store/uiStore"; +import Panel from "./Panel"; + +jest.mock("../../store/uiStore"); +jest.mock("../../store/navStore"); +jest.mock("../../lib/api"); +jest.mock("../../constants", () => + Promise.resolve({ + API_URL: "http://localhost:8000/api", // Mock the API_URL to a local server for testing + }) +); + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, +}); +const renderWithClient = (ui: React.ReactElement) => { + const { rerender, ...result } = render( + {ui} + ); + return { + ...result, + rerender: (rerenderUi: React.ReactElement) => + rerender( + + {rerenderUi} + + ), + }; +}; + +const wrapper = ({ children }) => ( + {children} +); + +describe("Panel Component", () => { + const mockSetSelectedParagraphId = jest.fn(); + const mockUseUIStore = { + selectedParagraphId: null, + setSelectedParagraphId: mockSetSelectedParagraphId, + }; + const mockNavState = { + celexId: "123", + articleId: 1, + }; + + beforeEach(() => { + jest.mocked(useNavState).mockReturnValue(mockNavState); + jest.mocked(useUIStore).mockReturnValue(mockUseUIStore); + }); + + afterEach(() => { + jest.clearAllMocks(); + queryClient.clear(); + }); + + test("renders loading state", () => { + (getArticle as jest.Mock).mockReturnValue(new Promise(() => {})); + const { getByText } = render(, { wrapper }); + expect(getByText("Loading...")).toBeInTheDocument(); + }); + + test("renders error state", async () => { + (getArticle as jest.Mock).mockRejectedValue(new Error("Failed to fetch")); + const { findByText } = renderWithClient(); + expect( + await findByText("An error has occurred: Failed to fetch") + ).toBeInTheDocument(); + }); + + test("renders article content", async () => { + const mockData = `
Test Content
`; + jest.mocked(getArticle).mockResolvedValue(mockData); + + const result = renderWithClient(); + expect(await result.findByText("Test Content")).toBeInTheDocument(); + }); + + test("highlights a paragraph on click", async () => { + const mockData = ` +
Paragraph 1
+
Paragraph 2
+ `; + (getArticle as jest.Mock).mockResolvedValue(mockData); + + const result = renderWithClient(); + + const paragraph1 = await result.findByText("Paragraph 1"); + const paragraph2 = await result.findByText("Paragraph 2"); + + fireEvent.click(paragraph1); + expect(paragraph1.classList.contains("highlight")).toBe(true); + expect(paragraph2.classList.contains("highlight")).toBe(false); + expect(mockSetSelectedParagraphId).toHaveBeenCalledWith("1"); + + fireEvent.click(paragraph2); + expect(paragraph1.classList.contains("highlight")).toBe(false); + expect(paragraph2.classList.contains("highlight")).toBe(true); + expect(mockSetSelectedParagraphId).toHaveBeenCalledWith("2"); + }); + + test("renders LanguageSwitcher and updates language", async () => { + jest + .mocked(getArticle) + .mockResolvedValue( + "
Test Content
" + ); + const result = renderWithClient(); + + const languageSwitcher = await result.findByRole("combobox"); + expect(languageSwitcher).toBeInTheDocument(); + + fireEvent.change(languageSwitcher, { target: { value: Language.ENG } }); + expect(jest.mocked(getArticle)).toHaveBeenCalledWith( + "123", + 1, + Language.ENG + ); + }); +}); diff --git a/frontend/src/components/Panel/Panel.tsx b/frontend/src/components/Panel/Panel.tsx index d302a57..b81cefe 100644 --- a/frontend/src/components/Panel/Panel.tsx +++ b/frontend/src/components/Panel/Panel.tsx @@ -1,31 +1,25 @@ -import { useQuery } from "@tanstack/react-query"; -import DOMPurify from "dompurify"; import { useEffect, useRef, useState } from "react"; -import { getArticle } from "../../lib/api"; import { Language } from "../../lib/types"; import useUIStore from "../../store/uiStore"; import LanguageSwitcher from "../LanguageSwitcher/LanguageSwitcher"; +import { useArticle } from "../../hooks/useArticle"; +import useNavState from "../../store/navStore"; import "../../styles/PanelContent.css"; import styles from "./Panel.module.css"; type PanelProps = { - celexId: string; language?: Language; - articleId: number; }; -function Panel({ celexId, language, articleId }: PanelProps) { +function Panel({ language }: PanelProps) { const { selectedParagraphId, setSelectedParagraphId } = useUIStore(); const [lang, setLang] = useState(language || Language.ENG); const articleRef = useRef(null); - const { data, isPending, error } = useQuery({ - queryKey: ["article", celexId, articleId, lang], - queryFn: () => getArticle(celexId, articleId, lang), - enabled: !!celexId && !!articleId, - }); + const { articleId, celexId } = useNavState(); + const { data, isPending, error } = useArticle(celexId, articleId, lang); useEffect(() => { const articleElement = articleRef.current; @@ -85,7 +79,7 @@ function Panel({ celexId, language, articleId }: PanelProps) {
); diff --git a/frontend/src/constants.ts b/frontend/src/constants.ts new file mode 100644 index 0000000..78af8dd --- /dev/null +++ b/frontend/src/constants.ts @@ -0,0 +1,3 @@ +const { VITE_API_URL: API_URL } = import.meta.env; + +export { API_URL }; diff --git a/frontend/src/hooks/useArticle.ts b/frontend/src/hooks/useArticle.ts new file mode 100644 index 0000000..66b30a3 --- /dev/null +++ b/frontend/src/hooks/useArticle.ts @@ -0,0 +1,15 @@ +import { useQuery } from "@tanstack/react-query"; +import { getArticle } from "../lib/api"; +import { Language } from "../lib/types"; + +export const useArticle = ( + celexId: string | null, + articleId: number | null, + lang: Language +) => { + return useQuery({ + queryKey: ["article", celexId, articleId, lang], + queryFn: () => getArticle(celexId!, articleId!, lang), + enabled: !!celexId && !!articleId, + }); +}; diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index ec59767..5897f3c 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -1,6 +1,14 @@ +import Axios from "axios"; +import { API_URL } from "../constants"; import { Division, Language } from "./types"; -const API_URL = import.meta.env.VITE_API_URL; +const axios = Axios.create({ + baseURL: API_URL, + timeout: 5000, + headers: { + "Content-Type": "application/json", + }, +}); async function getArticle( celexId: string, @@ -10,16 +18,16 @@ async function getArticle( console.debug( `Fetching article ${article} for CELEX ID ${celexId} in ${language} language` ); - const response = await fetch( - `${API_URL}/${celexId}/articles/${article}/${language}` + const response = await axios.get( + `${celexId}/articles/${article}/${language}` ); - return await response.text(); + return response.data; } async function getArticleIds(celexId: string): Promise { console.debug(`Fetching article list for CELEX ID ${celexId}`); - const response = await fetch(`${API_URL}/${celexId}/articles`); - return await response.json(); + const response = await axios.get(`${celexId}/articles`); + return response.data; } async function getToc( @@ -27,8 +35,8 @@ async function getToc( language: Language ): Promise { console.debug(`Fetching TOC for CELEX ID ${celexId}`); - const response = await fetch(`${API_URL}/${celexId}/toc/${language}`); - return (await response.json()) as Division[]; + const response = await axios.get(`${celexId}/toc/${language}`); + return response.data; } export { getArticle, getArticleIds, getToc };