From 18134acf4403e3a7644c162776529ef18fa27e07 Mon Sep 17 00:00:00 2001 From: Drikus Roor Date: Thu, 4 Jul 2024 11:56:16 +0200 Subject: [PATCH] refactor: Convert AppBar component to TypeScript --- frontend/src/components/AppBar/AppBar.jsx | 18 ------- .../src/components/AppBar/AppBar.test.jsx | 48 ------------------- .../src/components/AppBar/AppBar.test.tsx | 47 ++++++++++++++++++ frontend/src/components/AppBar/AppBar.tsx | 16 +++++++ frontend/src/components/Logo/Logo.tsx | 13 +++-- 5 files changed, 71 insertions(+), 71 deletions(-) delete mode 100644 frontend/src/components/AppBar/AppBar.jsx delete mode 100644 frontend/src/components/AppBar/AppBar.test.jsx create mode 100644 frontend/src/components/AppBar/AppBar.test.tsx create mode 100644 frontend/src/components/AppBar/AppBar.tsx diff --git a/frontend/src/components/AppBar/AppBar.jsx b/frontend/src/components/AppBar/AppBar.jsx deleted file mode 100644 index 906453398..000000000 --- a/frontend/src/components/AppBar/AppBar.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from "react"; - -import Logo from "@/components/Logo/Logo"; - - -// AppBar is a bar on top of the app, with navigation and title -const AppBar = ({ title, logoClickConfirm = null }) => { - - return ( -
- -

{title}

