⭐ 0/8
1 / 35
← → navegar · N notas presentador · F pantalla completa
🎙 Notas del presentador
Clase especial · QA Engineering

Coding Base

Fundamentos de programación para QA Testers.
De tester manual a Quality Engineer, un concepto a la vez.

JavaScriptTypeScriptPlaywright8 quizzes ⭐playgrounds en vivo 🎮

Bienvenida. Encuadre: hoy NO vamos a automatizar — hoy construimos las bases para que la próxima sesión escribamos scripts reales con Playwright. Menciona que hay quizzes con puntaje (esquina superior derecha) y zonas interactivas donde ellos participan. Pide que nadie se quede con dudas: el objetivo es entender CADA palabra del código.

Spoiler

Ya sabes programar. Solo que en papel.

Test case manualScript automatizado
Pasos numerados (1, 2, 3…)Líneas de código (se ejecutan en orden)
Datos de prueba ("usuario: ana@qa.com")Variables (const email = "ana@qa.com")
Resultado esperadoexpect(...) — la aserción
PrecondicionesSetup / hooks
Lo ejecuta un humano 🧍Lo ejecuta la máquina 🤖 (miles de veces, sin café)
💡

Un script es un test case que la máquina ejecuta por ti. Hoy solo aprendemos el idioma para escribirlo.

Mensaje anti-miedo: ellos YA piensan como programadores cuando escriben un test case — pasos ordenados, datos, resultado esperado. Programar es traducir eso a un idioma que la máquina entiende. Pregunta a la audiencia: "¿qué pasa si el paso 3 de tu test case es ambiguo?" — igual en código, la máquina necesita instrucciones exactas.

El plan

Una sola idea: zoom-out infinito 🔍

Empezamos en un dato diminuto y alejamos la cámara slide a slide hasta ver un repositorio completo.

⚛️

Acto 1 · Átomos

Valores, tipos, variables, operadores.

🧠

Acto 2 · Lógica

Funciones, decisiones, loops, datos.

🛡️

Acto 3 · TypeScript + async

Tipos que te protegen. Esperas elegantes.

🎭

Acto 4 · Tu primer test

Anatomía Playwright + playground en vivo.

🛰️

Acto 5 · Vista satelital

El repo completo. Ejecutar y leer resultados.

Reglas del juego

8 quizzes. Tu puntaje vive arriba a la derecha. Los playgrounds se tocan.

Explica la mecánica del zoom: el mismo código va a crecer frente a ellos — primero un valor, luego una variable, luego una función… hasta un repo. Nada aparece de la nada. Anuncia los quizzes: uno por concepto, puntaje acumulado, sin castigo por equivocarse. Duración estimada: 90-120 min con pausas.

valorvariablefunciónlógicaarchivorepo
Zoom nivel 1

Todo empieza con un dato

"Ana"

Esto es un valor: la pieza más pequeña de información que un programa puede manejar. Las comillas dicen "esto es texto". Sin contexto, sin nombre, sin lógica. Un átomo.

Slide minimalista a propósito: UNA idea. Un valor es un dato suelto. Compáralo con una celda suelta de su tabla de test data. Pregunta retórica: "¿de qué sirve un dato sin nombre?" — eso conecta con la siguiente slide (variables).

valorvariablefunciónlógicaarchivorepo

Los valores tienen tipos

📝

string

"Ana"
"ana@qa.com"
"Login exitoso"

Texto. Siempre entre comillas.

🔢

number

25
3.14
404

Números. Sin comillas. 404"404"

🚦

boolean

true
false

Verdadero o falso. El tipo favorito de QA: ¿pasó o falló?

🧪

Analogía QA: los campos de un formulario. Nombre = string, edad = number, "acepto términos" = boolean.

Tres tipos primitivos bastan para el 90% de los tests. Enfatiza la trampa de 404 vs "404": un status code numérico y un texto que parece número NO son lo mismo — esto vuelve en el quiz de operadores. Boolean es EL tipo de QA: toda aserción termina en true/false.

valorvariablefunciónlógicaarchivorepo

Variables: cajas con etiqueta 📦

const nombre = "Ana";
const edad = 25;
let intentos = 0;

const/let  → "voy a crear una caja"
nombre     → la etiqueta de la caja
=          → "guarda esto adentro"
"Ana"     → el valor guardado

🔒 const

Caja sellada. El valor no se puede reemplazar. Tu opción por defecto.

🔓 let

Caja reutilizable. El valor puede cambiar (contadores, reintentos).

