Skip to content
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
3f63538
Add font family in one var
OscarFava Oct 8, 2025
38523d0
Merge remote-tracking branch 'origin/develop' into ofava/vidsol-217-g…
OscarFava Oct 13, 2025
ef31ae7
Add custom MUI colors
OscarFava Oct 13, 2025
e43fb97
Clean theme provider and buttons
OscarFava Oct 13, 2025
d12a043
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
c145636
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
de6bccd
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
940ba11
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
a70eeae
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
4e87903
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
f8a8ec4
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
181ebd3
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
101a7dc
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
87d8d53
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
0d2cf2a
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
4f9a4fd
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
e5de09a
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
6a982f9
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
61f1129
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
f78355e
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
42b6c38
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
8db4cf5
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
d48b723
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
1792941
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 13, 2025
5dfed61
Fix test
OscarFava Oct 14, 2025
91f5baa
Fix deprecated
OscarFava Oct 15, 2025
3183b98
Add default font
OscarFava Oct 15, 2025
129dcde
Fix testing
OscarFava Oct 15, 2025
9b6519e
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
92f4367
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
41106dc
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
e170aeb
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
5b6fade
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
5ed4809
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
1a60234
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
db03a2c
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
5ca89ad
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
c33c15f
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
f52967a
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
c1c9b91
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
30b440a
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
1654453
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
a3174fb
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 15, 2025
143548e
Merge remote-tracking branch 'origin/develop' into ofava/vidsol-217-g…
OscarFava Oct 24, 2025
4c44066
Refactor components to use centralized color palette from customTheme
OscarFava Oct 24, 2025
405c68a
Fix testing
OscarFava Oct 24, 2025
62dd5d3
add keys to devices boxes
OscarFava Oct 24, 2025
a452c86
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
81b2cd8
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
60e067e
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
6e5ba34
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
702ae94
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
40bcbaf
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
c5b7dd7
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
19482be
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
43be1eb
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
620ffca
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
e3da4ec
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
8b8bba5
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
eb58585
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
2071ef3
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
43da185
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
08a424b
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
42cc0d5
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
0f480f7
Commit screenshot file: integration-tests/tests/visualComparisons.spe…
github-actions[bot] Oct 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 34 additions & 29 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import './css/App.css';
import './css/index.css';
import { CssBaseline, ThemeProvider } from '@mui/material';
import Room from './pages/MeetingRoom/index';
import GoodBye from './pages/GoodBye/index';
import WaitingRoom from './pages/WaitingRoom';
Expand All @@ -11,38 +12,42 @@ import { PublisherProvider } from './Context/PublisherProvider';
import RedirectToWaitingRoom from './components/RedirectToWaitingRoom';
import UnsupportedBrowserPage from './pages/UnsupportedBrowserPage';
import RoomContext from './Context/RoomContext';
import customTheme from './utils/customTheme/customTheme';

const App = () => {
return (
<Router>
<Routes>
<Route element={<RoomContext />}>
<Route
path="/waiting-room/:roomName"
element={
<PreviewPublisherProvider>
<WaitingRoom />
</PreviewPublisherProvider>
}
/>
<Route
path="/room/:roomName"
element={
<SessionProvider>
<RedirectToWaitingRoom>
<PublisherProvider>
<Room />
</PublisherProvider>
</RedirectToWaitingRoom>
</SessionProvider>
}
/>
</Route>
<Route path="/goodbye" element={<GoodBye />} />
<Route path="*" element={<LandingPage />} />
<Route path="/unsupported-browser" element={<UnsupportedBrowserPage />} />
</Routes>
</Router>
<ThemeProvider theme={customTheme}>
<CssBaseline />
<Router>
<Routes>
<Route element={<RoomContext />}>
<Route
path="/waiting-room/:roomName"
element={
<PreviewPublisherProvider>
<WaitingRoom />
</PreviewPublisherProvider>
}
/>
<Route
path="/room/:roomName"
element={
<SessionProvider>
<RedirectToWaitingRoom>
<PublisherProvider>
<Room />
</PublisherProvider>
</RedirectToWaitingRoom>
</SessionProvider>
}
/>
</Route>
<Route path="/goodbye" element={<GoodBye />} />
<Route path="*" element={<LandingPage />} />
<Route path="/unsupported-browser" element={<UnsupportedBrowserPage />} />
</Routes>
</Router>
</ThemeProvider>
);
};

Expand Down
129 changes: 53 additions & 76 deletions frontend/src/components/WaitingRoom/UserNameInput/UserNameInput.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { TextField, Button, InputAdornment } from '@mui/material';
import React, { Dispatch, MouseEvent, ReactElement, SetStateAction, useState } from 'react';
import { PersonOutline } from '@mui/icons-material';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import useUserContext from '../../../hooks/useUserContext';
Expand All @@ -15,24 +14,6 @@ export type UserNameInputProps = {
setUsername: Dispatch<SetStateAction<string>>;
};

declare module '@mui/material/styles' {
interface Palette {
blue: Palette['primary'];
}

interface PaletteOptions {
blue?: PaletteOptions['primary'];
}
}

