Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intento de mejorar coverage en new code #52

Merged
merged 8 commits into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Binary file added docs/images/03_diagrama_contexto_negocio.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/03_diagrama_contexto_tecnico.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/08_diagrama_modelo_dominio(V2).png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/images/Diagrama de contexto de negocio.jpg
Binary file not shown.
1,969 changes: 1,953 additions & 16 deletions docs/package-lock.json

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
"description": "Npm project just for the docs",
"main": "index.js",
"scripts": {
"build": "shx rm -rf build && asciidoctor -D build -a imagesdir=./images -r asciidoctor-diagram index.adoc && shx cp -R images build",
"deploy": "gh-pages -d build"
"build": "shx rm -rf build && asciidoctor -D build -a imagesdir=./images -r asciidoctor-diagram index.adoc && shx cp -R images build",
"deploy": "gh-pages -d build"
},
"dependencies": {
"gh-pages": "^3.2.3",
"shx": "^0.3.3"
"asciidoctor": "^3.0.4",
"gh-pages": "^3.2.3",
"shx": "^0.3.3"
}
}

}
14 changes: 12 additions & 2 deletions docs/src/03_system_scope_and_context.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ifndef::imagesdir[:imagesdir: ../images]
== Alcance del sistema y Contexto 💭

=== Contexto de negocio 💰
image::Diagrama de contexto de negocio.jpg["Diagrama de contexto de negocio"]
image::03_diagrama_contexto_negocio.png["Diagrama de contexto de negocio"]
En esta tabla se muestra el contexto de negocio de la aplicación. Las entradas son los mensajes que van desde el agente externo hacia la aplicación, y las salidas son los mensajes que van desde la aplicación hacia al agente externo.
[options="header",cols="1,2,3"]
|===
Expand All @@ -15,4 +15,14 @@ En esta tabla se muestra el contexto de negocio de la aplicación. Las entradas

=== Contexto técnico 🔧

image::Diagrama de contexto técnico.jpg["Diagrama de contexto técnico"]
image::03_diagrama_contexto_tecnico.png["Diagrama de contexto técnico"]
|===

|Agente externo|Entradas|Salidas
|Usuario|Datos registro, datos login, respuesta a cada pregunta|Preguntas, histórico
|WIQ|Peticiones del usuario | respuesta a las peticiones
|WebApp| Entradas del usuario | Salidas de WIQ
|Wikidata| Peticiones de datos | Datos
|Base de datos|Nuevos usuarios, preguntas de Wikidata y respuestas del usuario| validacion de usuarios, nuevas preguntas de Wikidata e historico
|Máquina Virtual| peticion de Despliegue | Despliegue
|===
13 changes: 3 additions & 10 deletions docs/src/04_solution_strategy.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,9 @@ Decisiones de cómo llegar a las metas principales (En desarrollo):

=== Decisiones organizativas 👥

El equipo estara dividido en 2 grupos. Los equipos son de documentación y de desarrollo. Los miembros de los grupos podran ir cambiando de rol si el proyecto asi lo necesita. Esta es la distribucion inicial.
Este grupo ha sido formado a partir de un grupo ya existente pasando de 5 integrantes a 3. Se ha decidido utilizar el proyecto inicial cuando se dio esta situacion para empezar de 0.

[options="header",cols="1,2"]
|===
|Equipo|Miembros
|Equipo documentación| Yago Navajas Gonzalez -> [email protected]
|Equipo desarrollo del proyecto|Zohaib Akhtar Kausar -> [email protected] +
Santiago Lopez Laso -> [email protected]
|===
No existe una división clara entre las funcionalidades que desempeña cada usuario, todos hacen de todo.

La realización de las actas de las reuniones diarias se le ha asignado la tarea a Sara Lamuño García.
Se realizará una reunion a la semana en clase y una reunión fuera de la escuela, para organizar y llevar recuento del trabajo realizado.

La división se ha realizado considerando la experiencia y los conocimientos previos de los integrantes del grupo. De esta manera, el trabajo se puede distribuir de manera realista y los integrantes podrán aportar de manera equitativa al proyecto. Todos los miembros comprenderán cómo funcionan las diferentes partes del proyecto; sin embargo, no todos tendrán las habilidades necesarias para realizar todas las tareas. Por lo tanto, esta es la forma más equilibrada de organizar al equipo.
10 changes: 6 additions & 4 deletions docs/src/08_concepts.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ ifndef::imagesdir[:imagesdir: ../images]
Estos conceptos todavía no han sido aprobados ni implementados, pero dan una idea general del proyecto.

=== Modelo de Dominio 🗺️
Esta es una primera versión del modelo de dominio muy simple, para hacerse una idea como funcionará la aplicación.
Esta no sera la versión final del modelo de dominio. Es una representación de la aplicación en la actualidad.

image::Diagrama de clases juego de preguntas.jpg["Modelo de dominio simple provisional"]
image::08_diagrama_modelo_dominio(V2).png["Modelo de dominio simple provisional"]


