DEFECT-1: email field was missing from edit modal form — added to schema, service (with unicity check + audit), and frontend form. DEFECT-2: reset password modal showed undefined — fixed API return type (temporaryPassword) and added Typography.Text copyable display. 4 Vitest + 2 Playwright E2E tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
72 lines
3.3 KiB
TypeScript
72 lines
3.3 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import { loginAs } from './fixtures/auth';
|
|
|
|
test.describe('Admin — User Edit + Reset Password', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await loginAs(page, 'admin');
|
|
await page.goto('/admin/users');
|
|
await page.waitForSelector('.ant-table-row', { timeout: 10000 });
|
|
});
|
|
|
|
// T-ADMIN-EDIT-EMAIL
|
|
test('edit user email via modal', async ({ page }) => {
|
|
const row = page.locator('.ant-table-row').filter({ hasText: 'test-commercial@test.local' });
|
|
await row.getByRole('button', { name: 'Редактировать' }).click();
|
|
|
|
const modal = page.getByRole('dialog', { name: 'Редактировать пользователя' });
|
|
await expect(modal).toBeVisible({ timeout: 5000 });
|
|
|
|
const emailInput = modal.getByRole('textbox', { name: /Email/i });
|
|
await expect(emailInput).toHaveValue('test-commercial@test.local');
|
|
|
|
await emailInput.clear();
|
|
await emailInput.fill('edited-commercial@test.local');
|
|
|
|
// Ensure nameRu is filled (required field, may be empty in seed)
|
|
const nameRuInput = modal.getByRole('textbox', { name: /Имя \(RU\)/i });
|
|
const nameRuVal = await nameRuInput.inputValue();
|
|
if (!nameRuVal) {
|
|
await nameRuInput.fill('Тест Продажников RU');
|
|
}
|
|
|
|
await modal.getByRole('button', { name: 'Сохранить' }).click();
|
|
await expect(modal).toBeHidden({ timeout: 5000 });
|
|
await expect(page.locator('.ant-table-row').filter({ hasText: 'edited-commercial@test.local' })).toBeVisible({ timeout: 5000 });
|
|
|
|
// Restore original email
|
|
const editedRow = page.locator('.ant-table-row').filter({ hasText: 'edited-commercial@test.local' });
|
|
await editedRow.getByRole('button', { name: 'Редактировать' }).click();
|
|
const modal2 = page.getByRole('dialog', { name: 'Редактировать пользователя' });
|
|
await expect(modal2).toBeVisible({ timeout: 5000 });
|
|
const emailInput2 = modal2.getByRole('textbox', { name: /Email/i });
|
|
await emailInput2.clear();
|
|
await emailInput2.fill('test-commercial@test.local');
|
|
await modal2.getByRole('button', { name: 'Сохранить' }).click();
|
|
await expect(modal2).toBeHidden({ timeout: 5000 });
|
|
});
|
|
|
|
// T-ADMIN-RESET-PWD
|
|
test('reset password shows copyable temporary password', async ({ page }) => {
|
|
const row = page.locator('.ant-table-row').filter({ hasText: 'test-acheteur@test.local' });
|
|
await row.getByRole('button', { name: 'Сбросить пароль' }).click();
|
|
|
|
const popconfirm = page.locator('.ant-popover:visible');
|
|
await popconfirm.getByRole('button', { name: 'Да' }).click();
|
|
|
|
// AntD v6 Modal.success — use .ant-modal-confirm
|
|
const successModal = page.locator('.ant-modal-confirm');
|
|
await expect(successModal).toBeVisible({ timeout: 10000 });
|
|
await expect(successModal.getByText('Временный пароль:')).toBeVisible();
|
|
|
|
// The password is rendered inside Typography.Text copyable
|
|
const pwdElement = successModal.locator('strong');
|
|
await expect(pwdElement).toBeVisible();
|
|
const pwd = await pwdElement.textContent();
|
|
expect(pwd).toBeTruthy();
|
|
expect(pwd!.trim()).toMatch(/^[0-9a-f]{12}$/);
|
|
|
|
await successModal.getByRole('button', { name: 'OK' }).click();
|
|
await expect(successModal).toBeHidden({ timeout: 5000 });
|
|
});
|
|
});
|