🧪 En testing

const email = "ana@qa.com"
Tus datos de prueba con nombre propio.

El desglose palabra por palabra es la clave de esta slide — léelo despacio. Regla práctica: usa const siempre; let solo cuando NECESITES cambiar el valor (la herramienta te avisará). En el playground siguiente van a romper un const a propósito para ver el error.

🎮 Playground en vivo

Tócalo. Rómpelo. Arréglalo.

variables.js — editable
▶ Presiona Ejecutar para ver la salida…

Primer momento interactivo: pide a alguien de la audiencia que dicte un cambio. Ejecuta el reto 2 — reasignar un const lanza "Assignment to constant variable" y ES BUENO: el lenguaje los protege. console.log = "muéstrame esto en la consola"; es la linterna del programador. Dedica 3-4 minutos.

⭐ QUIZ 1 · Variables y tipos

¿Cuál de estas líneas lanza un ERROR?

💡 const crea una caja sellada: reasignarla lanza TypeError: Assignment to constant variable. let sí permite cambiar el valor.

Primer quiz — establece el ritmo: leen, alguien vota en voz alta, click. Si aciertan a la primera suma punto. Refuerza: el error de const no es un bug tuyo, es el lenguaje protegiéndote de cambios accidentales.

valorvariablefunciónlógicaarchivorepo

Operadores: hacer y comparar

➕ Matemáticos

5 + 3      // 8
10 - 4     // 6
"QA" + "!" // "QA!"

Con strings, + une texto.

⚖️ Comparación

5 === 5    // true
5 !== 3    // true
10 > 7     // true

Siempre devuelven boolean.

🔗 Lógicos

a && b  // Y: ambas
a || b  // O: alguna
!a      // NO: invierte

Combinan condiciones.

⚠️

La trampa #1: = asigna (guarda en la caja) · === compara (¿son iguales?). Confundirlos es el bug clásico de principiante.

Tres familias, pero el 80% del tiempo usarán === para comparar. Insiste en la trampa = vs ===: una asigna, la otra pregunta. Menciona que existe == (doble), pero la regla profesional es usar SIEMPRE === (triple), que también compara el tipo — perfecto puente al quiz.

⭐ QUIZ 2 · Operadores

¿Qué imprime console.log(5 === "5")?

💡 === compara valor y tipo. 5 es number, "5" es string → false. En testing esto importa: un API que devuelve "404" (texto) no es lo mismo que 404 (número).

Este quiz suele dividir a la sala. La explicación conecta con APIs: status codes como texto vs número es un bug real que verán en integración. Si alguien menciona ==, celebra la pregunta y reafirma: siempre ===.

valorvariablefunciónlógicaarchivorepo

Funciones: recetas con nombre 🍳

function login(email, password) {
  const mensaje = "Bienvenida " + email;
  return mensaje;
}

const resultado = login("ana@qa.com", "secreto123");

function

"Voy a definir una receta."

login(email, password)

Nombre + parámetros: los ingredientes que recibirá.

return

Lo que la receta entrega al terminar.

login("ana@qa.com", …)

Llamarla = ejecutar la receta con ingredientes reales.

Distinción clave que confunde a todos: DEFINIR una función (escribir la receta) no la ejecuta; LLAMARLA (con paréntesis y argumentos) sí. Parámetros = nombres genéricos en la receta; argumentos = ingredientes concretos al llamar. El zoom creció: la variable de hace 5 slides ahora vive DENTRO de una función.

¿Por qué te importan? Reutilización

😫 Tester manual

TC-101: abrir login, escribir email, escribir password, click…
TC-102: abrir login, escribir email, escribir password, click…
TC-103: abrir login, escribir email… otra vez. y otra. y otra.

😎 Con una función

login("ana@qa.com", "secreto123");
login("luis@qa.com", "otraClave9");
login("mia@qa.com", "claveMia55");

Escribes los pasos una vez, los ejecutas con mil datos distintos.

💡

Una función es un test step reutilizable. Cuando el botón de login cambie, corriges UN lugar — no 40 test cases.

Este es el argumento de venta de la automatización entera: mantenimiento. Pregunta: "¿cuántos test cases tuyos repiten los mismos 4 pasos de login?" La respuesta emocional a esa pregunta ES la motivación para aprender funciones.

🎮 Playground en vivo

Tu primera función

functions.js — editable
▶ Presiona Ejecutar para ver la salida…