=== Experiencia de Usuario 👨‍🦰
Expand All @@ -21,7 +21,7 @@ Nos esforzamos por crear una experiencia de usuario comoda y accesible, donde ca

=== Arquitectura y Patrones de Diseño 📒

En Desarrollo.
Se usará una aquitectura basada en microservicios, para mantener la independencia entre las distintas partes de la aplicación. Esto nos permite tener una arquitectura flexible y modular que puede brindar beneficios significativos en términos de escalabilidad, flexibilidad tecnológica, agilidad en el desarrollo, resistencia a fallos y mantenibilidad del software.

=== Desarrollo ⚙️

Expand All @@ -33,6 +33,8 @@ En el desarrollo de nuestra aplicación, nos centramos en varios aspectos para g

* Automatización de pruebas: Implementamos pruebas automatizadas para garantizar que nuestra aplicación funcione correctamente en diferentes situaciones y escenarios. Esto nos ayuda a identificar y corregir errores de manera oportuna, manteniendo la calidad del software.

* Integración continua: La implementación exitosa de CI/CD proporciona un camino continuo hacia la entrega de software de alta calidad, permitiendo la automatización de pruebas, integración y despliegue, agilizando así el ciclo de vida del desarrollo y garantizando una entrega rápida y confiable de valor al cliente,

* Optimización de rendimiento: Nos esforzamos por mejorar el rendimiento de nuestra aplicación, optimizando el tiempo de carga, la velocidad de respuesta y el consumo de recursos. Esto garantiza una experiencia fluida para los usuarios, incluso en dispositivos y conexiones de red menos potentes.

En resumen, en el desarrollo de nuestra aplicación nos esforzamos por crear una arquitectura escalable, un código mantenible, pruebas automatizadas y un rendimiento aceptable . Esto nos permite ofrecer una aplicación confiable y de alta calidad a nuestros usuarios.
Expand All @@ -51,7 +53,7 @@ En resumen, en las operaciones de nuestra aplicación nos enfocamos en garantiza

=== Seguridad 🔒

La seguridad en nuestra aplicación es una de las prioridades. Nos comprometemos a proteger la información personal y sensible de nuestros usuarios, así como a prevenir cualquier amenaza o vulnerabilidad que pueda comprometer su seguridad mientras utilizan nuestra aplicación web dentro de nuetras capacidades y conocimientos.
Nos comprometemos a proteger la información personal y sensible de nuestros usuarios, así como a prevenir vulnerabilidades que pueda comprometer su seguridad mientras utilizan nuestra aplicación web dentro de nuetras capacidades y conocimientos.

Para ello, implementamos medidas de seguridad, como la encriptación de datos y la autenticación de usuarios mediante contraseñass.

Expand Down
1 change: 1 addition & 0 deletions docs/src/09_architecture_decisions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ Los enlaces proporcionan las decisiones de arquitectura via Wiki de GitHub.
* https://github.com/Arquisoft/wiq_es04d/wiki/ADR-3-%E2%80%90-Backend[ADR 3] - Backend
* https://github.com/Arquisoft/wiq_es04d/wiki/ADR-4-%E2%80%90-Base-de-datos[ADR 4] - Base de datos
* https://github.com/Arquisoft/wiq_es04d/wiki/ADR-5-%E2%80%90-Modo-de-generar-preguntas[ADR 5] - Modo de generar las preguntas
* https://github.com/Arquisoft/wiq_es04d/wiki/ADR-6-‐-Uso-de-ramas-en-Git[ADR 6] - Uso de ramas en Git
33 changes: 33 additions & 0 deletions users/authservice/auth-service.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,42 @@ afterAll(async () => {
});

describe('Auth Service', () => {
// Existing test
it('Should perform a login operation /login', async () => {
const response = await request(app).post('/login').send(user);
expect(response.status).toBe(200);
expect(response.body).toHaveProperty('username', 'testuser');
});

// New tests
it('Should reject login with incorrect credentials', async () => {
const response = await request(app).post('/login').send({ username: 'testuser', password: 'wrongpassword' });
expect(response.status).toBe(401);
expect(response.body).toHaveProperty('error', 'Invalid credentials');
});

it('Should require username and password fields for login', async () => {
const response = await request(app).post('/login').send({ username: 'testuser' }); // Missing password
expect(response.status).toBe(500);
expect(response.body).toHaveProperty('error');
});

it('Should validate a JWT token', async () => {
// First, login to get a valid token
const loginResponse = await request(app).post('/login').send(user);
expect(loginResponse.status).toBe(200);
const { token } = loginResponse.body;

// Now, validate the token
const validationResponse = await request(app).get(`/validate/${token}`);
expect(validationResponse.status).toBe(200);
expect(validationResponse.body).toHaveProperty('valid', true);
});

it('Should reject an invalid JWT token', async () => {
const validationResponse = await request(app).get('/validate/wrongtoken');
expect(validationResponse.status).toBe(200);
expect(validationResponse.body).toHaveProperty('valid', false);
});
});

34 changes: 33 additions & 1 deletion users/userservice/user-service.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ afterAll(async () => {
await mongoServer.stop();
});

