Data and Progress tests done

This commit is contained in:
AG
2025-12-09 21:45:35 +02:00
parent 2352ac04d6
commit bc9b685dec
4 changed files with 397 additions and 41 deletions

Binary file not shown.

397
tests/data-progress.spec.ts Normal file
View File

@@ -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();
});
});

View File

@@ -1,5 +0,0 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
// Recording...
});

View File

@@ -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();
});