Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Módulo 10: Proyecto de desarrollo ágil: Aplicación Fullstack Javascript

Horas 12
Clases (laboratorios) 4
Unidades 4

Aplicación Fullstack Javascript

Contenidos
  1. Aprendizaje esperado
  2. Introducción
  3. Antes de comenzar
    1. Recordatorio: Como resolver un Issue
  4. Símbolos a considerar
  5. Issue 1: Salir a producción tempranamente
    1. Tarea técnica
    2. Tarea funcional
    3. Consideraciones técnicas
    4. ANTES de mezclar el Pull Request
  6. Issue 2: Habilitar un servicio de autenticación
    1. Pre-requisito 1: Crear proyecto, una aplicación Firebase
    2. Pre-requisito 2: Habilitar servicio de Autenticación
    3. Descripción del Issue
    4. Tarea funcional
    5. Consideraciones técnicas
  7. Issue 3: Seguridad de la aplicación y pruebas de software
    1. Pre-requisito: Obtener una cuenta de Servicio de Firebase
    2. Descripción del Issue
    3. Tarea funcional
    4. Consideraciones Técnicas
  8. Issue 4: Dashoard de Indicadores Financieros
    1. Tarea funcional
    2. Consideraciones Técnicas

Aprendizaje esperado

Llevar a producción una aplicación Full Stack JavaScript

Introducción

Felicitaciones por estar en la instancia final del curso Fullstack JavaScript PRO

La idea es que con la resolución de este proyecto puedas aplicar todos los conceptos aprendidos en los laboratorios y demuestres tu nivel de JavaScript pero más importante aún: La responsabilidad de asignarse un issue de un proyecto y llevarlo a producción; todo esto utilizando el lenguaje JavaScript y las prácticas esperadas por el ecostistema digital ágil

Antes de comenzar

  • Tener una cuenta Github, Heroku y Google
  • Utiliza la versión 18 de NodeJS (utiliza NVM)
  • Agregar al usuario booleanchile como colaborador de su proyecto
  • Crear un proyecto (projects classic) de tipo “Automated Kanban”

Recordatorio: Como resolver un Issue

Más adelante describiremos los issues a resolver. No olvidar el proceso para resolver un issue es el siguiente:

  • Crear una rama
  • Crear un issue desde el tablero.
  • Al terminar la funcionalidad crear un Pull Request. Para el Pull Request no olvidar:
    • Agregar como revisor al usuario booleanchile
    • Agregar el comentario especial para cerrar el issue relacionado. Sin tienes dudas revisar acá
    • Puedes mezclar el Pull Request sin esperar la revisión. Esta se hará posteriormente

Símbolos a considerar

Toda vez que aparezcan los siguientes símbolos, debes reemplazarlos por un texto que se indica a continuación:

  • <STUDENT-APP-NAME>: Se refiere al nombre otorgado por el estudiante a su proyecto final que debe coincidir con el nombre de la aplicación.

Issue 1: Salir a producción tempranamente

Tarea técnica

Característica: Aplicación Express base con un ambiente 

La aplicación debe contar con un ambiente profesional de desarrollo a través de las prácticas recomendadas por Express y NodeJS.  
También se espera que se utilicen las prácticas básicas esperadas de un desarrollador Fullstack que se desenvuelve en equipos de alta productividad.

Escenario: Contamos con un ambiente de desarrollo NodeJS inicial que permita escalar una aplicación de Servidor

  Dado un desarrolador de software en el directorio del proyecto
  Cuando ejecuta el comando `npm run dev`
  Entonces se ejecuta el servidor NodeJS en modo desarrollo local
    Y cada vez que hacemos cambios en los archivos de extensión .js el servidor se actualiza
    Y existen las variables de entorno `NODE_ENV` y `PORT`

Escenario: Contamos con un Linter de código que se aplica cada vez antes de cada commit de git

  Dado un desarrolador de software en el directorio del proyecto
  Cuando ejecuta un commit de git
  Entonces se ejecuta el linter configurado con StandardJS impidiendo el commit en el caso que el linter falle
    Y existen el npm script "lint" en package.json que puede ser ejecutado utilizando el comando "npm run lint"

