614 lines
28 KiB
TypeScript
614 lines
28 KiB
TypeScript
import { test, expect } from './fixtures';
|
|
import { exec as cp_exec } from 'child_process';
|
|
import { promisify } from 'util';
|
|
|
|
const exec = promisify(cp_exec);
|
|
|
|
test.describe('V. User & System Management', () => {
|
|
|
|
test('5.1. A. User Profile - Update Personal Information', async ({ page, createUniqueUser }) => {
|
|
// Seed: Log in as a regular user
|
|
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();
|
|
|
|
// Handle potential first-time login
|
|
try {
|
|
await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 });
|
|
if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) {
|
|
await page.getByLabel('New Password').fill('StrongNewPass123!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
}
|
|
} catch (e) {
|
|
// Ignore timeout if it proceeds
|
|
}
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
|
|
// 2. Navigate to the 'Profile' section.
|
|
await page.getByRole('button', { name: 'Profile' }).click();
|
|
|
|
// 3. Modify 'Weight', 'Height', 'Birth Date', and 'Gender'.
|
|
await page.getByTestId('profile-weight-input').fill('75');
|
|
await page.getByTestId('profile-height-input').fill('180');
|
|
await page.getByTestId('profile-birth-date').fill('1990-01-01');
|
|
await page.getByTestId('profile-gender').selectOption('FEMALE');
|
|
|
|
// 4. Click 'Save Profile'.
|
|
await page.getByRole('button', { name: 'Save Profile' }).click();
|
|
await expect(page.getByText('Profile saved successfully')).toBeVisible();
|
|
|
|
// Verify persistence
|
|
await page.reload();
|
|
// After reload, we might be on dashboard or profile depending on app routing, but let's ensure we go to profile
|
|
if (!await page.getByRole('heading', { name: 'Profile' }).isVisible()) {
|
|
await page.getByRole('button', { name: 'Profile' }).click();
|
|
}
|
|
|
|
// Verify values
|
|
await expect(page.getByTestId('profile-weight-input')).toHaveValue('75');
|
|
await expect(page.getByTestId('profile-height-input')).toHaveValue('180');
|
|
await expect(page.getByTestId('profile-birth-date')).toHaveValue('1990-01-01');
|
|
await expect(page.getByTestId('profile-gender')).toHaveValue('FEMALE');
|
|
});
|
|
|
|
test('5.2. A. User Profile - Change Password', async ({ page, createUniqueUser }) => {
|
|
// Seed: Log in as a regular user
|
|
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();
|
|
|
|
// Handle potential first-time login
|
|
try {
|
|
await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 });
|
|
if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) {
|
|
await page.getByLabel('New Password').fill('StrongNewPass123!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
}
|
|
} catch (e) {
|
|
// Ignore timeout
|
|
}
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
|
|
// 2. Navigate to the 'Profile' section.
|
|
await page.getByRole('button', { name: 'Profile' }).click();
|
|
|
|
// 3. Enter a new password (min 4 characters) in the 'Change Password' field.
|
|
const newPassword = 'NewStrongPass!';
|
|
await page.getByRole('textbox', { name: 'New Password' }).fill(newPassword);
|
|
|
|
// 4. Click 'OK'.
|
|
await page.getByRole('button', { name: 'OK' }).click();
|
|
await expect(page.getByText('Password changed')).toBeVisible();
|
|
|
|
// Verify: The user can log in with the new password.
|
|
// Logout first
|
|
await page.getByRole('button', { name: 'Logout' }).click();
|
|
|
|
// Login with new password
|
|
await page.getByRole('textbox', { name: 'Email' }).fill(user.email);
|
|
await page.getByRole('textbox', { name: 'Password' }).fill(newPassword);
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
});
|
|
|
|
test('5.3. A. User Profile - Change Password (Too Short)', async ({ page, createUniqueUser }) => {
|
|
// Seed
|
|
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 {
|
|
await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 });
|
|
if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) {
|
|
await page.getByLabel('New Password').fill('StrongNewPass123!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
}
|
|
} catch (e) { }
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
|
|
// 2. Navigate to Profile
|
|
await page.getByRole('button', { name: 'Profile' }).click();
|
|
|
|
// 3. Enter short password
|
|
await page.getByRole('textbox', { name: 'New Password' }).fill('123');
|
|
|
|
// 4. Click OK
|
|
await page.getByRole('button', { name: 'OK' }).click();
|
|
|
|
// Expect Error
|
|
await expect(page.getByText('Password too short')).toBeVisible();
|
|
});
|
|
|
|
test('5.4. A. User Profile - Dedicated Daily Weight Logging', async ({ page, createUniqueUser }) => {
|
|
// Seed
|
|
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 {
|
|
await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 });
|
|
if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) {
|
|
await page.getByLabel('New Password').fill('StrongNewPass123!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
}
|
|
} catch (e) { }
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
|
|
// 2. Navigate to Profile
|
|
await page.getByRole('button', { name: 'Profile' }).click();
|
|
|
|
// 3. Expand Weight Tracker
|
|
await page.getByRole('button', { name: 'Weight Tracker' }).click();
|
|
|
|
// 4. Enter weight
|
|
const weight = '72.3';
|
|
await page.getByPlaceholder('Enter weight...').fill(weight);
|
|
|
|
// 5. Click Log
|
|
await page.getByRole('button', { name: 'Log', exact: true }).click();
|
|
|
|
// Expect success message
|
|
await expect(page.getByText('Weight logged successfully')).toBeVisible();
|
|
|
|
// Expect record in history
|
|
await expect(page.getByText(`${weight} kg`)).toBeVisible();
|
|
|
|
// Check if profile weight updated
|
|
await expect(page.getByRole('spinbutton').first()).toHaveValue(weight);
|
|
});
|
|
|
|
|
|
|
|
test('5.5. A. User Profile - Language Preference Change', async ({ page, createUniqueUser }) => {
|
|
// 1. Log in as a regular user.
|
|
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();
|
|
|
|
// Handle First Time Password Change if it appears
|
|
try {
|
|
await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 });
|
|
if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) {
|
|
await page.getByLabel('New Password').fill('StrongNewPass123!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
}
|
|
} catch (e) {
|
|
// Ignore timeout
|
|
}
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
|
|
// 2. Navigate to the 'Profile' section.
|
|
await page.getByRole('button', { name: 'Profile' }).click();
|
|
|
|
// 3. Select a different language (e.g., 'Русский') from the language dropdown.
|
|
await page.getByRole('combobox').nth(1).selectOption(['ru']); // Value is 'ru'
|
|
|
|
// 4. Click 'Save Profile'.
|
|
await page.getByRole('button', { name: /Сохранить профиль|Save Profile/ }).click();
|
|
|
|
// Expected Results: The UI language immediately switches to the selected language.
|
|
await expect(page.getByRole('heading', { name: 'Профиль', exact: true })).toBeVisible();
|
|
await expect(page.getByText(/Profile saved|Профиль успешно/)).toBeVisible(); // Wait for persistence
|
|
|
|
await expect(page.getByRole('button', { name: 'Сохранить профиль' })).toBeVisible();
|
|
|
|
// Expected Results: The preference persists across sessions.
|
|
await page.reload();
|
|
|
|
// Check if we are still logged in or need to login
|
|
if (await page.getByLabel('Email').isVisible()) {
|
|
await page.getByLabel('Email').fill(user.email);
|
|
await page.getByLabel('Password').fill(user.password || 'StrongNewPass123!');
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
}
|
|
|
|
// Verify language is still Russian
|
|
await page.getByRole('button', { name: /Профиль|Profile/ }).click();
|
|
await expect(page.getByRole('heading', { name: 'Профиль', exact: true })).toBeVisible();
|
|
});
|
|
|
|
test('5.6. A. User Profile - Delete Own Account', async ({ page, createUniqueUser }) => {
|
|
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 {
|
|
await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 });
|
|
if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) {
|
|
await page.getByLabel('New Password').fill('StrongNewPass123!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
}
|
|
} catch (e) { }
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
|
|
await page.getByRole('button', { name: 'Profile' }).click();
|
|
await page.getByRole('button', { name: 'Delete' }).click();
|
|
|
|
await expect(page.getByText('Are you sure?')).toBeVisible();
|
|
await page.getByRole('button', { name: 'Delete', exact: true }).last().click();
|
|
|
|
await expect(page).toHaveURL(/\/login/);
|
|
await expect(page.getByRole('button', { name: 'Login' })).toBeVisible();
|
|
|
|
await page.getByLabel('Email').fill(user.email);
|
|
await page.getByLabel('Password').fill(user.password || 'StrongNewPass123!');
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
|
|
await expect(page.getByText(/Invalid credentials|User not found/i)).toBeVisible();
|
|
});
|
|
|
|
// --- Admin Panel Tests ---
|
|
|
|
test('5.7. B. Admin Panel - View User List', async ({ page, createAdminUser, request }) => {
|
|
test.setTimeout(120000); // Extend timeout for multiple user creation
|
|
const adminUser = await createAdminUser();
|
|
|
|
// Create 25 users to populate the list using Promise.all for parallelism
|
|
const createdEmails: string[] = [];
|
|
const creationPromises = [];
|
|
|
|
for (let i = 0; i < 25; i++) {
|
|
const uniqueId = Math.random().toString(36).substring(7);
|
|
const email = `list.user.${i}.${uniqueId}@example.com`;
|
|
const password = 'StrongPassword123!';
|
|
createdEmails.push(email);
|
|
|
|
creationPromises.push(request.post('/api/auth/register', {
|
|
data: { email, password }
|
|
}));
|
|
}
|
|
|
|
const responses = await Promise.all(creationPromises);
|
|
for (const response of responses) {
|
|
await expect(response).toBeOK();
|
|
}
|
|
|
|
await page.goto('/');
|
|
await page.getByLabel('Email').fill(adminUser.email);
|
|
await page.getByLabel('Password').fill(adminUser.password);
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
|
|
try {
|
|
await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 });
|
|
if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) {
|
|
await page.getByLabel('New Password').fill('StrongAdminNewPass123!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
}
|
|
} catch (e) { }
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
|
|
await page.getByRole('button', { name: 'Profile' }).click();
|
|
|
|
// Expand Users List (Admin Area is a header)
|
|
await page.getByRole('button', { name: /Users List|User List/i }).click();
|
|
|
|
await expect(page.getByText(/Users List/i)).toBeVisible();
|
|
|
|
// Verify all created users are visible in the list
|
|
for (const email of createdEmails) {
|
|
await expect(page.getByText(email)).toBeVisible();
|
|
}
|
|
});
|
|
|
|
test('5.8. B. Admin Panel - Create New User', async ({ page, createAdminUser }) => {
|
|
const adminUser = await createAdminUser();
|
|
await page.goto('/');
|
|
await page.getByLabel('Email').fill(adminUser.email);
|
|
await page.getByLabel('Password').fill(adminUser.password);
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
|
|
try {
|
|
await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 });
|
|
if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) {
|
|
await page.getByLabel('New Password').fill('StrongAdminNewPass123!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
}
|
|
} catch (e) { }
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
|
|
await page.getByRole('button', { name: 'Profile' }).click();
|
|
|
|
const uniqueId = Math.random().toString(36).substring(7);
|
|
const newUserEmail = `new.user.${uniqueId}@example.com`;
|
|
const newUserPassword = 'NewUserPass123!';
|
|
|
|
const createUserSection = page.locator('div').filter({ has: page.getByRole('heading', { name: 'Create User' }) }).last();
|
|
await createUserSection.getByLabel('Email').fill(newUserEmail);
|
|
await createUserSection.getByLabel('Password').fill(newUserPassword);
|
|
|
|
await page.getByRole('button', { name: /Create User|Create/i }).click();
|
|
|
|
await expect(page.getByText(/User created|successfully/i)).toBeVisible();
|
|
|
|
const userListButton = page.getByRole('button', { name: /Users List/i });
|
|
if (await userListButton.getAttribute('aria-expanded') !== 'true') {
|
|
await userListButton.click();
|
|
}
|
|
|
|
const listContainer = page.locator('div.space-y-4.mt-4');
|
|
await expect(listContainer).toBeVisible();
|
|
await expect(listContainer.getByText(newUserEmail)).toBeVisible();
|
|
});
|
|
|
|
test('5.9. B. Admin Panel - Block/Unblock User', async ({ page, createAdminUser, createUniqueUser }) => {
|
|
|
|
|
|
const adminUser = await createAdminUser();
|
|
|
|
// 1. Login as Admin
|
|
await page.goto('/');
|
|
await page.getByLabel('Email').fill(adminUser.email);
|
|
await page.getByLabel('Password').fill(adminUser.password);
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
|
|
try {
|
|
await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 });
|
|
if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) {
|
|
await page.getByLabel('New Password').fill('StrongAdminNewPass123!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
}
|
|
} catch (e) { }
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
console.log('Logged in as Admin');
|
|
|
|
// 2. Create a Regular User (via API)
|
|
const regularUser = await createUniqueUser();
|
|
console.log('Regular user created:', regularUser.email);
|
|
|
|
// 3. Navigate to Admin Panel -> User List
|
|
await page.getByRole('button', { name: 'Profile' }).filter({ visible: true }).click();
|
|
|
|
// Ensure list is open and valid
|
|
const userListButton = page.getByRole('button', { name: /Users List/i });
|
|
// Check expanded state and Open if currently closed
|
|
const isExpanded = await userListButton.getAttribute('aria-expanded');
|
|
if (isExpanded !== 'true') {
|
|
await userListButton.click();
|
|
}
|
|
await expect(userListButton).toHaveAttribute('aria-expanded', 'true');
|
|
console.log('User list is open');
|
|
|
|
// Always Refresh to ensure latest users are fetched
|
|
await Promise.all([
|
|
page.waitForResponse(resp => resp.url().includes('/auth/users')),
|
|
page.getByTitle('Refresh List').click()
|
|
]);
|
|
|
|
// Ensure list remained open or re-open it
|
|
if (await userListButton.getAttribute('aria-expanded') !== 'true') {
|
|
console.log('List closed after refresh, re-opening...');
|
|
await userListButton.click();
|
|
}
|
|
|
|
// Verify user row exists
|
|
|
|
// Fallback to CSS selector if data-testid is missing due to build issues
|
|
const listContainer = page.locator('div.space-y-4.mt-4');
|
|
await expect(listContainer).toBeVisible();
|
|
|
|
|
|
const userRow = listContainer.locator('.bg-surface-container-high').filter({ hasText: regularUser.email }).first();
|
|
await expect(userRow).toBeVisible();
|
|
|
|
|
|
// 4. Block the User
|
|
// Use exact name matching or title since we added aria-label
|
|
const blockButton = userRow.getByRole('button', { name: 'Block', exact: true });
|
|
if (await blockButton.count() === 0) {
|
|
console.log('Block button NOT found!');
|
|
// fallback to find any button to see what is there
|
|
const buttons = await userRow.getByRole('button').all();
|
|
console.log('Buttons found in row:', buttons.length);
|
|
}
|
|
await expect(blockButton).toBeVisible();
|
|
await blockButton.click();
|
|
|
|
// Handle Block Confirmation Modal
|
|
await expect(page.getByText('Block User?').or(page.getByText('Заблокировать?'))).toBeVisible();
|
|
await page.getByRole('button', { name: /Confirm|Подтвердить/i }).click();
|
|
|
|
await expect(userRow.getByText(/Blocked|Block/i)).toBeVisible();
|
|
|
|
// 5. Verify Blocked User Cannot Login
|
|
// Logout Admin
|
|
const logoutButton = page.getByRole('button', { name: /Logout/i });
|
|
if (await logoutButton.isVisible()) {
|
|
await logoutButton.click();
|
|
} else {
|
|
await page.getByText(/Logout/i).click();
|
|
}
|
|
await expect(page.getByRole('button', { name: 'Login' })).toBeVisible();
|
|
|
|
// Attempt Login as Blocked User
|
|
await page.getByLabel('Email').fill(regularUser.email);
|
|
await page.getByLabel('Password').fill(regularUser.password);
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
|
|
// Assert Error Message
|
|
await expect(page.getByText(/Account is blocked/i)).toBeVisible();
|
|
|
|
// 6. Unblock the User
|
|
// Reload to clear any error states/toasts from previous attempt
|
|
await page.reload();
|
|
|
|
// Login as Admin again
|
|
await page.getByLabel('Email').fill(adminUser.email);
|
|
// Force the new password since we know step 1 changed it
|
|
await page.getByLabel('Password').fill('StrongAdminNewPass123!');
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
console.log('Admin logged back in');
|
|
|
|
await page.waitForTimeout(1000);
|
|
await page.getByRole('button', { name: 'Profile' }).filter({ visible: true }).click();
|
|
|
|
// Open list again
|
|
await userListButton.click();
|
|
await page.getByTitle('Refresh List').click();
|
|
|
|
// Unblock
|
|
const userRowAfter = listContainer.locator('.bg-surface-container-high').filter({ hasText: regularUser.email }).first();
|
|
await expect(userRowAfter).toBeVisible();
|
|
await userRowAfter.getByRole('button', { name: 'Unblock', exact: true }).click();
|
|
|
|
// Handle Unblock Modal
|
|
await expect(page.getByText('Unblock User?').or(page.getByText('Разблокировать?'))).toBeVisible();
|
|
await page.getByRole('button', { name: /Confirm|Подтвердить/i }).click();
|
|
// Wait for UI to update (block icon/text should disappear or change style)
|
|
// Ideally we check API response or UI change. Assuming "Blocked" text goes away or button changes.
|
|
// The original code checked for not.toBeVisible of blocked text, let's stick to that or button state
|
|
await expect(userRowAfter.getByText(/Blocked/i)).not.toBeVisible();
|
|
|
|
// 7. Verify Unblocked User Can Login
|
|
await page.getByRole('button', { name: 'Logout' }).click();
|
|
|
|
await page.getByLabel('Email').fill(regularUser.email);
|
|
await page.getByLabel('Password').fill(regularUser.password);
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
|
|
// Check for Change Password (first login) or direct Dashboard
|
|
await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 });
|
|
if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) {
|
|
await page.getByLabel('New Password').fill('StrongUserNewPass123!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
}
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
});
|
|
|
|
test('5.10. B. Admin Panel - Reset User Password', async ({ page, createAdminUser, createUniqueUser }) => {
|
|
const adminUser = await createAdminUser();
|
|
await page.goto('/');
|
|
await page.getByLabel('Email').fill(adminUser.email);
|
|
await page.getByLabel('Password').fill(adminUser.password);
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
try {
|
|
await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 });
|
|
if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) {
|
|
await page.getByLabel('New Password').fill('StrongAdminNewPass123!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
}
|
|
} catch (e) { }
|
|
|
|
const regularUser = await createUniqueUser();
|
|
const newPassword = 'NewStrongUserPass!';
|
|
|
|
await page.getByRole('button', { name: 'Profile' }).click();
|
|
|
|
// Ensure list is open and valid (Reusing logic from 5.9)
|
|
const userListButton = page.getByRole('button', { name: /Users List/i });
|
|
const isExpanded = await userListButton.getAttribute('aria-expanded');
|
|
if (isExpanded !== 'true') {
|
|
await userListButton.click();
|
|
}
|
|
await expect(userListButton).toHaveAttribute('aria-expanded', 'true');
|
|
|
|
// Always Refresh to ensure latest users are fetched
|
|
await Promise.all([
|
|
page.waitForResponse(resp => resp.url().includes('/auth/users')),
|
|
page.getByTitle('Refresh List').click()
|
|
]);
|
|
|
|
// Ensure list remained open
|
|
if (await userListButton.getAttribute('aria-expanded') !== 'true') {
|
|
await userListButton.click();
|
|
}
|
|
|
|
const listContainer = page.locator('div.space-y-4.mt-4');
|
|
await expect(listContainer).toBeVisible();
|
|
|
|
const userRow = listContainer.locator('.bg-surface-container-high').filter({ hasText: regularUser.email }).first();
|
|
await expect(userRow).toBeVisible();
|
|
|
|
await userRow.getByRole('textbox').fill(newPassword);
|
|
|
|
page.on('dialog', async dialog => {
|
|
console.log(`Dialog message: ${dialog.message()}`);
|
|
await dialog.accept();
|
|
});
|
|
await userRow.getByRole('button', { name: /Reset Pass/i }).click();
|
|
|
|
// Wait to ensure the operation completed (the dialog is the signal, but we might need a small buffer or check effect)
|
|
// Since dialog is handled immediately by listener, we might race.
|
|
// Better pattern: wait for the button to be enabled again or some UI feedback.
|
|
// But since we use window.alert, expecting the dialog content is tricky in Playwright if not careful.
|
|
// Let's add a small pause to allow backend to process before logout.
|
|
await page.waitForTimeout(1000);
|
|
|
|
await page.getByRole('button', { name: 'Logout' }).click();
|
|
await page.getByLabel('Email').fill(regularUser.email);
|
|
await page.getByLabel('Password').fill(newPassword);
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
|
|
// After reset, isFirstLogin is true, so we expect Change Password screen
|
|
await expect(page.getByRole('heading', { name: /Change Password/i })).toBeVisible({ timeout: 10000 });
|
|
await page.getByLabel('New Password').fill('BrandNewUserPass1!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
|
|
await expect(page.getByText('Free Workout')).toBeVisible();
|
|
});
|
|
|
|
test('5.11. B. Admin Panel - Delete User', async ({ page, createAdminUser, createUniqueUser }) => {
|
|
const adminUser = await createAdminUser();
|
|
await page.goto('/');
|
|
await page.getByLabel('Email').fill(adminUser.email);
|
|
await page.getByLabel('Password').fill(adminUser.password);
|
|
await page.getByRole('button', { name: 'Login' }).click();
|
|
try {
|
|
await expect(page.getByRole('heading', { name: /Change Password/i }).or(page.getByText('Free Workout'))).toBeVisible({ timeout: 5000 });
|
|
if (await page.getByRole('heading', { name: /Change Password/i }).isVisible()) {
|
|
await page.getByLabel('New Password').fill('StrongAdminNewPass123!');
|
|
await page.getByRole('button', { name: /Save|Change/i }).click();
|
|
}
|
|
} catch (e) { }
|
|
|
|
const userToDelete = await createUniqueUser();
|
|
|
|
await page.getByRole('button', { name: 'Profile' }).click();
|
|
|
|
// Ensure list is open and valid (Reusing logic from 5.9)
|
|
const userListButton = page.getByRole('button', { name: /Users List/i });
|
|
const isExpanded = await userListButton.getAttribute('aria-expanded');
|
|
if (isExpanded !== 'true') {
|
|
await userListButton.click();
|
|
}
|
|
await expect(userListButton).toHaveAttribute('aria-expanded', 'true');
|
|
|
|
// Always Refresh to ensure latest users are fetched
|
|
await Promise.all([
|
|
page.waitForResponse(resp => resp.url().includes('/auth/users')),
|
|
page.getByTitle('Refresh List').click()
|
|
]);
|
|
|
|
// Ensure list remained open
|
|
if (await userListButton.getAttribute('aria-expanded') !== 'true') {
|
|
await userListButton.click();
|
|
}
|
|
|
|
const listContainer = page.locator('div.space-y-4.mt-4');
|
|
await expect(listContainer).toBeVisible();
|
|
|
|
const userRow = listContainer.locator('.bg-surface-container-high').filter({ hasText: userToDelete.email }).first();
|
|
await expect(userRow).toBeVisible();
|
|
|
|
await userRow.getByRole('button', { name: /Delete/i }).click();
|
|
|
|
// Handle Delete Confirmation Modal
|
|
await expect(page.getByText('Delete User?').or(page.getByText('Удалить пользователя?'))).toBeVisible();
|
|
await page.getByRole('button', { name: /Confirm|Подтвердить/i }).click();
|
|
|
|
await expect(page.getByText(userToDelete.email)).not.toBeVisible();
|
|
});
|
|
});
|