import { test, expect } from './fixtures'; test.describe('Reproduction - Edit Modal Fields', () => { test('Verify Edit Fields for different Exercise Types', async ({ page, createUniqueUser, request }) => { const user = await createUniqueUser(); // Login await page.goto('/'); await page.getByLabel('Email').fill(user.email); await page.getByLabel('Password').fill(user.password); await page.getByRole('button', { name: 'Login' }).click(); // Wait for dashboard or password change try { const heading = page.getByRole('heading', { name: /Change Password/i }); const dashboard = page.getByText('Free Workout'); await expect(heading.or(dashboard)).toBeVisible({ timeout: 10000 }); if (await heading.isVisible()) { await page.getByLabel('New Password').fill('StrongNewPass123!'); await page.getByRole('button', { name: /Save|Change/i }).click(); await expect(dashboard).toBeVisible(); } } catch (e) { console.log('Login flow exception (might be benign if already logged in):', e); } // Seed exercises of different types const types = [ { type: 'PLYOMETRIC', name: 'Plyo Test', expectedFields: ['Reps'] }, { type: 'STRENGTH', name: 'Strength Test', expectedFields: ['Weight', 'Reps'] }, { type: 'CARDIO', name: 'Cardio Test', expectedFields: ['Time', 'Distance'] }, { type: 'STATIC', name: 'Static Test', expectedFields: ['Time', 'Weight', 'Body Weight'] }, // Check if Weight is expected based on History.tsx analysis { type: 'BODYWEIGHT', name: 'Bodyweight Test', expectedFields: ['Reps', 'Body Weight', 'Weight'] }, { type: 'HIGH_JUMP', name: 'High Jump Test', expectedFields: ['Height'] }, { type: 'LONG_JUMP', name: 'Long Jump Test', expectedFields: ['Distance'] }, ]; const exIds: Record = {}; for (const t of types) { const resp = await request.post('/api/exercises', { data: { name: t.name, type: t.type }, headers: { 'Authorization': `Bearer ${user.token}` } }); expect(resp.ok()).toBeTruthy(); const created = await resp.json(); // Adjust if the response structure is different (e.g. created.exercise) exIds[t.name] = created.id || created.exercise?.id || created.data?.id; } await page.reload(); // Construct a session payload const now = Date.now(); const setsStub = types.map(t => { const set: any = { exerciseId: exIds[t.name], timestamp: now + 1000, completed: true }; if (t.type === 'STRENGTH' || t.type === 'BODYWEIGHT' || t.type === 'PLYOMETRIC') set.reps = 10; if (t.type === 'STRENGTH' || t.type === 'BODYWEIGHT' || t.type === 'STATIC') set.weight = 50; if (t.type === 'BODYWEIGHT' || t.type === 'STATIC') set.bodyWeightPercentage = 100; if (t.type === 'CARDIO' || t.type === 'STATIC') set.durationSeconds = 60; if (t.type === 'CARDIO' || t.type === 'LONG_JUMP') set.distanceMeters = 100; if (t.type === 'HIGH_JUMP') set.height = 150; return set; }); const sessionResp = await request.post('/api/sessions', { data: { startTime: now, endTime: now + 3600000, type: 'STANDARD', // History shows STANDARD sessions differently than QUICK_LOG sets: setsStub }, headers: { 'Authorization': `Bearer ${user.token}` } }); if (!sessionResp.ok()) { console.log('Session Create Error:', await sessionResp.text()); } expect(sessionResp.ok()).toBeTruthy(); // Go to History await page.getByRole('button', { name: 'History' }).first().click(); // Find the session card and click Edit (Pencil icon) // There should be only one session await page.locator('.lucide-pencil').first().click(); await expect(page.getByText('Edit', { exact: true })).toBeVisible(); // Now verify fields for each exercise in the modal for (const t of types) { const exRow = page.locator('div').filter({ hasText: t.name }).last(); // Find the row for this exercise // This locator might be tricky if the row structure is complex. // In History.tsx: // {editingSession.sets.map((set, idx) => ( //
// ... {set.exerciseName} ... //
inputs here
//
// ))} // So we find the container that has the exercise name, then look for inputs inside it. const row = page.locator('.bg-surface-container-low').filter({ hasText: t.name }).first(); await expect(row).toBeVisible(); console.log(`Checking fields for ${t.type} (${t.name})...`); for (const field of t.expectedFields) { // Map field name to label text actually used in History.tsx // t('weight_kg', lang) -> "Weight" (assuming en) // t('reps', lang) -> "Reps" // t('time_sec', lang) -> "Time" // t('dist_m', lang) -> "Distance" // t('height_cm', lang) -> "Height" // t('body_weight_percent', lang) -> "Body Weight %" let labelPattern: RegExp; if (field === 'Weight') labelPattern = /Weight/i; else if (field === 'Reps') labelPattern = /Reps/i; else if (field === 'Time') labelPattern = /Time/i; else if (field === 'Distance') labelPattern = /Distance|Dist/i; else if (field === 'Height') labelPattern = /Height/i; else if (field === 'Body Weight') labelPattern = /Body Weight/i; else labelPattern = new RegExp(field, 'i'); await expect(row.getByLabel(labelPattern).first()).toBeVisible({ timeout: 2000 }) .catch(() => { throw new Error(`Missing field '${field}' for type '${t.type}'`); }); } } }); });