workspace-v1/shared/knowledge-base/reference/erp-inmobiliaria-legacy/gamilit/frontend/e2e/student-journey.spec.ts
rckrdmrd 66161b1566 feat: Workspace-v1 complete migration with NEXUS v3.4
Sistema NEXUS v3.4 migrado con:

Estructura principal:
- core/orchestration: Sistema SIMCO + CAPVED (27 directivas, 28 perfiles)
- core/catalog: Catalogo de funcionalidades reutilizables
- shared/knowledge-base: Base de conocimiento compartida
- devtools/scripts: Herramientas de desarrollo
- control-plane/registries: Control de servicios y CI/CD
- orchestration/: Configuracion de orquestacion de agentes

Proyectos incluidos (11):
- gamilit (submodule -> GitHub)
- trading-platform (OrbiquanTIA)
- erp-suite con 5 verticales:
  - erp-core, construccion, vidrio-templado
  - mecanicas-diesel, retail, clinicas
- betting-analytics
- inmobiliaria-analytics
- platform_marketing_content
- pos-micro, erp-basico

Configuracion:
- .gitignore completo para Node.js/Python/Docker
- gamilit como submodule (git@github.com:rckrdmrd/gamilit-workspace.git)
- Sistema de puertos estandarizado (3005-3199)

Generated with NEXUS v3.4 Migration System
EPIC-010: Configuracion Git y Repositorios
2026-01-04 03:37:42 -06:00

293 lines
10 KiB
TypeScript