- -
- ); -}; - -export default AppBar; diff --git a/frontend/src/components/AppBar/AppBar.test.jsx b/frontend/src/components/AppBar/AppBar.test.jsx deleted file mode 100644 index 1a84c53d7..000000000 --- a/frontend/src/components/AppBar/AppBar.test.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import React from 'react'; -import { render, fireEvent } from '@testing-library/react'; -import AppBar from './AppBar'; -import { BrowserRouter as Router } from 'react-router-dom'; -import { vi } from 'vitest'; - -describe('AppBar', () => { - - const BASE_URL = 'https://www.amsterdammusiclab.nl'; - - beforeEach(() => { - vi.resetModules(); - import.meta.env.VITE_AML_HOME = BASE_URL; - }); - - it('renders correctly', () => { - const { getByText } = render(, { wrapper: Router }); - - const titleElement = getByText('Test Title'); - expect(document.body.contains(titleElement)).to.be.true; - }); - - it('renders logo as Link for relative URL', () => { - const { getByLabelText } = render(, { wrapper: Router }); - const logo = getByLabelText('Logo'); - expect(logo.tagName).toBe('A'); - expect(logo.getAttribute('href')).toBe(BASE_URL); - }); - - it('renders logo as an a-element for absolute URL', () => { - const { getByLabelText } = render(, { wrapper: Router }); - const logo = getByLabelText('Logo'); - expect(logo.tagName).toBe('A'); - expect(logo.getAttribute('href')).toBe(BASE_URL); - }); - - it('prevents navigation when logoClickConfirm is provided and user cancels', () => { - // Mock window.confirm - window.confirm = vi.fn(() => false); - - const { getByLabelText } = render(, { wrapper: Router }); - const logo = getByLabelText('Logo'); - fireEvent.click(logo); - - expect(window.confirm).toHaveBeenCalledWith('Confirm?'); - }); - -}); diff --git a/frontend/src/components/AppBar/AppBar.test.tsx b/frontend/src/components/AppBar/AppBar.test.tsx new file mode 100644 index 000000000..c53b6e6f2 --- /dev/null +++ b/frontend/src/components/AppBar/AppBar.test.tsx @@ -0,0 +1,47 @@ +import { render, fireEvent } from '@testing-library/react'; +import AppBar from './AppBar'; +import { BrowserRouter as Router } from 'react-router-dom'; +import { vi, describe, beforeEach, it, expect } from 'vitest'; + +describe('AppBar', () => { + + const BASE_URL = 'https://www.amsterdammusiclab.nl'; + + beforeEach(() => { + vi.resetModules(); + import.meta.env.VITE_AML_HOME = BASE_URL; + }); + + it('renders correctly', () => { + const { getByText } = render(, { wrapper: Router }); + + const titleElement = getByText('Test Title'); + expect(document.body.contains(titleElement)).to.be.true; + }); + + it('renders logo as Link for relative URL', () => { + const { getByLabelText } = render(, { wrapper: Router }); + const logo = getByLabelText('Logo'); + expect(logo.tagName).toBe('A'); + expect(logo.getAttribute('href')).toBe(BASE_URL); + }); + + it('renders logo as an a-element for absolute URL', () => { + const { getByLabelText } = render(, { wrapper: Router }); + const logo = getByLabelText('Logo'); + expect(logo.tagName).toBe('A'); + expect(logo.getAttribute('href')).toBe(BASE_URL); + }); + + it('prevents navigation when logoClickConfirm is provided and user cancels', () => { + // Mock window.confirm + window.confirm = vi.fn(() => false); + + const { getByLabelText } = render(, { wrapper: Router }); + const logo = getByLabelText('Logo'); + fireEvent.click(logo); + + expect(window.confirm).toHaveBeenCalledWith('Confirm?'); + }); + +}); diff --git a/frontend/src/components/AppBar/AppBar.tsx b/frontend/src/components/AppBar/AppBar.tsx new file mode 100644 index 000000000..251d6d3d2 --- /dev/null +++ b/frontend/src/components/AppBar/AppBar.tsx @@ -0,0 +1,16 @@ +import Logo from "@/components/Logo/Logo"; + +interface AppBarProps { + title: string; + logoClickConfirm?: string | null; +} + +/** AppBar is a bar on top of the app, with navigation and title */ +const AppBar = ({ title, logoClickConfirm = null }: AppBarProps) => ( +
+ +

{title}

+ +
+); +export default AppBar; diff --git a/frontend/src/components/Logo/Logo.tsx b/frontend/src/components/Logo/Logo.tsx index 27df7842c..859aeb910 100644 --- a/frontend/src/components/Logo/Logo.tsx +++ b/frontend/src/components/Logo/Logo.tsx @@ -2,16 +2,19 @@ import { URLS, LOGO_URL, LOGO_TITLE } from "@/config"; import { Link } from "react-router-dom"; import useBoundStore from "@/util/stores"; +interface LogoProps { + logoClickConfirm: string | null; +} -const Logo: React.FC<{ logoClickConfirm: string | null }> = ({ logoClickConfirm = null }) => { +const Logo: React.FC = ({ logoClickConfirm }) => { const theme = useBoundStore((state) => state.theme); const { alt, title, file, target, rel } = theme?.logo || {}; const href = theme?.logo?.href || URLS.AMLHome; const logoUrl = file ?? LOGO_URL; - // Handle click on logo, to optionally confirm navigating - const onLogoClick = (e) => { + /** Handle click on logo, to optionally confirm navigating */ + const onLogoClick = (e: React.MouseEvent) => { if (logoClickConfirm) { if (!window.confirm(logoClickConfirm)) { e.preventDefault(); @@ -22,7 +25,7 @@ const Logo: React.FC<{ logoClickConfirm: string | null }> = ({ logoClickConfirm // Logo is a Link in case of relative url (/abc), // and a-element for absolute urls (https://www.example.com/) - const logoProps = { + const logoProps: React.HTMLProps = { onClick: onLogoClick, className: "aha__logo", "aria-label": "Logo", @@ -49,4 +52,4 @@ const Logo: React.FC<{ logoClickConfirm: string | null }> = ({ logoClickConfirm ) } -export default Logo; \ No newline at end of file +export default Logo;