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/.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 4cbbf76..9e240ac 100644
--- a/gatewayservice/gateway-service.js
+++ b/gatewayservice/gateway-service.js
@@ -3,13 +3,17 @@ 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;
 
 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());
@@ -54,9 +58,9 @@ 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};
   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});
@@ -64,10 +68,9 @@ 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?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});
@@ -75,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}`)
@@ -98,6 +100,22 @@ app.get('/getUserData', async (req, res) => {
   }
 });
 
+// Read the OpenAPI YAML file synchronously
+let 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..31a02ff
--- /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/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/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/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/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;
diff --git a/userservice/userservice/user-service.js b/userservice/userservice/user-service.js
index 3172ff1..99fb9a0 100644
--- a/userservice/userservice/user-service.js
+++ b/userservice/userservice/user-service.js
@@ -47,40 +47,58 @@ 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' });
   }
 })
 
+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)
@@ -100,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
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/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(<App />);
-  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(
-      <MemoryRouter>
-        <App />
-      </MemoryRouter>
-    );
-
-    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(
-      <MemoryRouter>
-        <App />
-      </MemoryRouter>
-    );
-
-    expect(screen.getByText(/Home/i)).toBeInTheDocument();
-  });
-
-  it('redirects to login when trying to access stats page without logging in', () => {
-    render(
-      <MemoryRouter initialEntries={['/stats']}>
-        <App />
-      </MemoryRouter>
-    );
-
-    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(
-      <MemoryRouter initialEntries={['/stats']}>
-        <App />
-      </MemoryRouter>
-    );
-
-    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 af102dc..fa6f20d 100644
--- a/webapp/src/components/Login.test.js
+++ b/webapp/src/components/Login.test.js
@@ -3,16 +3,25 @@ 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();
+    mockAxios.reset();  
   });
 
+  it('should render correctly', async () => {
+    render(<Login isLogged={false} setIsLogged={jest.fn()} username={''} setUsername={jest.fn()}/>);
+
+    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(<Login />);
+    render(<Login isLogged={false} setIsLogged={jest.fn()} username={'testUser'} setUsername={jest.fn()}/>);
 
     const usernameInput = screen.getByLabelText(/Username/i);
     const passwordInput = screen.getByLabelText(/Password/i);
@@ -27,25 +36,33 @@ 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(<Login isLogged={true} setIsLogged={jest.fn()} username={'testUser'} setUsername={jest.fn()}/>);
+    
     // 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(<Login />);
+    render(<Login isLogged={false} setIsLogged={jest.fn()} username={'testUer'} setUsername={jest.fn()}/>);
 
     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: '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);
@@ -54,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();
   });
 });
diff --git a/webapp/src/components/Pages/Juego.js b/webapp/src/components/Pages/Juego.js
index 6f35e59..367a24f 100644
--- a/webapp/src/components/Pages/Juego.js
+++ b/webapp/src/components/Pages/Juego.js
@@ -22,12 +22,13 @@ 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';
@@ -44,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 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) {
         console.error('Error al actualizar la respuesta correcta:', error);
@@ -55,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 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);
@@ -124,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)
@@ -205,15 +212,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 +234,40 @@ const Juego = ({isLogged, username, numPreguntas}) => {
     setPausarTemporizador(false);
   }
 
+  //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
+  }
+
   const handleRestart = () => {
     setRestartTemporizador(false); // Cambia el estado de restart a false, se llama aqui desde Temporizador.js
   };
+  
 
   
   return (
       <Container component="main" maxWidth="xs" sx={{ marginTop: 4 }}>
-        <div className="numPregunta"> <p> {numPreguntaActual} / {numPreguntas} </p> </div>
-        <Temporizador restart={restartTemporizador} tiempoInicial={20} tiempoAcabado={cambiarColorBotones} pausa={pausarTemporizador} handleRestart={handleRestart}/>
-        <h2> {pregunta} </h2>
-        <div className="button-container">
-          <button id="boton1" className="button" onClick={() => botonRespuesta(resFalse[1])}> {resFalse[1]}</button>
-          <button id="boton2" className="button" onClick={() => botonRespuesta(resFalse[2])}> {resFalse[2]}</button>
-          <button id="boton3" className="button" onClick={() => botonRespuesta(resFalse[0])}> {resFalse[0]}</button>
-          <button id="boton4" className="button" onClick={() => botonRespuesta(resFalse[3])}> {resFalse[3]}</button>
-        </div>
-        {ready ? <button id="botonSiguiente" className="button" onClick={() =>clickSiguiente()} > SIGUIENTE</button> : <></>}
+        {ready ? <>
+          <div className="numPregunta"> <p> {numPreguntaActual} / {numPreguntas} </p> </div>
+          <Temporizador restart={restartTemporizador} tiempoInicial={20} tiempoAcabado={cambiarColorBotones} pausa={pausarTemporizador} handleRestart={handleRestart}/>
+          <h2> {pregunta} </h2>
+          <div className="button-container">
+            <button id="boton1" className="button" onClick={() => botonRespuesta(resFalse[1])}> {resFalse[1]}</button>
+            <button id="boton2" className="button" onClick={() => botonRespuesta(resFalse[2])}> {resFalse[2]}</button>
+            <button id="boton3" className="button" onClick={() => botonRespuesta(resFalse[0])}> {resFalse[0]}</button>
+            <button id="boton4" className="button" onClick={() => botonRespuesta(resFalse[3])}> {resFalse[3]}</button>
+            <button id="botonSiguiente" className="button" onClick={() =>clickSiguiente()} > SIGUIENTE</button>
+          </div>
+          </>
+        : <h2> CARGANDO... </h2>}
+        {finishGame ? <>
+          <h2> PARTIDA FINALIZADA </h2>
+          <button id="botonSiguiente" className="button" onClick={() =>clickFinalizar()} > FINALIZAR PARTIDA</button>
+          </> : <></>}
       </Container>
   );
 };
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(<Temporizador tiempoInicial={tiempoInicial} />);
-    jest.advanceTimersByTime(1000);
+    render(<Temporizador tiempoInicial={tiempoInicial} pausa={false} />);
+    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(<Temporizador tiempoInicial={tiempoInicial} pausa={true} />);
-    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(<Temporizador tiempoInicial={tiempoInicial} />);
-    jest.advanceTimersByTime(1000);
+    act(() => {
+      jest.advanceTimersByTime(1000);
+    });
     const updatedCountdownElement = screen.getByText(tiempoInicial - 1);
     expect(updatedCountdownElement).toBeInTheDocument();
 
     // Simulate restart by changing the restart prop
-    rerender(<Temporizador tiempoInicial={tiempoInicial} restart={true} />);
+    rerender(<Temporizador tiempoInicial={tiempoInicial} restart={true} 
+      handleRestart={jest.fn()} />);
 
     // Countdown should restart
     const restartedCountdownElement = screen.getByText(tiempoInicial);
     expect(restartedCountdownElement).toBeInTheDocument();
-    jest.useRealTimers();
   });
 });
\ No newline at end of file