Deja que alguien resuelva el reto 2 en vivo (o guíalos línea a línea). Errores esperables: olvidar return (imprime undefined — explícalo: la función no entregó nada), olvidar paréntesis al llamar. Ambos errores son ORO pedagógico, no los esquives.

⭐ QUIZ 3 · Funciones

¿Qué imprime este código?

function sum(a, b) {
  return a + b;
}
console.log(sum(2, 3));
💡 2 y 3 son numbers (sin comillas) → + suma: 5. Si fueran "2" y "3" (strings), + los pegaría: "23". El tipo decide el comportamiento.

Combina funciones con la lección de tipos: el MISMO operador + se comporta distinto según el tipo. Si la sala duda entre A y B, vuelve un segundo a la slide de tipos. Este "aha" previene bugs reales de concatenación accidental.

valorvariablefunciónlógicaarchivorepo

if / else: el código decide 🔀

if (statusCode === 200) {
  console.log("✅ Test PASSED");
} else {
  console.log("❌ Test FAILED");
}

🤔 La pregunta

statusCode === 200 se evalúa a true o false (¡los booleans del Acto 1!).

✅ true → primer bloque

❌ false → bloque del else. Nunca ambos.

🧪 ¿Te suena?

Es tu resultado esperado: "SI el sistema muestra X, el test pasa; SI NO, falla". Llevas años escribiendo if/else en español.

Conecta con el boolean del Acto 1: la condición del if ES una expresión que produce true/false. El paralelo con "resultado esperado" de sus test cases es literal — toda aserción de Playwright es un if/else glorificado que decide PASSED o FAILED.

valorvariablefunciónlógicaarchivorepo

Loops: repetir sin sufrir 🔁

El clásico: for

for (let i = 0; i < 3; i++) {
  console.log("Intento #" + i);
}
// Intento #0, #1, #2

Tres piezas: inicio (i = 0) · condición (i < 3: ¿sigo?) · paso (i++: suma 1).

El elegante: for...of

const users = ["Ana", "Luis", "Mia"];

for (const user of users) {
  login(user);
}

"Por cada user de la lista, haz login." Esto es data-driven testing: mismos pasos, N datos.

No profundices en la sintaxis del for clásico todavía — la siguiente slide lo ejecuta paso a paso visualmente. El mensaje: loops convierten "ejecutar el mismo test con 50 usuarios" de una pesadilla manual a 3 líneas. for...of es el que más usarán.

🧠 Visualizador de memoria

El loop, paso a paso

const users = ["Ana", "Luis", "Mia"];
for (let i = 0; i < users.length; i++) {
console.log("Login de " + users[i]);
}
paso 0 / 9

📦 Memoria

— vacía —

Presiona "Siguiente paso" y mira cómo la máquina ejecuta línea por línea.
consola…

La slide más importante del Acto 2. Avanza paso a paso PREGUNTANDO antes de cada click: "¿qué línea sigue? ¿cuánto vale i?". Los loops dejan de ser magia cuando VEN a i mutar 0→1→2→3 y la condición volverse false. Tómate tu tiempo: 5 minutos aquí valen oro.

⭐ QUIZ 4 · Condicionales y loops

¿Qué imprime for (let i = 0; i < 3; i++) console.log(i)?

💡 i empieza en 0 (los programadores cuentan desde cero) y el loop corre mientras i < 3 — cuando i llega a 3, la condición es false y se detiene sin imprimir el 3.

Acaban de VER esto en el visualizador, así que la tasa de acierto debería ser alta — refuerzo positivo. Si fallan, vuelve una slide y repite los pasos 2-3 del visualizador. "Contar desde cero" reaparece en arrays a continuación.

valorvariablefunciónlógicaarchivorepo

Arrays: listas ordenadas 📋

const browsers = ["chrome", "firefox", "safari"];

browsers[0]      // "chrome"  ← ¡desde cero!
browsers[2]      // "safari"
browsers.length  // 3

browsers.push("edge");  // agrega al final

🔢 Índice

Cada posición tiene número, empezando en 0. El primero es [0], no [1].

📏 .length

Cuántos elementos hay. Lo usaste en el loop: i < users.length.

🧪 En testing

Una columna de tu tabla de test data: lista de emails, de browsers, de roles a probar.

El índice desde cero ya lo vieron dos veces (loop, quiz) — tercera exposición, ya debería asentarse. push es el único método que muestro: suficiente para armar datos. La analogía columna-de-test-data prepara la siguiente slide donde objetos = fila completa.

valorvariablefunciónlógicaarchivorepo

