From e221a5b6347f0a3ac615379417c6a0466ddf9328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jos=C3=A9=20Gonz=C3=A1lez=20Sierra?= Date: Thu, 4 Apr 2024 10:33:15 +0200 Subject: [PATCH 1/8] boton finalizar y mejoras visuales juego --- sonar-project.properties | 2 +- webapp/src/components/Pages/Juego.js | 47 +++++++++++++++++++--------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/sonar-project.properties b/sonar-project.properties index 90d5c49..acbc46c 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -12,7 +12,7 @@ sonar.projectName=wiq_es05a sonar.coverage.exclusions=**/*.test.js sonar.coverage.exclusions=* -sonar.sources=webapp/src/components,userservice/authservice,userservice/userservice,gatewayservice, questionservice +sonar.sources=webapp/src/components,userservice/authservice,userservice/userservice,gatewayservice,questionservice sonar.sourceEncoding=UTF-8 sonar.exclusions=node_modules/** sonar.javascript.lcov.reportPaths=**/coverage/lcov.info diff --git a/webapp/src/components/Pages/Juego.js b/webapp/src/components/Pages/Juego.js index 6f35e59..188882c 100644 --- a/webapp/src/components/Pages/Juego.js +++ b/webapp/src/components/Pages/Juego.js @@ -29,6 +29,8 @@ const Juego = ({isLogged, username, numPreguntas}) => { const [arPreg, setArPreg] = useState([]) + const [finishGame, setFinishGame] = useState(false) + //Variables para la obtencion y modificacion de estadisticas del usuario const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; @@ -205,15 +207,16 @@ const Juego = ({isLogged, username, numPreguntas}) => { console.log("termina descolorear") } - //Función que finaliza la partida (redirigir/mostrar stats...) - function finishGame(){ - updateCompletedGames(); - //TODO - } + //Primer render para un comportamiento diferente + useEffect(() => { + updateCompletedGames() + }, [finishGame]) //Funcion que se llama al hacer click en el boton Siguiente const clickSiguiente = () => { if(numPreguntaActual==numPreguntas){ + setFinishGame(true) + setReady(false) finishGame() return } @@ -226,23 +229,37 @@ const Juego = ({isLogged, username, numPreguntas}) => { setPausarTemporizador(false); } + //Funcion que se llama al hacer click en el boton Siguiente + const clickFinalizar = () => { + //almacenar aqui partida jugada a estadisticas + //y lo que se quiera + } + const handleRestart = () => { setRestartTemporizador(false); // Cambia el estado de restart a false, se llama aqui desde Temporizador.js }; + return ( -

{numPreguntaActual} / {numPreguntas}

- -

{pregunta}

-
- - - - -
- {ready ? : <>} + {ready ? <> +

{numPreguntaActual} / {numPreguntas}

+ +

{pregunta}

+
+ + + + + +
+ + :

CARGANDO...

} + {finishGame ? <> +

PARTIDA FINALIZADA

+ + : <>}
); }; From d7060ac7c5f4c4c26e4f5a6adc262ca893210374 Mon Sep 17 00:00:00 2001 From: UO276026 Date: Thu, 4 Apr 2024 11:00:07 +0200 Subject: [PATCH 2/8] Que actualice la bbdd AL TERMINAR la partida --- gatewayservice/gateway-service.js | 10 ++++++---- userservice/userservice/user-service.js | 22 ++++++++++++--------- webapp/src/components/Pages/Juego.js | 26 ++++++++++++++++--------- 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 4cbbf76..8ad137f 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -54,9 +54,10 @@ app.get('/pregunta', async (req, res) => { app.get('/updateCorrectAnswers', async (req, res) => { console.log(req.query) - const { username } = req.query; + const params = {username: req.query.username, numAnswers: req.query.numAnswers}; + //const { username } = req.query; try{ - const updateStatsResponse = await axios.get(userServiceUrl+ `/updateCorrectAnswers?username=${username}`) + const updateStatsResponse = await axios.get(userServiceUrl+ `/updateCorrectAnswers?params=${params}`) res.json(updateStatsResponse.data); }catch(error){ res.status(error.response.status).json({error: error.response.data.error}); @@ -65,9 +66,10 @@ app.get('/updateCorrectAnswers', async (req, res) => { app.get('/updateIncorrectAnswers', async (req, res) => { console.log(req.query) - const { username } = req.query; + //const { username } = req.query; + const params = {username: req.query.username, numAnswers: req.query.numAnswers}; try{ - const updateStatsResponse = await axios.get(userServiceUrl+ `/updateIncorrectAnswers?username=${username}`) + const updateStatsResponse = await axios.get(userServiceUrl+ `/updateIncorrectAnswers?params=${params}`) res.json(updateStatsResponse.data); }catch(error){ res.status(error.response.status).json({error: error.response.data.error}); diff --git a/userservice/userservice/user-service.js b/userservice/userservice/user-service.js index 3172ff1..6df2365 100644 --- a/userservice/userservice/user-service.js +++ b/userservice/userservice/user-service.js @@ -47,37 +47,41 @@ app.post('/adduser', async (req, res) => { app.get('/updateCorrectAnswers', async (req,res) => { console.log(req.query) - const { username } = req.query; + //const { username } = req.query; + const { username } = req.query.username; + const { numAnswers } = req.query.numAnswers; try { const user = await User.findOne({ username }); if (!user) { return res.status(404).json({ success: false, message: 'Usuario no encontrado' }); } // Incrementa las respuestas correctas del usuario - user.correctAnswers += 1; + user.correctAnswers = numAnswers; await user.save(); - return res.status(200).json({ success: true, message: 'Respuesta correcta actualizada con éxito' }); + return res.status(200).json({ success: true, message: 'Respuestas correctas actualizada con éxito' }); } catch (error) { - console.error('Error al actualizar la respuesta correcta:', error); - return res.status(500).json({ success: false, message: 'Error al actualizar la respuesta correcta' }); + console.error('Error al actualizar las respuestas correctas:', error); + return res.status(500).json({ success: false, message: 'Error al actualizar las respuestas correctas' }); } }) app.get('/updateIncorrectAnswers', async (req,res) => { console.log(req.query) - const { username } = req.query; + //const { username } = req.query; + const { username } = req.query.username; + const { numAnswers } = req.query.numAnswers; try { const user = await User.findOne({ username }); if (!user) { return res.status(404).json({ success: false, message: 'Usuario no encontrado' }); } // Incrementa las respuestas incorrectas del usuario - user.incorrectAnswers += 1; + user.incorrectAnswers = numAnswers; await user.save(); - return res.status(200).json({ success: true, message: 'Respuesta incorrecta actualizada con éxito' }); + return res.status(200).json({ success: true, message: 'Respuestas incorrectas actualizada con éxito' }); } catch (error) { console.error('Error al actualizar la respuesta correcta:', error); - return res.status(500).json({ success: false, message: 'Error al actualizar la respuesta incorrecta' }); + return res.status(500).json({ success: false, message: 'Error al actualizar las respuestas incorrectas' }); } }) diff --git a/webapp/src/components/Pages/Juego.js b/webapp/src/components/Pages/Juego.js index 188882c..d662881 100644 --- a/webapp/src/components/Pages/Juego.js +++ b/webapp/src/components/Pages/Juego.js @@ -22,15 +22,14 @@ const Juego = ({isLogged, username, numPreguntas}) => { const [restartTemporizador, setRestartTemporizador] = useState(false) const [firstRender, setFirstRender] = useState(false); - const[ready, setReady] = useState(false) - const [numPreguntaActual, setNumPreguntaActual] = useState(0) - const [arPreg, setArPreg] = useState([]) - const [finishGame, setFinishGame] = useState(false) + const [numRespuestasCorrectas, setNumRespuestasCorrectas] = useState(0) + const [numRespuestasIncorrectas, setNumRespuestasIncorrectas] = useState(0) + //Variables para la obtencion y modificacion de estadisticas del usuario const apiEndpoint = process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000'; @@ -46,8 +45,10 @@ const Juego = ({isLogged, username, numPreguntas}) => { //Control de las estadísticas const updateCorrectAnswers = async () => { try { - const response = await axios.get(`${apiEndpoint}/updateCorrectAnswers?username=${username}`); - console.log('Respuesta correcta actualizada con éxito:', response.data); + //const response = await axios.get(`${apiEndpoint}/updateCorrectAnswers?username=${username}`); + const params = {username: {username}, numAnswers: {numRespuestasCorrectas}}; + const response2 = await axios.get(`${apiEndpoint}/updateCorrectAnswers?params=${params}`); + console.log('Respuestas correctas actualizada con éxito:', response.data); // Realizar otras acciones según sea necesario } catch (error) { console.error('Error al actualizar la respuesta correcta:', error); @@ -57,7 +58,9 @@ const Juego = ({isLogged, username, numPreguntas}) => { const updateIncorrectAnswers = async () => { try { - const response = await axios.get(`${apiEndpoint}/updateIncorrectAnswers?username=${username}`); + //const response = await axios.get(`${apiEndpoint}/updateIncorrectAnswers?username=${username}`); + const params = {username: {username}, numAnswers: {numRespuestasIncorrectas}}; + const response2 = await axios.get(`${apiEndpoint}/updateIncorrectAnswers?params=${params}`); console.log('Respuesta incorrecta actualizada con éxito:', response.data); } catch (error) { console.error('Error al actualizar la respuesta incorrecta:', error); @@ -126,11 +129,13 @@ const Juego = ({isLogged, username, numPreguntas}) => { if(respuesta == resCorr){ console.log("entro a respuesta correcta") //Aumenta en 1 en las estadisticas de juegos ganado - updateCorrectAnswers(); + setNumRespuestasCorrectas(numRespuestasCorrectas++); + //updateCorrectAnswers(); setVictoria(true) } else{ - updateIncorrectAnswers(); + setNumRespuestasIncorrectas(numRespuestasIncorrectas++); + //updateIncorrectAnswers(); setVictoria(false) } //storeResult(victoria) @@ -231,6 +236,9 @@ const Juego = ({isLogged, username, numPreguntas}) => { //Funcion que se llama al hacer click en el boton Siguiente const clickFinalizar = () => { + //updateCompletedGames(); + updateCorrectAnswers(); + updateIncorrectAnswers(); //almacenar aqui partida jugada a estadisticas //y lo que se quiera } From f4d2bfd33d64d8287920d4044a3334fc302c236f Mon Sep 17 00:00:00 2001 From: UO276026 Date: Thu, 4 Apr 2024 11:00:28 +0200 Subject: [PATCH 3/8] ups --- webapp/src/components/Pages/Juego.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/Pages/Juego.js b/webapp/src/components/Pages/Juego.js index d662881..367a24f 100644 --- a/webapp/src/components/Pages/Juego.js +++ b/webapp/src/components/Pages/Juego.js @@ -47,7 +47,7 @@ const Juego = ({isLogged, username, numPreguntas}) => { try { //const response = await axios.get(`${apiEndpoint}/updateCorrectAnswers?username=${username}`); const params = {username: {username}, numAnswers: {numRespuestasCorrectas}}; - const response2 = await axios.get(`${apiEndpoint}/updateCorrectAnswers?params=${params}`); + const response = await axios.get(`${apiEndpoint}/updateCorrectAnswers?params=${params}`); console.log('Respuestas correctas actualizada con éxito:', response.data); // Realizar otras acciones según sea necesario } catch (error) { @@ -60,7 +60,7 @@ const Juego = ({isLogged, username, numPreguntas}) => { try { //const response = await axios.get(`${apiEndpoint}/updateIncorrectAnswers?username=${username}`); const params = {username: {username}, numAnswers: {numRespuestasIncorrectas}}; - const response2 = await axios.get(`${apiEndpoint}/updateIncorrectAnswers?params=${params}`); + const response = await axios.get(`${apiEndpoint}/updateIncorrectAnswers?params=${params}`); console.log('Respuesta incorrecta actualizada con éxito:', response.data); } catch (error) { console.error('Error al actualizar la respuesta incorrecta:', error); From 3a588705b31382fd441daf9a5763081d571a239f Mon Sep 17 00:00:00 2001 From: Fernando Jose Gonzalez Sierra Date: Mon, 8 Apr 2024 12:57:55 +0200 Subject: [PATCH 4/8] Test Login arreglados --- webapp/package-lock.json | 4 +- webapp/package.json | 2 +- webapp/src/components/Login.test.js | 75 +++++++++++++++++++++++++---- 3 files changed, 70 insertions(+), 11 deletions(-) diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 4410b88..8cb5c32 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -13,7 +13,6 @@ "@mui/material": "^5.15.3", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^14.1.2", - "@testing-library/user-event": "^14.5.2", "axios": "^1.6.5", "bootstrap": "^5.3.3", "browserify-zlib": "^0.2.0", @@ -33,6 +32,7 @@ "web-vitals": "^3.5.1" }, "devDependencies": { + "@testing-library/user-event": "^14.5.2", "axios-mock-adapter": "^1.22.0", "expect-puppeteer": "^9.0.2", "jest": "^29.3.1", @@ -6204,6 +6204,7 @@ "version": "14.5.2", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "dev": true, "engines": { "node": ">=12", "npm": ">=6" @@ -33230,6 +33231,7 @@ "version": "14.5.2", "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "dev": true, "requires": {} }, "@tootallnate/once": { diff --git a/webapp/package.json b/webapp/package.json index b90277d..d6d10f3 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -8,7 +8,6 @@ "@mui/material": "^5.15.3", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^14.1.2", - "@testing-library/user-event": "^14.5.2", "axios": "^1.6.5", "bootstrap": "^5.3.3", "browserify-zlib": "^0.2.0", @@ -54,6 +53,7 @@ ] }, "devDependencies": { + "@testing-library/user-event": "^14.5.2", "axios-mock-adapter": "^1.22.0", "expect-puppeteer": "^9.0.2", "jest": "^29.3.1", diff --git a/webapp/src/components/Login.test.js b/webapp/src/components/Login.test.js index af102dc..904c887 100644 --- a/webapp/src/components/Login.test.js +++ b/webapp/src/components/Login.test.js @@ -3,21 +3,64 @@ import { render, fireEvent, screen, waitFor, act } from '@testing-library/react' import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import Login from './Login'; +import userEvent from '@testing-library/user-event' const mockAxios = new MockAdapter(axios); describe('Login component', () => { beforeEach(() => { mockAxios.reset(); + + }); - it('should log in successfully', async () => { + it('should render correctly', async () => { + render(); + + expect(screen.getByLabelText(/Username/i)).toBeInTheDocument(); + expect(screen.getByLabelText(/Password/i)).toBeInTheDocument(); + expect(screen.getByRole('button', { name: /Login/i })).toBeInTheDocument(); + }) + + /*it('should log in successfully', async () => { render(); const usernameInput = screen.getByLabelText(/Username/i); const passwordInput = screen.getByLabelText(/Password/i); const loginButton = screen.getByRole('button', { name: /Login/i }); + userEvent.type(usernameInput, 'testUser') + userEvent.type(passwordInput, 'testPassword') + + // Trigger the login button click + fireEvent.click(loginButton); + + // Mock the axios.post request to simulate a successful response + mockAxios.onPost('http://localhost:8000/login').reply(200, { createdAt: '2024-01-01T12:34:56Z', + username: 'testUser', + error: { + response: { + data:{ + error: 'Unauthorized' }}}}); + + + + + + // Verify that the user information is displayed + await waitFor(() => { + expect(screen.getByText(/Hello testUser!/i)).toBeInTheDocument(); + }); + //expect(screen.getByText(/Your account was created on 1\/1\/2024/i)).toBeInTheDocument(); + });*/ + + it('should log in successfully', async () => { + render(); + + const usernameInput = screen.getByLabelText(/Username/i); + const passwordInput = screen.getByLabelText(/Password/i); + const loginButton = screen.getByRole('button', { name: /Login/i }); + // Mock the axios.post request to simulate a successful response mockAxios.onPost('http://localhost:8000/login').reply(200, { createdAt: '2024-01-01T12:34:56Z' }); @@ -27,25 +70,39 @@ describe('Login component', () => { fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); fireEvent.click(loginButton); }); + + // Verify that the user information is displayed + expect(screen.getByText(/Login successful/i)).toBeInTheDocument(); + //expect(screen.getByText(/Your account was created on 1\/1\/2024/i)).toBeInTheDocument(); + }); + it('logged in successfully', async () => { + render(); + // Verify that the user information is displayed - expect(screen.getByText(/Hello testUser!/i)).toBeInTheDocument(); - expect(screen.getByText(/Your account was created on 1\/1\/2024/i)).toBeInTheDocument(); + expect(screen.getByText(/Hello testUser!/i)).toBeInTheDocument(); + expect(screen.getByText(/Your account was created on/i)).toBeInTheDocument(); }); it('should handle error when logging in', async () => { - render(); + render(); const usernameInput = screen.getByLabelText(/Username/i); const passwordInput = screen.getByLabelText(/Password/i); const loginButton = screen.getByRole('button', { name: /Login/i }); // Mock the axios.post request to simulate an error response + /*mockAxios.onPost('http://localhost:8000/login').reply(401, { error: { + response: { + data:{ + error: 'Unauthorized' }}} + });*/ + mockAxios.onPost('http://localhost:8000/login').reply(401, { error: 'Unauthorized' }); - // Simulate user input - fireEvent.change(usernameInput, { target: { value: 'testUser' } }); - fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); + //Simulate + userEvent.type(usernameInput, 'testUser') + userEvent.type(passwordInput, 'testPassword') // Trigger the login button click fireEvent.click(loginButton); @@ -56,7 +113,7 @@ describe('Login component', () => { }); // Verify that the user information is not displayed - expect(screen.queryByText(/Hello testUser!/i)).toBeNull(); - expect(screen.queryByText(/Your account was created on/i)).toBeNull(); + //expect(screen.queryByText(/Hello testUser!/i)).toBeNull(); + //expect(screen.queryByText(/Your account was created on/i)).toBeNull(); }); }); From 85056de6c61f351b71b4ac94342af940678f2956 Mon Sep 17 00:00:00 2001 From: Fernando Jose Gonzalez Sierra Date: Mon, 8 Apr 2024 13:12:39 +0200 Subject: [PATCH 5/8] Update Temporizador.test.js --- webapp/src/components/Temporizador.test.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/webapp/src/components/Temporizador.test.js b/webapp/src/components/Temporizador.test.js index 1a22c36..3ad7fdd 100644 --- a/webapp/src/components/Temporizador.test.js +++ b/webapp/src/components/Temporizador.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { render, screen, fireEvent } from '@testing-library/react'; +import { render, screen, fireEvent, act } from '@testing-library/react'; import Temporizador from './Temporizador'; describe('Temporizador', () => { @@ -13,37 +13,41 @@ describe('Temporizador', () => { it('decreases countdown time when not paused', () => { jest.useFakeTimers(); const tiempoInicial = 60; - render(); - jest.advanceTimersByTime(1000); + render(); + act(() => { + jest.advanceTimersByTime(1000); + }); const updatedCountdownElement = screen.getByText(tiempoInicial - 1); expect(updatedCountdownElement).toBeInTheDocument(); - jest.useRealTimers(); }); it('stops countdown time when paused', () => { jest.useFakeTimers(); const tiempoInicial = 60; render(); - jest.advanceTimersByTime(1000); + act(() => { + jest.advanceTimersByTime(1000); + }); const updatedCountdownElement = screen.getByText(tiempoInicial); expect(updatedCountdownElement).toBeInTheDocument(); - jest.useRealTimers(); }); it('restarts countdown time when restart prop changes', () => { jest.useFakeTimers(); const tiempoInicial = 60; const { rerender } = render(); - jest.advanceTimersByTime(1000); + act(() => { + jest.advanceTimersByTime(1000); + }); const updatedCountdownElement = screen.getByText(tiempoInicial - 1); expect(updatedCountdownElement).toBeInTheDocument(); // Simulate restart by changing the restart prop - rerender(); + rerender(); // Countdown should restart const restartedCountdownElement = screen.getByText(tiempoInicial); expect(restartedCountdownElement).toBeInTheDocument(); - jest.useRealTimers(); }); }); \ No newline at end of file From 273dc0bc05a575a650fbdfecce1decbc3cbd8369 Mon Sep 17 00:00:00 2001 From: Fernando Jose Gonzalez Sierra Date: Mon, 8 Apr 2024 14:01:54 +0200 Subject: [PATCH 6/8] Eliminados test de App, App es actualmente un router simplemente. --- webapp/src/App.test.js | 68 ----------------------------- webapp/src/components/Login.test.js | 46 +------------------ 2 files changed, 1 insertion(+), 113 deletions(-) delete mode 100644 webapp/src/App.test.js diff --git a/webapp/src/App.test.js b/webapp/src/App.test.js deleted file mode 100644 index 0c8f791..0000000 --- a/webapp/src/App.test.js +++ /dev/null @@ -1,68 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import App from './App'; - -/*test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/Welcome to the 2024 edition of the Software Architecture course/i); - expect(linkElement).toBeInTheDocument(); -}); -*/ - -describe('App', () => { - - it('renders login page when not logged in', () => { - render( - - - - ); - - expect(screen.getByText(/Login/i)).toBeInTheDocument(); - }); - - it('renders home page when logged in', () => { - // Mock local storage to simulate being logged in - const mockLocalStorage = { - getItem: jest.fn(() => 'true'), - setItem: jest.fn(), - clear: jest.fn() - }; - global.localStorage = mockLocalStorage; - - render( - - - - ); - - expect(screen.getByText(/Home/i)).toBeInTheDocument(); - }); - - it('redirects to login when trying to access stats page without logging in', () => { - render( - - - - ); - - expect(screen.getByText(/Login/i)).toBeInTheDocument(); - }); - - it('renders stats page when logged in and trying to access stats page', () => { - // Mock local storage to simulate being logged in - const mockLocalStorage = { - getItem: jest.fn(() => 'true'), - setItem: jest.fn(), - clear: jest.fn() - }; - global.localStorage = mockLocalStorage; - - render( - - - - ); - - expect(screen.getByText(/Estadisticas/i)).toBeInTheDocument(); - }); -}); \ No newline at end of file diff --git a/webapp/src/components/Login.test.js b/webapp/src/components/Login.test.js index 904c887..fa6f20d 100644 --- a/webapp/src/components/Login.test.js +++ b/webapp/src/components/Login.test.js @@ -9,9 +9,7 @@ const mockAxios = new MockAdapter(axios); describe('Login component', () => { beforeEach(() => { - mockAxios.reset(); - - + mockAxios.reset(); }); it('should render correctly', async () => { @@ -22,38 +20,6 @@ describe('Login component', () => { expect(screen.getByRole('button', { name: /Login/i })).toBeInTheDocument(); }) - /*it('should log in successfully', async () => { - render(); - - const usernameInput = screen.getByLabelText(/Username/i); - const passwordInput = screen.getByLabelText(/Password/i); - const loginButton = screen.getByRole('button', { name: /Login/i }); - - userEvent.type(usernameInput, 'testUser') - userEvent.type(passwordInput, 'testPassword') - - // Trigger the login button click - fireEvent.click(loginButton); - - // Mock the axios.post request to simulate a successful response - mockAxios.onPost('http://localhost:8000/login').reply(200, { createdAt: '2024-01-01T12:34:56Z', - username: 'testUser', - error: { - response: { - data:{ - error: 'Unauthorized' }}}}); - - - - - - // Verify that the user information is displayed - await waitFor(() => { - expect(screen.getByText(/Hello testUser!/i)).toBeInTheDocument(); - }); - //expect(screen.getByText(/Your account was created on 1\/1\/2024/i)).toBeInTheDocument(); - });*/ - it('should log in successfully', async () => { render(); @@ -91,12 +57,6 @@ describe('Login component', () => { const passwordInput = screen.getByLabelText(/Password/i); const loginButton = screen.getByRole('button', { name: /Login/i }); - // Mock the axios.post request to simulate an error response - /*mockAxios.onPost('http://localhost:8000/login').reply(401, { error: { - response: { - data:{ - error: 'Unauthorized' }}} - });*/ mockAxios.onPost('http://localhost:8000/login').reply(401, { error: 'Unauthorized' }); @@ -111,9 +71,5 @@ describe('Login component', () => { await waitFor(() => { expect(screen.getByText(/Error: Unauthorized/i)).toBeInTheDocument(); }); - - // Verify that the user information is not displayed - //expect(screen.queryByText(/Hello testUser!/i)).toBeNull(); - //expect(screen.queryByText(/Your account was created on/i)).toBeNull(); }); }); From f98e481e6885e14e71287dc92b33595f15354aa4 Mon Sep 17 00:00:00 2001 From: Fernando Jose Gonzalez Sierra Date: Mon, 8 Apr 2024 15:41:03 +0200 Subject: [PATCH 7/8] Cambios OpenAPI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Creado archivo openapi.yaml con las especificaciones de nuestro gateway-service.js * Añadido un try y diferentes numeros de salida según la respuestas en questionservice/server.js * Actualizado el release.yml con lo nuevo de OpenAPI --- .github/workflows/release.yml | 4 + gatewayservice/gateway-service.js | 17 +- gatewayservice/openapi.yaml | 414 ++++++++++++++++++++++++ questionservice/server.js | 90 +++--- userservice/userservice/user-service.js | 29 +- 5 files changed, 495 insertions(+), 59 deletions(-) create mode 100644 gatewayservice/openapi.yaml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9c474c2..48d5656 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -105,6 +105,10 @@ jobs: needs: [e2e-tests] steps: - uses: actions/checkout@v4 + - name: Update OpenAPI configuration + run: | + DEPLOY_HOST=${{ secrets.DEPLOY_HOST }} + sed -i "s/SOMEIP/${DEPLOY_HOST}/g" gatewayservice/openapi.yaml - name: Publish to Registry uses: elgohr/Publish-Docker-Github-Action@v5 with: diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 8ad137f..7a8ba89 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -9,7 +9,6 @@ const port = 8000; const userServiceUrl = process.env.USER_SERVICE_URL || 'http://localhost:8001'; const authServiceUrl = process.env.AUTH_SERVICE_URL || 'http://localhost:8002'; const questionServiceUrl = process.env.QUESTION_SERVICE_URL || 'http://localhost:8003'; -const statServiceUrl = process.env.STAT_SERVICE_URL || 'http://localhost:8004'; app.use(cors()); app.use(express.json()); @@ -100,6 +99,22 @@ app.get('/getUserData', async (req, res) => { } }); +// Read the OpenAPI YAML file synchronously +openapiPath='./openapi.yaml' +if (fs.existsSync(openapiPath)) { + const file = fs.readFileSync(openapiPath, 'utf8'); + + // Parse the YAML content into a JavaScript object representing the Swagger document + const swaggerDocument = YAML.parse(file); + + // Serve the Swagger UI documentation at the '/api-doc' endpoint + // This middleware serves the Swagger UI files and sets up the Swagger UI page + // It takes the parsed Swagger document as input + app.use('/api-doc', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); +} else { + console.log("Not configuring OpenAPI. Configuration file not present.") +} + // Start the gateway service const server = app.listen(port, () => { console.log(`Gateway Service listening at http://localhost:${port}`); diff --git a/gatewayservice/openapi.yaml b/gatewayservice/openapi.yaml new file mode 100644 index 0000000..d75f6a1 --- /dev/null +++ b/gatewayservice/openapi.yaml @@ -0,0 +1,414 @@ +openapi: 3.0.0 +info: + title: Gatewayservice API + description: Gateway OpenAPI specification. + version: 0.1.0 +servers: + - url: http://localhost:8000 + description: Development server + - url: http://SOMEIP:8000 + description: Production server +paths: + /adduser: + post: + summary: Add a new user to the database. + operationId: addUser + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: User ID. + example: student + password: + type: string + description: User password. + example: pass + responses: + '200': + description: User added successfully. + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: User ID + password: + type: string + description: Hashed password + example: $2b$10$ZKdNYLWFQxzt5Rei/YTc/OsZNi12YiWz30JeUFHNdAt7MyfmkTuvC + _id: + type: string + description: Identification + example: 65f756db3fa22d227a4b7c7d + createdAt: + type: string + description: Creation date. + example: '2024-03-17T20:47:23.935Z' + ___v: + type: integer + example: '0' + '400': + description: Failed to add user. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: getaddrinfo EAI_AGAIN mongodb + /health: + get: + summary: Check the health status of the service. + operationId: checkHealth + responses: + '200': + description: Service is healthy. + content: + application/json: + schema: + type: object + properties: + status: + type: string + description: Health status. + example: OK + /login: + post: + summary: Log in to the system. + operationId: loginUser + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: User ID. + example: student + password: + type: string + description: User password. + example: pass + responses: + '200': + description: Login successful. Returns user token, username, and creation date. + content: + application/json: + schema: + type: object + properties: + token: + type: string + description: User token. + example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NWY3NTZkYjNmYTIyZDIyN2E0YjdjN2QiLCJpYXQiOjE3MTA3MDg3NDUsImV4cCI6MTcxMDcxMjM0NX0.VMG_5DOyQ4GYlJQRcu1I6ICG1IGzuo2Xuei093ONHxw + username: + type: string + description: Username. + example: student + createdAt: + type: string + description: Creation date. + example: '2024-03-17T20:47:23.935Z' + '401': + description: Invalid credentials. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Shows the error info.. + example: Invalid credentials + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error + /pregunta: + get: + summary: Generate a question. + operationId: pregunta + responses: + '200': + description: Returns the generated question with a right and three incorrect answers. + content: + application/json: + schema: + type: object + properties: + question: + type: string + description: Generated question. + example: ¿Cuál es la capital de España? + answerGood: + type: string + description: Respuesta correcta a la pregunta generada. + example: Madrid + answers: + type: array + description: Respuestas correcta e incorrectas. + items: + type: string + example: + - Madrid + - Abu Dabi + - Washinton D. C. + - Tokyo + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error + /updateCorrectAnswers: + get: + summary: Updates the data of the user, increasing his number of correct answers. + operationId: updateCorrectAnswers + parameters: + in: path + name: params + required: true + description: Parameters for the update (username and numAnswers) + schema: + type: object + properties: + username: + type: string + numAnswers: + type: integer + responses: + '200': + description: Updates the data correctly. + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + message: + type: string + example: Respuestas correctas actualizada con éxito + '404': + description: The user is not found. + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: false + message: + type: string + example: Usuario no encontrado + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: false + message: + type: string + description: Error information. + example: Error al actualizar las respuestas correctas + /updateIncorrectAnswers: + get: + summary: Updates the data of the user, increasing his number of incorrect answers. + operationId: updateIncorrectAnswers + parameters: + in: path + name: params + required: true + description: Parameters for the update (username and numAnswers) + schema: + type: object + properties: + username: + type: string + numAnswers: + type: integer + responses: + '200': + description: Updates the data correctly. + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + message: + type: string + example: Respuestas incorrectas actualizada con éxito + '404': + description: The user is not found. + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: false + message: + type: string + example: Usuario no encontrado + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: false + message: + type: string + description: Error information. + example: Error al actualizar las respuestas incorrectas + /updateCompletedGames: + get: + summary: Update the number of completed games by the user. + operationId: updateCompletedGames + parameters: + in: path + name: username + required: true + description: Username for the update of data + schema: + type: string + responses: + '200': + description: Finds the data of the user correctly. + content: + application/json: + schema: + type: user + properties: + success: + type: boolean + example: true + message: + type: string + example: Juegos completados actualizado con éxito + '404': + description: The user is not found. + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: false + message: + type: string + example: Usuario no encontrado + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: false + message: + type: string + description: Error information. + example: Error al actualizar Juegos completados + /getUserData: + get: + summary: Gets the data of an user. + operationId: getUserData + parameters: + in: path + name: username + required: true + description: Username for the search of data + schema: + type: string + responses: + '200': + description: Finds the data of the user correctly. + content: + application/json: + schema: + type: user + properties: + username: + type: string + example: Pablo + password: + type: integer + example: pass + createdAt: + type: date + correctAnswers: + type: integer + incorrectAnswers: + type: integer + completedGames: + type: integer + averageTime: + type: integer + '404': + description: The user is not found. + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: false + message: + type: string + example: Usuario no encontrado + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: false + message: + type: string + description: Error information. + example: Error al obtener los datos de usuario + diff --git a/questionservice/server.js b/questionservice/server.js index 0b38cac..16884dc 100644 --- a/questionservice/server.js +++ b/questionservice/server.js @@ -14,55 +14,59 @@ const questions = JSON.parse(fs.readFileSync('questions.json', 'utf8')); // Definimos una ruta GET en '/pregunta' app.get('/pregunta', async (req, res) => { - // Seleccionamos una consulta SPARQL de forma aleatoria del fichero de configuración - const questionItem = questions[Math.floor(Math.random() * questions.length)]; + try{ + // Seleccionamos una consulta SPARQL de forma aleatoria del fichero de configuración + const questionItem = questions[Math.floor(Math.random() * questions.length)]; - // URL del endpoint SPARQL de Wikidata - const url = "https://query.wikidata.org/sparql"; - // Consulta SPARQL seleccionada - const query = questionItem.query; + // URL del endpoint SPARQL de Wikidata + const url = "https://query.wikidata.org/sparql"; + // Consulta SPARQL seleccionada + const query = questionItem.query; - // Realizamos la solicitud HTTP GET al endpoint SPARQL con la consulta - const response = await axios.get(url, { params: { format: 'json', query } }); - // Extraemos los resultados de la consulta - const bindings = response.data.results.bindings; + // Realizamos la solicitud HTTP GET al endpoint SPARQL con la consulta + const response = await axios.get(url, { params: { format: 'json', query } }); + // Extraemos los resultados de la consulta + const bindings = response.data.results.bindings; - let wikidataCodePattern = /^Q\d+$/; - let correctAnswer = null; - let correctAnswerIndex = 0; + let wikidataCodePattern = /^Q\d+$/; + let correctAnswer = null; + let correctAnswerIndex = 0; - do { - // Seleccionamos un índice aleatorio para la respuesta correcta - correctAnswerIndex = Math.floor(Math.random() * bindings.length); - // Obtenemos la respuesta correcta - correctAnswer = bindings[correctAnswerIndex]; - } while (wikidataCodePattern.test(correctAnswer.questionSubjectLabel.value)); - - // Creamos la pregunta - console.log(questionItem.question); - const question = questionItem.question.replace('{sujetoPregunta}', correctAnswer.questionSubjectLabel.value); - - // Inicializamos las respuestas con la respuesta correcta - const answerGood = correctAnswer.answerSubjectLabel.value; - const answers = [answerGood]; - // Añadimos tres respuestas incorrectas - for (let i = 0; i < 3; i++) { - let randomIndex; do { - // Seleccionamos un índice aleatorio distinto al de la respuesta correcta - randomIndex = Math.floor(Math.random() * bindings.length); - } while (randomIndex === correctAnswerIndex); - // Añadimos la capital del país seleccionado aleatoriamente a las respuestas - answers.push(bindings[randomIndex].answerSubjectLabel.value); - } - // Mezclamos las respuestas - for (let i = answers.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - // Intercambiamos las respuestas en los índices i y j - [answers[i], answers[j]] = [answers[j], answers[i]]; + // Seleccionamos un índice aleatorio para la respuesta correcta + correctAnswerIndex = Math.floor(Math.random() * bindings.length); + // Obtenemos la respuesta correcta + correctAnswer = bindings[correctAnswerIndex]; + } while (wikidataCodePattern.test(correctAnswer.questionSubjectLabel.value)); + + // Creamos la pregunta + console.log(questionItem.question); + const question = questionItem.question.replace('{sujetoPregunta}', correctAnswer.questionSubjectLabel.value); + + // Inicializamos las respuestas con la respuesta correcta + const answerGood = correctAnswer.answerSubjectLabel.value; + const answers = [answerGood]; + // Añadimos tres respuestas incorrectas + for (let i = 0; i < 3; i++) { + let randomIndex; + do { + // Seleccionamos un índice aleatorio distinto al de la respuesta correcta + randomIndex = Math.floor(Math.random() * bindings.length); + } while (randomIndex === correctAnswerIndex); + // Añadimos la capital del país seleccionado aleatoriamente a las respuestas + answers.push(bindings[randomIndex].answerSubjectLabel.value); + } + // Mezclamos las respuestas + for (let i = answers.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + // Intercambiamos las respuestas en los índices i y j + [answers[i], answers[j]] = [answers[j], answers[i]]; + } + // Enviamos la pregunta y las respuestas como respuesta a la solicitud HTTP + res.status(200).json({ question: question, answerGood: answerGood, answers: answers }); + }catch(error){ + res.status(500).json({ error: 'Internal Server Error' }); } - // Enviamos la pregunta y las respuestas como respuesta a la solicitud HTTP - res.json({ question, answerGood, answers }); }); // Iniciamos el servidor en el puerto 8003 diff --git a/userservice/userservice/user-service.js b/userservice/userservice/user-service.js index 6df2365..99fb9a0 100644 --- a/userservice/userservice/user-service.js +++ b/userservice/userservice/user-service.js @@ -85,6 +85,20 @@ app.get('/updateIncorrectAnswers', async (req,res) => { } }) +app.get('/getUserData', async (req, res) => { + const { username } = req.query; + try { + const user = await User.findOne({ username }); + if (!user) { + return res.status(404).json({ success: false, message: 'Usuario no encontrado' }); + } + return res.status(200).json({ user }); + } catch (error) { + console.error('Error al obtener los datos de usuario:', error); + return res.status(500).json({ success: false, message: 'Error al obtener los datos de usuario' }); + } +}); + app.get('/updateCompletedGames', async (req,res) => { console.log(req.query) @@ -104,25 +118,10 @@ app.get('/updateCompletedGames', async (req,res) => { }) - const server = app.listen(port, () => { console.log(`User Service listening at http://localhost:${port}`); }); -app.get('/getUserData', async (req, res) => { - const { username } = req.query; - try { - const user = await User.findOne({ username }); - if (!user) { - return res.status(404).json({ success: false, message: 'Usuario no encontrado' }); - } - return res.status(200).json({ user }); - } catch (error) { - console.error('Error al obtener los datos de usuario:', error); - return res.status(500).json({ success: false, message: 'Error al obtener los datos de usuario' }); - } -}); - // Listen for the 'close' event on the Express.js server server.on('close', () => { // Close the Mongoose connection From 95eec4d0847d453e840a7099218e8cc4c9d66ad0 Mon Sep 17 00:00:00 2001 From: Fernando Jose Gonzalez Sierra Date: Mon, 8 Apr 2024 16:00:24 +0200 Subject: [PATCH 8/8] Arreglo de test de gateway, auth y user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Añadido las dependencias necesarias para swagger y openapi --- .github/workflows/build.yml | 4 +-- gatewayservice/gateway-service.js | 11 ++++--- gatewayservice/openapi.yaml | 4 +-- gatewayservice/package-lock.json | 34 +++++++++++++++++++- gatewayservice/package.json | 4 ++- userservice/authservice/auth-service.test.js | 2 +- 6 files changed, 47 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 410e842..29e5ad2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,8 +22,8 @@ jobs: - run: npm --prefix userservice/authservice test -- --coverage - run: npm --prefix userservice/userservice test -- --coverage - run: npm --prefix gatewayservice test -- --coverage - #- run: npm --prefix questionservice test -- --coverage - #- run: npm --prefix webapp test -- --coverage + - run: npm --prefix questionservice test -- --coverage + - run: npm --prefix webapp test -- --coverage - name: Analyze with SonarCloud uses: sonarsource/sonarcloud-github-action@master env: diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 7a8ba89..9e240ac 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -3,6 +3,11 @@ const axios = require('axios'); const cors = require('cors'); const promBundle = require('express-prom-bundle'); +//librerias para OpenAPI-Swagger +const swaggerUi = require('swagger-ui-express'); +const fs = require("fs"); +const YAML = require('yaml'); + const app = express(); const port = 8000; @@ -54,7 +59,6 @@ app.get('/pregunta', async (req, res) => { app.get('/updateCorrectAnswers', async (req, res) => { console.log(req.query) const params = {username: req.query.username, numAnswers: req.query.numAnswers}; - //const { username } = req.query; try{ const updateStatsResponse = await axios.get(userServiceUrl+ `/updateCorrectAnswers?params=${params}`) res.json(updateStatsResponse.data); @@ -64,8 +68,6 @@ app.get('/updateCorrectAnswers', async (req, res) => { }); app.get('/updateIncorrectAnswers', async (req, res) => { - console.log(req.query) - //const { username } = req.query; const params = {username: req.query.username, numAnswers: req.query.numAnswers}; try{ const updateStatsResponse = await axios.get(userServiceUrl+ `/updateIncorrectAnswers?params=${params}`) @@ -76,7 +78,6 @@ app.get('/updateIncorrectAnswers', async (req, res) => { }); app.get('/updateCompletedGames', async (req, res) => { - console.log(req.query) const { username } = req.query; try{ const updateStatsResponse = await axios.get(userServiceUrl+ `/updateCompletedGames?username=${username}`) @@ -100,7 +101,7 @@ app.get('/getUserData', async (req, res) => { }); // Read the OpenAPI YAML file synchronously -openapiPath='./openapi.yaml' +let openapiPath='./openapi.yaml'; if (fs.existsSync(openapiPath)) { const file = fs.readFileSync(openapiPath, 'utf8'); diff --git a/gatewayservice/openapi.yaml b/gatewayservice/openapi.yaml index d75f6a1..31a02ff 100644 --- a/gatewayservice/openapi.yaml +++ b/gatewayservice/openapi.yaml @@ -297,7 +297,7 @@ paths: type: string description: Error information. example: Error al actualizar las respuestas incorrectas - /updateCompletedGames: + /updateCompletedGames: get: summary: Update the number of completed games by the user. operationId: updateCompletedGames @@ -349,7 +349,7 @@ paths: type: string description: Error information. example: Error al actualizar Juegos completados - /getUserData: + /getUserData: get: summary: Gets the data of an user. operationId: getUserData diff --git a/gatewayservice/package-lock.json b/gatewayservice/package-lock.json index fc5f2d6..f89984c 100644 --- a/gatewayservice/package-lock.json +++ b/gatewayservice/package-lock.json @@ -12,7 +12,9 @@ "axios": "^1.6.5", "cors": "^2.8.5", "express": "^4.18.2", - "express-prom-bundle": "^7.0.0" + "express-prom-bundle": "^7.0.0", + "swagger-ui-express": "^5.0.0", + "yaml": "^2.4.1" }, "devDependencies": { "jest": "^29.7.0", @@ -4389,6 +4391,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swagger-ui-dist": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.14.0.tgz", + "integrity": "sha512-7qsKvc3gs5dnEIOclY4xkzacY85Pu9a/Gzkf+eezKLQ4BpErlI8BxYWADhnCx6PmFyU4fxH4AMKH+/d3Kml0Gg==" + }, + "node_modules/swagger-ui-express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", + "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, "node_modules/tdigest": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", @@ -4636,6 +4657,17 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/gatewayservice/package.json b/gatewayservice/package.json index bf85178..cf14d52 100644 --- a/gatewayservice/package.json +++ b/gatewayservice/package.json @@ -21,7 +21,9 @@ "axios": "^1.6.5", "cors": "^2.8.5", "express": "^4.18.2", - "express-prom-bundle": "^7.0.0" + "express-prom-bundle": "^7.0.0", + "swagger-ui-express": "^5.0.0", + "yaml": "^2.4.1" }, "devDependencies": { "jest": "^29.7.0", diff --git a/userservice/authservice/auth-service.test.js b/userservice/authservice/auth-service.test.js index afbedfa..7b55ee7 100644 --- a/userservice/authservice/auth-service.test.js +++ b/userservice/authservice/auth-service.test.js @@ -1,7 +1,7 @@ const request = require('supertest'); const { MongoMemoryServer } = require('mongodb-memory-server'); const bcrypt = require('bcrypt'); -const User = require('../../webapp/src/model/auth-model'); +const User = require('./auth-model'); let mongoServer; let app;