diff --git a/src/App.module.css b/src/App.module.css new file mode 100644 index 0000000..814f236 --- /dev/null +++ b/src/App.module.css @@ -0,0 +1,22 @@ +/* Spread header items. Make home button centered until there is not enough space. */ +.header { + display: flex; + flex-direction: row; + gap: 1rem; + align-items: center; + + /* Center each */ + & > div { + flex: 1; + + display: flex; + justify-content: center; + } + /* Except first and last */ + & > div:first-child { + justify-content: flex-start; + } + & > div:last-child { + justify-content: flex-end; + } +} diff --git a/src/App.tsx b/src/App.tsx index e2fd7b6..e665df5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -8,6 +8,7 @@ import UserManual from './pages/Manuals/Manuals.tsx'; import VisProg from "./pages/VisProgPage/VisProg.tsx"; import {useState} from "react"; import Logging from "./components/Logging/Logging.tsx"; +import styles from "./App.module.css"; function App(){ @@ -15,10 +16,10 @@ function App(){ return ( <> -
- © Utrecht University (ICS) - Home - +
+
© Utrecht University (ICS)
+
Home
+
diff --git a/src/components/Icons/Redo.tsx b/src/components/Icons/Redo.tsx deleted file mode 100644 index 4268fc5..0000000 --- a/src/components/Icons/Redo.tsx +++ /dev/null @@ -1,5 +0,0 @@ -export default function Redo({ fill }: { fill?: string }) { - return - - ; -} \ No newline at end of file diff --git a/src/components/Icons/Stop.tsx b/src/components/Icons/Stop.tsx new file mode 100644 index 0000000..5d4c991 --- /dev/null +++ b/src/components/Icons/Stop.tsx @@ -0,0 +1,5 @@ +export default function Stop({ fill }: { fill?: string }) { + return + + ; +} diff --git a/src/pages/MonitoringPage/MonitoringPage.module.css b/src/pages/MonitoringPage/MonitoringPage.module.css index 72e677c..cab20bc 100644 --- a/src/pages/MonitoringPage/MonitoringPage.module.css +++ b/src/pages/MonitoringPage/MonitoringPage.module.css @@ -46,6 +46,7 @@ University within the Software Project course. display: flex; justify-content: center; align-items: center; + padding: .5rem; } } diff --git a/src/pages/MonitoringPage/MonitoringPage.tsx b/src/pages/MonitoringPage/MonitoringPage.tsx index e7ef003..b1c8f9d 100644 --- a/src/pages/MonitoringPage/MonitoringPage.tsx +++ b/src/pages/MonitoringPage/MonitoringPage.tsx @@ -35,6 +35,11 @@ import { RobotConnected } from './MonitoringPageComponents'; import ExperimentLogs from "./components/ExperimentLogs.tsx"; +import Pause from "../../components/Icons/Pause.tsx"; +import Play from "../../components/Icons/Play.tsx"; +import Next from "../../components/Icons/Next.tsx"; +import Replay from "../../components/Icons/Replay.tsx"; +import Stop from "../../components/Icons/Stop.tsx"; // ---------------------------------------------------------------------- // 1. State management @@ -238,34 +243,39 @@ function ControlPanel({

Experiment Controls

+ > + > + > + > + >
); diff --git a/test/pages/monitoringPage/MonitoringPage.test.tsx b/test/pages/monitoringPage/MonitoringPage.test.tsx index 87f1f30..90ca051 100644 --- a/test/pages/monitoringPage/MonitoringPage.test.tsx +++ b/test/pages/monitoringPage/MonitoringPage.test.tsx @@ -122,8 +122,8 @@ describe('MonitoringPage', () => { describe('Control Buttons', () => { test('Pause calls API and updates UI', async () => { render(); - const pauseBtn = screen.getByText('❚❚'); - + const pauseBtn = screen.getByRole('button', { name: /pause/i }); + await act(async () => { fireEvent.click(pauseBtn); }); @@ -134,8 +134,8 @@ describe('MonitoringPage', () => { test('Play calls API and updates UI', async () => { render(); - const playBtn = screen.getByText('▶'); - + const playBtn = screen.getByRole('button', { name: /play/i }); + await act(async () => { fireEvent.click(playBtn); }); @@ -146,35 +146,35 @@ describe('MonitoringPage', () => { test('Next Phase calls API', async () => { render(); await act(async () => { - fireEvent.click(screen.getByText('⏭')); + fireEvent.click(screen.getByRole('button', { name: /next phase/i })); }); expect(MonitoringAPI.nextPhase).toHaveBeenCalled(); }); test('Reset Experiment calls logic and resets state', async () => { render(); - + // Mock graph reducer return (VisProg.graphReducer as jest.Mock).mockReturnValue([{ id: 'new-phase' }]); await act(async () => { - fireEvent.click(screen.getByText('⟲')); + fireEvent.click(screen.getByRole('button', { name: /reset experiment/i })); }); expect(VisProg.graphReducer).toHaveBeenCalled(); expect(mockSetProgramState).toHaveBeenCalledWith({ phases: [{ id: 'new-phase' }] }); expect(VisProg.runProgram).toHaveBeenCalled(); }); - + test('Reset Experiment handles errors gracefully', async () => { const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); (VisProg.runProgram as jest.Mock).mockRejectedValue(new Error('Fail')); - + render(); await act(async () => { - fireEvent.click(screen.getByText('⟲')); + fireEvent.click(screen.getByRole('button', { name: /reset experiment/i })); }); - + expect(consoleSpy).toHaveBeenCalledWith('Failed to reset program:', expect.any(Error)); consoleSpy.mockRestore(); });