<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Fran López</title>
    <description>The latest articles on DEV Community by Fran López (@franlopez).</description>
    <link>https://dev.to/franlopez</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1759397%2F56adb979-d30f-40d7-b9bb-32bc039c37c2.jpg</url>
      <title>DEV Community: Fran López</title>
      <link>https://dev.to/franlopez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/franlopez"/>
    <language>en</language>
    <item>
      <title>Hola, Playwright (II) - Integración CI con Github Actions.</title>
      <dc:creator>Fran López</dc:creator>
      <pubDate>Mon, 25 Nov 2024 12:34:38 +0000</pubDate>
      <link>https://dev.to/franlopez/hola-playwright-ii-integracion-ci-con-github-actions-2217</link>
      <guid>https://dev.to/franlopez/hola-playwright-ii-integracion-ci-con-github-actions-2217</guid>
      <description>&lt;h2&gt;
  
  
  Introducción
&lt;/h2&gt;

&lt;p&gt;En nuestro &lt;a href="https://dev.to/franlopez/configuracion-de-playwright-pruebas-end-to-end-e2e-paso-a-paso-en-un-proyecto-de-front-end-58e2"&gt;post anterior&lt;/a&gt; vimos como instalar Playwright, definir una prueba de end to end sencilla, y ejecutarla en un navegador local.&lt;/p&gt;

