Skip to content

Commit

Permalink
Enhanced e2e
Browse files Browse the repository at this point in the history
  • Loading branch information
fdodino committed Dec 11, 2024
1 parent fcb60a3 commit baf1840
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 18 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ y podría tomar más responsabilidades. Además, en este caso no tenemos control
Una vez que tenemos la lista de países, los mostramos en una grilla:

```svelte
{#each paises as pais, indice}
{#each paises as pais}
<button
class='pais'
data-testid={`pais-${indice}`}
data-testid={`pais-${pais.codigo}`}
onclick={() => goto(`/pais/${pais.codigo}`)}
>
<Bandera bandera={pais.bandera}/>
Expand All @@ -94,7 +94,7 @@ Una vez que tenemos la lista de países, los mostramos en una grilla:

El lector podrá pensar, ¿por qué un button y no un div? Esto tiene que ver con recomendaciones de usabilidad que Svelte aplica, por lo que si usamos un div te va a aparecer un molesto warning:

![warning por usar un div clickeable](./images/warningDiv.png)
![warning por usar un div clickeable](./images/warningDivNuevo.png)

Para más información podés ver [este artículo](https://svelte.dev/docs/svelte/compiler-warnings).

Expand Down Expand Up @@ -210,6 +210,8 @@ test('flujo principal: buscamos un país y al hacer click nos dirige a la págin

Sí podrán notar que todas las operaciones son asincrónicas, y requieren envolverse dentro de un `await`. Eso permite que esperemos un tiempo prudencial (5 segundos) hasta que el elemento que buscamos aparezca en el DOM. Seguimos prefiriendo la búsqueda por `data-testid`, o por `role` más que por clases css o texto.

> Otra cosa buena es que podemos abstraer flujos, como ir a la página de un país y volver al menú principal. Lo que sí debemos tener en cuenta es que necesitamos pasar la `page` como parámetro porque es el objeto donde se conserva el estado actual de nuestros tests e2e.
### Qué pasa cuando fallan los tests

Por suerte Playwright, al igual que otras tecnologías como Cypress, Selenium o TestCafé, ofrecen buenos mecanismos de análisis de errores:
Expand All @@ -218,7 +220,7 @@ Por suerte Playwright, al igual que otras tecnologías como Cypress, Selenium o

## Debouncing

Vamos a agregar un último feature, queremos permitir la búsqueda automática, a medida que escribimos. Pero la API tiene una limitación de 10 requests por minuto. Entonces no podemos capturar el evento onKeyDown ni onKeyUp. Lo que necesitamos es tomarnos un tiempo prudencial hasta enviar la consulta, concepto que se llama **debouncing** y que podemos ver con un ejemplo visual.
Vamos a agregar un último feature, queremos permitir la búsqueda automática, a medida que escribimos. Pero la API tiene una limitación de 10 requests por minuto. Entonces no podemos capturar el evento onKeyDown ni onKeyUp. Lo que necesitamos es tomarnos un tiempo para enviar la consulta, concepto que se llama **debouncing** y que podemos ver con un ejemplo visual.

![debouncing](./images/forms-debounce.gif)

Expand Down
33 changes: 23 additions & 10 deletions e2e/paises.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
import { expect, test } from '@playwright/test'
import { expect, Page, test } from '@playwright/test'

test('flujo principal: buscamos un país y al hacer click nos dirige a la página con la información de dicho país', async ({
page
}) => {
async function irAPaisYVolver(page: Page, codigoPais: string, nombrePais: string) {
const unPais = await page.getByTestId(`pais-${codigoPais}`)
await expect(unPais).toBeVisible()
unPais.click()
await expect(page).toHaveURL(`/pais/${codigoPais}`)
await expect(page.locator('h2')).toHaveText(nombrePais)
// podríamos eventualmente testear otros atributos
await page.getByTestId('volver').click()
await expect(page).toHaveURL('/')
await expect(page.getByTestId('paisBusqueda')).toHaveText('')
}

await page.goto('/')
await expect(page.locator('h2')).toBeVisible()

// Probamos la búsqueda disparada por el botón
await page.getByTestId('paisBusqueda').fill('ARGENTINA')
await page.getByTestId('buscar').click()
const unPais = await page.getByTestId('pais-0')
await expect(unPais).toBeVisible()
unPais.click()
await expect(page).toHaveURL('/pais/ARG')
await expect(page.locator('h2')).toHaveText('Argentina')
// podríamos eventualmente testear otros atributos
await page.getByTestId('volver').click()
await expect(page).toHaveURL('/')
await expect(page.getByTestId('paisBusqueda')).toHaveText('')
await irAPaisYVolver(page, 'ARG', 'Argentina')

// Probamos la búsqueda automática desde el input
await page.getByTestId('busquedaAutomatica').check()
await page.getByTestId('paisBusqueda').fill('ARGEN')
// necesitamos disparar el evento keyup
await page.keyboard.up('T')
await irAPaisYVolver(page, 'ARG', 'Argentina')
})
Binary file removed images/warningDiv.png
Binary file not shown.
Binary file added images/warningDivNuevo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@
{/if}
</div>
<div class='check'>
<input class='checkbox' type="checkbox" name="Buscar" id="buscar" bind:checked={busquedaAutomatica}>
<label for="buscar">Buscar automáticamente</label>
<input class='checkbox' type="checkbox" name="busquedaAutomatica" data-testid="busquedaAutomatica" bind:checked={busquedaAutomatica}>
<label for="busquedaAutomatica">Buscar automáticamente</label>
</div>
<div class='paises'>
{#each paises as pais, indice}
{#each paises as pais}
<button
class='pais'
data-testid={`pais-${indice}`}
data-testid={`pais-${pais.codigo}`}
onclick={() => goto(`/pais/${pais.codigo}`)}
>
<Bandera bandera={pais.bandera}/>
Expand Down

0 comments on commit baf1840

Please sign in to comment.