Tarea funcional

Característica: Aplicación Express publicada en producción utilizando Heroku

Se requiere poder acceder a la URL siguiente:

  https://<STUDENT-APP-NAME>.herokuapp.com


Escenario:
    Un usuario accediendo a la aplicación
    
    Dado un usuario en el Navegador Web
    Cuando ingresa a la url "https://<STUDENT-APP-NAME>.herokuapp.com"
    Entonces la aplicación Web es desplegada correctamente

Consideraciones técnicas

  • Utilizar Nodemon, Husky y ESLint
  • Deben existir los scripts “start”, “dev” y “lint” en package.json
  • Utilizar express generator para crear un proyecto NodeJS utilizando la opcion “–view” hbs para trabajar con handlebars, “–git” para agregar gitignore y “–force” para forzar la instalacion si el directorio actual no está vacío.
  • NO agregues localmente la linea de comandos de Heroku. Cuando mezclemos en la rama “main” se subirá automáticamente a Heroku

ANTES de mezclar el Pull Request

Si observas la sección Actions una vez que hayas mezclado tu Pull Request verás que está fallando. Necesitamos hacer un paso extra para poder subir a Heroku

  • Crea 3 variables de entorno para Github Actions utilizando la opción de secretos que puedes ver en [el siguiente enlance ] (https://docs.github.com/en/enterprise-cloud@latest/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-an-organization)
HEROKU_API_KEY                API KEY de tu cuenta personal de Heroku
HEROKU_OWNER_EMAIL            Email de autenticación en Heroku
HEROKU_APP_NAME               Nombre que le quieres dar a tu App (se creará automáticamente)

Si todo sale bien, al mezclar tu Pull Request verás que se publica de forma automática. Si quieres entender como funciona esto. Revisa el archivo en “.github/workflows/pipeline.yml” y consulta a tu lider técnico como funciona esto.


Issue 2: Habilitar un servicio de autenticación

Pre-requisito 1: Crear proyecto, una aplicación Firebase

Vamos a seguir las siguiente instrucciones para obtener los datos necesarios para trabajar e incluir la parte Frontend de Firebase.

  • Elegimos “add project” y elegimos un nombre para nuestro proyecto. Recomendamos <STUDENT-APP-NAME> pero puede ser cualquiera que te sea cómodo.

  • Agregamos el nombre y en el siguiente paso deshabilitamos la opción de Habilitar Google Analytics:

  • Comenzamos el proceso de agregar una app al ecosistema Firebase con el botón remarcado en la siguiente imagen:

  • Lo anterior nos permitirá crear una app que nos proveerá el código necesario para agregar tanto en el JavaScript que se ejecutará en el navegador, como en el servidor. Comenzaremos dandole un nombre a nuestra App. Acá nuevamente recomendamos <STUDENT-APP-NAME> pero puede ser cualquiera que te sea cómodo.

  • Luego que registramos la app, nos pedirá agregar el SDK de Firebase: Seleccionamos la opción “Usar una etiqueta <script>".

Será tu deber saber en que lugar de tu proyecto debes incluir este script que debe ser utilizado en la parte Frontend de tu aplicación. Piensa esto como tu clave pública y será luego en el servidor donde alojaremos nuestra llave privada.

Pre-requisito 2: Habilitar servicio de Autenticación

  • Vamos a la consola principal del proyecto y seleccionamos la opción “Authentication” como lo que muestra la siguiente imagen:

  • Vamos a aparecer en la pestaña “Users” y debemos seleccionar el botón “Configurar el método de acceso”:

  • En la sección que aparecemos seleccionaremos la opción “Correo electrónico/contraseña”

  • Habilitamos este servicio y presionamos “Guardar”. Notar que mantenemos desactivada la opción `Vínculo del correo electrónico (acceso sin contraseña)

  • Ahora crearemos un usuario presionando el tab Users tal como se indica en la siguiente imagen:

Presionamos el Botón

“Agregar usuario” y crearemos un usuario con el siguiente perfil:

Correo electrónico: test-e2e@boolean.cl
Contraseña: booleanacademia

Recuerda que este usuario, a pesar de estar en entorno productivo, será solamente para realizar pruebas.

Nota: NO CAMBIES ESTE USUARIO Y CONTRASEñA ya que será usado para revisar tu trabajo posteriormente.

Descripción del Issue

Ya que logramos realizar todos los pasos anteriores para habilitar nuestro sistema de autenticación, vamos a detallar los requerimientos a resolver.

Tarea funcional

Característica: Autenticación de usuario 

La aplicación debe desplegar un formulario de inicio de sesión en la ruta base de la aplicación 

Escenario: Inicio de sesión a través del formulario desplegado en la ruta raíz de la aplicación

  Dado un usuario en la página de inicio
  Cuando llena el formulario utilizando el usuario "test-e2e@boolean.cl"
    Y la contraseña "booleanacademia"
    Y presiona el botón "Iniciar Sesión"
  Entonces el usuario es dirigido a la página de Dashboard

Escenario: Inicio de sesión con campos obligatorios vacios

  Dado un usuario en la página de inicio
  Cuando presiona el botón "Iniciar Sesión"
  Then los campos muestran el mensaje "Este campo es obligatorio"

Escenario: Inicio de sesión fallido

  Dado un usuario en la página de inicio
  Cuando llena el formulario utilizando el usuario "cualquier_usuario@loquesea.net"
    Y la contraseña "321987"
    Y presiona el botón "Iniciar Sesión"
  Entonces se muestra un mensaje que dice "Usuario o Contreseña incorrectos"

Consideraciones técnicas

  • Utilizar la librería Pristine para la validación del formulario
  • Deben existir los scripts “start”, “dev” y “lint” en package.json
  • Agrega un script luego que utilizando addEventListener reconozca el evento “submit” de un formulario de autenticación.
  • Utilizar la siguiente guía para entender como utilizar el método signInWithEmailAndPassword
  • Crear 3 pruebas con Cypress y Cucumber Preprocessor que automaticen los ___

Issue 3: Seguridad de la aplicación y pruebas de software

Pre-requisito: Obtener una cuenta de Servicio de Firebase

Antes de resolver este issue vamos a crear un cuenta de servicio. ES MUY IMPORTANTE que el archivo generado en los pasos siguientes no sea registrado en el control de versiones. Si no me crees, por favor lee el siguiente artículo

  • Primero desde el panel principal del proyecto vamos a la esquina superior izquierda, en el icono “engranaje” seleccionamos la opción “Project Settings y en las pestañas seleccionar “Service accounts”

  • Luego presionamos el botón “Generate new private key” para generar el archivo que vamos a utilizar para autenticarnos al SDK de Firebase Admin.

Veremos un mensaje de advertencia que nos indicará que tengamos cuidado de mantener este archivo confidencial.

Una vez descargado el archivo lo incluimos en la raíz del proyecto. Luego agregamos al .gitignore la siguiente expresión

*-firebase-adminsdk-*.json

y nos aseguramos que el archivo quedó ignorado.

Descripción del Issue

Ya que logramos realizar todos los pasos anteriores para obtener la cuenta de servicio, vamos a detallar los requerimientos a resolver.

Tarea funcional

Característica: Carga de dashboard y validación de peticiones

La aplicación debe comunicarse desde el Frontend con el Backend 
al momento de cargar la página de dashboard enviando
una petición a un endpoint `/api/dashboard`
que debe responder un arreglo cualquiera (momentaneamente).

Escenario: Carga de dashboard exitosa

  Dado un usuario autenticado correctamente
    Y en la página de dashboard
  Cuando la página de dashboard se carga
  Entonces se hace una petición al endpoint `/api/dashboard`
  que debe devolver un arreglo

Escenario: Carga de dashboard erronea

  Dado un usuario autenticado correctamente
    Y en la página de dashboard
  Cuando la página de dashboard se carga
  Entonces se hace una petición al endpoint `/api/dashboard`
  que si falla debe mostrar un mensaje "dashboard no disponible momentaneamente"

Característica: Endpoints privados bajo la URL "/api/"

Todas las peticiones entrantes al Backend 
deben validar que se envía una cabecera de autorización y que esta es válida.

Escenario:  Request enviado sin cabezara Authorization

  Dado una petición sin una cabecera Authorization
  Cuando se envia hacia una URL con el prefijo "/api"
  Entonces Devuelve 401 y un mensaje "No token provided"

Escenario:  Request enviado con cabecera Authorization no del tipo "bearer"

  Dado una petición con una cabecera Authorization NO del tipo "bearer"
  Cuando se envia hacia una URL con el prefijo "/api"
  Entonces Devuelve 401 y un mensaje "Invalid token"

Escenario:  Request enviado con cabecera Authorization y token del tipo bearer invalido

  Dado una petición con una cabecera Authorization del tipo "bearer"
  Cuando se envia hacia una URL con el prefijo "/api"
  Entonces Devuelve 403 y un mensaje "Could not authorize"

Consideraciones Técnicas

  • En el FrontEnd en la página de Login, utiliza onAuthStateChanged y solo suscribir los cambios del formulario si el usuario NO está autenticado. Si ya lo está debe ser redirigido a la página “/dashboard”. Lee la siguiente guía para entender como saber si el usuario está o no autenticado.

  • Utiliza el método de firebase verifyIdToken para saber si la cabecera es válida o no. Mira un ejemplo de su uso acá
  • Crear pruebas de software de integración en el servidor que valide que cada petición entrante dados los casos descritos anteriormente en la tarea funcional. Para crear las pruebas de integración de Backend puedes utilizar el siguiente seudo-código como plantilla para tus pruebas:
// YOUR DEPENDENCIES 
...
const admin = require('firebase-admin');

jest.mock('firebase-admin', () => ({
  auth: jest.fn()
    .mockReturnValue({ verifyIdToken: jest.fn() }),
  credential: {
    applicationDefault: jest.fn(),
  },
  initializeApp: jest.fn()
}))


it('returns 401 when there is no authorization header', async () => {
  const response = /* TU CÓDIGO ACÁ */
  expect(response.body).toMatchObject({ message: 'No token provided' })
})
it('returns 401 when the token is not a bearer token', async ()=>{
  const response = /* TU CÓDIGO ACÁ */
  expect(response.body).toMatchObject({ message: 'Invalid token' })
})

it('returns 403 when an invalid token is passed',async () => {
  admin.auth().verifyIdToken.mockRejectedValue(new Error());
  const response = /* TU CÓDIGO ACÁ */
  expect(response.body).toMatchObject({ message: 'Could not authorize' })
})
  • Debes utilizar supertest para escribir estas pruebas
  • Investiga como utilizar CloudStorage y guarda tu cuenta de servicio ahí
  • Crear un archivo en la raíz llamado “.profile” en la raíz del proyecto con el siguiente contenido:
curl -X GET $SERVICE_ACCOUNT_FILE_URL

export GOOGLE_APPLICATION_CREDENTIALS=$SERVICE_ACCOUNT_FILE_NAME

Si quieres entender porque esto es necesario, lee el siguiente artículo

  • Crea 2 nuevas variables de entorno para Github Actions
SERVICE_ACCOUNT_FILE_URL      URL de Firebase Storage del archivo de cuenta de servicio con token para descargar de forma segura
SERVICE_ACCOUNT_FILE_NAME     el nombre del archivo de cuenta de servicio (incluyendo la extensión)

Issue 4: Dashoard de Indicadores Financieros

Tarea funcional

Característica: Carga de dashboard que muestra gráfico de variación del dólar

La aplicación debe comunicarse desde el Frontend con el Backend 
al momento de cargar la página de dashboard enviando
una petición a un endpoint `/api/dashboard`
que debe responder información pre-procesada desde el servicio https://mindicador.cl para obtener el valor del dólar de un mes

Escenario: Carga de dashboard exitosa del dólar

  Dado un usuario autenticado correctamente
    Y en la página de dashboard
  Cuando la página de dashboard se carga
  Entonces se muestra un gráfico con la variación del valor del dólar el último mes

Consideraciones Técnicas

  • Usar chart.js
  • Crear objetos y arreglos desde el Backend, con los datos desde la API de “mindicador.cl” que sean fácilmente consumibles por la librería chart.js en el Frontend

ÉXITO!