From bc9b685decc88e165ffab3372a7dc12bd0d1f71a Mon Sep 17 00:00:00 2001 From: AG Date: Tue, 9 Dec 2025 21:45:35 +0200 Subject: [PATCH] Data and Progress tests done --- server/prisma/test.db | Bin 864256 -> 958464 bytes tests/data-progress.spec.ts | 397 ++++++++++++++++++++++++++++++++++++ tests/test-1.spec.ts | 5 - tests/test-2.spec.ts | 36 ---- 4 files changed, 397 insertions(+), 41 deletions(-) create mode 100644 tests/data-progress.spec.ts delete mode 100644 tests/test-1.spec.ts delete mode 100644 tests/test-2.spec.ts diff --git a/server/prisma/test.db b/server/prisma/test.db index d4e88093a5be7b06cec1772fc99363431aec25c8..9121a76ed5807336b6bdd71c4b832215c7038ce3 100644 GIT binary patch delta 92583 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

T^b1m#L3l>$>S6{*)kT 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¬H2D_F9S7(zG@mPm%B`x=+TDk@YR^~^inz}aU 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 delta 18137 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 diff --git a/tests/data-progress.spec.ts b/tests/data-progress.spec.ts new file mode 100644 index 0000000..a9962fd --- /dev/null +++ b/tests/data-progress.spec.ts @@ -0,0 +1,397 @@ +import { test, expect } from './fixtures'; +import { randomUUID } from 'crypto'; + +// Helper for setup +async function loginAndSetup(page: any, createUniqueUser: any) { + const user = await createUniqueUser(); + await page.goto('/'); + await page.getByLabel('Email').fill(user.email); + await page.getByLabel('Password').fill(user.password); + await page.getByRole('button', { name: 'Login' }).click(); + + try { + const heading = page.getByRole('heading', { name: /Change Password/i }); + const dashboard = page.getByText('Free Workout'); + await expect(heading.or(dashboard)).toBeVisible({ timeout: 5000 }); + 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) { + // Login might already be done + } + return user; +} + +test.describe('IV. Data & Progress', () => { + + test('4.1. A. Session History - View Past Sessions', async ({ page, createUniqueUser, request }) => { + const user = await loginAndSetup(page, createUniqueUser); + + // Subtask 2.1: Complete a workout session + const exNameSession = 'Hist View Session ' + randomUUID().slice(0, 4); + await request.post('/api/exercises', { + data: { name: exNameSession, type: 'STRENGTH' }, + headers: { 'Authorization': `Bearer ${user.token}` } + }); + + await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click(); + + await page.getByRole('textbox', { name: /Select Exercise/i }).click(); + await page.getByText(exNameSession).click(); + + await page.getByLabel('Weight (kg)').first().fill('50'); + await page.getByLabel('Reps').first().fill('10'); + await page.getByRole('button', { name: /Log Set/i }).click(); + + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Confirm' }).click(); + + // Subtask 2.2: Log a sporadic set + const exNameSporadic = 'Hist View Sporadic ' + randomUUID().slice(0, 4); + await request.post('/api/exercises', { + data: { name: exNameSporadic, type: 'STRENGTH' }, + headers: { 'Authorization': `Bearer ${user.token}` } + }); + + await page.getByRole('button', { name: 'Quick Log' }).click(); + await page.getByRole('textbox', { name: /Select Exercise/i }).click(); + await page.getByText(exNameSporadic).click(); + + await page.getByLabel(/Reps/i).first().fill('12'); + await page.getByRole('button', { name: /Log Set/i }).click(); + + await page.getByRole('button', { name: 'Quit' }).click(); + + // 3. Navigate to History + await page.getByRole('button', { name: 'History' }).click(); + + // Verification + await expect(page.getByRole('heading', { name: 'History' })).toBeVisible(); + + // Check for Quick Log entry details + await expect(page.getByText(/50\s*kg\s*x\s*12\s*reps/).or(page.getByText(/x 12 reps/))).toBeVisible(); + + // Check for Workout Session entry (shows summary) + await expect(page.getByText('No plan').first()).toBeVisible(); + await expect(page.getByText('Sets:').first()).toBeVisible(); + + // Check for Quick Log heading + await expect(page.getByRole('heading', { name: 'Quick Log' })).toBeVisible(); + }); + + test('4.2. A. Session History - View Detailed Session', async ({ page, createUniqueUser, request }) => { + const user = await loginAndSetup(page, createUniqueUser); + + const exName = 'Detail View ' + randomUUID().slice(0, 4); + await request.post('/api/exercises', { + data: { name: exName, type: 'STRENGTH' }, + headers: { 'Authorization': `Bearer ${user.token}` } + }); + + // Complete session + await page.getByRole('button', { name: /Free Workout|Start Empty/i }).click(); + await page.getByRole('textbox', { name: /Select Exercise/i }).click(); + await page.getByText(exName).click(); + + await page.getByLabel('Weight (kg)').first().fill('50'); + await page.getByLabel('Reps').first().fill('10'); + await page.getByRole('button', { name: /Log Set/i }).click(); + + await expect(page.getByText('50 kg x 10 reps')).toBeVisible(); + + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Confirm' }).click(); + + // Navigate to History + await page.getByRole('button', { name: 'History' }).click(); + + // Click on a workout session entry + await page.getByText('No plan').first().click(); + + // Verification + await expect(page.getByRole('heading', { name: /Edit|Session Details/ })).toBeVisible(); + + // Check details + await expect(page.getByText('Start')).toBeVisible(); + await expect(page.getByText('End')).toBeVisible(); + await expect(page.getByText('Weight (kg)').first()).toBeVisible(); + + // Verify set details + await expect(page.getByRole('heading', { name: /Sets/ })).toBeVisible(); + }); + + test('4.3. A. Session History - Edit Past Session Details', async ({ page, createUniqueUser, request }) => { + const user = await loginAndSetup(page, createUniqueUser); + + const exName = 'Edit Sess ' + randomUUID().slice(0, 4); + await request.post('/api/exercises', { data: { name: exName, type: 'STRENGTH' }, headers: { 'Authorization': `Bearer ${user.token}` } }); + + await page.getByRole('button', { name: /Free Workout/i }).click(); + await page.getByRole('textbox', { name: /Select/i }).click(); + await page.getByText(exName).click(); + + await page.getByLabel(/Weight/i).first().fill('50'); + await page.getByLabel(/Reps/i).first().fill('10'); + await page.getByRole('button', { name: /Log/i }).click(); + + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Confirm' }).click(); + + await page.getByRole('button', { name: 'History' }).click(); + + // Open details + await page.getByText('No plan').first().click(); + + // Modify Body Weight (first spinbutton usually) + await page.getByRole('spinbutton').first().fill('75.5'); + + // Save + await page.getByRole('button', { name: 'Save' }).click(); + + // Verify + await expect(page.getByText('75.5kg')).toBeVisible(); + }); + + test('4.4. A. Session History - Edit Individual Set in Past Session', async ({ page, createUniqueUser, request }) => { + const user = await loginAndSetup(page, createUniqueUser); + + const exName = 'Edit Set ' + randomUUID().slice(0, 4); + await request.post('/api/exercises', { data: { name: exName, type: 'STRENGTH' }, headers: { 'Authorization': `Bearer ${user.token}` } }); + + await page.getByRole('button', { name: /Free Workout/i }).click(); + await page.getByRole('textbox', { name: /Select/i }).click(); + await page.getByText(exName).click(); + + await page.getByLabel(/Weight/i).first().fill('50'); + await page.getByLabel(/Reps/i).first().fill('10'); + await page.getByRole('button', { name: /Log/i }).click(); + + await expect(page.getByText('50 kg x 10 reps')).toBeVisible(); + + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Confirm' }).click(); + + await page.getByRole('button', { name: 'History' }).click(); + + // Open details + await page.getByText('No plan').first().click(); + + // Modify weight from 50 to 55 + // Be specific with locator if possible, or use first matching input + await page.locator('input[value="50"]').fill('55'); + + // Save + await page.getByRole('button', { name: 'Save' }).click(); + + // Verify + await page.getByText('No plan').first().click(); + await expect(page.locator('input[value="55"]')).toBeVisible(); + }); + + test('4.5. A. Session History - Delete Past Session', async ({ page, createUniqueUser, request }) => { + const user = await loginAndSetup(page, createUniqueUser); + + const exName = 'Del Sess ' + randomUUID().slice(0, 4); + await request.post('/api/exercises', { data: { name: exName, type: 'STRENGTH' }, headers: { 'Authorization': `Bearer ${user.token}` } }); + + await page.getByRole('button', { name: /Free Workout/i }).click(); + await page.getByRole('textbox', { name: /Select/i }).click(); + await page.getByText(exName).click(); + + await page.getByLabel(/Weight/i).first().fill('50'); + await page.getByLabel(/Reps/i).first().fill('10'); + await page.getByRole('button', { name: /Log/i }).click(); + + await expect(page.getByText('50 kg x 10 reps')).toBeVisible(); + + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Confirm' }).click(); + + await page.getByRole('button', { name: 'History' }).click(); + await expect(page.getByText('No plan').first()).toBeVisible(); + + // Delete (2nd button usually) + await page.getByRole('main').getByRole('button').nth(1).click(); + + // Confirm + await expect(page.getByRole('heading', { name: 'Delete workout?' })).toBeVisible(); + await page.getByRole('button', { name: 'Delete' }).click(); + + // Verify empty + await expect(page.getByText('History is empty')).toBeVisible(); + }); + + test('4.6. A. Session History - Edit Sporadic Set', async ({ page, createUniqueUser, request }) => { + const user = await loginAndSetup(page, createUniqueUser); + + const exName = 'Spor Edit ' + randomUUID().slice(0, 4); + await request.post('/api/exercises', { data: { name: exName, type: 'STRENGTH' }, headers: { 'Authorization': `Bearer ${user.token}` } }); + + await page.getByRole('button', { name: 'Quick Log' }).click(); + await page.getByRole('textbox', { name: /Select/i }).click(); + await page.getByText(exName).click(); + + await page.getByLabel(/Weight/i).first().fill('50'); + await page.getByLabel(/Reps/i).first().fill('12'); + await page.getByRole('button', { name: /Log/i }).click(); + await page.getByRole('button', { name: 'Quit' }).click(); + + await page.getByRole('button', { name: 'History' }).click(); + await expect(page.getByRole('heading', { name: 'Quick Log' })).toBeVisible(); + + // Edit (1st button for sporadic row) + await page.getByRole('main').getByRole('button').nth(0).click(); + + await expect(page.getByRole('heading', { name: 'Edit' })).toBeVisible(); + await page.locator('input[value="12"]').fill('15'); + await page.getByRole('button', { name: 'Save' }).click(); + + await expect(page.getByText(/50\s*kg\s*x\s*15\s*reps/)).toBeVisible(); + }); + + test('4.7. A. Session History - Delete Sporadic Set', async ({ page, createUniqueUser, request }) => { + const user = await loginAndSetup(page, createUniqueUser); + + const exName = 'Spor Del ' + randomUUID().slice(0, 4); + await request.post('/api/exercises', { data: { name: exName, type: 'STRENGTH' }, headers: { 'Authorization': `Bearer ${user.token}` } }); + + await page.getByRole('button', { name: 'Quick Log' }).click(); + await page.getByRole('textbox', { name: /Select/i }).click(); + await page.getByText(exName).click(); + await page.getByLabel(/Weight/i).first().fill('50'); + await page.getByLabel(/Reps/i).first().fill('12'); + await page.getByRole('button', { name: /Log/i }).click(); + await page.getByRole('button', { name: 'Quit' }).click(); + + await page.getByRole('button', { name: 'History' }).click(); + + // Delete (2nd button for sporadic row, or last button in main if only one row) + // With only one row, buttons are Edit, Delete. Delete is 2nd. + await page.getByRole('main').getByRole('button').last().click(); + + await expect(page.getByRole('dialog')).toBeVisible(); + await page.getByRole('button', { name: 'Delete' }).click(); + + await expect(page.getByText('50 kg x 12 reps')).not.toBeVisible(); + }); + + test('4.8. B. Performance Statistics - View Volume Chart', async ({ page, createUniqueUser, request }) => { + test.setTimeout(120000); + const user = await loginAndSetup(page, createUniqueUser); + const exName = 'Vol Chart ' + randomUUID().slice(0, 4); + await request.post('/api/exercises', { data: { name: exName, type: 'STRENGTH' }, headers: { 'Authorization': `Bearer ${user.token}` } }); + + // Session 1 + await page.getByRole('button', { name: /Free Workout/i }).click(); + await page.getByRole('textbox', { name: /Select/i }).click(); + await page.getByText(exName).click(); + await page.getByLabel(/Weight/i).first().fill('50'); + await page.getByLabel(/Reps/i).first().fill('10'); + await page.getByRole('button', { name: /Log/i }).click(); + + await expect(page.getByText('50 kg x 10 reps')).toBeVisible(); + + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Confirm' }).click(); + + // Session 2 + await page.getByRole('button', { name: /Free Workout/i }).click(); + await page.getByRole('textbox', { name: /Select/i }).click(); + await page.getByText(exName).click(); + await page.getByLabel(/Weight/i).first().fill('60'); + await page.getByLabel(/Reps/i).first().fill('10'); + await page.getByRole('button', { name: /Log/i }).click(); + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Confirm' }).click(); + + await page.getByRole('button', { name: 'Stats' }).click(); + await expect(page.getByText('Work Volume')).toBeVisible(); + }); + + test('4.9. B. Performance Statistics - View Set Count Chart', async ({ page, createUniqueUser, request }) => { + test.setTimeout(120000); + const user = await loginAndSetup(page, createUniqueUser); + const exName = 'Set Chart ' + randomUUID().slice(0, 4); + await request.post('/api/exercises', { data: { name: exName, type: 'STRENGTH' }, headers: { 'Authorization': `Bearer ${user.token}` } }); + + // Session 1 + await page.getByRole('button', { name: /Free Workout/i }).click(); + await page.getByRole('textbox', { name: /Select/i }).click(); + await page.getByText(exName).click(); + await page.getByLabel(/Weight/i).first().fill('50'); + await page.getByLabel(/Reps/i).first().fill('10'); + await page.getByRole('button', { name: /Log/i }).click(); + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Confirm' }).click(); + + // Session 2 + await page.getByRole('button', { name: /Free Workout/i }).click(); + await page.getByRole('textbox', { name: /Select/i }).click(); + await page.getByText(exName).click(); + await page.getByLabel(/Weight/i).first().fill('60'); + await page.getByLabel(/Reps/i).first().fill('10'); + await page.getByRole('button', { name: /Log/i }).click(); + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Confirm' }).click(); + + await page.getByRole('button', { name: 'Stats' }).click(); + await expect(page.getByText('Number of Sets')).toBeVisible(); + }); + + test('4.10. B. Performance Statistics - View Body Weight Chart', async ({ page, createUniqueUser, request }) => { + test.setTimeout(120000); + const user = await loginAndSetup(page, createUniqueUser); + const exName = 'BW Chart ' + randomUUID().slice(0, 4); + await request.post('/api/exercises', { data: { name: exName, type: 'STRENGTH' }, headers: { 'Authorization': `Bearer ${user.token}` } }); + + // Complete 2 sessions (to unlock stats page - assuming constraint) + // Session 1 + await page.getByRole('button', { name: /Free Workout/i }).click(); + await page.getByRole('textbox', { name: /Select/i }).click(); + await page.getByText(exName).click(); + await page.getByLabel(/Weight/i).first().fill('50'); + await page.getByLabel(/Reps/i).first().fill('10'); + await page.getByRole('button', { name: /Log/i }).click(); + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Confirm' }).click(); + + // Session 2 + await page.getByRole('button', { name: /Free Workout/i }).click(); + await page.getByRole('textbox', { name: /Select/i }).click(); + await page.getByText(exName).click(); + await page.getByLabel(/Weight/i).first().fill('60'); + await page.getByLabel(/Reps/i).first().fill('10'); + await page.getByRole('button', { name: /Log/i }).click(); + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Confirm' }).click(); + + // Log body weight history via API + const yesterday = new Date(); + yesterday.setDate(yesterday.getDate() - 1); + const dateStr = yesterday.toISOString().split('T')[0]; + + await page.evaluate(async ({ token, dateStr }) => { + await fetch('/api/weight', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }, + body: JSON.stringify({ weight: 70, dateStr }) + }); + }, { token: user.token, dateStr }); + + // Log today's weight via UI + await page.getByRole('button', { name: 'Profile' }).click(); + await page.getByRole('button', { name: 'Weight Tracker' }).click(); + await page.getByPlaceholder('Enter weight...').fill('72'); + await page.getByRole('button', { name: 'Log', exact: true }).click(); + await expect(page.getByText('Weight logged successfully')).toBeVisible(); + + await page.getByRole('button', { name: 'Stats' }).click(); + await expect(page.getByText('Body Weight History')).toBeVisible(); + }); + +}); diff --git a/tests/test-1.spec.ts b/tests/test-1.spec.ts deleted file mode 100644 index 5b3d48c..0000000 --- a/tests/test-1.spec.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { test, expect } from '@playwright/test'; - -test('test', async ({ page }) => { - // Recording... -}); \ No newline at end of file diff --git a/tests/test-2.spec.ts b/tests/test-2.spec.ts deleted file mode 100644 index d3f129d..0000000 --- a/tests/test-2.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { test, expect } from '@playwright/test'; - -test('test', async ({ page }) => { - await page.goto('http://localhost:3000/login'); - await page.getByRole('textbox', { name: 'Email' }).click(); - await page.getByRole('textbox', { name: 'Email' }).fill('admin@gymflow.ai'); - await page.getByRole('textbox', { name: 'Email' }).press('Tab'); - await page.getByRole('textbox', { name: 'Password' }).fill('admin123'); - await page.getByRole('button', { name: 'Login' }).click(); - await page.getByRole('button', { name: 'Plans' }).click(); - await page.getByRole('button', { name: 'Create Plan' }).click(); - await page.getByRole('textbox', { name: 'Name' }).click(); - await page.getByRole('textbox', { name: 'Name' }).fill('Smart Plan'); - await page.getByRole('button', { name: 'Add Exercise' }).click(); - await page.getByRole('button').filter({ hasText: /^$/ }).nth(2).click(); - await page.locator('[id="_r_3_"]').fill('Exercise A'); - await page.getByRole('button', { name: 'Create' }).click(); - await page.getByRole('button', { name: 'Add Exercise' }).click(); - await page.getByRole('button').filter({ hasText: /^$/ }).nth(3).click(); - await page.locator('[id="_r_4_"]').fill('Exercise B'); - await page.getByRole('button', { name: 'Create' }).click(); - await page.getByRole('button', { name: 'Save' }).click(); - await page.getByRole('button', { name: 'Start' }).nth(1).click(); - await page.getByRole('spinbutton', { name: 'Weight (kg)' }).click(); - await page.getByRole('spinbutton', { name: 'Weight (kg)' }).fill('12'); - await page.getByRole('spinbutton', { name: 'Reps' }).click(); - await page.getByRole('spinbutton', { name: 'Reps' }).fill('13'); - await page.getByRole('button', { name: 'Log Set' }).click(); - await page.getByRole('spinbutton', { name: 'Weight (kg)' }).click(); - await page.getByRole('spinbutton', { name: 'Weight (kg)' }).fill('13'); - await page.getByRole('spinbutton', { name: 'Reps' }).click(); - await page.getByRole('spinbutton', { name: 'Reps' }).fill('14'); - await page.getByRole('button', { name: 'Log Set' }).click(); - await page.getByRole('button', { name: 'Finish' }).click(); - await page.getByRole('button', { name: 'Confirm' }).click(); -}); \ No newline at end of file