diff --git a/v2/e2e/frontend-only.spec.ts b/v2/e2e/frontend-only.spec.ts index 7236e07..507b267 100644 --- a/v2/e2e/frontend-only.spec.ts +++ b/v2/e2e/frontend-only.spec.ts @@ -29,6 +29,7 @@ test("frontend sandbox keeps the current student UI without backend calls", asyn await expect(page.getByText("Sandbox local de Aula 3.0")).toBeVisible(); await page.getByRole("button", { name: "Ver interfaz de estudiante" }).click(); + await page.getByRole("button", { name: "Omitir", exact: true }).click(); await expect( page.getByText("Vista para contribuir al frontend"), ).toBeVisible(); @@ -66,6 +67,7 @@ test("frontend sandbox renders rewards while keeping redemptions disabled", asyn const backendRequests = watchBackendRequests(page); await page.goto("./"); await page.getByRole("button", { name: "Ver interfaz de estudiante" }).click(); + await page.getByRole("button", { name: "Omitir", exact: true }).click(); await page.getByRole("link", { name: "Premios" }).click(); await expect( page.getByRole("heading", { name: "Premios", exact: true }), @@ -80,6 +82,7 @@ test("frontend sandbox displays mentor controls but blocks mutations", async ({ const backendRequests = watchBackendRequests(page); await page.goto("./"); await page.getByRole("button", { name: "Ver panel del mentor" }).click(); + await page.getByRole("button", { name: "Entendido" }).click(); await expect( page.getByRole("heading", { name: "Panel de eeminionn" }), ).toBeVisible(); @@ -109,6 +112,7 @@ test("frontend sandbox remains usable on a narrow viewport", async ({ page }) => await page.setViewportSize({ width: 360, height: 800 }); await page.goto("./"); await page.getByRole("button", { name: "Ver interfaz de estudiante" }).click(); + await page.getByRole("button", { name: "Omitir", exact: true }).click(); await expect( page.getByText("Vista para contribuir al frontend"), diff --git a/v2/e2e/mentor.spec.ts b/v2/e2e/mentor.spec.ts index 704bc6f..a5af011 100644 --- a/v2/e2e/mentor.spec.ts +++ b/v2/e2e/mentor.spec.ts @@ -3,6 +3,10 @@ import { expect, test, type Page } from "@playwright/test"; async function loginAsMentor(page: Page) { await page.goto("./"); await page.getByRole("button", { name: "Entrar como eeminionn" }).click(); + const guide = page.getByRole("dialog", { name: "Lo esencial está en un solo lugar" }); + if (await guide.waitFor({ state: "visible", timeout: 2_000 }).then(() => true).catch(() => false)) { + await guide.getByRole("button", { name: "Entendido" }).click(); + } await expect( page.getByRole("heading", { name: "Panel de eeminionn" }), ).toBeVisible(); @@ -72,6 +76,16 @@ test("mentor overview prioritizes actions without duplicate navigation", async ( await expect(page.getByText("Ver más indicadores")).toBeVisible(); }); +test("mentor can reopen the classroom preparation summary", async ({ page }) => { + await loginAsMentor(page); + await page.getByRole("button", { name: "Abrir guía rápida" }).click(); + const guide = page.getByRole("dialog", { + name: "Lo esencial está en un solo lugar", + }); + await expect(guide.getByText("Hay estudiantes en el curso")).toBeVisible(); + await expect(guide.getByText("Hay al menos una tarea publicada")).toBeVisible(); +}); + test("mentor creates an assignment for selected students", async ({ page }) => { await loginAsMentor(page); await page.getByRole("link", { name: "Tareas", exact: true }).click(); @@ -93,6 +107,7 @@ test("mentor creates a reward and fulfills a student redemption", async ({ }) => { await page.goto("./"); await page.getByRole("button", { name: "Entrar como estudiante" }).click(); + await page.getByRole("button", { name: "Omitir", exact: true }).click(); await page.getByRole("link", { name: "Premios" }).click(); const reward = page.locator(".reward-card").filter({ hasText: "Pista extra" }); await reward.getByRole("button", { name: "Canjear" }).click(); @@ -104,6 +119,7 @@ test("mentor creates a reward and fulfills a student redemption", async ({ await page.getByRole("menuitem", { name: "Cerrar sesión" }).click(); await page.getByRole("button", { name: "Entrar como eeminionn" }).click(); + await page.getByRole("button", { name: "Entendido" }).click(); await page.getByRole("link", { name: "Premios", exact: true }).click(); const redemption = page .locator(".redemption-admin-row") diff --git a/v2/e2e/mobile.spec.ts b/v2/e2e/mobile.spec.ts index 9de8c4e..97625f4 100644 --- a/v2/e2e/mobile.spec.ts +++ b/v2/e2e/mobile.spec.ts @@ -5,6 +5,7 @@ test("mobile navigation and workspace remain inside the viewport", async ({ }) => { await page.goto("./"); await page.getByRole("button", { name: "Entrar como estudiante" }).click(); + await page.getByRole("button", { name: "Omitir", exact: true }).click(); await expect( page.getByRole("heading", { name: "Tienes 3 tareas pendientes" }), ).toBeVisible(); @@ -46,6 +47,7 @@ test("mobile rewards keep cards and confirmation inside the viewport", async ({ }) => { await page.goto("./"); await page.getByRole("button", { name: "Entrar como estudiante" }).click(); + await page.getByRole("button", { name: "Omitir", exact: true }).click(); await page.getByRole("button", { name: "Abrir navegación" }).click(); await page.getByRole("link", { name: "Premios" }).click(); await expect( diff --git a/v2/e2e/student.spec.ts b/v2/e2e/student.spec.ts index af7e384..5ba9135 100644 --- a/v2/e2e/student.spec.ts +++ b/v2/e2e/student.spec.ts @@ -4,6 +4,18 @@ import AxeBuilder from "@axe-core/playwright"; test.beforeEach(async ({ page }) => { await page.goto("./"); await page.getByRole("button", { name: "Entrar como estudiante" }).click(); + await page.getByRole("button", { name: "Omitir", exact: true }).click(); + await expect(page.getByRole("heading", { name: /Hola, Camila/ })).toBeVisible(); +}); + +test("student can reopen the short getting started guide", async ({ page }) => { + await page.getByRole("button", { name: "Abrir guía rápida" }).click(); + await expect(page.getByRole("heading", { name: "Abre tu próxima tarea" })).toBeVisible(); + await page.getByRole("button", { name: "Siguiente" }).click(); + await expect(page.getByRole("heading", { name: "Ejecuta antes de entregar" })).toBeVisible(); + await page.getByRole("button", { name: "Siguiente" }).click(); + await expect(page.getByRole("heading", { name: "Entrega y espera feedback" })).toBeVisible(); + await page.getByRole("button", { name: "Ir a mis tareas" }).click(); await expect(page.getByRole("heading", { name: /Hola, Camila/ })).toBeVisible(); }); diff --git a/v2/src/components/AppShell.tsx b/v2/src/components/AppShell.tsx index 7a8479c..e18a181 100644 --- a/v2/src/components/AppShell.tsx +++ b/v2/src/components/AppShell.tsx @@ -1,9 +1,10 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import { Bell, BookCopy, BookOpen, CalendarPlus, + CircleHelp, ChevronDown, ClipboardCheck, Eye, @@ -28,6 +29,10 @@ import { useNavigate, } from "react-router-dom"; import { ProfileAvatar } from "@/components/ProfileAvatar"; +import { + GettingStarted, + shouldOpenGettingStarted, +} from "@/components/GettingStarted"; import { getPendingReviews } from "@/models/reviews"; import { useClassroom } from "@/state/classroom-context"; @@ -68,6 +73,7 @@ export function AppShell() { const [profileOpen, setProfileOpen] = useState(false); const [previewOpen, setPreviewOpen] = useState(false); const [selectedStudentId, setSelectedStudentId] = useState(""); + const [guideOpen, setGuideOpen] = useState(false); const location = useLocation(); const navigate = useNavigate(); const unread = @@ -84,6 +90,12 @@ export function AppShell() { snapshot?.profiles.filter((entry) => entry.role === "student") ?? []; const pendingReviews = snapshot ? getPendingReviews(snapshot).length : 0; + useEffect(() => { + if (profile && !isStudentPreview && shouldOpenGettingStarted(profile.id)) { + setGuideOpen(true); + } + }, [isStudentPreview, profile]); + return (
PREPARAR EL AULA
+Este resumen se actualiza solo. No necesitas configurar nada desde aquí.
+PRIMEROS PASOS · {step + 1} DE {steps.length}
+{current.body}
+