Objetos: fichas con campos 🗂️

const user = {
  email: "ana@qa.com",
  password: "secreto123",
  role: "admin",
  active: true,
};

user.email   // "ana@qa.com"
user.role    // "admin"

🏷️ Propiedades

Pares nombre: valor. Como un formulario relleno: cada campo tiene etiqueta y contenido.

📍 El punto

user.email = "del objeto user, dame email". Lo verás MIL veces: page.click es exactamente esto.

🧪 Combo final

Array de objetos = tu tabla de test data completa: cada objeto una fila, cada propiedad una columna.

EL insight de esta slide: el punto de user.email es el MISMO punto de page.click() y expect().toBeVisible(). Cuando lleguen a Playwright ya habrán usado esa sintaxis 20 veces. Array de objetos = tabla de test data: cierra el círculo con su mundo conocido.

🎮 Playground en vivo

Todo junto: datos + loop

test-data.js — editable
▶ Presiona Ejecutar para ver la salida…

Este playground integra TODO el acto: array + objetos + for...of + if/else + comparación. Díselos explícitamente: "hace 30 minutos no podían leer esto; ahora pueden escribirlo". El reto introduce else if naturalmente. Es además un mini test RBAC real — admin vs viewer es exactamente lo que se prueba en apps multi-rol.

⭐ QUIZ 5 · Arrays y objetos

¿Qué imprime este código?

const fruits = ["uva", "kiwi", "mango"];
console.log(fruits[1]);
💡 Los arrays cuentan desde 0: fruits[0] es "uva", fruits[1] es "kiwi". Error clásico de todo principiante (y de varios seniors a las 6pm).

Cuarta exposición al índice-desde-cero. A esta altura deberían acertar casi todos — celebra el progreso del score. Cierra el Acto 2: "ya tienen TODA la lógica que un test necesita". Buen punto para pausa de 5 minutos si la sesión es de 2 horas.

Nivel siguiente

TypeScript = JavaScript + red de seguridad 🛡️

login.ts — Visual Studio Code
function login(email: string, password: string) {
  // ...
}

login("ana@qa.com", 12345);
⛔ Argument of type 'number' is not assignable to parameter of type 'string'.login.ts(5, 22) — ts(2345)

🏷️ Tipos explícitos

email: string declara qué tipo acepta cada parámetro. El contrato queda escrito.

⚡ Error ANTES de ejecutar

El subrayado rojo aparece mientras escribes — no en producción, no en el test run de las 3am.

🧪 ¿Te suena el concepto?

Encontrar el defecto lo más temprano posible… TypeScript es shift-left para tu propio código. 😉

Frame ganador: TypeScript no es "JS más difícil", es JS con un revisor automático. La conexión con shift-left les llega directo — detectan el bug en la fase más barata. El subrayado rojo de la slide es idéntico al que verán en VS Code. Bonus: los tipos alimentan el autocompletado, su mejor amigo al empezar.

Tipos que usarás desde el día 1

const email: string = "ana@qa.com";
const retries: number = 3;
const passed: boolean = true;

interface User {
  email: string;
  role: "admin" | "viewer";
}

📐 Anotación

: tipo después del nombre. La mayoría de veces TypeScript lo deduce solo y ni lo escribes.

📋 interface

El "plano" de un objeto: qué campos y de qué tipo. Tu test data con contrato.

🚧 Union: "admin" | "viewer"

Solo estos valores exactos. Escribes "admni" → error al instante. Adiós typos silenciosos.

No memorizar sintaxis — reconocerla al leerla. La inferencia es importante para bajar ansiedad: casi nunca anotan tipos a mano al empezar. El union type es el ejemplo más QA-friendly: un typo en un rol o un status es un bug que TypeScript mata gratis.

async / await: saber esperar

El problema

La web es lenta: la página carga, el servidor responde, la animación termina… Tu código corre en milisegundos; la web responde en segundos.

// 🤖💥 robot impaciente (SIN await):
page.goto("https://app.com/login");
page.click("#login-btn");
// click sobre una página que AÚN NO CARGÓ ❌

La solución

async function runTest() {
  await page.goto("https://app.com/login");
  await page.click("#login-btn");
}

await = "espera a que esto termine antes de seguir".
async = "esta función contiene esperas".

📜

Regla de oro Playwright: casi toda acción lleva await. Olvidarlo = tests intermitentes (flaky).