const theme = createTheme({
palette: {
blue: {
main: 'rgba(26,115,232,.9)',
},
},
});

/**
* UsernameInput Component
*
Expand Down Expand Up @@ -94,66 +75,62 @@ const UsernameInput = ({ username, setUsername }: UserNameInputProps): ReactElem
};

return (
<ThemeProvider theme={theme}>
<form className="flex w-full flex-col justify-center px-6 md:relative md:top-[-48px] md:max-w-[480px]">
<div className="mt-4 flex flex-col items-center justify-end">
<div className="mb-2 font-sans text-[28px] leading-8">{t('waitingRoom.title')}</div>
<div className="flex w-full flex-col content-end py-2 text-lg decoration-solid md:max-w-[480px]">
<p className="truncate">{roomName}</p>
</div>
<div className="mt-6 font-sans text-[24px] leading-8">
{t('waitingRoom.user.input.label')}
</div>
<div className="mb-5 flex w-full flex-wrap items-center justify-center">
<TextField
size="small"
margin="dense"
placeholder={t('waitingRoom.user.input.placeholder')}
onChange={onChangeParticipantName}
sx={{
display: 'flex',
width: '100%',
maxWidth: '212px',
marginTop: '20px',
paddingLeft: '0px',
}}
required
id="user-name"
name="Name"
error={isUserNameInvalid}
autoComplete="Name"
autoFocus
value={username}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<PersonOutline />
</InputAdornment>
),
inputProps: { maxLength: 60 },
}}
/>
</div>
<Button
onClick={handleJoinClick}
variant="contained"
color="primary"
<form className="flex w-full flex-col justify-center px-6 md:relative md:top-[-48px] md:max-w-[480px]">
<div className="mt-4 flex flex-col items-center justify-end">
<div className="mb-2 text-[28px] leading-8">{t('waitingRoom.title')}</div>
<div className="flex w-full flex-col content-end py-2 text-lg decoration-solid md:max-w-[480px]">
<p className="truncate">{roomName}</p>
</div>
<div className="mt-6 text-[24px] leading-8">{t('waitingRoom.user.input.label')}</div>
<div className="mb-5 flex w-full flex-wrap items-center justify-center">
<TextField
size="small"
margin="dense"
placeholder={t('waitingRoom.user.input.placeholder')}
onChange={onChangeParticipantName}
sx={{
width: '117px',
borderRadius: '24px',
color: 'white',
textTransform: 'none',
fontSize: '14px',
height: '48px',
display: 'flex',
width: '100%',
maxWidth: '212px',
marginTop: '20px',
paddingLeft: '0px',
}}
required
id="user-name"
name="Name"
error={isUserNameInvalid}
autoComplete="Name"
autoFocus
value={username}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<PersonOutline />
</InputAdornment>
),
inputProps: { maxLength: 60 },
}}
disabled={!username}
type="submit"
>
{t('button.join')}
</Button>
/>
</div>
</form>
</ThemeProvider>
<Button
onClick={handleJoinClick}
variant="contained"
color="primary"
sx={{
width: '117px',
borderRadius: '24px',
color: 'white',
textTransform: 'none',
fontSize: '14px',
height: '48px',
}}
disabled={!username}
type="submit"
>
{t('button.join')}
</Button>
</div>
</form>
);
};

Expand Down
159 changes: 159 additions & 0 deletions frontend/src/utils/customTheme/customTheme.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import { describe, it, expect } from 'vitest';
import customTheme, { colors, fonts, shadows, rgba } from './customTheme';

describe('customTheme', () => {
describe('colors object', () => {
it('should have primary colors defined', () => {
expect(colors.primary).toBe('#3E007E');
expect(colors.onPrimary).toBe('#FFFFFF');
expect(colors.primaryContainer).toBe('#6300C4');
expect(colors.surfaceTint).toBe('#7F02F7');
});

it('should have secondary colors defined', () => {
expect(colors.secondary).toBe('#2F293B');
expect(colors.onSecondary).toBe('#FFFFFF');
expect(colors.secondaryContainer).toBe('#4C4659');
});

it('should have background and surface colors', () => {
expect(colors.background).toBe('#FEF7FF');
expect(colors.surface).toBe('#FCF8F8');
expect(colors.onBackground).toBe('#1E1925');
expect(colors.onSurface).toBe('#000000');
});

it('should have error colors defined', () => {
expect(colors.error).toBe('#600004');
expect(colors.onError).toBe('#FFFFFF');
expect(colors.errorContainer).toBe('#98000A');
});
});

describe('fonts object', () => {
it('should have correct font family string', () => {
expect(fonts.family).toBe('Comic Sans MS,Marker Felt,Trebuchet MS,fantasy,cursive');
});
});

describe('shadows object', () => {
it('should have all shadow levels defined', () => {
expect(shadows.level1).toContain('0 3px 1px -2px rgba(0,0,0,0.2)');
expect(shadows.level2).toContain('0 2px 4px -1px rgba(0,0,0,0.2)');
expect(shadows.level3).toContain('0 5px 5px -3px rgba(0,0,0,0.2)');
});
});

describe('rgba helper function', () => {
it('should convert hex to rgba correctly', () => {
expect(rgba('#FF0000', 0.5)).toBe('rgba(255, 0, 0, 0.5)');
expect(rgba('#000000', 1)).toBe('rgba(0, 0, 0, 1)');
expect(rgba('#FFFFFF', 0.26)).toBe('rgba(255, 255, 255, 0.26)');
});

it('should handle hex colors with hash', () => {
expect(rgba('#3E007E', 0.04)).toBe('rgba(62, 0, 126, 0.04)');
});
});

describe('MUI theme object', () => {
it('should have correct palette colors', () => {
expect(customTheme.palette.primary.main).toBe(colors.primary);
expect(customTheme.palette.primary.contrastText).toBe(colors.onPrimary);
expect(customTheme.palette.background.default).toBe(colors.background);
expect(customTheme.palette.text.primary).toBe(colors.onBackground);
});

it('should have typography configured', () => {
expect(customTheme.typography.fontFamily).toBe(fonts.family);
});

it('should be in light mode', () => {
expect(customTheme.palette.mode).toBe('light');
});

it('should have button component overrides', () => {
const buttonOverrides = customTheme.components?.MuiButton?.styleOverrides;
expect(buttonOverrides).toBeDefined();

Check failure on line 77 in frontend/src/utils/customTheme/customTheme.spec.ts

View workflow job for this annotation

GitHub Actions / run

src/utils/customTheme/customTheme.spec.ts > customTheme > MUI theme object > should have button component overrides

AssertionError: expected undefined not to be undefined ❯ src/utils/customTheme/customTheme.spec.ts:77:31
expect(buttonOverrides?.containedPrimary).toBeDefined();
});

it('should have correct button primary styles', () => {
const primaryButton = customTheme.components?.MuiButton?.styleOverrides?.containedPrimary;

if (
typeof primaryButton === 'object' &&
primaryButton !== null &&
'backgroundColor' in primaryButton &&
'color' in primaryButton &&
'boxShadow' in primaryButton
) {
expect((primaryButton as { backgroundColor: string }).backgroundColor).toBe(colors.primary);
expect((primaryButton as { color: string }).color).toBe(colors.onPrimary);
expect((primaryButton as { boxShadow: string }).boxShadow).toBe(shadows.level1);
}
});
});

describe('theme structure validation', () => {
it('should have all required theme properties', () => {
expect(customTheme.palette).toBeDefined();
expect(customTheme.components).toBeDefined();
expect(customTheme.typography).toBeDefined();
});

it('should have component overrides for major components', () => {
const { components } = customTheme;
expect(components?.MuiButton).toBeDefined();

Check failure on line 107 in frontend/src/utils/customTheme/customTheme.spec.ts

View workflow job for this annotation

GitHub Actions / run

src/utils/customTheme/customTheme.spec.ts > customTheme > theme structure validation > should have component overrides for major components

AssertionError: expected undefined not to be undefined ❯ src/utils/customTheme/customTheme.spec.ts:107:37
expect(components?.MuiAppBar).toBeDefined();
expect(components?.MuiPaper).toBeDefined();
expect(components?.MuiTextField).toBeDefined();
expect(components?.MuiTooltip).toBeDefined();
});
});

describe('color consistency', () => {
it('should use consistent primary color across components', () => {
const buttonPrimary = customTheme.components?.MuiButton?.styleOverrides?.containedPrimary;
const outlinedPrimary = customTheme.components?.MuiButton?.styleOverrides?.outlinedPrimary;
const textPrimary = customTheme.components?.MuiButton?.styleOverrides?.textPrimary;

if (
typeof buttonPrimary === 'object' &&
buttonPrimary !== null &&
'backgroundColor' in buttonPrimary &&
typeof outlinedPrimary === 'object' &&
outlinedPrimary !== null &&
'color' in outlinedPrimary &&
typeof textPrimary === 'object' &&
textPrimary !== null &&
'color' in textPrimary
) {
expect((buttonPrimary as { backgroundColor: string }).backgroundColor).toBe(colors.primary);
expect((outlinedPrimary as { color: string }).color).toBe(colors.primary);
expect((textPrimary as { color: string }).color).toBe(colors.primary);
}
});

it('should use consistent surface colors', () => {
const appBar = customTheme.components?.MuiAppBar?.styleOverrides?.root;
const paper = customTheme.components?.MuiPaper?.styleOverrides?.root;

if (
typeof appBar === 'object' &&
appBar !== null &&
typeof paper === 'object' &&
paper !== null
) {
if (typeof appBar === 'object' && appBar !== null && 'backgroundColor' in appBar) {
expect((appBar as { backgroundColor: string }).backgroundColor).toBe(colors.surface);
}
if (typeof paper === 'object' && paper !== null && 'backgroundColor' in paper) {
expect((paper as { backgroundColor: string }).backgroundColor).toBe(
colors.surfaceContainer
);
}
}
});
});
});
Loading
Loading