AI Plan generation enhanced

This commit is contained in:
AG
2025-12-16 11:24:09 +02:00
parent 8d4eed77ea
commit cb0bd1a55d
4 changed files with 305 additions and 70 deletions

View File

@@ -0,0 +1,106 @@
import { test, expect } from './fixtures';
import { randomUUID } from 'crypto';
test.describe('AI Plan Creation', () => {
test('2.14 A. Workout Plans - Create Plan with AI (Parametrized)', async ({ page, createUniqueUser }) => {
const user = await loginAndSetup(page, createUniqueUser);
// Mock the AI endpoint
await page.route('**/api/ai/chat', async route => {
const plan = {
name: 'AI Advanced Plan',
description: 'Generated High Intensity Plan',
exercises: [
{ name: 'Mock Push-ups', isWeighted: false, restTimeSeconds: 60, type: 'BODYWEIGHT', unilateral: false },
{ name: 'Mock Weighted Pull-ups', isWeighted: true, restTimeSeconds: 90, type: 'BODYWEIGHT', unilateral: false }
]
};
// The service expects { response: "string_or_json" }
await route.fulfill({
json: {
response: JSON.stringify(plan)
}
});
});
// Navigate to Plans
await page.getByRole('button', { name: 'Plans' }).first().click();
// Click FAB to open menu
const fab = page.getByLabel('Create Plan').or(page.getByRole('button', { name: '+' }));
await fab.click();
// Click "With AI"
await page.getByRole('button', { name: 'With AI' }).click();
// Verify Defaults
await expect(page.getByText('Create Plan with AI')).toBeVisible();
// Equipment default: No equipment
// Checking visual state might be hard if it's custom styled, but we can check the selected button style or text
const eqSection = page.locator('div').filter({ hasText: 'Equipment' }).last();
// Assuming "No equipment" is selected. We can check class or aria-pressed if available, or just proceed to change it.
// Level default: Intermediate
const levelSection = page.locator('div').filter({ hasText: 'Level' }).last();
// Just verify buttons exist
await expect(levelSection.getByRole('button', { name: 'Intermediate' })).toBeVisible();
// Intensity default: Moderate
const intensitySection = page.locator('div').filter({ hasText: 'Intensity' }).last();
await expect(intensitySection.getByRole('button', { name: 'Moderate' })).toBeVisible();
// Modify Inputs
// Change Level to Advanced
await levelSection.getByRole('button', { name: 'Advanced' }).click();
// Change Intensity to High
await intensitySection.getByRole('button', { name: 'High' }).click();
// Change Equipment to Free Weights
await eqSection.getByRole('button', { name: /Free weights/i }).click();
// Click Generate
await page.getByRole('button', { name: 'Generate' }).click();
// Verify Preview
// Wait for preview to appear (mock response)
await expect(page.getByText('Generated Plan')).toBeVisible({ timeout: 10000 });
await expect(page.getByText('Mock Push-ups')).toBeVisible();
await expect(page.getByText('Mock Weighted Pull-ups')).toBeVisible();
// Icons check (weighted vs bodyweight) - optional visual check
// Click Save Plan
await page.getByRole('button', { name: 'Save Plan' }).click();
// Verify Saved
// Should close sheet and show plan list
await expect(page.getByText('AI Advanced Plan')).toBeVisible();
await expect(page.getByText('Generated High Intensity Plan')).toBeVisible();
});
});
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 or dashboard loaded fast
}
return user;
}