scieee AI-readable full text Open interactive document viewer

Medusa: una aplicación web progresiva para la simulación de inversiones en criptodivisas

Roselló Martín, Jorge

Abstract

Medusa es una aplicación web progresiva que te permite simular la compra y la venta de criptodivisas. El proyecto tiene dos componentes: el servidor y el cliente. El servidor integra una API para poder acceder a los precios de las divisas en tiempo real. El lado del cliente de Medusa se ha diseñado para que sea fácil e intuitivo de usar, permitiendo el acceso a usuarios que sienten curiosidad por invertir en criptodivisas pero desconocen cómo hacerlo. Para acceder a Medusa no es necesario registrarse con un correo y una contraseña, solo se necesita una cuenta de Google. La aplicación web es accesible a través del enlace: https://medusapp.live El código tanto del cliente como del servidor se encuentran alojados en un repositorio de Github y pueden ser accedidos a través de los siguientes enlaces: https://github.com/beybo/medusa https://github.com/beybo/medusa-server

Full text

Medusa: una aplicación web progresiva para la simulación de inversiones en criptodivisas Medusa: a progressive web app for simulating cryptocurrency investments Trabajo de Fin de Grado Curso 2020–2021 Autor Jorge Roselló Martín Director Enrique Martín Martín Grado en Ingeniería de Software Facultad de Informática Universidad Complutense de Madrid Medusa: una aplicación web progresiva para la simulación de inversiones en criptodivisas Medusa: a progressive web app for simulating cryptocurrency investments Trabajo de Fin de Grado en Ingeniería de Software Departamento de Sistemas Informáticos y Computación Autor Jorge Roselló Martín Director Enrique Martín Martín Convocatoria: Junio 2021 Grado en Ingeniería de Software Facultad de Informática Universidad Complutense de Madrid Agradecimientos A mi tutor Enrique, que me ha ayudado con el proyecto y siempre ha estado ahí contestando mis dudas y dándome muy buenos consejos. A mis padres por siempre creer en mí y apoyarme en todo lo que me he propuesto. A Álvaro por ayudarme a corregir fallos de escritura a última hora. Y por último a ti, Valeria, gracias por escucharme y por motivarme a seguir adelante, sin ti Medusa no hubiera sido posible. v Resumen Medusa es una aplicación web progresiva que te permite simular la compra y la venta de criptodivisas. El proyecto tiene dos componentes: el servidor y el cliente. El servidor integra una API para poder acceder a los precios de las divisas en tiempo real. El lado del cliente de Medusa se ha diseñado para que sea fácil e intuitivo de usar, permitiendo el acceso a usuarios que sienten curiosidad por invertir en criptodivisas pero desconocen cómo hacerlo. Para acceder a Medusa no es necesario registrarse con un correo y una contraseña, solo se necesita una cuenta de Google. La aplicación web es accesible a través del enlace: https://medusapp.live El código tanto del cliente como del servidor se encuentran alojados en un repositorio de Github y pueden ser accedidos a través de los siguientes enlaces: https://github.com/beybo/medusa https://github.com/beybo/medusa-server Palabras clave Vue.js, criptodivisa, PWA, aplicación web progresiva, SPA, aplicación página única, Node.js, JavaScript, simulador, WebSocket vii Abstract Medusa is a progressive web application that allows you to simulate the purchase and sale of cryptocurrencies. The project has two components: the server and the client. The server integrates and API to access cryptocurrency prices in real time. The client has been designed to be easy and intuitive to use, allowing access to users interested in investing but do not know how to do it. To use Medusa, not necessary to register using a user and a password, you only need a Google account. The web application is accessible through the link: https://medusapp.live The code of the client and the server is hosted on a Github repo and can be accessed through the following links: https://github.com/beybo/medusa https://github.com/beybo/medusa-server Keywords Vue.js, criptodivisa, PWA, progressive web application, SPA, single page application, Node.js, JavaScript, simulator, WebSocket ix Índice de código 5.1. Estado del almacén de Medusa. . . . . . . . . . . . . . . . . . . . . . . . . . 23 6.1. Definición del esquema de Usuario . . . . . . . . . . . . . . . . . . . . . . . 31 6.2. Definición del atributo “cartera” perteneciente al esquema de Usuario . . . . 31 6.3. Definición de un transacción perteneciente al atributo “transacciones” de unacartera..................................... 32 6.4. Definición del esquema de Eliminado. . . . . . . . . . . . . . . . . . . . . . . 32 7.1. Manifest.json generado por Workbox . . . . . . . . . . . . . . . . . . . . . . 36 xvii Cap´ ıtulo 1 Introducción En este capítulo se va a explicar la motivación para desarrollar Medusa, los objetivos y el plan de trabajo que se ha seguido. 1.1. Motivación Las criptodivisas son un tema de conversación cada vez más recurrente, a pesar de que muchas personas no las entienden o no saben cómo funcionan, están interesadas en invertir algo de dinero. Siempre que ocurre una subida o una bajada del precio todo el mundo habla de ello. El problema de las criptodivisas es que son un mercado muy volátil, lo que puede provocar que las inversiones realizadas caigan en picado o se tripliquen. Por ello, es importante educar y permitir que las personas puedan simular la inversión en el mercado de las criptodivisas sin ningún tipo riesgo, de esta idea nace Medusa. 1.2. Objetivos El objetivo principal de este proyecto es desarrollar un simulador web de inversión en criptodivisas usando tecnologías y bibliotecas modernas. Las metas concretas de Medusa son: Construir una aplicación web progresiva con un diseño moderno y atractivo que sea fácil de usar para que cualquier usuario independientemente de su nivel técnico pueda utilizarla. Diseñar la web para que sea una aplicación de página única, así la experiencia de usuario de la web va a ser comparable a la de una aplicación nativa, ya que no hay cargas entre páginas. Realizar una comunicación en tiempo real con el servidor, que permita actualizar elementos como los precios de las criptodivisas sin interacción por parte del usuario. Registrar y autenticar usuarios mediante su cuenta de Google para no tener que implementar un sistema de registro propio, y con esto alentar a los usuarios a usar la aplicación ya que no es necesario registrarse usando un usuario y una contraseña. 1 2Capítulo 1. Introducción Marzo Abril Mayo Junio Análisis de requisitos Implementación Despliegue Memoria 11/03 19/03 26/04 15/05 Figura 1.1: Planificación del trabajo de fin de grado 1.3. Plan de trabajo Medusa empezó su desarrollo en el mes de marzo, esto se debe a que estaba en otro trabajo de fin de grado al comienzo del curso, pero en el mes de marzo decidí salirme del proyecto ya que estaba más orientado a la investigación, y me costaba compaginarlo con las clases y mi actual trabajo. Así que decidí empezar un trabajo de fin de grado por mi cuenta orientado al desarrollo de una aplicación. Es por esto que las tareas se han tenido que condensar para poder cumplir con las fechas establecidas. En la figura 1.1 se puede apreciar la planificación que se ha seguido en el proyecto de Medusa, las tareas del diagrama son: Análisis de requisitos (11 de marzo de 2021 a 18 de marzo de 2021): elección de las tecnologías clave para el desarrollo de Medusa. En esta fase del proyecto se decidió el uso de tecnologías como Vue.js [1] para el lado del cliente. Se decidió usar Vue.js en vez de frameworks similares como Angular [2] o React [3] por que Vue.js tiene una curva de aprendizaje más sencilla y por el sistema de componentes que utiliza. Implementación (19 de marzo de 2021 a 15 de mayo de 2021): desarrollo de la aplicación web progresiva y el servidor. En esta tarea se ha invertido el mayor tiempo del proyecto. La figura 1.2 contiene una linea temporal con los hitos más importantes de la implementación de Medusa. Despliegue (16 abril de 2021 a 24 abril de 2021): despliegue de Medusa para que pueda ser accedida de manera pública. Fue necesario la configuración de un dominio, además de la puesta en marcha del servidor y del cliente. Memoria (16 de mayo de 2021 a 15 de junio de 2021: elaboración de la memoria del proyecto donde se detalla el desarrollo. 1.4. Organización de la memoria En el capítulo 3 se presentan y se explican todas las tecnologías y conceptos que forman parte de Medusa. En el siguiente capítulo, el 4, se aclara la organización de los sistemas que componen Medusa y cómo interactúan entre ellos. En el capítulo 5 se explica con detalle las principales tareas realizadas para la implementación del cliente en Medusa. El capítulo 6 es muy similar al anterior solo que se detalla todo lo relacionado con el servidor de Medusa. En el capítulo 7 se detalla todo lo necesario para que una web pueda ser aplicación web progresiva y también se explica la implementación de Medusa como PWA. 1.4. Organización de la memoria 3 Abril Marzo (16 de marzo) Primeras pruebas con el interfaz y el servidor. (20 de marzo) Agregado Vuex y el inicio de sesión con Google. (23 de marzo) Rediseño total de la web para que tenga un aspecto más moderno. (28 de marzo) Reestructuración de muchos de los componentes de Vue.js. (11 de marzo) Inicio del desarrollo de Medusa. (2 de abril) Agregada la funcionalidad para comprar y vender divisas. (6 de abril) Cambio del diseño de los iconos y de los gráficos. Mayo (14 de abril) Primera versión de la vista de ranking. (17 de abril) Adaptación de la interfaz para móvil. (28 de abril) Nuevo gráfico de tarta en la vista de carteras. (30 de abril) Agregado datos para 1 día, 1 semana y 1 mes a los gráficos de barras. (1 de mayo) Agregada la biblioteca downsample para reducir el tamaño de los datos. (3 de mayo) Primeras pruebas para hacer que Medusa sea una PWA. (8 de mayo a 15 de mayo) Arreglo de fallos. Figura 1.2: Hitos de la implementación de Medusa En el capítulo 8 se especifica cómo ha sido el despliegue de Medusa y qué servicios se han utilizado. El capítulo 9 contiene un ejemplo paso a paso donde se muestra el uso de Medusa. Por último, el capítulo 10 contiene las conclusiones del desarrollo de Medusa y el trabajo futuro que se puede llegar a realizar. Chapter 2 Introduction This chapter will explain the motivation behind Medusa, the objectives and the workplan that has been followed. 2.1. Motivation Cryptocurrencies are an increasingly recurring topic of conversation nowadays, despite the fact that many people don’t understand them or don’t know how they work, they are interested in investing some money. Whenever the price rises or falls everyone is talking about it. The problem with cryptocurrencies is that the market is very volatile, which can cause investments made to plummet or triple in value. That’s why it’s very important to educate and allow people to simulate cryptocurrencies investments without any risk, Medusa was born from this idea. 2.2. Objectives The main objectives of this project is to develop a web simulator for criptocurrency investments using modern technologies an libraries. The main goals are: Build a progressive web application with a modern and attractive design while being easy to use, so any user regardless of their technical level can use it. The web application must be a single page app, so the user experience will be comparable to that of a native application, since there are no refresh between pages. The communication between the server and the client must be in real time, which allows updating elements such as cryptocurrencies prices without user interaction. The registration and login should be done using a Google account, so that there is no need to implement a custom authentication system. It also encourages users to use the application because they don’t need to register using a custom user and password. 5 6Chapter 2. Introduction March April May June Requirement Analysis Implementation Deployment Report 11/03 19/03 26/04 15/05 Figure 2.1: Medusa project planning 2.3. Workplan Medusa development started in the month of March, this is because I was in another project at the beginning of the course, but in March I decided to abandon the project as it was more research oriented and it was extremely challenging for me to combine it with work and classes. The figure 2.1 shows the planning that has been followed in the project, the tasks in the diagram are: Requirements analysis (March 11, 2021 to March 18, 2021): choice of the key technologies for the project. This is when technologies like Vue.js [1] where selected for the client-side. It was decided to use Vue.js instead of similar frameworks like Angular [2] or React [3], because Vue.js has an easier learning curve and because of the components system that it uses. Implementation (March 19, 2021 to May 15, 2021): development of the progressive web application and the server. This task has been the most expensive in terms of time invested. The figure 2.2 contains a timeline of the key milestones of the implementation of Medusa. Deployment (April 16, 2021 to April 24, 2021): deployment of Medusa so that it can be publicly accessed. A domain was required for this task, in addition to the configuration of the server and the client. Report (May 16, 2021 to June 15, 2021): creation of the project report where the development of the project is detailed. 2.4. Content In chapter 3 all the technologies and concepts that are part of Medusa are presented and explained. In the next chapter, chapter 4, clarifies the organization of the systems that make up Medusa and how they interact with each other. In chapter 5 the implementation of the client is explained in detail. Chapter 6 is very similar to the previous one but instead of the client, the server is explained. In chapter 7 all the requirements for a website to be a progressive web application are detailed and the implementation of Medusa as a progressive web app is also explained. Chapter 8 specifies how Medusa has been deployed and what services have been used for the deployment. Chapter 9 contains a step-by-step example showing the use of Medusa. Finally, chapter 11 contains the conclusion of the development of Medusa an the future work that may be done. 2.4. Content 7 April March (March 16) First user interface and server tests. (March 20) Added Vuex and Google account support. (March 23) Total redesign of the app with a more modern design. (March 28) Refactoring of the Vue.js componentes. (March 11) Start of development. (April 2) Added funcionality to buy and sell currencies. (April 6) Change the design of the icons and graphics. May (April 14) First version of the ranking page. (April 17) Phone adaptation of the app. (April 28) New piechart on the wallets page. (April 30) Added new ranges to the price charts (1 day, 1 week, 1 month). (May 1) Added de downsample library to reduce the size of the price data. (May 3) First tests to make Medusa a PWA. (May 8 to May 15) Bug fixing. Figure 2.2: Milestones of the implementation of Medusa 14 Capítulo 3. Preliminares eyJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEiLCJub21icmUiOiJQZXBlIn0. zrXAwXWa5XLdGjOm1TC0yraMyFI7yWPdriHk0b8Zcc eyJ0e... { "typ":"JWT", "alg":"HS256" } Cabecera eyJpZ... {  "id":1,  "nombre":"Pepe" } Carga útil zrXAw... HMACSHA256( BASE64(Cabecera)+"."+ BASE64(Carga Útil) ,"secreto") Firma Figura 3.2: JWT y decodificación de los tres elementos que lo componen Todas las cuentas de Google tienen un identificador único. Cuando se inicia sesión usando la API de Google el identificador es accesible. En el caso de Medusa el ID de Google es utilizado para poder contrastar con la base de datos el usuario, en el caso de que no exista se inicia el proceso de registro de un usuario nuevo. 3.5.3. Intercambio de recursos de origen cruzado El intercambio de recursos de origen cruzado (CORS) [22] es un mecanismo del navegador que habilita a una página web el acceso controlado a recursos que están ubicados fuera del dominio actual. La configuración de CORS se manda desde el servidor al cliente en las cabeceras HTTP. Las peticiones que utilizan CORS son: Peticiones AJAX. Fuentes web. Texturas WebGL. Imágenes dibujadas en una etiqueta canvas usando el método drawImage. Hojas de estilo (para acceso CSSOM). 3.5. Seguridad y autenticación 15 Scripts (para excepciones inmutadas). En todas las peticiones del listado anterior, el navegador por defecto bloquea el acceso a los recursos en el caso de que estén en un origen distinto, por origen distinto se entiende: un esquema diferente (HTTP o HTTPS), un dominio diferente (incluye los subdominios) y un puerto diferente. Para ponerlo en contexto con un ejemplo, si un script de la web ejemplo.com quiere acceder a una fuente alojada en prueba.ejemplo.com, es necesario que prueba.ejemplo.com tenga configurada las cabeceras CORS correctamente para permitir el acceso a ejemplo.com. Cap´ ıtulo 4 Organización del sistema Los componentes principales de Medusa son el cliente y el servidor, que se comunican entre ellos usando dos protocolos: HTTP y WebSockets. La autenticación se realiza usando la API OAuth 2.0 de Google. La API que el proyecto usa para obtener los precios de las divisas en tiempo real, es la de Coingecko. Por último, la aplicación utiliza MongoDB para almecenar los datos relativos a los usuarios. En la figura 4.1 se puede observar el mapa de sistemas de Medusa. El cliente interactúa tanto con el propio servidor de Medusa, como con la API de Google para realizar el inicio de sesión. Por otro lado, el servidor de Medusa (todos los elementos dentro del rectángulo negro), interactúa con la base de datos, con la API de Coingecko y con la API de Google para verificar el inicio de sesión. A continuación, detallaremos la interacción entre componentes que se produce en las dos tareas que utilizan APIs externas: el proceso de autenticación y la obtención de precios de las distintas divisas. 4.1. Autenticación Como se ha mencionado anteriormente, toda la autenticación se hace utilizando la API de Google OAuth 2.0. Esta decisión se tomó al principio del desarrollo por dos razones principalmente: 1. Agilizar el desarrollo al no tener que hacer un sistema de inicio de sesión propio, donde tener que almacenar las contraseñas, enviar correos de confirmación, reseteos de contraseña, etc. 2. Incentivar su uso al no tener que registrarte con tu correo, lo que consigue que más usuarios se acaben registrando [23]. El proceso de autenticación de Medusa interactúa con dos sistemas, primero con Google para verificar que la cuenta es válida, y segundo con la propia base de datos de Medusa para verificar si el usuario existe. El proceso de inicio de sesión/registro se puede observar en la figura 4.2 y tiene los siguientes pasos: 1. El cliente inicia sesión usando su cuenta de Google. Google devuelve al cliente un token de acceso. 2. El token de acceso es mandado al servidor por el cliente. 17 18 Capítulo 4. Organización del sistema Cliente (Medusa) Servidor Servidor (Google) Autenticación que Genera un Token Verificación del Token Enviado por el Cliente HTTP : Para autenticarse Websocket : El resto de comunicaciones. BDD Servidor (API Coingecko) Servidor (Medusa) Figura 4.1: Mapa de sistemas de Medusa 3. El servidor verifica que el token de acceso es válido y comprueba si el ID de Google ya está registrado en Medusa. 4-a. En el caso de que el ID de Google exista, el servidor genera un JWT con el campo registrado como true, que manda al cliente. 4-b. Si no existe el ID de Google, el servidor manda al cliente un JWT con el campo registrado como false para que se proceda con el registro. 4-b1. El cliente manda el JWT generado anteriormente junto con el nombre de usuario elegido. 4-b2 Si el nombre de cliente es válido, el servidor manda al cliente un JWT con el campo registrado atrue para que realice el inicio de sesión. 5. El cliente se conecta al servidor mediante un WebSocket usando el JWT generado por el servidor. 4.2. Precios de las divisas Un elemento crucial para el funcionamiento de Medusa es disponer del precio de las divisas en tiempo real. Como puedes comprar y vender divisas y tiene que reflejarse en tu cuenta, es importante que el servidor y el cliente tengan el precio de las divisas sincronizado en todo momento. El servidor lo necesita para verificar que se puede realizar una compra de la divisa, y el cliente para que el usuario pueda consultar los precios y decidir saber qué divisas comprar y vender. 4.2. Precios de las divisas 19 Cliente de Medusa API de Google Iniciar sesión con Google Servidor de Medusa Token de Acceso Obtener Token Inicio de Sesión (Token de Acceso) JWT (Campo registrado: true o false) Verificar Token de Acceso Token de Acceso Verificado Registro (JWT + Nombre Usuario) JWT (Campo registrado: true) Conexión al WebSocket (Usando JWT) El proceso de registro sólo ocurre si el campo registrado es false . El campo registrado es false si no hay una cuenta en la BDD con el ID de Google del token de acceso . Registro Figura 4.2: Diagrama del proceso para iniciar sesión y registro de Medusa Para que funcione todo este sistema era importante encontrar una API robusta y estable y que se adaptara a mis necesidades. Finalmente me decidí por la API de Coingecko [24]. Como tiene una biblioteca de JavaScript [25], la implementación en el servidor fue muy sencilla. Uno de los puntos positivos de usar la API de Coingecko es que no necesitas ningún tipo de clave para poder usar su servicio. La única limitación es que no puedes hacer más de 10 llamadas al segundo por dirección IP [26]. Coingecko además opera el 99,78 % del tiempo sin caídas [27]. La API es llamada cada 30 segundos para poder refrescar los precios, si detecta que hay precios nuevos, primero los almacena para los nuevos clientes que se conecten, y luego los manda a los clientes que están conectados en ese momento al servidor mediante los WebSockets. Cap´ ıtulo 5 Detalles del cliente En este capítulo se detalla todo lo relacionado con el cliente de Medusa. El objetivo al desarrollar la interfaz de Medusa era que fuera lo más intuitiva posible. La figura 5.1 es el mapa web de Medusa, donde las dos únicas páginas accesibles sin haber iniciado sesión son: Login yRegistro. En el caso de que un usuario inicie sesión por primera vez, debe completar el registro. 5.1. Creación de la interfaz usando Vue.js Uno de los principales objetivos al realizar Medusa fue el de crear una aplicación de página única (SPA). Para facilitar el desarrollo de una SPA se ha utilizado el framework de Vue.js. Adicionalmente, existen algunas bibliotecas oficiales que brindan funcionalidad extra a un proyecto de Vue.js. Las dos bibliotecas que se han integrado en Medusa son: Vue Router [28] y Vuex [29]. 5.1.1. Vue Router Como Medusa es una SPA, es importante implementar un sistema que te permita navegar entre los distintos componentes. Gracias a Vue Router puedes definir todas las rutas de la web y enlazarlas a los distintos componentes de Vue.js. En la tabla 5.1 se pueden apreciar las rutas principales de Medusa con el componente de Vue.js al que se han enlazado. Una de las ventajas de usar Vue Router es que en el momento en el que se navega a otro componente, la URL de la barra del navegador cambiará, permitiendo por ejemplo poder pulsar atrás en el navegador para volver al componente anterior. Esto permite que la experiencia de usuario sea la misma que al usar una página web tradicional. Vue Router te permite definir una ruta comodín para cuando la URL introducida no exista. En el caso de Medusa, esa ruta se enlaza con el componente de Error404.vue, el cual contiene una página de error 404 con el diseño de Medusa. Para que Vue Router funcione correctamente, es importante configurar el servidor del cliente para que todas las peticiones se redirijan al fichero index.html. 5.1.2. Vuex Como se ha explicado en la sección 3.3.4 de los preliminares, Vue.js es un framework progresivo que implementa un renderizado progresivo de los componentes. Para ello, cada componente de Vue.js tiene asociado un estado. El estado de un componente como 21 22 Capítulo 5. Detalles del cliente Página Inicial Registro Accesibles sin iniciar sesión Carteras Ránking Perfil Cartera Login Figura 5.1: Mapa de la web de Medusa Cartera.vue es una variable que contiene los datos de la cartera que se esté viendo. La complejidad aumenta cuando existen muchos componentes que comparten estado, en este caso, hay que desarrollar un sistema en cascada donde el componente padre tiene el estado y lo va compartiendo con los componentes hijos. En el caso de que uno de los subcomponentes realice una modificación del estado, se lo tiene que comunicar al componente padre a través de un evento para que pueda actualizar el estado y a su vez a los otros subcomponentes. Hacerlo de esta forma implica aumentar la complejidad del código, y para evitarlo los desarrolladores de Vue.js crearon Vuex. Vuex está diseñado usando el patrón de diseño de Flux [30]. Vuex es una biblioteca para administrar el estado de la aplicación permitiendo concentrar el estado que comparten los componentes en lo que se denomina un almacén. El almacén es accesible desde cualquier componente, además, es reactivo, lo que quiere decir que en el momento en el que un componente modifique el estado del almacén, el resto de componentes que usan ese estado van a ser notificados de manera automática recibiendo el valor actualizado. El almacén de Vuex está dividido en: state: contiene el estado del almacén. En el extracto de código 5.1 se puede observar la definición del estado para el almacén de Vuex en Medusa. Hay valores como el de conectado que permite a los componentes saber si el cliente está conectado al socket. mutations: las mutaciones son las funciones que modifican el estado del almacén. 5.1. Creación de la interfaz usando Vue.js 23 Ruta Componente / Login.vue /registro Registro.vue /inicio Inicio.vue /carteras Carteras.vue /cartera/:id Cartera.vue /cartera-fiat CarteraFiat.vue /ranking Ranking.vue /perfil Perfil.vue * Error404.vue Tabla 5.1: Rutas y a que componente de Medusa pertenecen. 1{ 2 3usuario :{ 4id_google:’’, 5nombre :’’, 6resets :0, 7fecha_registro :’’, 8cartera :{...} 9}, 10 11 ranking :[], 12 13 divisas :{...}, 14 15 conectado:false, 16 tema :" claro ", 17 cargando:false 18 } Código 5.1: Estado del almacén de Medusa. Solo son llamadas desde las acciones del almacén. actions: las acciones son funciones que se llaman desde el componente. Se ejecutan siempre de forma asíncrona, por lo tanto, es aquí donde se llama por ejemplo a una API si queremos usar su resultado en el almacén. Para que una acción modifique el estado del almacén tiene que usar una función definida como mutación. getters: son funciones que devuelven el estado del almacén. Los getters son las funciones que se usan en los componentes para poder acceder al estado del almacén. En la figura 5.2 se puede observar un esquema con todos los componentes del almacén de Vuex. Un componente de Vue.js interactúa solo con las acciones y los getters. 30 Capítulo 6. Detalles del servidor api coingecko.js google.js controlador criptodivisas.js socket.js usuario.js modelo criptodivisas.js usuario.js eliminado.js rutas login.js index.js Figura 6.1: Estructura del servidor de Medusa o borrado su cuenta. El atributo cartera se trata de un objeto donde cada atributo es una cartera distinta. Además de las criptodivisas existe la cartera de fiat, que contiene los euros del usuario. Cuando se crea un nuevo usuario o se resetea uno actual, el valor de la cartera de fiat es de 10.000,00 e, y el resto de 0,00 e. El extracto de código 6.2 contiene la definición del atributo cartera del esquema de Usuario. Como se ha mencionado anteriormente, el atributo cartera contiene todas las carteras del usuario (8 carteras de criptodivisas y 1 de fiat). Cada cartera tiene como atributos: la cantidad y un vector con las transacciones. Las transacciones se definen como en la referencia de código 6.3. El atributo tipo es un enumerado con dos valores (compra y venta), de esta forma, en el momento de la inserción de una nueva transacción Mongoose puede realizar una validación. Un atributo que es utilizado solo en las transacciones de la cartera de fiat es el de detalles, cuyo valor es el nombre de la criptodivisa implicada en la transacción. Por ejemplo, en el caso de una comprar 100,00 ede Bitcoin, se añade una nueva transacción de tipo venta a la cartera de fiat con el valor de “bitcoin” en el atributo detalles. 6.1.2. Esquema de Eliminado Cuando un usuario borra su cuenta, se agrega a la colección de eliminados. El extracto de código 6.4 es la definición del esquema de Eliminado. Los atributos que tiene son el ID de Google y el número de resets que tiene el usuario. De esta manera si un usuario vuelve a crear su cuenta con el mismo ID de Google, se restaura su número de resets. 6.2. Express Express es la biblioteca que se ha usado para procesar las peticiones HTTP que recibe el servidor. Se han integrado dos bibliotecas auxiliares a Express: helmet: permite mejorar la seguridad de una aplicación que usa Express, gracias a la configuración de algunas cabeceras HTTP. En total configura 11 cabeceras HTTP a través de middlewares de Express. Algunas de estas cabeceras son: 6.2. Express 31 1{ 2id_google:{ 3type :String , 4required:true 5}, 6nombre :{ 7type :String , 8required:true 9}, 10 email:{ 11 type :String , 12 required:true 13 }, 14 fecha_registro :{ 15 type :Date, 16 default :Date.now 17 }, 18 resets :{ 19 type :Number , 20 default :0 21 }, 22 cartera :{...} 23 } Código 6.1: Definición del esquema de Usuario 22 cartera :{ 23 bitcoin :{ 24 cantidad:Number, 25 transacciones:[... ] 26 }, 27 28 ... 29 30 fiat :{ 31 cantidad:Number, 32 transacciones:[... ] 33 } 34 35 } Código 6.2: Definición del atributo “cartera” perteneciente al esquema de Usuario 32 Capítulo 6. Detalles del servidor 1{ 2_id :false, 3cantidad:Number, 4fecha:{ 5type :Date, 6default :Date.now 7}, 8precio :Number , 9tipo :{ 10 type :String , 11 enum :[’compra ’,’venta ’], 12 default :’compra ’ 13 }, 14 comision:{ 15 type :Number , 16 default :0 17 }, 18 detalles:String 19 } Código 6.3: Definición de un transacción perteneciente al atributo “transacciones” de una cartera. 1{ 2id_google:{ 3type :String , 4required:true 5}, 6resets :{ 7type :Number , 8default :0 9}, 10 } Código 6.4: Definición del esquema de Eliminado. 6.2. Express 33 •Content-Security-Policy: se configura para mitigar ataques de cross-site scripting. •Strict-Transport-Security: esta cabecera permite a un navegador priorizar el uso de HTTPS en el caso de que la conexión se haya realizado a través de HTTP. body-parser: permite parsear los cuerpos de las peticiones HTTP entrantes. Se usa para poder acceder a los datos que se mandan desde el cliente en una petición POST. En el manejador de rutas para la URI /login se han definido dos rutas POST: /google y/registro. 6.2.1. Ruta /login/google Esta es la ruta donde se inicia sesión usando Google. Recibe un objeto llamado google que tiene todos los datos necesarios para verificar que el inicio de sesión se ha realizado correctamente en el cliente usando una cuenta de Google. Una vez comprobado que el inicio de sesión y los datos son correctos, comprueba si en la base de datos existe el ID de Google de la cuenta. El servidor genera un JWT con los siguientes datos: email: el email de la cuenta de Google que se ha utilizado para iniciar sesión. id: el identificador de la cuenta de Google. registrado: si el usuario ya está registrado en Medusa o no (puede ser true o false). 6.2.2. Ruta /login/registro En esta ruta se hace el registro de un usuario de Medusa. Recibe dos valores por POST: nombre ytoken. El valor del campo nombre contiene el nombre de usuario, y el campo token contiene el JWT que se generó al intentar hacer inicio de sesión. Para que el registro se complete es necesario que: 1. El JWT enviado sea válido. 2. El campo registrado del token tenga el valor false. 3. El nombre de usuario solo tenga letras y números, y una longitud de 5 a 14 caracteres. 4. No haya un usuario de Medusa con el mismo nombre. 5. No exista otro usuario con el mismo ID de la cuenta de Google. Antes de crear el usuario, también se comprueba si el ID de Google está en la colección de eliminados, esto es necesario en el caso de que el usuario ya tuviera una cuenta anteriormente y así poder cargar el número de resets que tenía. Finalmente, el servidor devuelve un JWT al cliente para que pueda realizar la conexión al servidor mediante los WebSockets. 34 Capítulo 6. Detalles del servidor 6.3. Comunicación con el cliente usando Socket.io Para realizar la comunicación con el cliente a través de WebSockets se ha utilizado la biblioteca de Socket.io [44]. Como es necesario verificar que la conexión al socket se está realizando con una persona que ha iniciado sesión, se ha integrado la biblioteca socketiojwt [47]. De esta forma, si en la conexión inicial al socket el cliente no adjunta un JWT válido se rechaza la conexión. Socket.io utiliza un sistema de mensajes donde puedes escuchar o enviar mensajes. El servidor puede emitir un mensaje a: Un socket específico. Todos los sockets. Los sockets de una sala (en inglés: room). Para enviar un mensaje a una sala, es necesario saber su nombre. Las salas te permiten dividir a los sockets en grupos. Cuando un nuevo cliente se conecta a Medusa, su socket se une a una sala que tiene como nombre el _id del documento con sus datos de MongoDB. Esto se hace para que en el caso de que haya varias conexiones del mismo usuario, las acciones se puedan propagar. Es decir, si un usuario está conectado desde dos pestañas del navegador y en una hace una compra de una divisa, se va a reflejar en tiempo real en la otra pestaña. Como el token tiene el ID del usuario, en el momento de la conexión se accede a la base de datos para cargar todos los datos del usuario y enviarlos al cliente. El ID del usuario se agrega como atributo al socket para que en el momento en el que se quiera hacer una operación contra la base de datos, se pueda saber a qué usuario pertenece el socket. El servidor escucha los siguientes mensajes que emite el cliente: TRANSACCION: este mensaje lo emite el cliente cuando quiere crear una nueva transacción. Antes de crear la transacción comprueba si es válida y para ello verifica aspectos como: si el ID de la divisa existe o si el precio es el mismo que tiene registrado el servidor. En el caso de la compra, se comprueba si el usuario tiene suficientes fondos en su cartera de fiat para poder realizarla. RANKING: devuelve un listado con el ranking de los usuarios que tienen más dinero. Para calcular el orden del ranking, se suma el valor en euros de todas las carteras. resetear: vacía todas las carteras de criptodivisas del usuario. La cartera de fiat se modifica para que tenga un balance de 10.000,00 e. Además, suma uno al número de resets del usuario y lo guarda en la base de datos. borrar-cuenta: se borra la cuenta del usuario de la base de datos. Asimismo, suma uno al número de resets y lo guarda en la colección de eliminados de la base de datos junto al ID de la cuenta de Google. Además, desconecta a todos los clientes que hayan hecho inicio de sesión con ese usuario. Cap´ ıtulo 7 Generación de la aplicación web progresiva Tal y como se verá a continuación, los requisitos principales para que una página web sea PWA se implementan en el lado del cliente, salvo el de que sea accesible por HTTPS. Al usar Vue.js, he podido utilizar el plugin oficial cli-plugin-pwa [48], facilitándome mucho el proceso de hacer de Medusa una aplicación web progresiva. 7.1. Requisitos para la instalación Para que una página web pueda ser instalable como PWA, tiene que cumplir los siguientes requisitos: La aplicación web no tiene que haberse instalado anteriormente como PWA. La página web tiene que ser accesible por HTTPS. La web tiene que tener en la raíz el fichero manifest.json [49] que contenga los campos: •short_name: el nombre de la aplicación. •icons: los iconos que va a usar, debe incluir obligatoriamente uno de 192px y otro de 512px. •start_url: la ruta inicial. •display: la forma en la que se va a mostrar la aplicación cuando se instale. Puede tener 3 valores: fullscreen,standalone ominimal-ui. Registrar un service worker que contenga un manejador para el evento fetch 7.2. Medusa como PWA Como Medusa es una PWA, en el momento en el que detecta que el usuario tiene un dispositivo donde se puede realizar la instalación, se muestra una pequeña ventana emergente, informando al usuario de la posibilidad de instalar Medusa. En iPhone y en Safari para Mac no se muestra la ventana emergente, ya que Apple bloquea la API de JavaScript. 35 36 Capítulo 7. Generación de la aplicación web progresiva 1{ 2"name ":" Medusa ", 3"short_name":" Medusa ", 4"theme_color":"# fff ", 5"icons ":[ 6{ 7"src":" icon/android -icon -192x192.png", 8"sizes ":"192x192", 9"type ":" image / png" 10 }, 11 { 12 "src":" icon/android -icon -512x512.png", 13 "sizes ":"512x512", 14 "type ":" image / png" 15 }, 16 ... 17 ], 18 "start_url":"/" , 19 " display ":"standalone", 20 "background_color":"#677eb6" 21 } Código 7.1: Manifest.json generado por Workbox 7.3. Service worker Por defecto, el service worker que genera Workbox de forma automática implementa únicamente la funcionalidad mínima para que la web sea instalable. Cómo yo quería implementar funcionalidad extra, tuve que hacer un script para que luego Workbox lo inyecte al service worker que genera. La primera funcionalidad extra que quise implementar en el service worker fue la de poder cachear un listado de ficheros. De esta forma en el caso de que el usuario intentase entrar a Medusa sin conexión a internet, se cargaría una página de error con un diseño propio. Los ficheros que cachea Medusa para lograr esto son: offline.html: es el fichero HTML con la página de error. Quicksand-VariableFont_wght.ttf: el fichero con la fuente de Medusa. favicon.ico: el favicon de la web. La segunda funcionalidad extra implementada en el service worker, es que en el caso de que se lance una versión nueva de Medusa, la web lo detectaría e informaría al usuario mostrando una ventana emergente que refresca la página. Refrescando la página se reinstala el service worker y se cargan los ficheros actualizados de la web. 7.4. Prueba de la implementación de la aplicación web progresiva 37 Figura 7.1: Resultado de Medusa en un test de Lighthouse 7.4. Prueba de la implementación de la aplicación web progresiva Para comprobar que la implementación de PWA es correcta, usé Lighthouse [50]. Lighthouse es una herramienta creada por Google que, entre otras cosas, te informa de todos los requisitos que faltan para que tu web sea PWA. Otra de las utilidades de Lighthouse es la de poder realizar tests a tu web. La primera vez que lancé el test de Lighthouse la puntuación de accesibilidad fue de un 89, esto se debía a que había añadido una etiqueta HTML que impedía hacer zoom [51]. En la figura 7.1 se muestra un resultado de un test de Lighthouse de Medusa habiendo modificado la etiqueta HTML mencionada anteriormente. El 93 de Best Practices se debe a que Lighthouse recomienda que no se muestre por consola ningún tipo de aviso (warning), pero la API de Google OAuth 2.0 muestra avisos por consola que no se pueden ocultar. Cap´ ıtulo 8 Despliegue de la aplicación Para realizar el despliegue de Medusa, me aproveché de muchas de las ofertas disponibles al registrarme en el lote para estudiantes Github [52]. En la tabla 8.1 se pueden encontrar un resumen de todos los servicios utilizados para el despliegue de Medusa. 8.1. Dominio para la web Al realizar el despliegue, el nombre del dominio fue lo primero que se registró. Para el registro se uso Name.com [53], ya que te regalaban un registro gratis. El dominio elegido fue: “medusapp.live”. El dominio principal se ha configurado para que tenga dos subdominios: servidor.medusapp.live: apunta al servidor de Medusa. dev.medusapp.live: apunta a la versión de desarrollo del cliente de Medusa. El cliente se conecta a una ejecución local del servidor para poder hacer pruebas, sin que afecten a los usuarios finales. Tanto los subdominios como el dominio principal están configurados para que solo sean accesibles utilizando HTTPS. 8.2. Cliente La parte del cliente se hospeda en la plataforma de aplicaciones de Digital Ocean [54]. Elegí esta plataforma porque ya había trabajado antes con ella. Una de las ventajas de usar una plataforma de aplicaciones como la de Digital Ocean, es que no tienes que configurar nada del servidor. Lo único necesario es subir el código y ellos se encargan de construirlo y Componente Servicio usado Dominio web Name.com [53] Hosting para el cliente Digital Ocean [54] Hosting para el servidor Heroku [55] Base de datos MongoDB Atlas [56] Control de errores Sentry.io [57] Tabla 8.1: Servicios externos utilizados para el despliegue de Medusa 39 46 Capítulo 9. Ejemplo de uso La figura 9.4 muestra la parte inferior de la página de inicio. La parte inferior contiene información sobre la criptodivisa seleccionada, se describe el proyecto y los objetivos de la divisa, además existe un botón para abrir el artículo de Wikipedia de la criptodivisa para poder seguir informándose. Por último, hay un apartado de enlaces relevantes que contiene los siguientes enlaces: 1. Página principal de la criptodivisa. 2. Twitter de la criptodivisa. 3. Enlace al subreddit oficial. 4. Repositorio de Github del proyecto. Figura 9.4: Página de inicio (parte 2) 47 En la figura 9.5 se puede observar la página de carteras. El Total contiene la suma total en euros del precio de todas las divisas que tiene el usuario. A la izquierda está el botón para poder ver un gráfico de las carteras, y a la derecha está el botón que te permite reordenar las carteras por valor o por nombre. El porcentaje que está debajo del valor en euros de cada cartera representa las ganancias o perdidas actuales para esa divisa. Figura 9.5: Página de las carteras 48 Capítulo 9. Ejemplo de uso La figura 9.6 contiene el gráfico en forma de tarta con la información de todas las carteras de criptodivisas del usuario. El gráfico es interactivo, en el momento en el que se haga clic o se pase el ratón por encima de uno de los componentes, se muestra en el centro el logo de la divisa y en la parte inferior el valor de la cartera de esa divisa. Figura 9.6: Página de las carteras con el gráfico 49 En la figura 9.7 se muestra la página con la cartera de Ethereum. Todos los gráficos de precios de Medusa tienen el color de la divisa seleccionada. Además, con los botones que están en la parte inferior del gráfico se puede cambiar la franja de tiempo para visualizar los precios de las divisas. Figura 9.7: Página de la cartera de Ethereum (parte 1) 50 Capítulo 9. Ejemplo de uso La figura 9.8 muestra la parte inferior de la página de la cartera de Ethereum. Inicialmente se compra o vende las divisas escribiendo el número de euros deseados, con el botón de las flechas se puede cambiar para en vez de tener que escribir en euros, puedas usar las unidades de la moneda (ej: comprar 1 bitcoin). El módulo de transacciones realizadas te permite visualizar todas las transacciones de la cartera actual. Figura 9.8: Página de la cartera de Ethereum (parte 2) 51 En la figura 9.9 se puede observar la página del ranking. En ella se ordena de mayor a menor todos los usuarios de la web por el valor en euros de todas sus carteras. También se muestra el número de resets que ha realizado el usuario. Figura 9.9: Página del ranking 52 Capítulo 9. Ejemplo de uso La figura 9.10 contiene la página del perfil de un usuario. En esta página se muestra la siguiente información: el nombre de usuario, imagen de perfil, fecha de registro y número de resets. Además, tienes los siguientes cuatro botones: Cerrar Sesión: cierra la sesión actual y redirige a la página de inicio de sesión. Tema Oscuro: habilita o deshabilita el tema oscuro para Medusa. Por defecto Medusa carga con el mismo tema (claro o oscuro) que el dispositivo gracias a la propiedad de CSS prefers-color-scheme [59]. Resetear Cuenta: vacía todas las carteras, menos la de euros que toma un valor de 10.000 ey suma un reset a la cuenta. Se muestra una ventana emergente de confirmación antes de realizar el reset para verificar que realmente se quiere realizar esa acción. Borrar Cuenta: se elimina la cuenta y sus datos. El ID de Google de la cuenta se almacena en una colección para llevar un registro de los resets en caso de que se vuelva a registrar el mismo usuario. Igual que con el reset, se muestra una ventana emergente de confirmación. Figura 9.10: Página de perfil 53 En la figura 9.11 se puede apreciar la página de carteras con el tema oscuro de Medusa. Todos los componentes de la interfaz se adaptan al tema oscuro para que no haya ningún tipo de error visual. Figura 9.11: Página de las carteras con el tema oscuro 54 Capítulo 9. Ejemplo de uso La figura 9.12 contiene la página de la cartera de Bitcoin con el tema oscuro. Como se puede observar, los gráficos también se adaptan sin ningún tipo de problema al tema oscuro. Figura 9.12: Página de la cartera de Bitcoin con el tema oscuro 55 Por último, en la figura 9.13 se puede visualizar cómo se muestra Medusa en móvil. Toda la web se adapta sin ningún tipo de problema a dispositivos móviles, ya que es totalmente responsive. El menú superior se traslada a la parte inferior para actuar como una barra de navegación típica de las aplicaciones móviles. Figura 9.13: Medusa en dispositivos móviles 62 BIBLIOGRAFÍA [17] NPM. npm - build amazing things. https://www.npmjs.com/, 2021. Accedido: 202105-04. [18] Google. Mongodb. https://www.mongodb.com/es, 2021. Accedido: 2021-05-04. [19] . Rfc 7519 - jwt. https://datatracker.ietf.org/doc/html/rfc7519, 2021. Accedido: 2021-05-23. [20] Hardt, D., Ed. The oauth 2.0 authorization framework. https://datatracker.ietf. org/doc/html/rfc6749, 2021. Accedido: 2021-05-23. [21] Google. Google developer console. https://console.developers.google.com/, 2021. Accedido: 2021-05-23. [22] Mozilla. Control de acceso http (cors). https://developer.mozilla.org/es/docs/ Web/HTTP/CORS, 2021. Accedido: 2021-05-23. [23] Google. Case studies featured apps. https://developers.google.com/identity/ sign-in/case-studies?hl=en, 2021. Accedido: 2021-05-20. [24] Coingecko. Coingecko api. https://www.coingecko.com/es/api, 2021. Accedido: 2021-05-21. [25] miscavage. Coingecko node api. https://github.com/miscavage/CoinGecko-API, 2021. Accedido: 2021-05-24. [26] Coingecko. Coingecko api terms. https://www.coingecko.com/es/api_terms, 2021. Accedido: 2021-05-24. [27] Coingecko. Coingecko status. https://status.coingecko.com/, 2021. Accedido: 2021-05-21. [28] Vue.js. Vue router - the official router for vue.js. https://router.vuejs.org/, 2021. Accedido: 2021-05-30. [29] Vue.js. Vuex. https://vuex.vuejs.org/, 2021. Accedido: 2021-05-30. [30] Facebook. Flux - application architecture for building user interfaces. https:// facebook.github.io/flux/, 2021. Accedido: 2021-05-30. [31] MetinSeylan. Vue-socket.io. https://github.com/MetinSeylan/Vue-Socket.io, 2021. Accedido: 2021-05-30. [32] MetinSeylan. Vue-socket.io - vuex integration. https://github.com/MetinSeylan/ Vue-Socket.io#-vuex-integration, 2021. Accedido: 2021-05-30. [33] MetinSeylan. Vue-socket.io - component level usage. https://github.com/ MetinSeylan/Vue-Socket.io#-component-level-usage, 2021. Accedido: 2021-0530. [34] Chart.js. Chart.js - open source html5 charts for your website. https://www.chartjs. org, 2021. Accedido: 2021-05-22. [35] apertureless. vue-chartjs - easy and beautiful charts with chart.js and vue.js. https: //vue-chartjs.org/, 2021. Accedido: 2021-05-31. BIBLIOGRAFÍA 63 [36] janjakubnanista. downsample - downsampling methods for time series visualisation. https://github.com/janjakubnanista/downsample, 2021. Accedido: 2021-05-31. [37] Sveinn Steinarsson. Downsampling time series for visual representation. PhD thesis, University of Iceland, 2013. LTTB en la página 21 a la 25. [38] Jason Long. Identicons! https://github.blog/2013-08-14-identicons/, 2021. Accedido: 2021-05-31. [39] Mozilla. Math.random(). https://developer.mozilla.org/es/docs/Web/ JavaScript/Reference/Global_Objects/Math/random, 2021. Accedido: 2021-05-31. [40] davidbau. seedrandom.js - seeded random number generator for javascript. https: //github.com/davidbau/seedrandom, 2021. Accedido: 2021-05-31. [41] Mozilla. Htmlcanvaselement.todataurl(). https://developer.mozilla.org/es/ docs/Web/API/HTMLCanvasElement/toDataURL, 2021. Accedido: 2021-05-31. [42] hisour. Espacio de color yiq. https://www.hisour.com/es/ yiq-color-space-26084/, 2021. Accedido: 2021-05-31. [43] Express. Express - infraestructura web rápida, minimalista y flexible para node.js. https://expressjs.com/es/, 2021. Accedido: 2021-05-27. [44] Socket.io. Socket.io. https://socket.io/, 2021. Accedido: 2021-05-27. [45] Mongoose. Mongoose - elegant mongodb object modeling for node.js. https:// mongoosejs.com/, 2021. Accedido: 2021-05-29. [46] Martin Lorenz, Günter Hesse, and Jan-Peer Rudolph. Object-relational mapping revised-a guideline review and consolidation. In ICSOFT-EA, pages 157–168, 2016. [47] auth0. socketio-jwt. https://www.npmjs.com/package/socketio-jwt, 2021. Accedido: 2021-05-29. [48] Vue.js. @vue/cli-plugin-pwa. https://cli.vuejs.org/core-plugins/pwa.html, 2021. Accedido: 2021-05-24. [49] Pete LePage, François Beaufort, Thomas Steiner. Add a web app manifest. https: //web.dev/add-manifest/, 2021. Accedido: 2021-05-24. [50] Google. Lighthouse. https://developers.google.com/web/tools/lighthouse?hl= es, 2021. Accedido: 2021-05-24. [51] Mozilla. Viewport width and screen width. https://developer.mozilla.org/ en-US/docs/Web/HTML/Viewport_meta_tag#viewport_width_and_screen_width, 2021. Accedido: 2021-05-30. [52] Github. Github student developer pack. https://education.github.com/pack, 2021. Accedido: 2021-05-23. [53] Name.com. Name.com. https://www.name.com/es-la, 2021. Accedido: 2021-05-23. [54] Digital Ocean. Digital ocean app platform. https://www.digitalocean.com/ products/app-platform/, 2021. Accedido: 2021-05-23. 64 BIBLIOGRAFÍA [55] Heroku. Heroku - cloud application platform. https://www.heroku.com, 2021. Accedido: 2021-05-23. [56] MongoDB. Mongodb atlas. https://www.mongodb.com/es/cloud/atlas, 2021. Accedido: 2021-05-23. [57] Sentry. Sentry.io. https://sentry.io, 2021. Accedido: 2021-05-23. [58] Heroku. Heroku - about. https://www.heroku.com/about, 2021. Accedido: 2021-0523. [59] W3C. prefers-color-scheme media feature. https://drafts.csswg.org/ mediaqueries-5/#prefers-color-scheme, 2021. Accedido: 2021-05-23. [60] Coinmarketcap. Principales 100 criptomonedas por capitalización de mercado. https: //coinmarketcap.com/, 2021. Accedido: 2021-05-23. [61] Facebook. Jest - delightful javascript testing. https://github.com/facebook/jest, 2021. Accedido: 2021-05-23. [62] Mocha.js. Mocha - simple, flexible, fun. https://mochajs.org/, 2021. Accedido: 2021-05-23.