import { test, expect } from '@playwright/test'; test.describe('Aluno - Materiais', () => { // TODO: Fazer login como aluno // test.beforeEach(async ({ page }) => { // await page.goto('/auth/login'); // await page.getByLabel(/email/i).fill('student@teste.com'); // await page.getByLabel(/senha/i).fill('123456'); // await page.getByRole('button', { name: /entrar/i }).click(); // await page.waitForURL(/\/dispatcher|\/dashboard\/student/); // }); test.describe('Dashboard do Aluno', () => { test.beforeEach(async ({ page }) => { await page.goto('/dashboard/student'); }); test('deve mostrar turmas matriculadas', async ({ page }) => { await expect(page.getByText(/turmas|classes|minhas turmas/i)).toBeVisible(); }); test('deve mostrar cards de turmas com informações', async ({ page }) => { const classCard = page.locator('[data-testid="class-card"], .card').first(); if (await classCard.isVisible()) { await expect(classCard.getByText(/inglês|português/i, { ignoreCase: true })).toBeVisible(); } }); }); test.describe('Materiais por Turma', () => { test.beforeEach(async ({ page }) => { // TODO: Navegar para página de uma turma específica await page.goto('/dashboard/student/class/class-id'); }); test('deve mostrar seção de materiais', async ({ page }) => { await expect(page.getByText(/materiais|arquivos|materials/i)).toBeVisible(); }); test('deve mostrar materiais agrupados por categoria', async ({ page }) => { const materialsSection = page.getByText(/materiais/i).locator('..'); const categoryBadges = materialsSection.locator('[data-testid="category-badge"]'); const count = await categoryBadges.count(); if (count > 0) { // Deve ter cor for (let i = 0; i < Math.min(count, 3); i++) { const badge = categoryBadges.nth(i); const classes = await badge.getAttribute('class') || ''; expect(classes).toMatch(/bg-/); } } }); test('deve listar arquivos de cada categoria', async ({ page }) => { const materialsSection = page.getByText(/materiais/i).locator('..'); const fileLinks = materialsSection.getByRole('link', { name: /abrir|baixar/i }); const count = await fileLinks.count(); if (count > 0) { await expect(fileLinks.nth(0)).toBeVisible(); } }); test('deve mostrar tamanho do arquivo', async ({ page }) => { const materialsSection = page.getByText(/materiais/i).locator('..'); const sizeText = page.getByText(/\d+\.?\d* KB|MB/i).first(); if (await sizeText.isVisible()) { await expect(sizeText).toBeVisible(); } }); }); test.describe('Download de Arquivo', () => { test.beforeEach(async ({ page }) => { await page.goto('/dashboard/student/class/class-id'); }); test('deve baixar arquivo ao clicar no botão', async ({ page }) => { const downloadButton = page.getByRole('link', { name: /baixar|download/i }).first(); if (await downloadButton.isVisible()) { const downloadPromise = page.waitForEvent('download'); await downloadButton.click(); const download = await downloadPromise; expect(download.suggestedFilename()).toBeTruthy(); } }); test('deve abrir PDF em nova aba', async ({ page }) => { const openButton = page.getByRole('link', { name: /abrir/i }).first(); if (await openButton.isVisible()) { const newPagePromise = page.waitForEvent('popup'); await openButton.click(); const newPage = await newPagePromise; await expect(newPage).toHaveURL(/\.pdf/i); } }); test('deve mostrar preview de imagem', async ({ page }) => { const imageLink = page.getByRole('link', { name: /abrir/i }).first(); if (await imageLink.isVisible()) { await imageLink.click(); // Pode abrir modal com preview const preview = page.locator('img[src*="/uploads/"]').first(); if (await preview.isVisible()) { await expect(preview).toBeVisible(); } } }); }); test.describe('Filtros de Categoria', () => { test.beforeEach(async ({ page }) => { await page.goto('/dashboard/student/class/class-id'); }); test('deve ter botões de filtro por categoria', async ({ page }) => { const categoryBadges = page.locator('[data-testid="category-badge"]'); const count = await categoryBadges.count(); if (count > 0) { // Ao clicar, deve filtrar materiais await categoryBadges.nth(0).click(); await page.waitForTimeout(500); // Verificar se filtrou (pode mostrar apenas materiais da categoria) } }); test('deve mostrar todos ao clicar no filtro ativo', async ({ page }) => { // Primeiro clicar em uma categoria const categoryBadges = page.locator('[data-testid="category-badge"]'); if ((await categoryBadges.count()) > 0) { await categoryBadges.nth(0).click(); await page.waitForTimeout(500); // Clicar novamente para limpar filtro await categoryBadges.nth(0).click(); await page.waitForTimeout(500); // Deve mostrar todos novamente } }); }); test.describe('Histórico de Aulas', () => { test.beforeEach(async ({ page }) => { await page.goto('/dashboard/student/class/class-id/history'); }); test('deve mostrar lista de aulas registradas', async ({ page }) => { await expect(page.getByText(/histórico|lessons|aulas/i)).toBeVisible(); }); test('deve mostrar data, tópico e presença', async ({ page }) => { const lessonRow = page.locator('[data-testid="lesson-row"], tr').nth(1); if (await lessonRow.isVisible()) { await expect(lessonRow.getByText(/\d{2}\/\d{2}/)).toBeVisible(); const topicCell = lessonRow.locator('td').nth(1); if (await topicCell.isVisible()) { await expect(topicCell.getByText(/tópico/i)).toBeVisible(); } } }); test('deve mostrar presença do aluno em cada aula', async ({ page }) => { const attendanceCell = page.locator('tbody tr td').nth(2); if (await attendanceCell.isVisible()) { const text = await attendanceCell.textContent(); // Pode ser emoji ou texto expect(text).toMatch(/presente|ausente|atrasado|✓|✗|◑/i); } }); test('deve mostrar link para materiais da aula', async ({ page }) => { const lessonRow = page.locator('[data-testid="lesson-row"], tr').nth(1); if (await lessonRow.isVisible()) { const materialsLink = lessonRow.getByRole('link', { name: /materiais/i }); if (await materialsLink.isVisible()) { await expect(materialsLink).toBeVisible(); } } }); }); test.describe('Presença Global', () => { test.beforeEach(async ({ page }) => { await page.goto('/dashboard/student/class/class-id'); }); test('deve mostrar taxa de presença geral', async ({ page }) => { await expect(page.getByText(/presença|attendance/i)).toBeVisible(); const percentage = page.getByText(/\d+%/i).first(); if (await percentage.isVisible()) { await expect(percentage).toBeVisible(); } }); test('deve mostrar presença de forma visual (gráfico ou barra)', async ({ page }) => { // Pode ter gráfico de barras ou outra visualização const chart = page.locator('[data-testid="attendance-chart"], canvas, svg'); if (await chart.isVisible()) { await expect(chart).toBeVisible(); } }); }); test.describe('Responsividade - Mobile', () => { test('materiais devem ser usáveis em mobile', async ({ page }) => { await page.setViewportSize({ width: 375, height: 667 }); await page.goto('/dashboard/student/class/class-id'); // Deve mostrar lista sem scroll horizontal const hasHorizontalScroll = await page.evaluate(() => { return document.body.scrollWidth > document.body.clientWidth; }); expect(hasHorizontalScroll).toBe(false); }); test('cards de turma devem se ajustar em mobile', async ({ page }) => { await page.setViewportSize({ width: 375, height: 667 }); await page.goto('/dashboard/student'); const classCards = page.locator('[data-testid="class-card"]'); const count = await classCards.count(); if (count > 0) { // Em mobile, devem estar em coluna única const firstCard = classCards.nth(0); const secondCard = classCards.nth(1); if (await secondCard.isVisible()) { const firstBox = await firstCard.boundingBox(); const secondBox = await secondCard.boundingBox(); // Devem estar um abaixo do outro expect(secondBox.y).toBeGreaterThan(firstBox.y + firstBox.height); } } }); }); test.describe('Busca de Materiais', () => { test('deve ter campo de busca', async ({ page }) => { await page.goto('/dashboard/student/class/class-id'); const searchInput = page.getByPlaceholder(/buscar|pesquisar|search/i); if (await searchInput.isVisible()) { await expect(searchInput).toBeVisible(); } }); test('deve filtrar materiais ao buscar', async ({ page }) => { const searchInput = page.getByPlaceholder(/buscar/i); if (await searchInput.isVisible()) { await searchInput.fill('PDF'); await page.waitForTimeout(500); // Deve mostrar apenas materiais com "PDF" const fileLinks = page.getByRole('link', { name: /abrir/i }); const count = await fileLinks.count(); if (count > 0) { for (let i = 0; i < count; i++) { const text = await fileLinks.nth(i).textContent(); // Pode não filtrar estritamente, mas deve priorizar resultados } } } }); }); });