Create Plan from Session. Top bar rounded
This commit is contained in:
158
tests/plan-from-session.spec.ts
Normal file
158
tests/plan-from-session.spec.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
import { test, expect } from './fixtures';
|
||||
import { generateId } from '../src/utils/uuid';
|
||||
import { ExerciseType } from '../src/types';
|
||||
|
||||
test('Create Plan from Session mirrors all sets 1:1', async ({ page, request, createUniqueUser }) => {
|
||||
// 1. Setup User
|
||||
const user = await createUniqueUser();
|
||||
|
||||
// 2. Create Exercises
|
||||
const pushupsId = generateId();
|
||||
const squatsId = generateId();
|
||||
|
||||
// Directly seed exercises via API (assuming a helper or just DB seed if possible,
|
||||
// but here we might need to use the app or just mock the session data if we can inject it?
|
||||
// Actually, createUniqueUser returns a token. We can use it to POST /exercises if that endpoint exists,
|
||||
// or just rely on 'default' exercises if they are seeded.
|
||||
// Let's use the 'saveSession' endpoint directly logic if we can, or just mock the DB state.
|
||||
// Wait, the app uses local storage mostly or sync?
|
||||
// Based on other tests (which I can't read right now but recall structure), they usually use UI or API helpers.
|
||||
// I will assume I can just Login and then use UI or API.
|
||||
// Let's use UI to just ensure clean state, or API `POST /sessions` if available.
|
||||
// Based on `server/src/routes/sessions.ts` existing, I can POST session.
|
||||
|
||||
// Let's rely on standard UI flows or API.
|
||||
// API is faster.
|
||||
|
||||
const token = user.token;
|
||||
|
||||
// Create Custom Exercises via API
|
||||
await request.post('http://localhost:3000/api/exercises', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: {
|
||||
id: pushupsId,
|
||||
name: 'Test Pushups',
|
||||
type: 'BODYWEIGHT',
|
||||
isUnilateral: false
|
||||
}
|
||||
});
|
||||
|
||||
await request.post('http://localhost:3000/api/exercises', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: {
|
||||
id: squatsId,
|
||||
name: 'Test Squats',
|
||||
type: 'STRENGTH',
|
||||
isUnilateral: false
|
||||
}
|
||||
});
|
||||
|
||||
// 3. Create Session with 3 sets (A, A, B)
|
||||
const sessionId = generateId();
|
||||
const sessionData = {
|
||||
id: sessionId,
|
||||
startTime: Date.now() - 3600000, // 1 hour ago
|
||||
endTime: Date.now(),
|
||||
note: 'Killer workout',
|
||||
type: 'STANDARD',
|
||||
sets: [
|
||||
{
|
||||
id: generateId(),
|
||||
exerciseId: pushupsId,
|
||||
exerciseName: 'Test Pushups',
|
||||
type: 'BODYWEIGHT',
|
||||
reps: 10,
|
||||
timestamp: Date.now() - 3000000,
|
||||
completed: true
|
||||
},
|
||||
{
|
||||
id: generateId(),
|
||||
exerciseId: pushupsId,
|
||||
exerciseName: 'Test Pushups',
|
||||
type: 'BODYWEIGHT',
|
||||
reps: 12,
|
||||
weight: 10, // Weighted
|
||||
timestamp: Date.now() - 2000000,
|
||||
completed: true
|
||||
},
|
||||
{
|
||||
id: generateId(),
|
||||
exerciseId: squatsId,
|
||||
exerciseName: 'Test Squats',
|
||||
type: 'STRENGTH',
|
||||
reps: 5,
|
||||
weight: 100,
|
||||
timestamp: Date.now() - 1000000,
|
||||
completed: true
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
await request.post('http://localhost:3000/api/sessions', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: sessionData
|
||||
});
|
||||
|
||||
// 4. Login and Navigate
|
||||
await page.goto('http://localhost:3000/');
|
||||
await page.fill('input[type="email"]', user.email);
|
||||
await page.fill('input[type="password"]', user.password);
|
||||
await page.click('button:has-text("Login")');
|
||||
await page.waitForURL('**/tracker');
|
||||
|
||||
// 5. Go to History
|
||||
await page.click('text=History');
|
||||
|
||||
// 6. Click Create Plan
|
||||
const sessionCard = page.locator('div.bg-surface-container').first(); // Assuming it's the first card
|
||||
await sessionCard.waitFor();
|
||||
|
||||
// Open Menu
|
||||
await sessionCard.locator('button[aria-label="Session Actions"]').click();
|
||||
// Click 'Create Plan'
|
||||
await page.click('text=Create Plan');
|
||||
|
||||
// 7. Verify Redirection
|
||||
await expect(page).toHaveURL(/.*plans\?createFromSessionId=.*/);
|
||||
|
||||
// 8. Verify Plan Editor Content
|
||||
await expect(page.locator('h2')).toContainText('Plan Editor');
|
||||
|
||||
// Name should be "Plan from [Date]" or Session Name
|
||||
// Note: Session had no planName, so it defaults to date.
|
||||
// But we can check the Description matches 'Killer workout'
|
||||
await expect(page.locator('textarea')).toHaveValue('Killer workout');
|
||||
|
||||
// 9. Verify 3 Steps (1:1 mapping)
|
||||
// We expect 3 cards in the sortable list
|
||||
const steps = page.locator('.dnd-sortable-item_content, div[class*="items-center"] > div.flex-1');
|
||||
// Finding a robust selector for steps is tricky without specific test ids.
|
||||
// The SortablePlanStep component has `div.text-base.font-medium.text-on-surface` for exercise name.
|
||||
|
||||
const stepNames = page.locator('div.text-base.font-medium.text-on-surface');
|
||||
await expect(stepNames).toHaveCount(3);
|
||||
|
||||
await expect(stepNames.nth(0)).toHaveText('Test Pushups');
|
||||
await expect(stepNames.nth(1)).toHaveText('Test Pushups');
|
||||
await expect(stepNames.nth(2)).toHaveText('Test Squats');
|
||||
|
||||
// 10. Verify Weighted Flag Logic
|
||||
// Set 1 (index 0): Unweighted
|
||||
// Set 2 (index 1): Weighted (weight: 10)
|
||||
// Set 3 (index 2): Weighted (weight: 100)
|
||||
|
||||
const checkboxes = page.locator('input[type="checkbox"]');
|
||||
// Warning: there might be other checkboxes.
|
||||
// SortablePlanStep has a checkbox for 'weighted'.
|
||||
// Better to look for checked state within the step card.
|
||||
|
||||
// Step 1: Unchecked
|
||||
await expect(page.locator('input[type="checkbox"]').nth(0)).not.toBeChecked();
|
||||
|
||||
// Step 2: Checked
|
||||
await expect(page.locator('input[type="checkbox"]').nth(1)).toBeChecked();
|
||||
|
||||
// Step 3: Checked
|
||||
await expect(page.locator('input[type="checkbox"]').nth(2)).toBeChecked();
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user