import { test, expect } from '@playwright/test'; test.describe('Professor - Correção de Provas', () => { // TODO: Fazer login como professor // test.beforeEach(async ({ page }) => { // await page.goto('/auth/login'); // await page.getByLabel(/email/i).fill('teacher@teste.com'); // await page.getByLabel(/senha/i).fill('123456'); // await page.getByRole('button', { name: /entrar/i }).click(); // await page.waitForURL(/\/dispatcher|\/dashboard\/teacher/); // }); test.describe('Lista de Provas da Turma', () => { test.beforeEach(async ({ page }) => { await page.goto('/dashboard/teacher/class/class-id'); }); test('deve mostrar provas atribuídas à turma', async ({ page }) => { const assignmentList = page.locator('[data-testid="assignment-list"]'); if (await assignmentList.isVisible()) { await expect(assignmentList.getByText(/prova/i)).toBeVisible(); } }); test('deve mostrar status da prova', async ({ page }) => { const assignmentList = page.locator('[data-testid="assignment-list"]'); if (await assignmentList.isVisible()) { // Status: pendente, em andamento, concluída const statusBadge = assignmentList.locator('[data-testid="status-label"]').first(); if (await statusBadge.isVisible()) { await expect(statusBadge).toBeVisible(); } } }); test('deve mostrar número de alunos que fizeram a prova', async ({ page }) => { const assignmentList = page.locator('[data-testid="assignment-list"]'); if (await assignmentList.isVisible()) { const progressText = assignmentList.getByText(/\d+\/\d+/i).first(); if (await progressText.isVisible()) { await expect(progressText).toBeVisible(); } } }); test('deve ter botão de ver resultados', async ({ page }) => { const assignmentCard = page.locator('[data-testid="assignment-card"]').first(); if (await assignmentCard.isVisible()) { const resultsButton = assignmentCard.getByRole('link', { name: /resultados|correções/i }); if (await resultsButton.isVisible()) { await expect(resultsButton).toBeVisible(); } } }); }); test.describe('Página de Resultados da Turma', () => { test.beforeEach(async ({ page }) => { // TODO: Navegar para resultados de uma turma específica await page.goto('/dashboard/teacher/class/class-id/results'); }); test('deve mostrar lista de tentativas', async ({ page }) => { await expect(page.getByText(/tentativas|resultados/i)).toBeVisible(); await expect(page.locator('table')).toBeVisible(); }); test('deve mostrar aluno, prova, nota e status', async ({ page }) => { const table = page.locator('table').first(); if (await table.isVisible()) { await expect(table.getByText(/aluno|student/i)).toBeVisible(); await expect(table.getByText(/prova|template/i)).toBeVisible(); await expect(table.getByText(/nota|score/i)).toBeVisible(); await expect(table.getByText(/status/i)).toBeVisible(); } }); test('deve mostrar badge de status de correção', async ({ page }) => { const table = page.locator('table').first(); if (await table.isVisible()) { const statusCell = table.locator('tbody tr td').last(); if (await statusCell.isVisible()) { // Status: pending, partially_graded, fully_graded const label = statusCell.locator('[data-testid="label"], .label').first(); if (await label.isVisible()) { const classes = await label.getAttribute('class') || ''; expect(classes).toMatch(/label-(gray|amber|emerald)/); } } } }); }); test.describe('Corrigir Prova - Modal', () => { test.beforeEach(async ({ page }) => { await page.goto('/dashboard/teacher/class/class-id/results'); // Abrir modal de correção const gradeButton = page.getByRole('button', { name: /corrigir|grade/i }).first(); if (await gradeButton.isVisible()) { await gradeButton.click(); } }); test('deve abrir modal com detalhes da tentativa', async ({ page }) => { await expect(page.locator('.fixed.inset-0')).toBeVisible(); await expect(page.getByText(/correção|grading/i)).toBeVisible(); }); test('deve mostrar informações do aluno', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { await expect(page.getByText(/aluno|student/i)).toBeVisible(); // Deve mostrar data de envio await expect(page.getByText(/\d{2}\/\d{2}\/\d{4}/)).toBeVisible(); } }); test('deve mostrar questões da prova', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { const questions = page.locator('[data-testid="question-card"]'); const count = await questions.count(); if (count > 0) { // Primeira questão deve ter enunciado await expect(questions.nth(0).getByPlaceholder(/enunciado|questão/i)).toBeVisible(); } } }); }); test.describe('Corrigir Questão Textual', () => { test.beforeEach(async ({ page }) => { // Abrir modal de correção com questão textual // await page.goto('/dashboard/teacher/class/class-id/results'); // await page.getByRole('button', { name: /corrigir/i }).click(); }); test('deve mostrar resposta do aluno', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { const textQuestion = page.locator('[data-testid="text-question"]').first(); if (await textQuestion.isVisible()) { await expect(textQuestion.getByPlaceholder(/resposta/i)).not.toBeEmpty(); } } }); test('deve permitir dar pontos parciais', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { const textQuestion = page.locator('[data-testid="text-question"]').first(); if (await textQuestion.isVisible()) { const pointsInput = textQuestion.getByRole('spinbutton', { name: /pontos/i }); if (await pointsInput.isVisible()) { await pointsInput.fill('3.5'); const value = await pointsInput.inputValue(); expect(value).toBe('3.5'); } } } }); test('deve ter campo de feedback', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { const textQuestion = page.locator('[data-testid="text-question"]').first(); if (await textQuestion.isVisible()) { const feedbackInput = textQuestion.getByPlaceholder(/feedback|comentário/i); if (await feedbackInput.isVisible()) { await feedbackInput.fill('Bom trabalho, mas pode melhorar a gramática.'); await expect(feedbackInput).toHaveValue(/gramática/i); } } } }); }); test.describe('Questões de Múltipla Escolha', () => { test('deve mostrar resposta selecionada pelo aluno', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { const mcQuestion = page.locator('[data-testid="mc-question"]').first(); if (await mcQuestion.isVisible()) { // Opção correta deve estar marcada const correctOption = mcQuestion.locator('[data-testid="correct-option"]').first(); if (await correctOption.isVisible()) { await expect(correctOption).toBeVisible(); } // Opção errada deve estar marcada se o aluno errou const wrongOption = mcQuestion.locator('[data-testid="wrong-option"]').first(); if (await wrongOption.isVisible()) { await expect(wrongOption).toBeVisible(); } } } }); test('deve mostrar opção correta', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { const mcQuestion = page.locator('[data-testid="mc-question"]').first(); if (await mcQuestion.isVisible()) { const correctOption = mcQuestion.locator('[data-testid="correct-option"]').first(); if (await correctOption.isVisible()) { await expect(correctOption.getByText(/correta/i)).toBeVisible(); } } } }); test('não deve permitir modificar correção automática', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { const mcQuestion = page.locator('[data-testid="mc-question"]').first(); if (await mcQuestion.isVisible()) { // Opções devem ser readonly const options = mcQuestion.locator('input[type="radio"]'); const count = await options.count(); for (let i = 0; i < count; i++) { await expect(options.nth(i)).toBeDisabled(); } } } }); }); test.describe('Salvar Correção', () => { test.beforeEach(async ({ page }) => { // Abrir modal de correção // await page.goto('/dashboard/teacher/class/class-id/results'); // await page.getByRole('button', { name: /corrigir/i }).first().click(); }); test('deve calcular nota total automaticamente', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { // Deve mostrar nota total calculada const totalScore = page.getByText(/nota total|total score/i); if (await totalScore.isVisible()) { await expect(totalScore).toBeVisible(); } } }); test('deve salvar correção com sucesso', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { await page.getByRole('button', { name: /salvar|concluir/i }).click(); // Deve fechar modal await expect(page.locator('.fixed.inset-0')).not.toBeVisible({ timeout: 5000 }); // Deve mostrar mensagem de sucesso ou atualizar status // await expect(page.getByText(/correção salva|sucesso/i)).toBeVisible(); } }); test('deve atualizar status para "corrigido"', async ({ page }) => { // TODO: Implementar fluxo completo // 1. Abrir correção // 2. Salvar // 3. Verificar se status mudou na lista }); }); test.describe('Correção Parcial', () => { test('deve indicar provas parcialmente corrigidas', async ({ page }) => { await page.goto('/dashboard/teacher/class/class-id/results'); // Deve ter badges para: pending, partially_graded, fully_graded const partialBadge = page.locator('[data-testid="status-label"]') .filter({ hasText: /parcial/i }); const count = await partialBadge.count(); expect(count).toBeGreaterThanOrEqual(0); }); test('deve mostrar ícone de pendência para questões não corrigidas', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { // Questões textuais sem correção devem ter indicador const ungradedQuestions = page.locator('[data-testid="needs-grading"]'); const count = await ungradedQuestions.count(); if (count > 0) { await expect(ungradedQuestions.nth(0).getByText(/pendente|corrigir/i)).toBeVisible(); } } }); }); test.describe('Cancelar Correção', () => { test('deve ter botão de cancelar', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { await expect(page.getByRole('button', { name: /cancelar/i })).toBeVisible(); } }); test('deve fechar modal sem salvar ao cancelar', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { await page.getByRole('button', { name: /cancelar/i }).click(); await expect(page.locator('.fixed.inset-0').not.toBeVisible(); } }); test('deve perder alterações não salvas', async ({ page }) => { if (await page.locator('.fixed.inset-0').isVisible()) { // Fazer alterações const textQuestion = page.locator('[data-testid="text-question"]').first(); if (await textQuestion.isVisible()) { const pointsInput = textQuestion.getByRole('spinbutton', { name: /pontos/i }); if (await pointsInput.isVisible()) { await pointsInput.fill('5'); } } // Cancelar await page.getByRole('button', { name: /cancelar/i }).click(); // Abrir novamente - não deve ter os 5 pontos // await page.getByRole('button', { name: /corrigir/i }).first().click(); // const newPoints = page.getByRole('spinbutton', { name: /pontos/i }).first(); // const value = await newPoints.inputValue(); // expect(value).not.toBe('5'); } }); }); });