describe('User Service', () => {
describe('User Service Validation', () => {
it('should add a new user on POST /adduser', async () => {
const newUser = {
username: 'testuser',
Expand All @@ -27,4 +27,36 @@ describe('User Service', () => {
expect(response.status).toBe(200);
expect(response.body).toHaveProperty('username', 'testuser');
});

it('should reject a user without a username', async () => {
const newUser = {
password: 'testpassword',
};

const response = await request(app).post('/adduser').send(newUser);
expect(response.status).toBe(400);
expect(response.body.error).toContain('Missing required field: username');
});

it('should reject a user without a password', async () => {
const newUser = {
username: 'testuser2',
};

const response = await request(app).post('/adduser').send(newUser);
expect(response.status).toBe(400);
expect(response.body.error).toContain('Missing required field: password');
});

it('should not allow adding a user with an existing username', async () => {
const newUser = {
username: 'testuser',
password: 'testpassword',
};
// Intentamos añadir el mismo usuario otra vez
const response = await request(app).post('/adduser').send(newUser);
expect(response.status).toBe(400);
expect(response.body.error).toBe('User already exists');
});

});
89 changes: 68 additions & 21 deletions webapp/src/components/pages/Jugar.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import {render, screen, waitFor} from '@testing-library/react';
import { act, render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import Jugar from './Jugar';
import { AuthContext } from '../../AuthContext';
Expand All @@ -8,42 +8,49 @@ import axios from 'axios';

// Mock de useNavigate
const mockedNavigate = jest.fn();
const questions = [
{
question: "¿Cuál es la capital de Alemania?",
answers: [
{ answer: "Berlín", correct: true },
{ answer: "Múnich", correct: false },
{ answer: "Hamburgo", correct: false },
{ answer: "Colonia", correct: false },
],
}
];

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: () => mockedNavigate,
}));

// Mock de axios
jest.mock('axios');

describe('Jugar Component Tests', () => {
beforeEach(() => {
// Configura axios.get para devolver las preguntas mockeadas
axios.get.mockResolvedValue({ data: questions });

// Asegúrate de mockear axios.post para evitar errores al llamar a .then sobre su retorno
axios.post.mockResolvedValue({ data: { message: "Historial guardado con éxito" } });
});

test('redirects to login if not logged in', () => {
render(
<BrowserRouter>
<AuthContext.Provider value={{ isLoggedIn: false }}>
<Jugar />
</AuthContext.Provider>
</BrowserRouter>
<BrowserRouter>
<AuthContext.Provider value={{ isLoggedIn: false }}>
<Jugar />
</AuthContext.Provider>
</BrowserRouter>
);

// Verifica que se haya llamado a navigate con '/login'
expect(mockedNavigate).toHaveBeenCalledWith('/login');
});
test('check the questions', async () => {
const questions = [
{
question: "¿Cuál es la capital de Alemania?",
answers: [
{ answer: "Berlín", correct: true },
{ answer: "Múnich", correct: false },
{ answer: "Hamburgo", correct: false },
{ answer: "Colonia", correct: false },
],
}
];


axios.get.mockResolvedValue({ data: questions });

test('check the questions', async () => {
render(
<BrowserRouter>
<AuthContext.Provider value={{ isLoggedIn: true }}>
Expand All @@ -59,6 +66,46 @@ describe('Jugar Component Tests', () => {
expect(screen.getByText(/Múnich/i)).toBeInTheDocument();
expect(screen.getByText(/Hamburgo/i)).toBeInTheDocument();
expect(screen.getByText(/Colonia/i)).toBeInTheDocument();
expect(screen.getByText(/Pregunta 1 de 1/i)).toBeInTheDocument();
});
const timerBar = document.querySelector('.timer-bar');
expect(timerBar).toBeInTheDocument();
expect(timerBar).toHaveStyle('width: 100%');
});

test('selects correct answer, clicks next', async () => {
render(
<BrowserRouter>
<AuthContext.Provider value={{ isLoggedIn: true }}>
<Jugar />
</AuthContext.Provider>
</BrowserRouter>
);

await waitFor(() => {
// Asegúrate de que las preguntas se cargaron correctamente
expect(screen.getByText(/¿Cuál es la capital de Alemania?/i)).toBeInTheDocument();
});

// Encuentra y selecciona la respuesta correcta
const correctAnswer = screen.getByText('Berlín');
await act(async () => {
correctAnswer.click();
});

// Encuentra y haz clic en el botón de siguiente
const nextButton = screen.getByText('Siguiente');
await act(async () => {
nextButton.click();
});

// Como es la última pregunta, el quiz debe finalizar y mostrar el contenedor de resultados
await waitFor(() => {
// Verifica que se muestre el contenedor de resultados
expect(screen.getByText('Quiz Finalizado')).toBeInTheDocument();
// Verifica los aciertos y errores
expect(screen.getByText('Aciertos: 1')).toBeInTheDocument();
expect(screen.getByText('Errores: 0')).toBeInTheDocument();
});
});
});