&lt;p&gt;Esto está muy bien, podríamos pedirles a nuestros desarrolladores que antes de mezclar a main sus cambios, lanzaran estos tests e2e en sus máquinas y solo subieran los cambios si todo va bien, pero podríamos encontrarnos varios problemas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Primero, que es muy normal que con las prisas a uno se le pase hacerlo y directamente suba los cambios (esto podríamos evitarlo utilizando &lt;a href="https://dev.to/franlopez/configuracion-de-husky-lint-staged-y-prettier-para-fromatear-en-precommit-ilj"&gt;herramientas como husky, más info en este post&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Segundo, si usáramos una tool como &lt;em&gt;Husky&lt;/em&gt; que forzara al desarrollador a ejecutar los tests en cada &lt;em&gt;push&lt;/em&gt;, estaríamos sobrecargando su máquina y haciendo más lento el proceso, cuando igual lo que queremos es que solo se ejecute en una &lt;em&gt;pull request&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tercero, puede que la máquina del desarrollador no sea el escenario ideal, igual está dentro de una &lt;em&gt;VPN&lt;/em&gt;, o tiene acceso a la red... y no queremos que esto afecte a los tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;¿Te imaginas un proceso en el que, cada vez que crees una Pull Request, automáticamente se inicie una máquina limpia, se ejecuten todos los tests en ella y, si todo sale bien, se permita fusionar la rama sin contratiempos?&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Bienvenido al maravilloso mundo de los &lt;em&gt;CI/CD&lt;/em&gt;, en este post vamos a ver cómo configurar un pipeline de &lt;em&gt;CI/CD&lt;/em&gt; en Github Actions para ejecutar nuestros tests de Playwright en cada Pull Request.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR;
&lt;/h2&gt;

&lt;p&gt;Partimos del primer post de esta serie (ya tenemos playwright instalado y configurado)&lt;/p&gt;

&lt;p&gt;Para poder incluir los &lt;em&gt;tests&lt;/em&gt; de &lt;em&gt;e2e&lt;/em&gt; en nuestro flujo de integración continua, si usamos &lt;em&gt;Github Actions&lt;/em&gt;, tenemos que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Definir un comando en nuestro &lt;em&gt;package.json&lt;/em&gt; que ejecute los tests de e2e sin levantar interfaz de usuario. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;./package.json&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;  "scripts": {
    "dev": "vite",
    "build": "tsc &amp;amp;&amp;amp; vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives
 --max-warnings 0",
    "preview": "vite preview",
    "format": "prettier --write .",
    "test": "vitest",
    "prepare": "husky || \"No need to install husky\"",
    "tsc-check": "tsc --noEmit",
    "e2e": "playwright test --ui",
&lt;span class="gi"&gt;+   "ci:e2e": "playwright test"
&lt;/span&gt;  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;En nuestro flujo de &lt;em&gt;Github Actions&lt;/em&gt; añadir una entrada para que los ejecute cuando se lance una &lt;em&gt;Pull Request&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;./.github/workflows/ci.yml&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI workflow&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pull_request&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;e2e-tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use Node.js 18.13.0&lt;/span&gt;
       &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v2&lt;/span&gt;
        &lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;18.13.0'&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;npm'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
       &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run build&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check TypeScript Types&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run tsc-check&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run E2E tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run ci:e2e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;¿Quieres ver cómo funciona esto paso a paso?&lt;/em&gt; Sigue leyendo :).&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 1: El ejemplo que vamos a usar
&lt;/h2&gt;

&lt;p&gt;Arrancamos del &lt;a href="https://dev.to/franlopez/configuracion-de-playwright-pruebas-end-to-end-e2e-paso-a-paso-en-un-proyecto-de-front-end-58e2"&gt;primer post de esta serie&lt;/a&gt;, donde instalábamos playwright, hacíamos el setup y escribíamos nuestro primer test de e2e.&lt;/p&gt;

&lt;p&gt;Tomamos como punto de partida el primer post de esta serie. &lt;/p&gt;

&lt;p&gt;El ejemplo que estamos utilizando como base es el proyecto Open Source &lt;a href="https://mongomodeler.com/" rel="noopener noreferrer"&gt;Mongo Modeler&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 2: Lanzando test sin interfaz de usuario
&lt;/h2&gt;

&lt;p&gt;En el primer post de esta serie vimos como podemos lanzar los &lt;em&gt;tests&lt;/em&gt; de &lt;em&gt;e2e&lt;/em&gt; con una interfaz de usuario que nos permite ver en tiempo real cómo se ejecutan los &lt;em&gt;tests&lt;/em&gt;, esto está muy bien en tiempo de desarrollo, ya que podemos ver si la interacción con la interfaz es la esperada y podemos incluso depurar e ir atrás y adelante en la línea del tiempo.&lt;/p&gt;

&lt;p&gt;Cuando nuestros &lt;em&gt;tests&lt;/em&gt; ya están listos, lo que queremos es que se puedan lanzar desde el terminal y nos devuelvan un resultado, abrir la &lt;em&gt;interfaz de usuario&lt;/em&gt; en nuestra &lt;em&gt;máquina local&lt;/em&gt; podría meter ruido, y... lo más importante, en una &lt;em&gt;máquina virtual&lt;/em&gt; o &lt;em&gt;contenedor&lt;/em&gt; de un servidor de &lt;em&gt;integración continua&lt;/em&gt; no tenemos &lt;em&gt;interfaz de usuario&lt;/em&gt;, son máquinas mínimas y tiramos de &lt;em&gt;terminal&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;¿Qué podemos hacer?&lt;/em&gt; &lt;em&gt;Playwright&lt;/em&gt; nos permite lanzar los tests sin interfaz de usuario, para ello vamos a crearnos un comando adicional en nuestro &lt;em&gt;package.json&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;  "scripts": {
    "dev": "vite",
    "build": "tsc &amp;amp;&amp;amp; vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives
 --max-warnings 0",
    "preview": "vite preview",
    "format": "prettier --write .",
    "test": "vitest",
    "prepare": "husky || \"No need to install husky\"",
    "tsc-check": "tsc --noEmit",
    "e2e": "playwright test --ui",
&lt;span class="gi"&gt;+   "ci:e2e": "playwright test"
&lt;/span&gt;  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si lo probamos en nuestro terminal con &lt;code&gt;npm run ci:e2e&lt;/code&gt; veremos que se lanzan los tests sin interfaz de usuario.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run ci:e2e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si lanzamos este comando, podemos ver que se lanzan los tests y no se abre ningún navegador.&lt;br&gt;
Al lanzar este comando, vemos como sólo se informa de los resultados vía salida del terminal de texto asociado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzccrf0j4abtb8gb08r5f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzccrf0j4abtb8gb08r5f.png" alt="Imagen utilizando el comando y pasando los test e2e sin interfaz de ususario" width="800" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ya estamos listos para integrar esto en nuestro flujo de integración continua.&lt;/p&gt;
&lt;h2&gt;
  
  
  Paso 3: Definiendo un &lt;em&gt;workflow&lt;/em&gt; de &lt;em&gt;Github Actions&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Github actions&lt;/em&gt; funciona de una manera muy sencilla:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;En la raíz de tu proyecto creas una carpeta &lt;code&gt;.github&lt;/code&gt; y dentro otra &lt;code&gt;worfklows&lt;/code&gt;, la ruta completa sería la siguiente: &lt;code&gt;.github/workflows&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dentro de esa carpeta crearemos ficheros con extensión &lt;code&gt;.yml&lt;/code&gt; que definirán los &lt;em&gt;workflows&lt;/em&gt; que queremos que se ejecuten en nuestro proyecto.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cuando hagamos &lt;em&gt;push&lt;/em&gt; de las acciones, &lt;em&gt;Github&lt;/em&gt; las detecta y está listo para ejecutarlas en el momento que le hayamos indicado (por ejemplo, cuando vayamos a hacer una &lt;em&gt;Pull Request&lt;/em&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Lo de forzar a que ciertas carpetas tengan un nombre concreto es una convención de &lt;em&gt;Github&lt;/em&gt;, si no lo haces así, no se ejecutarán los &lt;em&gt;workflows&lt;/em&gt;, se llama configuración por &lt;em&gt;convención&lt;/em&gt; o &lt;em&gt;nomenclatura&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ya sabemos dónde colocar nuestros &lt;em&gt;workflows&lt;/em&gt;, &lt;em&gt;¿Definimos uno?&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Seguimos la nomenclatura de &lt;em&gt;yml&lt;/em&gt; y las entradas que nos permite &lt;em&gt;Github Actions&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creamos un archivo, por ejemplo, lo podemos llamar &lt;code&gt;ci.yml&lt;/code&gt; y lo colocamos en la carpeta &lt;code&gt;.github/workflows&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;En ese archivo le damos un nombre.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Después le decimos cuándo se va a lanzar el flujo, en este caso queremos que se lance cuando se haga una &lt;em&gt;pull request&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Como va quedando:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;./.github/workflows/ci.yml&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI workflow&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pull_request&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Cuidado con las tabulaciones, en &lt;code&gt;yml&lt;/code&gt; es importante.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ahora vamos a definir los jobs que se van a ejecutar, en este caso vamos a lanzar los tests de e2e.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Más información sobre como funcionan las &lt;a href="https://lemoncode.net/lemoncode-blog/2020/2/12/hola-docker-ci-cd-github-actions" rel="noopener noreferrer"&gt;Github Actions en este post&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En este caso, le podemos decir que lance el &lt;em&gt;job&lt;/em&gt; de &lt;em&gt;e2e&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;./.github/workflows/ci.yml&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;name: CI workflow
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;on: pull_request
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+  e2e-tests:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v2
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+      - name: Use Node.js 18.13.0
+       uses: actions/setup-node@v2
+        with:
+          node-version: '18.13.0'
+          cache: 'npm'
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+      - name: Install dependencies
+        run: npm ci
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+      - name: Build
+       run: npm run build
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+      - name: Check TypeScript Types
+        run: npm run tsc-check
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gi"&gt;+      - name: Run E2E tests
+        run: npm run ci:e2e
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Que le estamos diciendo aquí:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Tenemos un &lt;em&gt;job&lt;/em&gt; llamado &lt;code&gt;e2e-tests&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Se va a ejecutar en una máquina con sistema operativo &lt;code&gt;ubuntu&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Después vamos a traernos el código de nuestro repositorio.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Le decimos que usé la versión de Node.js &lt;code&gt;18.13.0&lt;/code&gt; (lo añade a la máquina que ejecuta el job).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Instalamos las dependencias, fíjate que aquí usamos &lt;em&gt;npm ci&lt;/em&gt; en vez de &lt;em&gt;npm install&lt;/em&gt;. Esto lo hacemos para que no modifique el fichero &lt;em&gt;package-lock.json&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Para asegurarnos que está todo bien construido, lanzamos el comando &lt;em&gt;npm run build&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;También lanzamos un chequeo de los tipos de &lt;em&gt;TypeScript&lt;/em&gt; con &lt;em&gt;npm run tsc-check&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Por último, lanzamos los tests de &lt;em&gt;e2e&lt;/em&gt; con &lt;em&gt;npm run ci:e2e&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ya está todo listo para que, cuando hagamos &lt;em&gt;commit&lt;/em&gt; y &lt;em&gt;push&lt;/em&gt; de este archivo, &lt;em&gt;Github Actions&lt;/em&gt; detecte que hay un nuevo &lt;em&gt;workflow&lt;/em&gt; y lo ejecute cuando se haga una &lt;em&gt;Pull Request&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A tener en cuenta: en el ejemplo de &lt;em&gt;MongoModeler&lt;/em&gt;, el flujo de &lt;em&gt;ci&lt;/em&gt; ejecuta dos &lt;em&gt;jobs&lt;/em&gt; uno para comprobar que todo está ok y lanzar las &lt;em&gt;pruebas unitarias&lt;/em&gt;, y otro para lanzar las &lt;em&gt;e2e&lt;/em&gt;, como queda el flujo total:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;./.github/workflows/ci.yml&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI workflow&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pull_request&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ci&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use Node.js 18.13.0&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;18.13.0'&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;npm'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install front&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run tsc-check&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Tests front&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;

  &lt;span class="na"&gt;e2e-tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use Node.js 18.13.0&lt;/span&gt;
       &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v2&lt;/span&gt;
        &lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;18.13.0'&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;npm'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run build&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check TypeScript Types&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run tsc-check&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run E2E tests&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run ci:e2e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Paso 4: Subiendo los cambios
&lt;/h2&gt;

&lt;p&gt;Ahora lo tenemos todo listo, Abrimos una &lt;em&gt;pull request&lt;/em&gt; y hacemos &lt;em&gt;commit&lt;/em&gt; y &lt;em&gt;push&lt;/em&gt;. Nos llevaríamos los cambios a la &lt;em&gt;rama main&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 5: Probando el proceso
&lt;/h2&gt;

&lt;p&gt;Cuando hacemos PR se lanza los &lt;em&gt;jobs&lt;/em&gt; que hemos definido anteriormente, vemos como pasan correctamente. Con lo cual le estamos dando robustez a nuestro proyecto. Además, podemos ver detalles de la ejecución del mismo e incluso el terminal de como va el proceso. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frybr6w46pmegrgnd06xa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frybr6w46pmegrgnd06xa.png" alt="imagen de la pr viendo como pasa los jobs" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pincha en datails.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jut5joowzqt3lhyo0ql.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jut5joowzqt3lhyo0ql.png" alt="Imagen terminal ejecutando los test" width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 6: Settings y forzar a que pasen para poder hacer merge
&lt;/h2&gt;

&lt;p&gt;Una funcionalidad interesante que nos ofrece &lt;em&gt;Github&lt;/em&gt; es que poder impedir que alguien haga &lt;em&gt;merge&lt;/em&gt; si no pasan los &lt;em&gt;e2e test&lt;/em&gt; (con la opción de añadir excepciones para por ejemplo perfiles &lt;em&gt;administradores&lt;/em&gt;). Para ello, entramos en nuestro portal de &lt;em&gt;Github&lt;/em&gt; y nos vamos a los &lt;em&gt;settings&lt;/em&gt; del &lt;em&gt;repositorio&lt;/em&gt; y elegimos del panel izquierdo &lt;em&gt;Rules / Rules Sets&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8q0lh9nt027zy80k66hp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8q0lh9nt027zy80k66hp.png" alt="Imagen de settings donde se ve Rules y Rulesets" width="532" height="559"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pincha en "New ruleset"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllo8jsrob2ntynnguaj0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fllo8jsrob2ntynnguaj0.png" alt="Imagen New ruleset" width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se nos abre un formulario, le damos un nombre a esa regla, le podemos llamar: pass-tests-before-merge y le decimos que la regla está activa.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcmfrliuz1duzo3czqemp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcmfrliuz1duzo3czqemp.png" alt="Imagen donde damos nombre a la regla y la ponemos activa" width="580" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Después tenemos la opción, por ejemplo un &lt;em&gt;admin&lt;/em&gt; se pueda saltar esa regla si queremos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubu7ri0epqns49kyfhnm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubu7ri0epqns49kyfhnm.png" alt="Imagen Bypass list, role de admin" width="800" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ojo con este bypass, sólo es útil para usuarios en concreto y casos puntuales justificados.&lt;/p&gt;

&lt;p&gt;Lo siguiente es elegir a qué ramas va a aplicar, en nuestro caso la rama default se llama &lt;code&gt;dev&lt;/code&gt; y la &lt;code&gt;main&lt;/code&gt; es la que va a producción, así que pedimos que se apliquen en esas dos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8q6r66fqo99lozyywre.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8q6r66fqo99lozyywre.png" alt="Imagen target branches seleccionando default y main" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Y en el apartado de Rules marcamos Require Status check to pass:&lt;br&gt;
Está bien marcar el primer check(Requires branches to up to data before merging), así nos aseguramos que la rama que tenemos tiene la última versión de dev o main.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9rjtrhgqn9yb593op6q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9rjtrhgqn9yb593op6q.png" alt="Imagen Rules marcando las casillas, Require Status check to pass y Requires branches to up to data before merging" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Y para los checks, pinchamos en &lt;code&gt;+ Add Checks&lt;/code&gt;  y buscamos el nombre del flujo de github que tenemos definido en nuestra carpeta de workflows (la que está bajo .github/workflows)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxwvasx786bqftw002k8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxwvasx786bqftw002k8.png" alt="Imagen add checks y añadiendo ci es el nombre de nuestro archivo" width="800" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahí vemos que sale vació, pero si tecleamos &lt;code&gt;ci&lt;/code&gt; (como se llama nuestro flujo), aparece y podemos seleccionarlo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgd57ccdkz3aqvtx7bwl3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgd57ccdkz3aqvtx7bwl3.png" alt="Imagen escribiendo ci en el buscador de add checks" width="476" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Se nos tiene que quedar algo así como:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94e26t86o8d0nb4xchml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94e26t86o8d0nb4xchml.png" alt="Imagen de como se queda todo marcado y ci añadido" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para finalizar pulsamos en el botón de create que hay al final del formulario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvjabu8gc4kf09nqxw1av.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvjabu8gc4kf09nqxw1av.png" alt="Imagen enseñando el boton create al final del formulario para finalizar" width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Repositorio de ejemplo
&lt;/h2&gt;

&lt;p&gt;Te dejo un enlace al proyecto de github con la configuración completa:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Lemoncode/mongo-modeler" rel="noopener noreferrer"&gt;Enlace al repositorio con el proyecto y su configuración completa&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión y siguientes pasos
&lt;/h2&gt;

&lt;p&gt;Ya tienes todo listo para que tus tests e2e con Playwright corran como parte de tu proceso de CI/CD en GitHub Actions. Esto es oro puro para asegurarte de que todo esté bajo control antes de llevar cambios a producción. Ideal para esas aplicaciones que van creciendo y donde cada bug que arreglas tiene el potencial de invitar a un par más a la fiesta 😉. Menos sorpresas, más confianza.&lt;/p&gt;

&lt;p&gt;En el próximo post de esta serie, daremos un paso más y aprenderemos cómo escribir tests e2e que interactúan directamente con APIs de servidor. ¡Prepárate para llevar tus pruebas al siguiente nivel! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Sobre mí
&lt;/h2&gt;

&lt;p&gt;Hola, me llamo Fran y soy desarrollador Front End + QA, si quieres conectar conmigo, te dejo aquí mi &lt;a href="https://www.linkedin.com/in/francisco-l%C3%B3pez-torres/" rel="noopener noreferrer"&gt;perfil de Linked in&lt;/a&gt;, ¡encantado de conectar! &lt;/p&gt;

</description>
      <category>e2e</category>
      <category>testing</category>
      <category>tutorial</category>
      <category>playwright</category>
    </item>
    <item>
      <title>Hola, Playwright (I) - Conceptos e2e y configuración inicial.</title>
      <dc:creator>Fran López</dc:creator>
      <pubDate>Wed, 30 Oct 2024 12:50:30 +0000</pubDate>
      <link>https://dev.to/franlopez/configuracion-de-playwright-pruebas-end-to-end-e2e-paso-a-paso-en-un-proyecto-de-front-end-58e2</link>
      <guid>https://dev.to/franlopez/configuracion-de-playwright-pruebas-end-to-end-e2e-paso-a-paso-en-un-proyecto-de-front-end-58e2</guid>
      <description>&lt;h2&gt;
  
  
  Introducción
&lt;/h2&gt;

&lt;p&gt;Si hablamos de &lt;code&gt;Unit Testing&lt;/code&gt; seguramente te resulte familiar, ... Es lo que vamos haciendo para generar piezas robustas de código, ... Eso sí, piezas por separado, &lt;em&gt;¿Qué pasa cuando las juntamos?&lt;/em&gt;... pues que pueden surgir problemas, aquí podemos seguir avanzando y hablar de pruebas de &lt;code&gt;integración&lt;/code&gt;, pero... &lt;em&gt;¿Y si pudiéramos ir un paso más allá?&lt;/em&gt; &lt;em&gt;¿Por qué no automatizar pruebas manuales con la aplicación real funcionando?&lt;/em&gt; Bienvenido al lado oscuro de QA 🤗.&lt;/p&gt;

&lt;p&gt;Las pruebas de extremo a extremo (E2E) nos permiten probar aplicaciones web en tiempo real de forma automática, simulando la interacción de un usuario con la aplicación, es decir, es como si una persona estuviera interactuando con la aplicación y comprobando visualmente que obtiene el resultado esperado.&lt;/p&gt;

&lt;p&gt;Lo potente de esta aproximación es que puedes lanzar las pruebas cuando quieras y sin tener un humano detrás para comprobar manualmente que todo ha salido como esperabas.&lt;/p&gt;

&lt;p&gt;Una herramienta muy potente para realizar este tipo de pruebas es PlayWright (Microsoft). En este post vamos a ver cómo podemos configurar PlayWright en nuestro proyecto de Front para crear y ejecutar pruebas E2E automatizadas.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR;
&lt;/h2&gt;

&lt;p&gt;PlayWright es una herramienta de automatización de pruebas de extremo a extremo que permite escribir pruebas en JavaScript, TypeScript y Python. Se basa en que tú interactúas mediante código con el navegador, como lo haría un usuario real (haciendo clic, escribiendo texto, etc.) y después podemos comprobar los resultados de la interacción leyendo el DOM.&lt;/p&gt;

&lt;p&gt;Playwright es una herramienta de pruebas de caja blanca. No conoce los detalles de tu código, esto nos permite probar cualquier aplicación web, independientemente de la tecnología que utilices.&lt;/p&gt;

&lt;p&gt;Para usar Playwright:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Necesitas instalarlo en tu proyecto.&lt;/li&gt;
&lt;li&gt;Configurarlo correctamente.&lt;/li&gt;
&lt;li&gt;Definir tus pruebas.&lt;/li&gt;
&lt;li&gt;Lanzarlas y esperar resultados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;¿Con ganas de entrar en detalle?&lt;/em&gt; Sigue leyendo...&lt;/p&gt;

&lt;h2&gt;
  
  
  Paso 1: Entendiendo PlayWright y e2e testing
&lt;/h2&gt;

&lt;p&gt;Cuando desarrollamos unit tests, estamos probando piezas separadas, o si me aprietas, podemos probar a hacer test de integración y probar un conjunto de ellas, pero... Esto no es suficiente, cuando desplegamos una aplicación, debemos de tener alguna garantía de que el usuario pueda completar flujos de principio a fin. Siempre puede haber fallos tontos que no sean fáciles de detectar con tests unitarios o de integración.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;¿Qué se hacía en muchos casos?&lt;/em&gt; Tener a testers manuales, es decir, personas que se hacían un guion con pasos e iban manualmente probando la aplicación, es decir:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Arrancas la aplicación en un entorno de QA (test), preproducción, o incluso producción (se puede plantear ejecutar tests de end to end en producción).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tienes un guion con unos pasos. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Prueba a hacer los pasos y vas anotando y comprobando que todo funciona como esperas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fow1chkxrab8t07fv8kmk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fow1chkxrab8t07fv8kmk.gif" alt="Pasos QA Manual, tester define pasos, los ejecuta de forma manual y comprueba los resultados" width="1614" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esto de primeras puede parecer algo asumible, pero a poco que tu proyecto avanza te encuentras que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;El proyecto crece y cada vez tiene más funcionalidad, y lo que es peor, introducir una nueva característica puede romper una anterior.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hacer un test manual de una característica puede ser viable la primera vez, pero cuando quieres salir a producción, lo suyo es, poder testearlo todo. Imagínate si la aplicación crece cuanto pueden tardar en ejecutar manualmente todos los tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Y si hablamos que tenemos que ser ágiles y poder desplegar a producción varias veces al día, no puedes estar esperando a que un tester manual pruebe todo.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;¿Y si pudiéramos pasar esos test manuales a código? Es decir, que un bot simulará que pinchas en un botón, que tecleas en un input y después comprobará que el resultado es el esperado. Un ejemplo simple: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Un bot pincha en el input de usuario y teclea el email de una cuenta.&lt;/li&gt;
&lt;li&gt;El mismo bot pincha en el input de contraseña y teclea la contraseña.&lt;/li&gt;
&lt;li&gt;Y ahora busca el botón de login y pincha en él.&lt;/li&gt;
&lt;li&gt;Por último, comprueba que ha entrado en la aplicación y que el usuario está logueado (ha navegado a la página principal y en la cabecera de arriba a la derecha aparece el nombre del usuario).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esto es lo que se conoce como &lt;strong&gt;End to End Testing&lt;/strong&gt; o &lt;strong&gt;e2e Testing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F08ivn8lcd4ugsk1hch2w.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F08ivn8lcd4ugsk1hch2w.gif" alt="Test automático, la principal diferencia está en que pasamos la checklist a código y un bot puede lanzar los test y realizar las comprobaciones de forma desatendida" width="480" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La primera vez, crear ese script automático nos va a costar más que ejecutar un test de forma manual, pero a la larga, nos va a permitir:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Poder ejecutar esos tests de forma automática.&lt;/li&gt;
&lt;li&gt;Poder ejecutar esos tests de forma automática en cualquier entorno (QA, preproducción, producción), así como en diferentes navegadores.&lt;/li&gt;
&lt;li&gt;Poder ejecutar esos tests de forma automática en cualquier momento.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Paso 2: Instalando la herramienta
&lt;/h2&gt;

&lt;p&gt;Como hemos comentado vamos a utilizar PlayWright para definir y lanzar pruebas e2e, es decir vamos a realizar pruebas en modo "caja negra": yo no sé en qué lenguaje o que detalles de implementación tiene tu solución, lo que voy a hacer es interactuar en el navegador con tu aplicación y comprobar que todo funciona correctamente &lt;em&gt;¿Cómo?&lt;/em&gt; Como si fuera un usuario real, es decir, voy a hacer clic en botones, rellenar formularios, comprobar que se muestran los datos esperados, etc.&lt;/p&gt;

&lt;p&gt;Así que, &lt;em&gt;¿Cómo se instala PlayWright?&lt;/em&gt; Aquí viene la parte buena: la instalación de Playwright es sencilla y se realiza a través de npm o yarn, como cualquier otro proyecto Node.js. Así, evitamos instalaciones complejas con múltiples pasos y asistentes. Tienes dos opciones para organizar el proyecto de pruebas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crear el proyecto de E2E dentro del repositorio principal de frontend
Puedes crear una subcarpeta dentro de tu proyecto frontend para centralizar las pruebas E2E. Una estructura típica sería:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  /proyecto
    /frontend
      /e2e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Crear un proyecto de pruebas como repositorio independiente (algo común en equipos de QA especializados), pero en este caso tendrías que tener en cuenta que tendrías que tener una forma de comunicar el proyecto de e2e con el proyecto de front end, es importante considerar cómo se comunicará con el proyecto frontend. Una práctica recomendada es utilizar una variable de entorno o un archivo de configuración que permita enlazar ambos proyectos de manera sencilla, o bien que el equipo de QA trabaje directamente sobre una versión desplegada en un entorno concreto, al que normalmente se le llama entorno de QA o entorno de testing. Esto último facilita que las pruebas se ejecuten sobre una versión estable de la aplicación sin interferir con el desarrollo en curso.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nos ponemos manos a la obra, ya tenemos nuestra carpeta vacía esperando a que inicialicemos nuestro proyecto de pruebas. Para ello, abrimos un terminal y ejecutamos el siguiente comando desde la terminal de bash o ms-dos:&lt;/p&gt;

&lt;p&gt;Si somos de npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init playwright@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si somos de yarn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn create playwright
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto va a realizar una serie de pasos por nosotros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configura el proyecto de Playwright:&lt;/strong&gt; Crea una estructura básica de archivos para las pruebas, con carpetas y archivos de ejemplo que te ayudarán a comenzar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Descarga automáticamente los navegadores:&lt;/strong&gt; Al ejecutar el comando, &lt;em&gt;Playwright&lt;/em&gt; también descarga versiones específicas de los navegadores (&lt;em&gt;Chromium, Firefox y WebKit&lt;/em&gt;) que necesita para ejecutar las pruebas. Esto asegura que las pruebas se realicen de manera consistente en los entornos adecuados.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Incluye archivos de configuración:&lt;/strong&gt; Crea archivos de configuración iniciales (&lt;em&gt;playwright.config.js&lt;/em&gt;) para personalizar y ejecutar las pruebas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cuando le damos a enter, la herramienta nos hará una serie de preguntas:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;√ Where to put your end-to-end tests? · e2e&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;¿ En que carpeta vamos a crear tus tests?&lt;/em&gt; Lo normal es poner &lt;em&gt;e2e&lt;/em&gt; o &lt;em&gt;tests&lt;/em&gt;, pero puedes poner el nombre que quieras.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmd2ah2zihd67gucdk30x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmd2ah2zihd67gucdk30x.png" alt="Captura de la terminal con la primera pregunta ya citada anteriormente" width="800" height="66"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add a GitHub Actions workflow? (y/N) · false&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Uno de los puntos fuertes del e2e testing automático es que puedes incluirlo en tu ciclo de CI/CD (integración continua y despliegue continuo). &lt;em&gt;¿Esto qué es?&lt;/em&gt; Pues, que por ejemplo, cuando vayas a subir código a tu repositorio o quieras mezclar a tu rama principal.&lt;br&gt;
Automáticamente, se ejecuta la batería de pruebas e2e y, si todo está correcto, se permite mezclar la rama o subir a producción.&lt;/p&gt;

&lt;p&gt;En este paso de creación vamos a decirle que no. En otro post de esta serie os comentaremos cómo configurarlo de forma manual y así poder tener un control más fino.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98zt3yopes9dtp7isrgu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F98zt3yopes9dtp7isrgu.png" alt="Captura de la terminal con la siguiente pregunta" width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;√ Install Playwright browsers (can be done manually via 'npx playwright install')? (Y/n)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Por último, nos pregunta si queremos instalar los navegadores necesarios para ejecutar las pruebas. Es recomendable aceptar (opción "Y") en este momento, ya que, si decidimos no instalarlos ahora, tendremos que hacerlo manualmente más adelante usando el comando npx playwright install.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0gonc6fbfn6ijiivg9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0gonc6fbfn6ijiivg9o.png" alt="Captura de la terminal con todas las preguntas" width="800" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;¿Y por qué tengo que instalar navegadores si ya los tengo en mi máquina?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Playwright&lt;/em&gt; instala versiones específicas de cada navegador (&lt;em&gt;Chromium, Firefox, y WebKit&lt;/em&gt;) que han sido verificadas para funcionar de manera consistente con su entorno de pruebas. Esto asegura que las pruebas sean estables y predecibles, independientemente de las versiones que tengas instaladas localmente o de las actualizaciones que reciban esos navegadores en el futuro, además estas versiones personalizadas de los navegadores permiten evitar posibles inconsistencias entre máquinas de desarrollo o en entornos CI/CD, asegurando que las pruebas se comporten igual en cualquier entorno en el que se ejecuten.&lt;/p&gt;

&lt;p&gt;Una vez ejecutado este wizard, nos ha tenido que quedar una estructura de carpetas parecida a lo siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  /Mongo-Modeler
    /e2e
    /src
    /playwright.config.js
    /package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  paso 3: Configurando PlayWright
&lt;/h2&gt;

&lt;p&gt;Ya tenemos nuestro proyecto e2e inicializado y PlayWright, nos queda:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configurarlo para que sepa contra qué sitio web van a correr las pruebas.&lt;/li&gt;
&lt;li&gt;Definir una prueba e2e.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ahora toca configurarlo para poder ejecutar las pruebas de nuestro proyecto.&lt;/p&gt;

&lt;p&gt;Vamos a realizarlo sobre el proyecto Open Source Mongo Modeler.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqva31ttavqhjrblistet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqva31ttavqhjrblistet.png" alt="Imagen del proyecto Open Source Mongo Modeler con algunas tablas" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En este caso, hemos decidido ejecutar los e2e test directamente desde el entorno de desarrollo, por lo que tenemos que indicarle a playwright:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cómo levantar ese servidor de desarrollo (en el caso de Mongo Modeler se arranca con el comando &lt;code&gt;npm run dev&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Contra que URL va a correr las pruebas (en el caso de Mongo Modeler la aplicación corre en local en &lt;code&gt;localhost:5173&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Está opción es buena para poder probar los e2e tests en local, e incluirlo en tu ciclo de integración continua, también hay equipos de QA que prefieren tenerlo todo en un entorno de servidor y simular que estamos tirando contra entorno real. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;playwright.config.ts&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+ const BASE_URL = 'http://localhost:5173/';
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  export default defineConfig({
    testDir: './E2E',
    fullyParallel: true,
    forbidOnly: !!process.env.CI,
    retries: process.env.CI ? 2 : 0,
    workers: process.env.CI ? 1 : undefined,
    reporter: 'html',
    use: {
   /* Base URL to use in actions like `await page.goto('/')`. */
&lt;span class="gi"&gt;+     baseURL: BASE_URL,
&lt;/span&gt;      trace: 'on-first-retry',
    },
  webServer: {
&lt;span class="gi"&gt;+   command: 'npm run dev',
+   url: BASE_URL,
&lt;/span&gt;&lt;span class="gd"&gt;-   url: 'http://127.0.0.1:3000',
&lt;/span&gt;    reuseExistingServer: !process.env.CI,
   },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y ahora en el &lt;code&gt;package.json&lt;/code&gt; añadimos el comando para ejecutar los tests e2e:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;  "scripts": {
    "dev": "vite",
    "build": "tsc &amp;amp;&amp;amp; vite build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives
 --max-warnings 0",
    "preview": "vite preview",
    "format": "prettier --write .",
    "test": "vitest",
    "prepare": "husky || \"No need to install husky\"",
    "tsc-check": "tsc --noEmit",
&lt;span class="gi"&gt;+    "e2e": "playwright test --ui"
&lt;/span&gt;  },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Aquí le indicamos que levante playwright y que use la interfaz de usuario, en artículos siguientes veremos otra opción para ejecutar los tests sin interfaz de usuario, esto es muy útil cuando queremos integrarlo en un entorno de integración continua, o si queremos añadirlo como un paso previo a un commit o push.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ya estamos listos para crear nuestro primer test e2e y ejecutarlo, vamos a por el siguiente paso.&lt;/p&gt;

&lt;h2&gt;
  
  
  paso 4: Creo mi primer test e2e
&lt;/h2&gt;

&lt;p&gt;Si lanzamos ahora los tests e2e, fallarían, porque no hay ningún test definido, vamos a crear uno simple.&lt;/p&gt;

&lt;p&gt;Cuando arrancamos la aplicación, se muestra una ventana de landing en la que hay un botón que dice "Launch MongoDB Designer", cuando pulsamos ese botón, nos redirige a la página que contiene el editor.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;¿Qué vamos a probar?&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navegamos a la raíz del proyecto.&lt;/li&gt;
&lt;li&gt;Pulsamos en el botón "Launch MongoDB Designer".&lt;/li&gt;
&lt;li&gt;Comprobamos que, en efecto, navega a la ruta "/editor.html".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esta sería la página de landing&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl0qsb9syvnjtpv7wgi6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl0qsb9syvnjtpv7wgi6x.png" alt="Pantalla de inicio del proyecto Mongo Modeler" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esta sería la página del editor&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv192bgw6m3wnm859av3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv192bgw6m3wnm859av3i.png" alt="Se ve el editor de nuestro proyecto Mongo Modeler" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El comportamiento esperado:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpmx3e8ww4ss5302ka2e1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpmx3e8ww4ss5302ka2e1.gif" alt="animacion de la dos fotos anteriores, representando comportamiento" width="1050" height="824"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para definir este caso:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debajo de la carpeta &lt;code&gt;e2e&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Creamos el fichero &lt;code&gt;launch-mongodb-designer-link.spec.ts&lt;/code&gt; (&lt;code&gt;spec&lt;/code&gt; viene de &lt;code&gt;specification&lt;/code&gt;, también podremos usar &lt;code&gt;test&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ya que tenemos el fichero, le añadimos el siguiente contenido&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;./e2e/launch-mongodb-designer-link.spec.ts&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@playwright/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;navigates to and verifies MongoDB Designer URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;goto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Launch MongoDB Designer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:5173/editor.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;¿Qué estamos haciendo aquí?&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Definimos un test y le indicamos con una descripción en texto que cubre.&lt;/li&gt;
&lt;li&gt;Indicamos que es un test asíncrono (tenemos que esperar a que se resuelvan acciones).&lt;/li&gt;
&lt;li&gt;Le indicamos que vaya a la raíz de la aplicación.&lt;/li&gt;
&lt;li&gt;Buscamos el enlace que tiene el texto "Launch MongoDB Designer" y hacemos clic (se puede buscar un elemento por muchos criterios, en este caso lo hacemos por el rol y el nombre, también se pueden buscar por id, ...).&lt;/li&gt;
&lt;li&gt;Una vez encontrado ese botón, simulamos un clic del usuario.&lt;/li&gt;
&lt;li&gt;Una vez que se ha hecho clic, comprobamos que la navegación se ha realizado, y que en el navegador está en la URL esperada.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ya que tenemos el test, solo tenemos que ejecutar desde la línea de comandos &lt;code&gt;npm run e2e&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run e2e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al lanzar esto desde el terminal, podemos ver que se abre la UI de playwright.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3d4nhzr3e5zcqxq7amlc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3d4nhzr3e5zcqxq7amlc.png" alt="UI de playwright para e2e test" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora podemos darle al botón play o la tecla F5 del teclado y lanza todos los test. Como podemos ver tiene el Check de éxito.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uor6syrsk9uunqdzitq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uor6syrsk9uunqdzitq.png" alt="Ui de playwright para e2e test check de éxito" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En este caso &lt;code&gt;MongoModeler&lt;/code&gt; es una aplicación pura de Front, &lt;em&gt;¿Qué pasaría si tuviera que interactuar con una API Rest o similar?&lt;/em&gt; Aquí tengo varias estrategias:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Puedo definir mocks para respuestas específicas de la API.&lt;/li&gt;
&lt;li&gt;Puedo definir un servidor de Mock que tenga los mismos contratos que la API real.&lt;/li&gt;
&lt;li&gt;También puedo tirar contra entorno real o QA&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Todo esto lo veremos en los siguientes posts de esta serie.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repositorio de ejemplo
&lt;/h2&gt;

&lt;p&gt;Te dejo un enlace al proyecto de github con la configuración completa:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Lemoncode/mongo-modeler" rel="noopener noreferrer"&gt;Enlace al repositorio con el proyecto y su configuración completa&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión y siguientes pasos
&lt;/h2&gt;

&lt;p&gt;Al arrancar un proyecto, todo puede parecer muy sencillo, desarrollas un par de ventanas, tienes tus pruebas unitarias, manualmente haces un par de comprobaciones y ya estamos listos, pero a poco que el proyecto crece, estos checks van tomando más tiempos y lo que es peor, metiendo un cambio puedes romper accidentalmente otras cosas.&lt;/p&gt;

&lt;p&gt;Es por eso que es importante contar con pruebas automatizadas, y en este caso, con pruebas E2E. Con Playwright, puedes automatizar estas pruebas de extremo a extremo de manera sencilla y eficiente, y asegurarte de que tu aplicación funcione correctamente en cada actualización.&lt;/p&gt;

&lt;p&gt;En el siguiente post de esta serie vamos a ver cómo integrar Playwright en un proceso de CI/CD pudiendo lanzar estas pruebas cada vez que vayas a levantar una Pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sobre mí
&lt;/h2&gt;

&lt;p&gt;Hola, me llamo Fran y  soy desarrollador Front End + QA, si quieres conectar conmigo, te dejo aquí mi &lt;a href="https://www.linkedin.com/in/francisco-l%C3%B3pez-torres/" rel="noopener noreferrer"&gt;perfil de Linked in&lt;/a&gt;, ¡encantado de conectar!&lt;/p&gt;

</description>
      <category>e2e</category>
      <category>testing</category>
      <category>tutorial</category>
      <category>playwright</category>
    </item>
    <item>
      <title>Configuración de Husky, lint-staged y Prettier para formatear en precommit.</title>
      <dc:creator>Fran López</dc:creator>
      <pubDate>Fri, 12 Jul 2024 09:56:48 +0000</pubDate>
      <link>https://dev.to/franlopez/configuracion-de-husky-lint-staged-y-prettier-para-fromatear-en-precommit-ilj</link>
      <guid>https://dev.to/franlopez/configuracion-de-husky-lint-staged-y-prettier-para-fromatear-en-precommit-ilj</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcxv97ao02o2tbcrz8mi7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcxv97ao02o2tbcrz8mi7.gif" alt="El GIF muestra un flujo de trabajo automatizado usando Husky, lint-staged y GitHub. Primero, un desarrollador está trabajando en su computadora portátil. Luego, aparece el logotipo de Husky, indicando el uso de Husky para gestionar git hooks. Finalmente, se muestra el logotipo de GitHub, sugiriendo que los cambios se suben al repositorio de GitHub. Esto ilustra cómo Husky puede automatizar tareas para asegurar que el código esté correctamente formateado antes de ser commitido." width="1506" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducción
&lt;/h2&gt;

&lt;p&gt;¿Alguna vez has experimentado que, a pesar de haber acordado usar Prettier en tu equipo, un nuevo integrante no tiene el plugin instalado y sube código sin formatear correctamente?&lt;/p&gt;

&lt;p&gt;¿Existe alguna forma de asegurarnos de que cualquier código que subimos a nuestro repositorio de Git cumpla con ciertos estándares mínimos?&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR;
&lt;/h2&gt;

&lt;p&gt;Para configurar Husky, lint-staged y Prettier para formatear el código en pre-commit.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Instala las herramientas necesarias:&lt;/strong&gt; Instala Husky para manejar los hooks de Git, lint-staged para procesar solo los archivos modificados, y Prettier para el formateo del código.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configura Husky:&lt;/strong&gt; Inicializa Husky en tu proyecto y agrega un hook de pre-commit que ejecute lint-staged. Esto asegura que ciertos comandos se ejecuten automáticamente antes de cada commit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configura lint-staged:&lt;/strong&gt; Especifica en lint-staged que Prettier debe ejecutarse en los archivos que coincidan con las extensiones de tu proyecto. Esto asegura que solo los archivos modificados y añadidos al área de staging sean procesados por Prettier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configura Prettier:&lt;/strong&gt; Define las reglas de formateo que deseas usar en tu proyecto mediante un archivo de configuración de Prettier.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;¿Quieres saber más en detalle? Sigue leyendo...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Husky se basa en los git hooks, scripts que se ejecutan antes o después de determinados comandos de Git.&lt;br&gt;
Por ejemplo, cuando hacemos un commit, podemos tener el hook pre-commit que se ejecutará antes de realizar el commit. De esta manera, podemos configurar Husky para que ejecute herramientas como Prettier, incluso una batería de tests. Si todo va bien, el commit se realizará; de lo contrario, se producirá un error y el commit no se llevará a cabo. Esto nos asegura que el código en el repositorio esté siempre formateado según las reglas establecidas por Prettier.&lt;/p&gt;

&lt;p&gt;Sin embargo, ejecutar estas herramientas en todos los archivos del proyecto cada vez que hacemos un commit podría ser ineficiente, especialmente en proyectos grandes, ya que demoraría el proceso. Aquí es donde entra en juego lint-staged. Con lint-staged, solo se procesan los archivos que han sido modificados y añadidos al staging del repositorio. Esto reduce significativamente el número de archivos que necesitan ser revisados, haciendo que el proceso sea más rápido y eficiente.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Paso 1: Instalación de dependencias
&lt;/h2&gt;

&lt;p&gt;Asegúrate de que tienes &lt;strong&gt;&lt;code&gt;Node.js&lt;/code&gt;&lt;/strong&gt; y &lt;strong&gt;&lt;code&gt;npm&lt;/code&gt;&lt;/strong&gt; (o &lt;strong&gt;&lt;code&gt;yarn&lt;/code&gt;&lt;/strong&gt;) instalados en tu proyecto. A continuación, instala Husky, lint-staged y prettier,  mediante npm o yarn.&lt;/p&gt;

&lt;p&gt;Teclea esto en la terminal de &lt;strong&gt;bash&lt;/strong&gt; o &lt;strong&gt;ms-dos&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;npm:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;husky prettier lint-staged &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;yarn:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add husky prettier lint-staged &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  paso 2: Configurar .prettierrc .prettierignore
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Crea un archivo &lt;strong&gt;&lt;code&gt;.prettierrc.json&lt;/code&gt;&lt;/strong&gt; en la raíz de tu proyecto y añade tus reglas.&lt;/li&gt;
&lt;li&gt;Ejemplo:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;.prettierrc.json&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+ {
+   "printWidth": 80,
+   "singleQuote": true,
+   "useTabs": false,
+   "tabWidth": 2,
+   "semi": true,
+   "bracketSpacing": true,
+   "trailingComma": "es5",
+   "arrowParens": "avoid",
+   "endOfLine": "lf"
+ }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Crea otro archivo &lt;strong&gt;&lt;code&gt;.prettierignore&lt;/code&gt;&lt;/strong&gt; en la raíz de tu proyecto. Es para que prettier no mire en esos ficheros.

&lt;ul&gt;
&lt;li&gt;Ejemplo:&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;.prettierignore&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+ {
+   node_modules
+   dist
+ }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Paso 3: Configurar husky y el pre-commit
&lt;/h2&gt;

&lt;p&gt;Añade un hook pre-commit que se ejecutará antes de cada commit. Para pasar prettier y formatear el código.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El comando init simplifica la configuración de husky en un proyecto. Crea un script pre-commit en &lt;strong&gt;&lt;code&gt;.husky/&lt;/code&gt;&lt;/strong&gt; y actualiza el script prepare en &lt;strong&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/strong&gt;. Las modificaciones se pueden hacer más tarde para adaptarse a su flujo de trabajo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Teclea esto en la terminal de &lt;strong&gt;bash&lt;/strong&gt; o &lt;strong&gt;ms-dos&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; npx husky init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Añade una configuración para lint-staged en &lt;strong&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/strong&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+ "lint-staged": {
+    "*.{ts,tsx}": [
+      "prettier --write"
+    ],
+    "*.css": [
+      "prettier --write"
+    ]
+  }
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;En la raíz tenemos la carpeta &lt;strong&gt;&lt;code&gt;.husky&lt;/code&gt;&lt;/strong&gt;, dentro de ella un fichero llamado &lt;strong&gt;&lt;code&gt;pre-commit&lt;/code&gt;&lt;/strong&gt;, añadimos lo siguiente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;code&gt;./.husky/pre-commit&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+ #!/usr/bin/env sh
+ . "$(dirname -- "$0")/_/husky.sh"
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;- npm test
&lt;/span&gt;&lt;span class="gi"&gt;+ npx lint-staged
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  paso 4: Prueba la configuración
&lt;/h2&gt;

&lt;p&gt;Introduce cambios en un archivo .ts,tsx o css (mal formateados) y podrá ver como se lanza el precommit formatea automáticamente los ficheros.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repositorio de ejemplo
&lt;/h2&gt;

&lt;p&gt;Te dejo un enlace a un proyecto de github vacío con la configuración completada:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Franlop7/husky-configured/tree/main" rel="noopener noreferrer"&gt;Enlace al repositorio con el proyecto vacío con la configuración completada&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Cuando trabajas en equipo (incluso tú solo), es muy importante tener una base de código que sea homogénea y garantizar que cumpla unos mínimos, si no hay mucho riesgo de que el proyecto se te vaya de madre y no tengas manera de controlarlo.&lt;br&gt;
Husky te permite integrar ganchos de git de una manera muy sencilla, en nuestro caso con lint-staged lo hemos configurado de forma que formatee automáticamente los archivos que se van a subir al repositorio, y con prettier nos aseguramos de que el código cumpla con un estándar de formateo consistente, ya te puedes olvidar de ir persiguiendo a tus compañeros para que instalen el plugin y lo configuren correctamente.&lt;br&gt;
Si te animas, puedes añadir más herramientas a tu flujo de trabajo, como ESLint para detectar errores y problemas de estilo en tu código, o Jest para ejecutar pruebas unitarias. ¿Hasta dónde llegar? Aquí depende del equipo con el que estés trabajando y las necesidades que tengas. Si nunca has usado estas herramientas, te recomiendo que empieces poco a poco, y que tu equipo vaya madurando.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sobre mí
&lt;/h2&gt;

&lt;p&gt;Hola, me llamo Fran y  soy desarrollador Front End + QA, si quieres conectar conmigo, te dejo aquí mi &lt;a href="https://www.linkedin.com/in/francisco-l%C3%B3pez-torres/" rel="noopener noreferrer"&gt;perfil de Linked in&lt;/a&gt;, ¡encantado de conectar!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>spanish</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