NO expliques promesas ni event loop — agujero negro innecesario hoy. El modelo mental del robot impaciente basta: la máquina es más rápida que la web y hay que frenarla. Regla mecánica: acción de Playwright → await adelante; función con awaits → async adelante. El 90% de tests flaky de principiante = un await olvidado.

⭐ QUIZ 6 · TypeScript + async

¿Por qué escribimos await page.click("#save-btn")?

💡 Sin await, el código sigue corriendo sin esperar el click → el siguiente paso actúa sobre una página a medio cambiar → test flaky (a veces pasa, a veces no). El await olvidado es la causa #1 de tests intermitentes.

La opción A es la trampa peligrosa: sin await a veces SÍ funciona (por suerte de timing) y por eso el bug es traicionero. Introduce la palabra "flaky" aquí — la van a escuchar toda su carrera. Fin del Acto 3: ya tienen todas las piezas del idioma.

valorvariablefunciónlógicaarchivorepo

Anatomía de un test real — ya conoces cada pieza

login.spec.ts
import { test, expect } from "@playwright/test";

test("login exitoso", async ({ page }) => {
  await page.goto("https://app.com/login");
  await page.fill("#email", "ana@qa.com");
  await page.fill("#password", "secreto123");
  await page.click("#login-btn");

  await expect(page.locator("#welcome")).toBeVisible();
});

📦 import

"Tráeme las herramientas test y expect de la caja Playwright."

🧪 test("…", async … )

¡Una función que recibe el nombre del caso… y otra función con los pasos! Sí: las funciones viajan como valores.

🤖 page.fill / page.click

Funciones con parámetros (Acto 2) + el punto de objetos (Acto 2) + await (Acto 3).

✅ expect(...).toBeVisible()

Tu resultado esperado hecho código. Si no se cumple → test FAILED.

Slide cumbre: recorre el código línea por línea preguntando "¿qué reconocen aquí?" — strings, funciones, params, el punto, async/await: TODO visto. Único concepto nuevo: pasar una función como argumento a test(); no lo teorices, di "le entregamos al runner los pasos para que los ejecute cuando toque". El expect es su resultado esperado de toda la vida.

Locators: cómo el robot "ve" 👁️

