From 040d3457b876eab2f0102a365213c3c147bbe2df Mon Sep 17 00:00:00 2001 From: Sero73 Date: Wed, 30 Apr 2025 20:43:19 +0200 Subject: [PATCH 1/7] Test webapp de game y session context --- sonar-project.properties | 2 +- webapp/src/context/SessionContext.test.js | 151 +++++++++++++++++++++ webapp/src/game/HourglassTimer.test.js | 57 ++++++++ webapp/src/game/game.js | 5 +- webapp/src/game/game.test.js | 116 +++++++++++------ webapp/src/game/gameManager.js | 4 +- webapp/src/game/gameManager.test.js | 152 ++++++++++++++++++++++ 7 files changed, 444 insertions(+), 43 deletions(-) create mode 100644 webapp/src/context/SessionContext.test.js create mode 100644 webapp/src/game/HourglassTimer.test.js create mode 100644 webapp/src/game/gameManager.test.js diff --git a/sonar-project.properties b/sonar-project.properties index 3a41481fbc..637624239c 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,7 +6,7 @@ sonar.language=js sonar.projectName=wichat_es6b sonar.coverage.exclusions=**/*.test.js -sonar.sources=webapp/src/components,users/authservice,users/userservice,llmservice,gatewayservice,questionservice +sonar.sources=webapp/src/components,webapp/src/context,webapp/src/game,users/authservice,users/userservice,llmservice,gatewayservice,questionservice sonar.sourceEncoding=UTF-8 sonar.exclusions=node_modules/** sonar.javascript.lcov.reportPaths=**/coverage/lcov.info \ No newline at end of file diff --git a/webapp/src/context/SessionContext.test.js b/webapp/src/context/SessionContext.test.js new file mode 100644 index 0000000000..ce3bbbe4c9 --- /dev/null +++ b/webapp/src/context/SessionContext.test.js @@ -0,0 +1,151 @@ +import React from 'react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import { SessionContext, SessionProvider } from './SessionContext'; +import { v4 as uuidv4 } from 'uuid'; +import { BrowserRouter } from 'react-router-dom'; + +// Mock de uuid +jest.mock('uuid', () => ({ + v4: jest.fn() +})); + +// Configuración de las flags futuras de React Router +const routerConfig = { + future: { + v7_startTransition: true, + v7_relativeSplatPath: true + } +}; + +describe('SessionContext', () => { + beforeEach(() => { + localStorage.clear(); + jest.clearAllMocks(); + // Configuramos el mock para devolver 'mocked-uuid' + uuidv4.mockReturnValue('mocked-uuid'); + }); + + const TestComponent = () => { + const { sessionId, username, isLoggedIn, avatar, createSession, destroySession, updateAvatar } = React.useContext(SessionContext); + + return ( +
+
{sessionId}
+
{username}
+
{isLoggedIn.toString()}
+
{avatar}
+ + + +
+ ); + }; + + const renderWithContext = () => { + return render( + + + + + + ); + }; + + it('should initialize with default values when no session exists', () => { + renderWithContext(); + + expect(screen.getByTestId('session-id')).toHaveTextContent(''); + expect(screen.getByTestId('username')).toHaveTextContent(''); + expect(screen.getByTestId('is-logged-in')).toHaveTextContent('false'); + expect(screen.getByTestId('avatar')).toHaveTextContent('/default_user.jpg'); + }); + + it('should create a new session and store it in localStorage', async () => { + const { rerender } = renderWithContext(); + + fireEvent.click(screen.getByText('Crear Sesión')); + + // Verificamos que se haya llamado a uuidv4 + expect(uuidv4).toHaveBeenCalled(); + + // Esperamos a que se actualice el estado + await waitFor(() => { + expect(localStorage.getItem('sessionId')).toBe('mocked-uuid'); + }); + + // Rerenderizamos para asegurar que el estado se ha actualizado + rerender( + + + + + + ); + + // Verificamos que el sessionId se haya actualizado en el componente + expect(screen.getByTestId('session-id')).toHaveTextContent('mocked-uuid'); + expect(screen.getByTestId('username')).toHaveTextContent('testuser'); + expect(screen.getByTestId('is-logged-in')).toHaveTextContent('true'); + expect(screen.getByTestId('avatar')).toHaveTextContent('/white.png'); + }); + + it('should destroy session and clear localStorage when logout', async () => { + localStorage.setItem('sessionId', 'test-session'); + localStorage.setItem('username', 'testuser'); + localStorage.setItem('avatar', '/test-avatar.jpg'); + + const { rerender } = renderWithContext(); + + fireEvent.click(screen.getByText('Destruir Sesión')); + + await waitFor(() => { + expect(localStorage.getItem('sessionId')).toBeNull(); + }); + + rerender( + + + + + + ); + + expect(screen.getByTestId('session-id')).toHaveTextContent(''); + expect(screen.getByTestId('username')).toHaveTextContent(''); + expect(screen.getByTestId('is-logged-in')).toHaveTextContent('false'); + expect(screen.getByTestId('avatar')).toHaveTextContent('/white.png'); + }); + + it('should update avatar and store it in localStorage', async () => { + const { rerender } = renderWithContext(); + + fireEvent.click(screen.getByText('Actualizar Avatar')); + + await waitFor(() => { + expect(localStorage.getItem('avatar')).toBe('/new-avatar.jpg'); + }); + + rerender( + + + + + + ); + + expect(screen.getByTestId('avatar')).toHaveTextContent('/new-avatar.jpg'); + }); + + it('should restore session from localStorage on mount', async () => { + localStorage.setItem('sessionId', 'test-session'); + localStorage.setItem('username', 'testuser'); + localStorage.setItem('avatar', '/test-avatar.jpg'); + + renderWithContext(); + + expect(screen.getByTestId('session-id')).toHaveTextContent('test-session'); + expect(screen.getByTestId('username')).toHaveTextContent('testuser'); + expect(screen.getByTestId('is-logged-in')).toHaveTextContent('true'); + expect(screen.getByTestId('avatar')).toHaveTextContent('/test-avatar.jpg'); + }); +}); \ No newline at end of file diff --git a/webapp/src/game/HourglassTimer.test.js b/webapp/src/game/HourglassTimer.test.js new file mode 100644 index 0000000000..936159cddc --- /dev/null +++ b/webapp/src/game/HourglassTimer.test.js @@ -0,0 +1,57 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import CircularTimer from './HourglassTimer'; + +describe('HourglassTimer', () => { + it('should render correctly with time and progress', async () => { + const timeLeft = 30; + const totalTime = 40; + render(); + + const timerText = screen.getByText(`${timeLeft}s`); + await expect(timerText).toBeInTheDocument(); + }); + + it('should show warning color when time is low', async () => { + const timeLeft = 7; + const totalTime = 40; + render(); + + const progressCircle = screen.getByRole('progressbar'); + await expect(progressCircle).toHaveStyle({ + color: 'gold' + }); + }); + + it('should show normal color when time is sufficient', async () => { + const timeLeft = 30; + const totalTime = 40; + render(); + + const progressCircle = screen.getByRole('progressbar'); + await expect(progressCircle).toHaveStyle({ + color: 'green' + }); + }); + + it('should show danger color when time is critical', async () => { + const timeLeft = 3; + const totalTime = 40; + render(); + + const progressCircle = screen.getByRole('progressbar'); + await expect(progressCircle).toHaveStyle({ + color: 'red' + }); + }); + + it('should calculate progress correctly', async () => { + const timeLeft = 20; + const totalTime = 40; + render(); + + const progressCircle = screen.getByRole('progressbar'); + const expectedProgress = ((timeLeft / totalTime - 2)) * 100; + await expect(progressCircle).toHaveAttribute('aria-valuenow', expectedProgress.toString()); + }); +}); \ No newline at end of file diff --git a/webapp/src/game/game.js b/webapp/src/game/game.js index d70f51c2e2..debbdce818 100644 --- a/webapp/src/game/game.js +++ b/webapp/src/game/game.js @@ -18,7 +18,6 @@ class Game { async fetchQuestions(callback) { console.log("Fetching questions..."); - //const tipoPreguntas = ["Geografia", "Cultura", "Pintores", "Futbolistas", "Cantantes"]; const urls = Array.from({ length: 10 }, () => { const thematic = this.tipoPreguntas[Math.floor(Math.random() * this.tipoPreguntas.length)]; @@ -63,6 +62,10 @@ class Game { callback([...questionsArray]); // Usamos [...questionsArray] para evitar mutaciones externas } } + + // Actualizamos this.questions y devolvemos el array completo + this.questions = questionsArray.filter(q => q !== null); + return this.questions; } catch (error) { console.error("Error fetching questions:", error); return null; diff --git a/webapp/src/game/game.test.js b/webapp/src/game/game.test.js index 23ddc11550..561dbafb5b 100644 --- a/webapp/src/game/game.test.js +++ b/webapp/src/game/game.test.js @@ -1,22 +1,32 @@ import axios from 'axios'; import Game from './game'; -import { wait, waitFor, screen, render } from '@testing-library/react'; -import { experimentalStyled } from '@mui/material'; -import { BrowserRouter, MemoryRouter } from 'react-router-dom'; -import { SessionContext } from '../context/SessionContext'; jest.mock('axios'); describe('Game class', () => { let game; + const mockQuestions = [ + { + responseQuestion: '¿Cuál es la capital de España?', + responseOptions: ['Madrid', 'Barcelona', 'Sevilla', 'Valencia'], + responseCorrectOption: 'Madrid', + responseImage: 'madrid.jpg' + }, + { + responseQuestion: '¿Cuál es el río más largo del mundo?', + responseOptions: ['Amazonas', 'Nilo', 'Yangtsé', 'Misisipi'], + responseCorrectOption: 'Amazonas', + responseImage: 'amazonas.jpg' + } + ]; beforeEach(() => { - game = new Game(['Geografia', 'Cultura']); + game = new Game(['Geografia', 'Cultura']); jest.clearAllMocks(); }); afterEach(() => { - jest.resetAllMocks(); + jest.useRealTimers(); }); it('should initialize with empty questions and score 0', () => { @@ -24,41 +34,40 @@ describe('Game class', () => { expect(game.score).toBe(0); }); - // it('show timeout message', async () => { - - // render( - // - // - // - // - // - // ); - - - - // jest.advanceTimersByTime(30000); - - - // await waitFor(() => { - // console.log(document.body.innerHTML); // Inspecciona el contenido del DOM - // const timeoutMessage = screen.getByTestId('timeout-message'); - // expect(timeoutMessage).toBeInTheDocument(); - // }); - - // }); - - it('pass to the next question if timeout', async () => { - jest.advanceTimersByTime(31000); - - expect(game.questions).toEqual([]); - expect(game.score).toBe(0); + it('pass to the next question if timeout', () => { + jest.useFakeTimers(); + jest.advanceTimersByTime(31000); + expect(game.questions).toEqual([]); + expect(game.score).toBe(0); + }); + + it('should fetch questions successfully', async () => { + // Mock para todas las llamadas a axios.get + axios.get.mockImplementation(() => Promise.resolve({ + data: { + responseQuestion: '¿Cuál es la capital de España?', + responseOptions: ['Madrid', 'Barcelona', 'Sevilla', 'Valencia'], + responseCorrectOption: 'Madrid', + responseImage: 'madrid.jpg' + } + })); + + const mockCallback = jest.fn(); + const result = await game.fetchQuestions(mockCallback); + + expect(axios.get).toHaveBeenCalled(); + expect(mockCallback).toHaveBeenCalled(); + expect(result).not.toBeNull(); + expect(result.length).toBeGreaterThan(0); + expect(game.questions.length).toBeGreaterThan(0); }); it('should handle error when fetching questions', async () => { - axios.get.mockRejectedValueOnce(new Error('Network Error')); + axios.get.mockRejectedValueOnce(new Error('Network Error')); const mockCallback = jest.fn(); - + const result = await game.fetchQuestions(mockCallback); + expect(result).toBeNull(); expect(mockCallback).not.toHaveBeenCalled(); }); @@ -70,9 +79,9 @@ describe('Game class', () => { pregunta: '¿Cuál es la capital de España?', opciones: ['Madrid', 'Barcelona', 'Sevilla', 'Valencia'], respuesta_correcta: 0, - imagen: 'imagen1.jpg', - tipo: 'Geografia', - }, + imagen: 'madrid.jpg', + tipo: 'Geografia' + } ]; // Respuesta correcta @@ -88,4 +97,33 @@ describe('Game class', () => { game.score = 50; expect(game.getTotalScore()).toBe(50); }); + + it('should cancel requests correctly', () => { + const originalController = game.controller; + game.cancelRequests(); + + expect(game.controller).not.toBe(originalController); + expect(game.controller.signal).toBeDefined(); + }); + + it('should handle multiple questions correctly', async () => { + // Mock para todas las llamadas a axios.get + axios.get.mockImplementation(() => Promise.resolve({ + data: { + responseQuestion: '¿Cuál es la capital de España?', + responseOptions: ['Madrid', 'Barcelona', 'Sevilla', 'Valencia'], + responseCorrectOption: 'Madrid', + responseImage: 'madrid.jpg' + } + })); + + const mockCallback = jest.fn(); + const result = await game.fetchQuestions(mockCallback); + + expect(axios.get).toHaveBeenCalled(); + expect(mockCallback).toHaveBeenCalled(); + expect(result).not.toBeNull(); + expect(result.length).toBeGreaterThan(0); + expect(game.questions.length).toBeGreaterThan(0); + }); }); \ No newline at end of file diff --git a/webapp/src/game/gameManager.js b/webapp/src/game/gameManager.js index a08531062a..2252619a62 100644 --- a/webapp/src/game/gameManager.js +++ b/webapp/src/game/gameManager.js @@ -24,7 +24,7 @@ const Jugar = () => { const [timeLeft, setTimeLeft] = useState(40); const [gameFinished, setGameFinished] = useState(false); const [questions, setQuestions] = useState([]); - const [setLoading] = useState(true); + const [loading, setLoading] = useState(true); const [snackbarOpen, setSnackbarOpen] = useState(false); const [snackbarMessage, setSnackbarMessage] = useState(''); const [hint, setHint] = useState({}); @@ -323,7 +323,7 @@ const Jugar = () => { gameInstance.cancelRequests(); } }; - }, [navigate, selectedCategories,setLoading]); + }, [navigate, selectedCategories]); // Fix: Timer management useEffect(() => { diff --git a/webapp/src/game/gameManager.test.js b/webapp/src/game/gameManager.test.js new file mode 100644 index 0000000000..676fdcba4d --- /dev/null +++ b/webapp/src/game/gameManager.test.js @@ -0,0 +1,152 @@ +import React from 'react'; +import { render, screen, fireEvent, waitFor, act } from '@testing-library/react'; +import { BrowserRouter } from 'react-router-dom'; +import { SessionContext } from '../context/SessionContext'; +import GameManager from './gameManager'; +import axios from 'axios'; + +jest.mock('axios'); + +// Configuración de las flags futuras de React Router +const routerConfig = { + future: { + v7_startTransition: true, + v7_relativeSplatPath: true + } +}; + +describe('GameManager', () => { + const mockQuestions = [ + { + id: 'q1', + pregunta: '¿Cuál es la capital de España?', + opciones: ['Madrid', 'Barcelona', 'Sevilla', 'Valencia'], + respuesta_correcta: 0, + imagen: 'madrid.jpg', + tipo: 'Geografia' + } + ]; + + const mockSession = { + username: 'testuser', + isLoggedIn: true, + createSession: jest.fn(), + destroySession: jest.fn() + }; + + const renderGameManager = () => { + return render( + + + + + + ); + }; + + beforeEach(() => { + jest.clearAllMocks(); + localStorage.clear(); + localStorage.setItem('username', 'testuser'); + + axios.get.mockResolvedValue({ + data: { + responseQuestion: mockQuestions[0].pregunta, + responseOptions: mockQuestions[0].opciones, + responseCorrectOption: mockQuestions[0].opciones[0], + responseImage: mockQuestions[0].imagen + } + }); + + axios.post.mockResolvedValue({ + data: { + answer: 'Esta es una pista sobre la respuesta correcta' + } + }); + }); + + it('should render loading state initially', async () => { + renderGameManager(); + expect(screen.getByText('Cargando preguntas...')).toBeInTheDocument(); + }); + + it('should fetch and display questions', async () => { + renderGameManager(); + + await waitFor(() => { + expect(screen.queryByText('Cargando preguntas...')).not.toBeInTheDocument(); + }, { timeout: 5000 }); + + await waitFor(() => { + mockQuestions[0].opciones.forEach(option => { + expect(screen.getByText(option)).toBeInTheDocument(); + }); + }); + }); + + it('should handle answer selection correctly', async () => { + renderGameManager(); + + await waitFor(() => { + expect(screen.queryByText('Cargando preguntas...')).not.toBeInTheDocument(); + }, { timeout: 5000 }); + + const correctAnswer = screen.getByText(mockQuestions[0].opciones[0]); + fireEvent.click(correctAnswer); + + await waitFor(() => { + expect(screen.getByText('+10')).toBeInTheDocument(); + }); + }); + + // it('should handle timeout correctly', async () => { + // jest.useFakeTimers(); + // renderGameManager(); + + // await waitFor(() => { + // expect(screen.queryByText('Cargando preguntas...')).not.toBeInTheDocument(); + // }, { timeout: 5000 }); + + // act(() => { + // jest.advanceTimersByTime(31000); + // }); + + // await waitFor(() => { + // const timeoutMessage = screen.getByTestId('timeout-message'); + // expect(timeoutMessage).toBeInTheDocument(); + // }); + + // jest.useRealTimers(); + // }); + + // it('should handle game completion', async () => { + // renderGameManager(); + + // await waitFor(() => { + // expect(screen.queryByText('Cargando preguntas...')).not.toBeInTheDocument(); + // }, { timeout: 5000 }); + + // const correctAnswer = screen.getByText(mockQuestions[0].opciones[0]); + // fireEvent.click(correctAnswer); + + // await waitFor(() => { + // expect(screen.getByText('¡Juego terminado!')).toBeInTheDocument(); + // }); + // }); + + // it('should handle chat functionality', async () => { + // renderGameManager(); + + // await waitFor(() => { + // expect(screen.queryByText('Cargando preguntas...')).not.toBeInTheDocument(); + // }, { timeout: 5000 }); + + // const chatInput = screen.getByPlaceholderText('Escribe un mensaje...'); + // fireEvent.change(chatInput, { target: { value: '¿Puedes darme una pista?' } }); + // fireEvent.keyPress(chatInput, { key: 'Enter', code: 'Enter' }); + + // await waitFor(() => { + // expect(screen.getByText('Pista:')).toBeInTheDocument(); + // }); + // }); +}); \ No newline at end of file From 86e56af525548ceacef4727d4247b06a0d29d13b Mon Sep 17 00:00:00 2001 From: Sero73 Date: Wed, 30 Apr 2025 20:49:28 +0200 Subject: [PATCH 2/7] =?UTF-8?q?peque=C3=B1os=20cambios=20en=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webapp/src/components/AvatarSelection.test.js | 14 +++++--- webapp/src/components/UserProfile.js | 10 +++--- webapp/src/components/UserProfile.test.js | 36 ++++++++++++------- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/webapp/src/components/AvatarSelection.test.js b/webapp/src/components/AvatarSelection.test.js index c3ce9ae547..28dc1ff11a 100644 --- a/webapp/src/components/AvatarSelection.test.js +++ b/webapp/src/components/AvatarSelection.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import { render, screen, fireEvent, waitFor, act } from '@testing-library/react'; import { BrowserRouter } from 'react-router-dom'; import AvatarSelection from './AvatarSelection'; import { SessionContext } from '../context/SessionContext'; @@ -76,7 +76,11 @@ describe('AvatarSelection component', () => { it('should handle avatar selection', async () => { renderWithContext(); - await selectAvatar(); + + await act(async () => { + await selectAvatar(); + }); + const confirmButton = screen.getByTestId('confirm-button'); expect(confirmButton).not.toBeDisabled(); }); @@ -85,8 +89,10 @@ describe('AvatarSelection component', () => { const mockUpdateAvatar = jest.fn(); renderWithContext({ updateAvatar: mockUpdateAvatar }); - await selectAvatar(); - await confirmSelection(); + await act(async () => { + await selectAvatar(); + await confirmSelection(); + }); expect(mockUpdateAvatar).toHaveBeenCalledWith('/icono_cactus.png'); }); diff --git a/webapp/src/components/UserProfile.js b/webapp/src/components/UserProfile.js index cf6bd01bf3..736c7df6d5 100644 --- a/webapp/src/components/UserProfile.js +++ b/webapp/src/components/UserProfile.js @@ -113,8 +113,8 @@ const UserProfile = () => { > Estadísticas Generales - - + + { - + { - + { - + ({ ...jest.requireActual('react-router-dom'), useNavigate: () => mockNavigate, @@ -16,20 +24,24 @@ jest.mock('react-router-dom', () => ({ // Tests separados por funcionalidad describe('UserProfile - Estado inicial', () => { + beforeEach(() => { + mockAxios.reset(); + }); + it('muestra mensaje de carga al inicio', () => { mockAxios.onGet().reply(200, {}); render( - + ); - expect(screen.getByText('Cargando perfil...')).toBeInTheDocument(); + expect(screen.getByText('Cargando...')).toBeInTheDocument(); }); it('redirige a inicio si no hay usuario autenticado', async () => { localStorage.removeItem('username'); render( - + ); @@ -53,7 +65,7 @@ describe('UserProfile - Estadísticas', () => { it('muestra total de partidas jugadas', async () => { render( - + ); @@ -66,7 +78,7 @@ describe('UserProfile - Estadísticas', () => { it('muestra puntos totales', async () => { render( - + ); @@ -79,7 +91,7 @@ describe('UserProfile - Estadísticas', () => { it('muestra tiempo promedio', async () => { render( - + ); @@ -95,7 +107,7 @@ describe('UserProfile - Estadísticas', () => { mockAxios.onGet(`${apiEndpoint}/stats/testuser`).reply(404, { error: 'User not found' }); render( - + ); @@ -139,7 +151,7 @@ describe('UserProfile - Estadísticas', () => { mockAxios.onGet(`${apiEndpoint}/history/testuser`).reply(200, []); render( - + ); @@ -154,7 +166,7 @@ describe('UserProfile - Estadísticas', () => { mockAxios.onGet(`${apiEndpoint}/history/testuser`).reply(200, [mockGame]); render( - + ); @@ -173,7 +185,7 @@ describe('UserProfile - Estadísticas', () => { }); render( - + ); @@ -203,7 +215,7 @@ describe('UserProfile - Estadísticas', () => { it('navega a /game al hacer clic en Jugar', async () => { render( - + ); @@ -218,7 +230,7 @@ describe('UserProfile - Estadísticas', () => { it('navega a /ranking al hacer clic en Rankings', async () => { render( - + ); From 3e7a25a80eaf7b0ff4ae140d90292080e100f152 Mon Sep 17 00:00:00 2001 From: Sero73 Date: Wed, 30 Apr 2025 20:55:42 +0200 Subject: [PATCH 3/7] cambios para hcaer que funcione prefix webapp --- webapp/src/App.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/webapp/src/App.test.js b/webapp/src/App.test.js index 153d888f93..6390f7fb07 100644 --- a/webapp/src/App.test.js +++ b/webapp/src/App.test.js @@ -1,4 +1,4 @@ -import { render, screen, waitFor } from '@testing-library/react'; +import { render, screen, waitFor, act } from '@testing-library/react'; import App from './App'; import { SessionContext } from './context/SessionContext'; import userEvent from '@testing-library/user-event'; @@ -53,7 +53,6 @@ test('renders login form by default', async () => { ); - // Click en el botón de inicio const startButton = screen.getByTestId('start-button'); From 0097e01ffe8df3f75101b14460b4e9c5af42f75c Mon Sep 17 00:00:00 2001 From: Sero73 Date: Thu, 1 May 2025 00:12:45 +0200 Subject: [PATCH 4/7] Ahora pasan todos los test unitarios, probando si sonarqube lee dentro de webapp los elementos restantes --- webapp/src/components/AvatarSelection.js | 38 ++- webapp/src/components/AvatarSelection.test.js | 311 +++++++++--------- webapp/src/components/UserProfile.test.js | 2 +- 3 files changed, 183 insertions(+), 168 deletions(-) diff --git a/webapp/src/components/AvatarSelection.js b/webapp/src/components/AvatarSelection.js index d11aaeec2a..a9dbec9d4f 100644 --- a/webapp/src/components/AvatarSelection.js +++ b/webapp/src/components/AvatarSelection.js @@ -23,18 +23,25 @@ const AvatarSelection = () => { await updateAvatar(selectedAvatar); setSnackbarMessage('Avatar cambiado con éxito'); setOpenSnackbar(true); + setError(''); } catch (err) { - setError(err.message || 'Error al actualizar el avatar'); + const errorMessage = err.message || 'Error al actualizar el avatar'; + setError(errorMessage); + setSnackbarMessage(`Error: ${errorMessage}`); + setOpenSnackbar(true); } } }; const handleCloseSnackbar = () => { setOpenSnackbar(false); + setError(''); }; - const handleCloseError = () => { - setError(''); + const handleReturnToProfile = () => { + if (username) { + navigate(`/profile/${username}`); + } }; return ( @@ -62,7 +69,7 @@ const AvatarSelection = () => { alignItems: 'center' }}> Profile pic {