import { test, expect } from '@playwright/test';
/**
* Student Journey E2E Tests
*
* Critical user flow: Login → Dashboard → Browse Modules → Start Exercise → Complete → Earn Rewards
*/
test.describe('Student Dashboard', () => {
test.skip('should display student dashboard after login', async ({ page }) => {
// NOTE: Requires test user setup
// Login as student user
// await loginAsStudent(page);
// Should see dashboard
await expect(page).toHaveURL(/\/student\/dashboard/);
// Dashboard should have key sections
await expect(page.locator('text=/progreso|progress/i')).toBeVisible();
await expect(page.locator('text=/módulos|modules/i')).toBeVisible();
});
test.skip('should display user stats on dashboard', async ({ page }) => {
// Login as student
// await loginAsStudent(page);
// Should show XP
await expect(page.locator('text=/XP|experiencia/i')).toBeVisible();
// Should show level
await expect(page.locator('text=/nivel|level|rango/i')).toBeVisible();
// Should show progress indicators
const progressBars = await page.locator('[role="progressbar"], progress, .progress').count();
expect(progressBars).toBeGreaterThan(0);
});
});
test.describe('Module Selection', () => {
test.skip('should display available modules', async ({ page }) => {
// await loginAsStudent(page);
await page.goto('/student/modules');
// Should show list of modules
const modules = await page.locator('[data-testid="module-card"], .module-card, article').count();
expect(modules).toBeGreaterThan(0);
// Each module should have:
// - Title
// - Description or preview
// - Start/Continue button
});
test.skip('should show module difficulty levels', async ({ page }) => {
// await loginAsStudent(page);
await page.goto('/student/modules');
// Should display difficulty indicators
const hasDifficulty =
(await page.locator('text=/fácil|easy|básico/i').count()) > 0 ||
(await page.locator('text=/intermedio|medium/i').count()) > 0 ||
(await page.locator('text=/difícil|hard|avanzado/i').count()) > 0;
expect(hasDifficulty).toBeTruthy();
});
test.skip('should allow filtering modules', async ({ page }) => {
// await loginAsStudent(page);
await page.goto('/student/modules');
// Look for filter controls
const hasFilters =
(await page.locator('select, [role="combobox"]').count()) > 0 ||
(await page.locator('button:has-text("Filtrar"), button:has-text("Filter")').count()) > 0;
expect(hasFilters).toBeTruthy();
});
});
test.describe('Exercise Flow', () => {
test.skip('should start an exercise', async ({ page }) => {
// await loginAsStudent(page);
// await navigateToModule(page);
// Click start exercise button
await page.getByRole('button', { name: /iniciar|start|comenzar/i }).first().click();
// Should navigate to exercise page
await expect(page).toHaveURL(/\/exercise|\/ejercicio/);
// Should show exercise content
await expect(page.locator('[data-testid="exercise-content"], .exercise-content')).toBeVisible();
});
test.skip('should display exercise question', async ({ page }) => {
// await loginAsStudent(page);
// await startExercise(page);
// Should show question text
const hasQuestion =
(await page.locator('[data-testid="question"], .question, h2, h3').count()) > 0;
expect(hasQuestion).toBeTruthy();
// Should show options (for multiple choice)
const options = await page.locator('input[type="radio"], button[role="radio"]').count();
expect(options).toBeGreaterThanOrEqual(2); // At least 2 options
});
test.skip('should allow answer selection', async ({ page }) => {
// await loginAsStudent(page);
// await startExercise(page);
// Select an option
const firstOption = page.locator('input[type="radio"], button[role="radio"]').first();
await firstOption.click();
// Option should be selected
await expect(firstOption).toBeChecked();
// Submit button should be enabled
const submitButton = page.getByRole('button', { name: /enviar|submit|confirmar/i });
await expect(submitButton).toBeEnabled();
});
test.skip('should submit answer and show feedback', async ({ page }) => {
// await loginAsStudent(page);
// await startExercise(page);
// Select answer
await page.locator('input[type="radio"], button[role="radio"]').first().click();
// Submit
await page.getByRole('button', { name: /enviar|submit/i }).click();
// Should show feedback
await expect(
page.locator('text=/correcto|correct|incorrecto|incorrect|bien|mal/i')
).toBeVisible({ timeout: 5000 });
// Should show continue/next button
await expect(page.getByRole('button', { name: /siguiente|next|continuar/i })).toBeVisible();
});
test.skip('should track exercise progress', async ({ page }) => {
// await loginAsStudent(page);
// await startExercise(page);
// Should show progress indicator (e.g., "Question 1 of 10")
const hasProgress =
(await page.locator('text=/\\d+ de \\d+|\\d+ of \\d+/i').count()) > 0 ||
(await page.locator('[role="progressbar"]').count()) > 0;
expect(hasProgress).toBeTruthy();
});
test.skip('should complete exercise and show results', async ({ page }) => {
// await loginAsStudent(page);
// await completeExercise(page);
// Should show completion screen
await expect(
page.locator('text=/completado|completed|finalizado|terminado/i')
).toBeVisible();
// Should show score
await expect(page.locator('text=/puntuación|score|resultado/i')).toBeVisible();
// Should show XP earned
await expect(page.locator('text=/XP|experiencia ganada/i')).toBeVisible();
});
});
test.describe('Gamification Elements', () => {
test.skip('should display XP gain animation', async ({ page }) => {
// await loginAsStudent(page);
// await completeExercise(page);
// Should show XP animation or notification
// This might be a toast, modal, or animated number
const hasXPNotification =
(await page.locator('[data-testid="xp-notification"], .xp-earned, .toast').count()) > 0;
expect(hasXPNotification).toBeTruthy();
});
test.skip('should show achievement unlock', async ({ page }) => {
// NOTE: This would require completing specific conditions
// to unlock an achievement
// await loginAsStudent(page);
// await performActionThatUnlocksAchievement(page);
// Should show achievement modal/notification
await expect(page.locator('text=/logro|achievement|desbloquear/i')).toBeVisible({
timeout: 10000,
});
});
test.skip('should display leaderboard', async ({ page }) => {
// await loginAsStudent(page);
await page.goto('/student/leaderboard');
// Should show leaderboard table
await expect(page.locator('table, [role="table"]')).toBeVisible();
// Should have columns: Rank, Name, XP, Level
await expect(page.locator('text=/rango|rank|posición/i')).toBeVisible();
await expect(page.locator('text=/nombre|name|usuario/i')).toBeVisible();
await expect(page.locator('text=/XP|puntos/i')).toBeVisible();
});
test.skip('should highlight current user in leaderboard', async ({ page }) => {
// await loginAsStudent(page);
await page.goto('/student/leaderboard');
// Current user row should be highlighted
const highlightedRow = page.locator('[data-testid="current-user-row"], .current-user, .highlight');
await expect(highlightedRow).toBeVisible();
});
});
test.describe('Progress Tracking', () => {
test.skip('should show module completion status', async ({ page }) => {
// await loginAsStudent(page);
await page.goto('/student/progress');
// Should show completed modules
const completedModules = await page.locator('text=/completado|completed|✓/i').count();
// Should show in-progress modules
const inProgressModules = await page.locator('text=/en progreso|in progress/i').count();
// Should have at least one status shown
expect(completedModules + inProgressModules).toBeGreaterThan(0);
});
test.skip('should display overall progress percentage', async ({ page }) => {
// await loginAsStudent(page);
await page.goto('/student/progress');
// Should show percentage (e.g., "75% completed")
const hasPercentage = await page.locator('text=/\\d+%/').count();
expect(hasPercentage).toBeGreaterThan(0);
});
test.skip('should show recent activity', async ({ page }) => {
// await loginAsStudent(page);
await page.goto('/student/dashboard');
// Should show recent activity section
await expect(page.locator('text=/actividad reciente|recent activity/i')).toBeVisible();
// Should list recent exercises or modules
const activityItems = await page.locator('[data-testid="activity-item"], .activity-item, li').count();
expect(activityItems).toBeGreaterThan(0);
});
});
/**
* Helper functions (to be implemented with actual test data)
*/
async function loginAsStudent(page: any) {
await page.goto('/login');
await page.getByLabel(/email/i).fill('student@test.com');
await page.getByLabel(/password/i).fill('Test123!');
await page.getByRole('button', { name: /login/i }).click();
await page.waitForURL(/\/student\/dashboard/);
}
async function navigateToModule(page: any) {
await page.goto('/student/modules');
await page.locator('[data-testid="module-card"]').first().click();
}
async function startExercise(page: any) {
await navigateToModule(page);
await page.getByRole('button', { name: /start/i }).click();
}
async function completeExercise(page: any) {
await startExercise(page);
// Answer all questions (simplified - assumes 5 questions)
for (let i = 0; i < 5; i++) {
await page.locator('input[type="radio"]').first().click();
await page.getByRole('button', { name: /submit|next/i }).click();
await page.waitForTimeout(500);
}
}