¿Cómo hacer pruebas unitarias en un modal en Angular Material?

En este post voy a enseñar como hacer pruebas unitarias de un modal / popup / ventana emergente de Angular Material. Voy a empezar con un proyecto desde cero, junto con la instalación de Angular Material y mostrando paso a paso lo que hago para hacer las pruebas unitarias de dicho componente.


Creando el proyecto

Lo primero que vamos a hacer es crear un proyecto vacío, ubicamos la carpeta donde queremos alojar el proyecto y ejecutamos el siguiente comando:

ng new PruebasAngular

Añadiendo Angular Material a nuestro proyecto

Luego de que nuestro proyecto este creado instalamos Angular Material con el siguiente comando:

ng add @angular/material

Una vez se termine de descargar todo, vamos a importar los módulos de los componentes que necesitamos, ubicamos nuestro archivo app.module.ts, agregamos los siguientes import a nuestro proyecto:

import {MatDialogModule} from ‘@angular/material/dialog’;
import {MatButtonModule} from ‘@angular/material/button’;

Luego añadimos estos módulos que importamos a nuestro array de imports de nuestro app.module.ts , quedaría de la siguiente manera

imports-angular-material

Creando el componente de contenido de nuestro modal / popup / ventana emergente.

Para hacer un modal en Angular Material requerimos pasarle un contenido, para esto vamos a generar un componente con el contenido que queramos, utilizamos el siguiente comando:

ng g c components/popupcontent

Una vez se genere el componente vamos a tener la siguiente estructura:

Vamos a modificar el contenido de nuestro componente, vamos a agregar texto de prueba y hacer uso de los botones de Angular Material, puedes poner lo que quieras, esto es lo que yo quise poner:

<div>
  Lorem, ipsum dolor sit amet consectetur adipisicing elit. Adipisci repellendus aut deleniti quo sequi, animi error,
  similique, dicta cum aperiam beatae magnam expedita architecto dolorum dignissimos iure autem modi incidunt!
  Lorem ipsum dolor sit amet consectetur adipisicing elit. Quaerat, eligendi? Iure explicabo perspiciatis incidunt
  veniam illo minima nihil corporis architecto dolores autem quas aperiam inventore accusantium, fugit iusto cumque?
  Dolorem?

  <mat-dialog-actions align="end">
    <button mat-button mat-dialog-close>Cancelar</button>
    <button mat-button [mat-dialog-close]="true" cdkFocusInitial>Acepto</button>
  </mat-dialog-actions>

</div>

La parte de [mat-dialog-close] se refiere a la respuesta que vamos a recibir cuando demos clic en Acepto

Añadiendo el botón y la función que llame el modal

En el archivo app.component.html vamos a crear un botón con un método que va a ser el que va a llamar la función de MatDialog que permite abrir el modal.

<div>
  <button mat-button (click)="openDialog()">Open dialog</button>
  <router-outlet></router-outlet>
</div>

Yo llame a mi método openDialog(), si arroja un error es porque no se ha creado la función en app.component.ts, es el siguiente paso que vamos a realizar.

Nos dirigimos al archivo app.component.ts , lo primero que vamos a hacer es importar el dialog de material

import { MatDialog } from ‘@angular/material/dialog’;

Creamos el constructor para hacer la inyección de nuestro componente de la siguiente manera:

constructor(public dialog: MatDialog) {}

Ahora creamos un método que nos va a permitir abrir el modal cuando demos clic en el botón

openDialog() {
  	//Pasamos nuestro componente del contenido que queremos pasar al modal
    const dialogRef = this.dialog.open(PopupcontentComponent);

    dialogRef.afterClosed().subscribe(result => {
      console.log(`Dialog result: ${result}`);
    });
  }

Este modal comprende dos partes:

  • El método .open(contenido) pertenece a MatDialog que previamente inyectamos en nuestro constructor.
  • El método afterClosed básicamente es lo que queremos hacer cuando se cierre el modal, en este caso vamos a imprimir la respuesta true o [], recordemos que este resultado fue lo que pusimos en [mat-dialog-close]

Nos dirigimos a app.module.ts para agregar lo siguiente:

entryComponents: [PopupcontentComponent]

Necesitamos agregar entryComponents porque el contenido entrante del modal es agregado dinámicamente, si necesitas mas información de entryComponents lo mejor que puedes mirar es la documentación.

Nuestro archivo app.module.ts se vería de la siguiente manera:

Probemos que nuestro modal este funcionando

Utilizamos el comando ng -serve para levantar el servidor

Modal de Angular Material funcionando.

Es hora de las pruebas!

Si en este momento ejecutamos el comando ng test nos vamos a encontrar con el siguiente error, se origina en el archivo de pruebas de nuestro componente del contenido del modal:

Tenemos que saber que cuando estamos haciendo pruebas de algún componente de Angular Material en nuestro archivo de pruebas siempre se deben importar los módulos de Material que estemos usando, esta importación se hace en el método beforeEach.

Para nuestro ejemplo usamos botones de material y el MatDialog, por consiguiente debemos agregar lo siguiente en nuestro archivo .ts del contenido del modal

imports: [MatButtonModule, MatDialogModule]

Quedando en mi caso mi archivo popupcontent.component.spec.ts de la siguiente manera:

Nos dirigimos a app.component.spec.ts y lo primero que vamos a hacer es agregar el modulo de MatDialogModule en los imports de la misma manera que hicimos anteriormente, Después de agregar esto nuestras pruebas deberían estar corriendo correctamente.

Ahora vamos a hacer la prueba de verdad, ubicados en app.component.spec.ts lo primero que vamos a hacer es crear dos variables que van a actuar como espías del modal.

let dialogSpy: jasmine.Spy;
let dialogRefSpyObj = jasmine.createSpyObj({afterClosed: of({}), close: null});

En el beforeEach vamos a instanciar dialogSpy de la siguiente manera:

dialogSpy = spyOn(TestBed.get(MatDialog), 'open').and.returnValue(dialogRefSpyObj);

Donde le decimos con spyOn, el nombre del objeto y el método del objeto que va a ser espiado.

Nuestro archivo iría de la siguiente manera:

Con esto previamente realizado pasamos a hacer nuestro caso de prueba:

En este caso la prueba es que nuestro método openDialog si este funcionando como deba es decir que abra el modal.

Ejecutamos nuestras pruebas con el comando ng test

Como podemos observar la prueba que hicimos va a la perfección, ahora vamos a comprobar si de verdad esas líneas de código se están probando, vamos a utilizar el comando de cobertura de pruebas ng test — –watch=false –code-coverage

Perfecto, esta todo al 100% pero… vamos a verlo mejor de una forma mas gráfica, vamos a ver el reporte que nos genero la herramienta de coverage, nos vamos a la parte de coverage que se encuentra en la carpeta de nuestro proyecto y abrimos el index.html

Eso es todo por este tutorial, si te ha sido de ayuda no olvides puntuar y te dejo el link del proyecto en mi repositorio personal.

Leave a Reply

Your email address will not be published.