Initial commit
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Aluno - Provas', () => {
|
||||
// TODO: Fazer login como aluno antes de cada teste
|
||||
// test.beforeEach(async ({ page }) => {
|
||||
// await page.goto('/auth/login');
|
||||
// await page.getByLabel(/email/i).fill('[email protected]');
|
||||
// await page.getByLabel(/senha/i).fill('123456');
|
||||
// await page.getByRole('button', { name: /entrar/i }).click();
|
||||
// await page.waitForURL(/\/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 seção de provas disponíveis', async ({ page }) => {
|
||||
await expect(page.getByText(/provas|exames|avaliações/i)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Lista de Provas Disponíveis', () => {
|
||||
test('deve mostrar provas para fazer', async ({ page }) => {
|
||||
await page.goto('/dashboard/student/assignments');
|
||||
|
||||
await expect(page.getByText(/provas|exames/i)).toBeVisible();
|
||||
});
|
||||
|
||||
test('deve mostrar informações da prova', async ({ page }) => {
|
||||
await page.goto('/dashboard/student/assignments');
|
||||
|
||||
const examCard = page.locator('[data-testid="assignment-card"]').first();
|
||||
if (await examCard.isVisible()) {
|
||||
await expect(examCard.getByText(/título/i)).toBeVisible();
|
||||
await expect(examCard.getByText(/prazo|deadline/i)).toBeVisible();
|
||||
await expect(examCard.getByText(/tempo|time/i)).toBeVisible();
|
||||
}
|
||||
});
|
||||
|
||||
test('deve ter botão para iniciar prova', async ({ page }) => {
|
||||
await page.goto('/dashboard/student/assignments');
|
||||
|
||||
const startButton = page.getByRole('link', { name: /iniciar|começar|fazer/i }).first();
|
||||
if (await startButton.isVisible()) {
|
||||
await startButton.click();
|
||||
await expect(page).toHaveURL(/\/assignments\/\w+\/take/);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Fazendo Prova', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// TODO: Navegar para uma prova específica
|
||||
// await page.goto('/dashboard/student/assignments/assignment-id/take');
|
||||
});
|
||||
|
||||
test('deve mostrar título e instruções da prova', async ({ page }) => {
|
||||
// await expect(page.getByText(/título/i)).toBeVisible();
|
||||
// await expect(page.getByText(/instruções/i)).toBeVisible();
|
||||
});
|
||||
|
||||
test('deve mostrar timer de contagem regressiva', async ({ page }) => {
|
||||
// await expect(page.getByText(/\d+:\d+|\d+ min/i)).toBeVisible();
|
||||
});
|
||||
|
||||
test('deve mostrar questões', async ({ page }) => {
|
||||
// await expect(page.getByText(/questão|pergunta/i)).toBeVisible();
|
||||
});
|
||||
|
||||
test('deve responder múltipla escolha', async ({ page }) => {
|
||||
// const firstOption = page.locator('input[type="radio"]').first();
|
||||
// await firstOption.check();
|
||||
// await expect(firstOption).toBeChecked();
|
||||
});
|
||||
|
||||
test('deve responder questão textual', async ({ page }) => {
|
||||
// const textAnswer = page.getByPlaceholder(/digite|escreva/i).first();
|
||||
// if (await textAnswer.isVisible()) {
|
||||
// await textAnswer.fill('Resposta de teste');
|
||||
// }
|
||||
});
|
||||
|
||||
test('deve navegar entre questões', async ({ page }) => {
|
||||
// const nextButton = page.getByRole('button', { name: /próxima|avançar/i });
|
||||
// if (await nextButton.isVisible()) {
|
||||
// await nextButton.click();
|
||||
// // Verificar se mudou de questão
|
||||
// }
|
||||
});
|
||||
|
||||
test('deve submeter prova com confirmação', async ({ page }) => {
|
||||
// Responder pelo menos uma questão
|
||||
// const firstOption = page.locator('input[type="radio"]').first();
|
||||
// if (await firstOption.isVisible()) {
|
||||
// await firstOption.check();
|
||||
// }
|
||||
|
||||
// Clicar em submeter
|
||||
// await page.getByRole('button', { name: /submeter|enviar|finalizar/i }).click();
|
||||
|
||||
// Confirmar
|
||||
// await expect(page.getByText(/tem certeza|confirma/i)).toBeVisible();
|
||||
// await page.getByRole('button', { name: /confirmar|sim/i }).click();
|
||||
|
||||
// Deve redirecionar
|
||||
// await expect(page).toHaveURL(/\/dashboard\/student/);
|
||||
});
|
||||
|
||||
test('não deve editar após submeter', async ({ page }) => {
|
||||
// Tentar acessar prova já submetida
|
||||
// await page.goto('/dashboard/student/assignments/submitted-id/take');
|
||||
|
||||
// Deve mostrar mensagem ou redirecionar
|
||||
// await expect(page.getByText(/já submetida|não disponível/i)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Resultados de Provas', () => {
|
||||
test('deve mostrar provas corrigidas', async ({ page }) => {
|
||||
// TODO: Navegar para resultados
|
||||
// await page.goto('/dashboard/student/results');
|
||||
|
||||
// await expect(page.getByText(/resultados|notas/i)).toBeVisible();
|
||||
});
|
||||
|
||||
test('deve mostrar nota obtida', async ({ page }) => {
|
||||
// const resultCard = page.locator('[data-testid="result-card"]').first();
|
||||
// await expect(resultCard.getByText(/\d+\/\d+/)).toBeVisible();
|
||||
});
|
||||
|
||||
test('deve mostrar porcentagem', async ({ page }) => {
|
||||
// const resultCard = page.locator('[data-testid="result-card"]').first();
|
||||
// await expect(resultCard.getByText(/\d+%/)).toBeVisible();
|
||||
});
|
||||
|
||||
test('deve mostrar correção do professor', async ({ page }) => {
|
||||
// const viewButton = page.getByRole('button', { name: /ver|detalhes/i }).first();
|
||||
// await viewButton.click();
|
||||
|
||||
// await expect(page.getByText(/correção|feedback/i)).toBeVisible();
|
||||
});
|
||||
|
||||
test('deve mostrar respostas corretas e erradas', async ({ page }) => {
|
||||
// await page.goto('/dashboard/student/results/result-id');
|
||||
|
||||
// const correctAnswer = page.locator('[data-testid="correct-answer"]').first();
|
||||
// if (await correctAnswer.isVisible()) {
|
||||
// await expect(correctAnswer).toHaveClass(/emerald|green|success/i);
|
||||
// }
|
||||
|
||||
// const wrongAnswer = page.locator('[data-testid="wrong-answer"]').first();
|
||||
// if (await wrongAnswer.isVisible()) {
|
||||
// await expect(wrongAnswer).toHaveClass(/red|error|danger/i);
|
||||
// }
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Timer da Prova', () => {
|
||||
test('deve contar regressivamente', async ({ page }) => {
|
||||
// await page.goto('/dashboard/student/assignments/assignment-id/take');
|
||||
|
||||
// const initialTime = await page.getByText(/\d+:\d+/).textContent();
|
||||
// await page.waitForTimeout(60000); // Esperar 1 minuto
|
||||
|
||||
// const newTime = await page.getByText(/\d+:\d+/).textContent();
|
||||
// expect(newTime).not.toBe(initialTime);
|
||||
});
|
||||
|
||||
test('deve submeter automaticamente quando timer acabar', async ({ page }) => {
|
||||
// TODO: Testar com prova curta
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Prova após prazo', () => {
|
||||
test('não deve permitir iniciar prova após prazo', async ({ page }) => {
|
||||
// TODO: Tentar acessar prova expirada
|
||||
// await page.goto('/dashboard/student/assignments/expired-id/take');
|
||||
|
||||
// await expect(page.getByText(/prazo expirado|não disponível/i)).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,283 @@
|
||||
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('[email protected]');
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user