Massive backend refactoring done

This commit is contained in:
AG
2025-12-10 14:56:20 +02:00
parent 502943f7d0
commit 95a5e37748
47 changed files with 1898 additions and 1416 deletions

View File

@@ -50,6 +50,8 @@ test.describe('I. Core & Authentication', () => {
}
console.log('Failed to handle first login. Dumping page content...');
const fs = require('fs'); // Playwright runs in Node
await fs.writeFileSync('auth_failure.html', await page.content());
console.log(await page.content());
throw e;
}

View File

@@ -93,7 +93,7 @@ test.describe('IV. Data & Progress', () => {
// 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.getByRole('button', { name: exName }).click();
await page.getByLabel('Weight (kg)').first().fill('50');
await page.getByLabel('Reps').first().fill('10');
@@ -130,7 +130,7 @@ test.describe('IV. Data & Progress', () => {
await page.getByRole('button', { name: /Free Workout/i }).click();
await page.getByRole('textbox', { name: /Select/i }).click();
await page.getByText(exName).click();
await page.getByRole('button', { name: exName }).click();
await page.getByLabel(/Weight/i).first().fill('50');
await page.getByLabel(/Reps/i).first().fill('10');
@@ -162,7 +162,7 @@ test.describe('IV. Data & Progress', () => {
await page.getByRole('button', { name: /Free Workout/i }).click();
await page.getByRole('textbox', { name: /Select/i }).click();
await page.getByText(exName).click();
await page.getByRole('button', { name: exName }).click();
await page.getByLabel(/Weight/i).first().fill('50');
await page.getByLabel(/Reps/i).first().fill('10');
@@ -198,7 +198,7 @@ test.describe('IV. Data & Progress', () => {
await page.getByRole('button', { name: /Free Workout/i }).click();
await page.getByRole('textbox', { name: /Select/i }).click();
await page.getByText(exName).click();
await page.getByRole('button', { name: exName }).click();
await page.getByLabel(/Weight/i).first().fill('50');
await page.getByLabel(/Reps/i).first().fill('10');
@@ -231,7 +231,7 @@ test.describe('IV. Data & Progress', () => {
await page.getByRole('button', { name: 'Quick Log' }).click();
await page.getByRole('textbox', { name: /Select/i }).click();
await page.getByText(exName).click();
await page.getByRole('button', { name: exName }).click();
await page.getByLabel(/Weight/i).first().fill('50');
await page.getByLabel(/Reps/i).first().fill('12');
@@ -259,7 +259,7 @@ test.describe('IV. Data & Progress', () => {
await page.getByRole('button', { name: 'Quick Log' }).click();
await page.getByRole('textbox', { name: /Select/i }).click();
await page.getByText(exName).click();
await page.getByRole('button', { name: 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();
@@ -286,7 +286,7 @@ test.describe('IV. Data & Progress', () => {
// 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.getByRole('button', { name: 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();
@@ -299,7 +299,7 @@ test.describe('IV. Data & Progress', () => {
// 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.getByRole('button', { name: 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();
@@ -319,7 +319,7 @@ test.describe('IV. Data & Progress', () => {
// 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.getByRole('button', { name: 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();
@@ -329,7 +329,7 @@ test.describe('IV. Data & Progress', () => {
// 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.getByRole('button', { name: 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();
@@ -350,7 +350,7 @@ test.describe('IV. Data & Progress', () => {
// 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.getByRole('button', { name: 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();
@@ -360,7 +360,7 @@ test.describe('IV. Data & Progress', () => {
// 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.getByRole('button', { name: 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();

24
tests/debug_login.spec.ts Normal file
View File

@@ -0,0 +1,24 @@
import { test, expect } from './fixtures';
test('Debug Login Payload', async ({ page, createUniqueUser }) => {
const user = await createUniqueUser();
console.log('Created user:', user);
await page.goto('/');
// Intercept login request
await page.route('**/api/auth/login', async route => {
const request = route.request();
const postData = request.postDataJSON();
console.log('LOGIN REQUEST BODY:', JSON.stringify(postData, null, 2));
console.log('LOGIN REQUEST HEADERS:', JSON.stringify(request.headers(), null, 2));
await route.continue();
});
await page.getByLabel('Email').fill(user.email);
await page.getByLabel('Password').fill(user.password);
await page.getByRole('button', { name: 'Login' }).click();
// Wait a bit for request to happen
await page.waitForTimeout(3000);
});

View File

@@ -37,13 +37,13 @@ export const test = base.extend<MyFixtures>({
const body = await response.json();
// If registration fails because we hit a collision (unlikely) or other error, fail the test
if (!response.ok()) {
if (!response.ok() || !body.success) {
console.error(`REGISTRATION FAILED: ${response.status()} ${response.statusText()}`);
console.error(`RESPONSE BODY: ${JSON.stringify(body, null, 2)}`);
throw new Error(`Failed to register user: ${JSON.stringify(body)}`);
}
return { email, password, id: body.user.id, token: body.token };
return { email, password, id: body.data.user.id, token: body.data.token };
};
// Use the fixture
@@ -65,7 +65,7 @@ export const test = base.extend<MyFixtures>({
try {
const { stdout, stderr } = await exec(`npx ts-node promote_admin.ts ${user.email}`, {
cwd: 'server',
env: { ...process.env, APP_MODE: 'test', DATABASE_URL: 'file:./prisma/test.db', DATABASE_URL_TEST: 'file:./prisma/test.db' }
env: { ...process.env, APP_MODE: 'test', DATABASE_URL: 'file:d:/Coding/gymflow/server/test.db', DATABASE_URL_TEST: 'file:d:/Coding/gymflow/server/test.db' }
});
if (stderr) {
console.error(`Promote Admin Stderr: ${stderr}`);
@@ -74,8 +74,10 @@ export const test = base.extend<MyFixtures>({
if (!stdout.includes(`User ${user.email} promoted to ADMIN`)) {
throw new Error('Admin promotion failed or unexpected output.');
}
} catch (error) {
} catch (error: any) {
console.error(`Error promoting user ${user.email} to ADMIN:`, error);
if (error.stdout) console.log(`Failed CMD Stdout: ${error.stdout}`);
if (error.stderr) console.error(`Failed CMD Stderr: ${error.stderr}`);
throw error;
}
return user;

52
tests/smoke.spec.ts Normal file
View File

@@ -0,0 +1,52 @@
import { test, expect } from '@playwright/test';
test.describe('Smoke Tests - Backend Refactor', () => {
test('Login, Exercises, and Session Flow', async ({ request }) => {
const email = `smoke_${Date.now()}@example.com`;
const password = 'password123';
// 1. Register
const registerRes = await request.post('http://localhost:3001/api/auth/register', {
data: { email, password }
});
expect(registerRes.ok()).toBeTruthy();
const registerBody = await registerRes.json();
// Check new structure
expect(registerBody.success).toBe(true);
expect(registerBody.data).toHaveProperty('token');
const token = registerBody.data.token;
// 2. Get Exercises
const exercisesRes = await request.get('http://localhost:3001/api/exercises', {
headers: { Authorization: `Bearer ${token}` }
});
expect(exercisesRes.ok()).toBeTruthy();
const exercisesBody = await exercisesRes.json();
expect(exercisesBody.success).toBe(true);
expect(Array.isArray(exercisesBody.data)).toBe(true);
// 3. Create Session
const sessionRes = await request.post('http://localhost:3001/api/sessions', {
headers: { Authorization: `Bearer ${token}` },
data: {
id: "test-session-" + Date.now(),
startTime: new Date().toISOString(),
sets: []
}
});
expect(sessionRes.ok()).toBeTruthy();
const sessionBody = await sessionRes.json();
expect(sessionBody.success).toBe(true);
expect(sessionBody.data).toHaveProperty('id');
// 4. Get Active Session
const activeRes = await request.get('http://localhost:3001/api/sessions/active', {
headers: { Authorization: `Bearer ${token}` }
});
expect(activeRes.ok()).toBeTruthy();
const activeBody = await activeRes.json();
expect(activeBody.success).toBe(true);
expect(activeBody.data).toHaveProperty('session');
expect(activeBody.data.session.id).toBe(sessionBody.data.id);
});
});