Tú ves…Playwright necesita…
"el campo de email"page.fill("#email", …) — por su id (#)
"el botón azul de Login"page.getByRole("button", { name: "Login" }) — por su rol visible
"el mensaje de bienvenida"page.locator("#welcome") — apunta al elemento, listo para verificar
🕵️

Cada elemento de una página tiene "dirección": su selector. Encontrarla es destreza detective de QA — y la vas a practicar AHORA mismo.

Concepto puente: el robot no ve píxeles, ve el árbol HTML, y el selector es la dirección postal del elemento. Hoy usamos ids (#email) por simplicidad; menciona que getByRole es la práctica profesional moderna y la verán en la sesión hands-on. Transición directa al playground de inspección.

🎮 Playground · Modo detective

Inspecciona la app — pasa el mouse 🔍

https://bunkai-bank.test/login

🏦 Bunkai Bank

Acceso a tu cuenta

✅ ¡Bienvenida, Ana!
❌ Credenciales inválidas

1️⃣ Activa el modo inspección

Y pasa el mouse sobre la mini-app.

2️⃣ Misión

Encuentra el selector del campo email, del password y del botón. Apúntalos: los usarás en la próxima slide.

💡 En la vida real

Esto mismo se hace con DevTools (click derecho → Inspeccionar) o con el inspector de Playwright.

Momento lúdico: activa el modo inspección y deja que la audiencia te dirija. El tooltip naranja muestra el selector de cada elemento (#email, #password, #login-btn, #welcome). Pídeles anotar los selectores — en la siguiente slide los usan de verdad. La app también funciona: pueden tipear y hacer login manual (ana@qa.com / secreto123).

🎮 Playground · El gran momento

Tu primer test, ejecutándose en vivo 🤖

https://bunkai-bank.test/login

🏦 Bunkai Bank

Acceso a tu cuenta

✅ ¡Bienvenida, Ana!
❌ Credenciales inválidas
mi-primer-test.spec.ts
▶ Ejecuta el test y mira el cursor fantasma…

EL momento wow de la clase — no lo apures. Ejecuta el script tal cual: el cursor fantasma se mueve, tipea y clickea; el expect pasa en verde. Luego ROMPE el test en vivo: cambia la password a "incorrecta" y re-ejecuta → aparece el error y el banner FAILED. Lección: el test no "se rompió" — ENCONTRÓ algo. Eso es exactamente su trabajo. Invita a alguien a dictar otra variación (email vacío, expect del #error-msg…).

⭐ QUIZ 7 · Anatomía Playwright

¿Qué hace await page.fill("#email", "ana@qa.com")?

💡 fill = rellenar: primer argumento el selector (dónde), segundo el texto (qué). Verificar contenido sería expect(...).toHaveValue(...) — las acciones actúan, los expect verifican.

Refuerza la distinción acciones (goto, fill, click — hacen cosas) vs aserciones (expect — verifican cosas). Un test = acciones que llevan la app a un estado + aserciones que comprueban el resultado esperado. Esa estructura es universal en cualquier framework de pruebas.

valorvariablefunciónlógicaarchivorepo

Zoom final: del átomo al repositorio 🛰️

mi-proyecto/
├─ package.json ← la "cédula": nombre, dependencias, comandos
├─ playwright.config.ts ← configuración: browsers, URL base, timeouts
├─ node_modules/ ← las herramientas instaladas (no se toca)
└─ tests/
   ├─ login.spec.ts ← ⭐ tu test vive aquí
   └─ signup.spec.ts ← cada feature, su archivo

🔭 El viaje completo

"Ana" — un valor
const email — con nombre
login(email, pass) — dentro de una función
if / for — con lógica
login.spec.ts — en un archivo
tests/ — en una carpeta
mi-proyecto/ — en un repositorio 🎉

Un repo es solo carpetas y archivos organizados. Nada de magia: cada nivel lo construiste hoy.

Cierre del arco del zoom-out: recorre la columna derecha de abajo hacia arriba o de arriba a abajo y muestra que CADA nivel lo construyeron en la sesión. Del árbol solo importan tres cosas: package.json (la cédula), tests/ (donde escriben) y config. node_modules se instala solo y no se toca. Spec = especificación: cada archivo .spec.ts especifica el comportamiento esperado de una feature.

Ejecutar y leer el veredicto 🏁

✅ Cuando todo pasa

$ npx playwright test

Running 1 test using 1 worker

   login.spec.ts:3 › login exitoso (2.1s)

  1 passed (2.5s)

❌ Cuando algo falla — lee con calma

   login.spec.ts:3 › login exitoso

  Error: expect(locator).toBeVisible()
  Locator: locator("#welcome")
  Expected: visible
  Received: hidden
    at login.spec.ts:8:48

El error te dice qué esperaba, qué encontró y en qué línea. Leer errores con calma = tu superpoder QA.

Desactiva el pánico al rojo: el error de Playwright es un reporte de bug bien escrito — expected vs received más la línea exacta. Ellos LEEN reportes de bugs todos los días; esto es lo mismo. Un test que falla puede significar bug encontrado (¡victoria!) o test mal escrito — distinguir ambos es el oficio que practicarán en hands-on.

⭐ QUIZ 8 · El integrador final

A este test le falta UNA palabra. ¿Cuál?

test("guardar cambios", async ({ page }) => {
  page.click("#save-btn");   // ⚠️ algo falta aquí…
  await expect(page.locator("#saved-msg")).toBeVisible();
});
💡 Sin await, el test NO espera el click y corre directo al expect → el mensaje aún no existe → falla intermitente (flaky). Acabas de diagnosticar el bug más común de la automatización. Bienvenida/o al oficio. 🎓

Quiz final integrador: diagnostican un bug REAL de código de automatización — el await faltante que produce flakiness. Si la mayoría acierta, la clase cumplió su objetivo. Conecta con el quiz 6: misma causa, ahora ELLOS la detectan en código ajeno.

Misión cumplida

Tu puntaje final

— / 8

1️⃣

Instala el kit

VS Code + Node.js. 10 minutos, gratis.

2️⃣

Crea tu proyecto

npm init playwright@latest
y el árbol de la slide 32 aparece solo.

3️⃣

Continúa el roadmap

Siguiente etapa — Dojo Lab 1: tus primeros specs reales, en la Dojoteca. 🚀

Ir a los Decks del DOJO →

Hoy: valores → variables → funciones → lógica → TypeScript → async → tu primer test. Ya hablas el idioma.

Lee el puntaje grupal y celebra sin importar el número — el score mide participación, no aptitud. Cierra con el mapa del viaje completo en una frase. Anuncia fecha/formato de la sesión hands-on y los 2 prerequisitos (VS Code + Node instalados). Comparte este archivo HTML: los playgrounds funcionan offline y pueden re-practicar solos en casa.