chore: enhance user lifecycle tests with invite dialog and loading handling
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { test, expect, loginUser } from '../fixtures/auth-fixtures';
|
||||
import { waitForLoadingComplete } from '../utils/wait-helpers';
|
||||
import { waitForDialog, waitForLoadingComplete } from '../utils/wait-helpers';
|
||||
|
||||
async function getAuthToken(page: import('@playwright/test').Page): Promise<string> {
|
||||
return await page.evaluate(() => {
|
||||
@@ -18,7 +18,7 @@ async function openInviteUserForm(page: import('@playwright/test').Page): Promis
|
||||
const inviteButton = page.getByRole('button', { name: /invite.*user|add user|create user/i }).first();
|
||||
await expect(inviteButton).toBeVisible({ timeout: 15000 });
|
||||
await inviteButton.click();
|
||||
await expect(page.getByRole('dialog')).toBeVisible({ timeout: 15000 });
|
||||
await waitForDialog(page, { timeout: 15000 });
|
||||
}
|
||||
|
||||
async function fillInviteForm(
|
||||
@@ -44,9 +44,25 @@ async function fillInviteForm(
|
||||
const sendButton = page.getByRole('dialog')
|
||||
.getByRole('button', { name: /send.*invite|create|submit/i })
|
||||
.first();
|
||||
|
||||
const createResponse = page.waitForResponse(
|
||||
(response) => response.url().includes('/api/v1/users') && response.request().method() === 'POST',
|
||||
{ timeout: 15000 }
|
||||
).catch(() => null);
|
||||
|
||||
await expect(sendButton).toBeVisible({ timeout: 15000 });
|
||||
await sendButton.click();
|
||||
await createResponse;
|
||||
await waitForLoadingComplete(page, { timeout: 15000 });
|
||||
|
||||
const inviteDialog = page.getByRole('dialog').first();
|
||||
const doneButton = inviteDialog.getByRole('button', { name: /done|close|cancel/i }).first();
|
||||
if (await doneButton.isVisible().catch(() => false)) {
|
||||
await doneButton.click();
|
||||
}
|
||||
await inviteDialog.waitFor({ state: 'hidden', timeout: 10000 }).catch(() => {
|
||||
// Some implementations auto-close on submit.
|
||||
});
|
||||
}
|
||||
|
||||
async function openCreateProxyHostForm(page: import('@playwright/test').Page): Promise<void> {
|
||||
@@ -55,6 +71,7 @@ async function openCreateProxyHostForm(page: import('@playwright/test').Page): P
|
||||
const addButton = page.getByRole('button', { name: /add.*proxy.*host/i }).first();
|
||||
await expect(addButton).toBeVisible({ timeout: 15000 });
|
||||
await addButton.click();
|
||||
await waitForDialog(page, { timeout: 15000 });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,7 +153,7 @@ test.describe('Data Consistency', () => {
|
||||
const token = await getAuthToken(page);
|
||||
|
||||
const response = await page.request.get(
|
||||
'http://127.0.0.1:8080/api/users',
|
||||
'/api/v1/users',
|
||||
{
|
||||
headers: { 'Authorization': `Bearer ${token || ''}` },
|
||||
ignoreHTTPSErrors: true,
|
||||
@@ -173,7 +190,7 @@ test.describe('Data Consistency', () => {
|
||||
const token = await getAuthToken(page);
|
||||
|
||||
const usersResponse = await page.request.get(
|
||||
'http://127.0.0.1:8080/api/users',
|
||||
'/api/v1/users',
|
||||
{
|
||||
headers: { 'Authorization': `Bearer ${token || ''}` },
|
||||
ignoreHTTPSErrors: true,
|
||||
@@ -187,7 +204,7 @@ test.describe('Data Consistency', () => {
|
||||
|
||||
if (user) {
|
||||
const updateResponse = await page.request.patch(
|
||||
`http://127.0.0.1:8080/api/users/${user.id}`,
|
||||
`/api/v1/users/${user.id}`,
|
||||
{
|
||||
data: { name: updatedName },
|
||||
headers: { 'Authorization': `Bearer ${token || ''}` },
|
||||
@@ -240,7 +257,7 @@ test.describe('Data Consistency', () => {
|
||||
const token = await getAuthToken(page);
|
||||
|
||||
const response = await page.request.get(
|
||||
'http://127.0.0.1:8080/api/users',
|
||||
'/api/v1/users',
|
||||
{
|
||||
headers: { 'Authorization': `Bearer ${token || ''}` },
|
||||
ignoreHTTPSErrors: true,
|
||||
@@ -269,7 +286,7 @@ test.describe('Data Consistency', () => {
|
||||
const token = await getAuthToken(page);
|
||||
|
||||
const usersResponse = await page.request.get(
|
||||
'http://127.0.0.1:8080/api/users',
|
||||
'/api/v1/users',
|
||||
{
|
||||
headers: { 'Authorization': `Bearer ${token || ''}` },
|
||||
ignoreHTTPSErrors: true,
|
||||
@@ -284,7 +301,7 @@ test.describe('Data Consistency', () => {
|
||||
if (user) {
|
||||
// Send two concurrent updates
|
||||
const update1 = page.request.patch(
|
||||
`http://127.0.0.1:8080/api/users/${user.id}`,
|
||||
`/api/v1/users/${user.id}`,
|
||||
{
|
||||
data: { name: 'Update One' },
|
||||
headers: { 'Authorization': `Bearer ${token || ''}` },
|
||||
@@ -293,7 +310,7 @@ test.describe('Data Consistency', () => {
|
||||
);
|
||||
|
||||
const update2 = page.request.patch(
|
||||
`http://127.0.0.1:8080/api/users/${user.id}`,
|
||||
`/api/v1/users/${user.id}`,
|
||||
{
|
||||
data: { name: 'Update Two' },
|
||||
headers: { 'Authorization': `Bearer ${token || ''}` },
|
||||
@@ -327,8 +344,8 @@ test.describe('Data Consistency', () => {
|
||||
await test.step('Create proxy', async () => {
|
||||
await openCreateProxyHostForm(page);
|
||||
|
||||
await page.getByRole('textbox', { name: /domain names/i }).first().fill(testProxy.domain);
|
||||
await page.getByRole('textbox', { name: /target|forward/i }).first().fill(testProxy.target);
|
||||
await page.getByRole('textbox', { name: /domain names|domain/i }).first().fill(testProxy.domain);
|
||||
await page.getByLabel(/forward host|target|forward/i).first().fill(testProxy.target);
|
||||
await page.getByRole('textbox', { name: /description/i }).first().fill(testProxy.description);
|
||||
|
||||
const submitButton = page.getByRole('button', { name: /create|submit/i }).first();
|
||||
@@ -341,7 +358,7 @@ test.describe('Data Consistency', () => {
|
||||
|
||||
// Try to modify with invalid data that should fail validation
|
||||
const response = await page.request.patch(
|
||||
`http://127.0.0.1:8080/api/proxy-hosts`,
|
||||
`/api/v1/proxy-hosts`,
|
||||
{
|
||||
data: { domain: '' }, // Empty domain should fail
|
||||
headers: { 'Authorization': `Bearer ${token || ''}` },
|
||||
@@ -400,7 +417,9 @@ test.describe('Data Consistency', () => {
|
||||
}
|
||||
|
||||
// Try submitting anyway
|
||||
const submitButton = page.getByRole('button', { name: /send.*invite|create|submit/i }).first();
|
||||
const submitButton = page.getByRole('dialog')
|
||||
.getByRole('button', { name: /send.*invite|create|submit/i })
|
||||
.first();
|
||||
if (!(await submitButton.isDisabled())) {
|
||||
await submitButton.click();
|
||||
await waitForLoadingComplete(page, { timeout: 15000 });
|
||||
@@ -433,7 +452,7 @@ test.describe('Data Consistency', () => {
|
||||
await waitForLoadingComplete(page, { timeout: 15000 });
|
||||
|
||||
// Get first page
|
||||
const page1Items = await page.locator('[role="row"], [class*="user-item"]').count();
|
||||
const page1Items = await page.locator('table tbody tr').count();
|
||||
expect(page1Items).toBeGreaterThan(0);
|
||||
|
||||
// Navigate to page 2 if pagination exists
|
||||
@@ -442,7 +461,7 @@ test.describe('Data Consistency', () => {
|
||||
await nextButton.click();
|
||||
await waitForLoadingComplete(page, { timeout: 15000 });
|
||||
|
||||
const page2Items = await page.locator('[role="row"], [class*="user-item"]').count();
|
||||
const page2Items = await page.locator('table tbody tr').count();
|
||||
expect(page2Items).toBeGreaterThanOrEqual(0);
|
||||
|
||||
// Go back to page 1
|
||||
@@ -451,7 +470,7 @@ test.describe('Data Consistency', () => {
|
||||
await prevButton.click();
|
||||
await waitForLoadingComplete(page, { timeout: 15000 });
|
||||
|
||||
const backPage1Items = await page.locator('[role="row"], [class*="user-item"]').count();
|
||||
const backPage1Items = await page.locator('table tbody tr').count();
|
||||
expect(backPage1Items).toBe(page1Items);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { test, expect, loginUser } from '../fixtures/auth-fixtures';
|
||||
import { waitForLoadingComplete } from '../utils/wait-helpers';
|
||||
|
||||
/**
|
||||
* Integration: Multi-Component Workflows
|
||||
@@ -21,9 +22,10 @@ test.describe('Multi-Component Workflows', () => {
|
||||
password: 'MultiFlow123!',
|
||||
};
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/', { waitUntil: 'networkidle' });
|
||||
await page.waitForSelector('[role="main"]', { timeout: 5000 });
|
||||
test.beforeEach(async ({ page, adminUser }) => {
|
||||
await loginUser(page, adminUser);
|
||||
await waitForLoadingComplete(page, { timeout: 15000 });
|
||||
await expect(page.getByRole('main')).toBeVisible({ timeout: 15000 });
|
||||
});
|
||||
|
||||
test.afterEach(async ({ page }) => {
|
||||
|
||||
@@ -1,4 +1,90 @@
|
||||
import { test, expect, loginUser, TEST_PASSWORD } from '../fixtures/auth-fixtures';
|
||||
import { waitForDialog, waitForLoadingComplete } from '../utils/wait-helpers';
|
||||
|
||||
async function openInviteUserDialog(page: import('@playwright/test').Page): Promise<void> {
|
||||
await page.goto('/users', { waitUntil: 'networkidle' });
|
||||
await waitForLoadingComplete(page, { timeout: 15000 });
|
||||
|
||||
const inviteButton = page.getByRole('button', { name: /invite.*user|add user|create user/i }).first();
|
||||
await expect(inviteButton).toBeVisible({ timeout: 15000 });
|
||||
await inviteButton.click();
|
||||
await waitForDialog(page, { timeout: 15000 });
|
||||
}
|
||||
|
||||
async function createUserFromInviteDialog(
|
||||
page: import('@playwright/test').Page,
|
||||
user: { email: string; name: string; password: string }
|
||||
): Promise<void> {
|
||||
const dialog = page.getByRole('dialog').first();
|
||||
|
||||
const emailInput = dialog.getByPlaceholder(/user@example/i).or(dialog.getByLabel(/email/i)).first();
|
||||
await expect(emailInput).toBeVisible({ timeout: 15000 });
|
||||
await emailInput.fill(user.email);
|
||||
|
||||
const nameInput = dialog.getByPlaceholder(/name/i).or(dialog.getByLabel(/name/i)).first();
|
||||
if (await nameInput.isVisible().catch(() => false)) {
|
||||
await nameInput.fill(user.name);
|
||||
}
|
||||
|
||||
const passwordInput = dialog.getByLabel(/password/i).first();
|
||||
if (await passwordInput.isVisible().catch(() => false)) {
|
||||
await passwordInput.fill(user.password);
|
||||
}
|
||||
|
||||
const createResponse = page.waitForResponse(
|
||||
(response) => response.url().includes('/api/v1/users') && response.request().method() === 'POST',
|
||||
{ timeout: 15000 }
|
||||
).catch(() => null);
|
||||
|
||||
const submitButton = dialog.getByRole('button', { name: /send.*invite|create.*user|create|submit/i }).first();
|
||||
await expect(submitButton).toBeVisible({ timeout: 15000 });
|
||||
await submitButton.click();
|
||||
await createResponse;
|
||||
await waitForLoadingComplete(page, { timeout: 15000 });
|
||||
|
||||
const doneButton = dialog.getByRole('button', { name: /done|close|cancel/i }).first();
|
||||
if (await doneButton.isVisible().catch(() => false)) {
|
||||
await doneButton.click();
|
||||
}
|
||||
await dialog.waitFor({ state: 'hidden', timeout: 10000 }).catch(() => {
|
||||
// Some implementations auto-close the dialog.
|
||||
});
|
||||
}
|
||||
|
||||
async function navigateToLogin(page: import('@playwright/test').Page): Promise<void> {
|
||||
const logoutButton = page.getByRole('button', { name: /logout/i }).first();
|
||||
if (await logoutButton.isVisible().catch(() => false)) {
|
||||
await logoutButton.click();
|
||||
} else {
|
||||
await page.goto('/login', { waitUntil: 'domcontentloaded' });
|
||||
}
|
||||
|
||||
const emailInput = page.locator('input[type="email"]').or(page.getByLabel(/email/i)).first();
|
||||
await expect(emailInput).toBeVisible({ timeout: 15000 });
|
||||
}
|
||||
|
||||
async function loginWithCredentials(
|
||||
page: import('@playwright/test').Page,
|
||||
email: string,
|
||||
password: string
|
||||
): Promise<void> {
|
||||
const emailInput = page.locator('input[type="email"]').or(page.getByLabel(/email/i)).first();
|
||||
const passwordInput = page.locator('input[type="password"]').or(page.getByLabel(/password/i)).first();
|
||||
|
||||
await expect(emailInput).toBeVisible({ timeout: 15000 });
|
||||
await expect(passwordInput).toBeVisible({ timeout: 15000 });
|
||||
await emailInput.fill(email);
|
||||
await passwordInput.fill(password);
|
||||
|
||||
const loginResponse = page.waitForResponse(
|
||||
(response) => response.url().includes('/api/v1/auth/login') && response.request().method() === 'POST',
|
||||
{ timeout: 15000 }
|
||||
).catch(() => null);
|
||||
|
||||
await page.getByRole('button', { name: /login|sign in/i }).first().click();
|
||||
await loginResponse;
|
||||
await waitForLoadingComplete(page, { timeout: 15000 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Integration: Admin → User E2E Workflow
|
||||
@@ -30,18 +116,8 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
await test.step('STEP 1: Admin creates new user', async () => {
|
||||
const start = Date.now();
|
||||
|
||||
await page.goto('/users', { waitUntil: 'networkidle' });
|
||||
|
||||
const addButton = page.getByRole('button', { name: /add|create/i }).first();
|
||||
await addButton.click();
|
||||
|
||||
await page.getByLabel(/email/i).fill(testUser.email);
|
||||
await page.getByLabel(/name/i).fill(testUser.name);
|
||||
await page.getByLabel(/password/i).first().fill(testUser.password);
|
||||
|
||||
const submitButton = page.getByRole('button', { name: /create|submit/i }).first();
|
||||
await submitButton.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await openInviteUserDialog(page);
|
||||
await createUserFromInviteDialog(page, testUser);
|
||||
|
||||
const duration = Date.now() - start;
|
||||
console.log(`✓ User created in ${duration}ms`);
|
||||
@@ -77,13 +153,7 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
await test.step('STEP 4: New user logs in', async () => {
|
||||
const start = Date.now();
|
||||
|
||||
await page.getByLabel(/email/i).fill(testUser.email);
|
||||
await page.getByLabel(/password/i).fill(testUser.password);
|
||||
|
||||
const loginButton = page.getByRole('button', { name: /login/i });
|
||||
await loginButton.click();
|
||||
|
||||
await page.waitForLoadState('networkidle');
|
||||
await loginWithCredentials(page, testUser.email, testUser.password);
|
||||
const duration = Date.now() - start;
|
||||
|
||||
console.log(`✓ User logged in in ${duration}ms`);
|
||||
@@ -119,10 +189,7 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
}
|
||||
|
||||
// Login as admin
|
||||
await page.getByLabel(/email/i).fill(adminEmail);
|
||||
await page.getByLabel(/password/i).fill(TEST_PASSWORD);
|
||||
await page.getByRole('button', { name: /login/i }).click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await loginWithCredentials(page, adminEmail, TEST_PASSWORD);
|
||||
|
||||
// Check audit logs
|
||||
await page.goto('/audit', { waitUntil: 'networkidle' }).catch(() => {
|
||||
@@ -138,18 +205,8 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
// Admin modifies role → user gains new permissions immediately
|
||||
test('Role change takes effect immediately on user refresh', async ({ page }) => {
|
||||
await test.step('Create test user with default role', async () => {
|
||||
await page.goto('/users', { waitUntil: 'networkidle' });
|
||||
|
||||
const addButton = page.getByRole('button', { name: /add|create/i }).first();
|
||||
await addButton.click();
|
||||
|
||||
await page.getByLabel(/email/i).fill(testUser.email);
|
||||
await page.getByLabel(/name/i).fill(testUser.name);
|
||||
await page.getByLabel(/password/i).first().fill(testUser.password);
|
||||
|
||||
const submitButton = page.getByRole('button', { name: /create|submit/i }).first();
|
||||
await submitButton.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await openInviteUserDialog(page);
|
||||
await createUserFromInviteDialog(page, testUser);
|
||||
});
|
||||
|
||||
await test.step('User logs in and notes current permissions', async () => {
|
||||
@@ -157,10 +214,7 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
await logoutButton.click();
|
||||
await page.waitForURL(/login/);
|
||||
|
||||
await page.getByLabel(/email/i).fill(testUser.email);
|
||||
await page.getByLabel(/password/i).fill(testUser.password);
|
||||
await page.getByRole('button', { name: /login/i }).click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await loginWithCredentials(page, testUser.email, testUser.password);
|
||||
});
|
||||
|
||||
await test.step('Admin upgrades user role (in parallel)', async () => {
|
||||
@@ -189,18 +243,8 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
};
|
||||
|
||||
await test.step('Create user to delete', async () => {
|
||||
await page.goto('/users', { waitUntil: 'networkidle' });
|
||||
|
||||
const addButton = page.getByRole('button', { name: /add|create/i }).first();
|
||||
await addButton.click();
|
||||
|
||||
await page.getByLabel(/email/i).fill(deletableUser.email);
|
||||
await page.getByLabel(/name/i).fill(deletableUser.name);
|
||||
await page.getByLabel(/password/i).first().fill(deletableUser.password);
|
||||
|
||||
const submitButton = page.getByRole('button', { name: /create|submit/i }).first();
|
||||
await submitButton.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await openInviteUserDialog(page);
|
||||
await createUserFromInviteDialog(page, deletableUser);
|
||||
});
|
||||
|
||||
await test.step('Admin deletes user', async () => {
|
||||
@@ -222,11 +266,7 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
await page.waitForURL(/login/);
|
||||
}
|
||||
|
||||
await page.getByLabel(/email/i).fill(deletableUser.email);
|
||||
await page.getByLabel(/password/i).fill(deletableUser.password);
|
||||
await page.getByRole('button', { name: /login/i }).click();
|
||||
|
||||
await page.waitForLoadState('networkidle');
|
||||
await loginWithCredentials(page, deletableUser.email, deletableUser.password);
|
||||
});
|
||||
|
||||
await test.step('Verify login failed with appropriate error', async () => {
|
||||
@@ -247,18 +287,8 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
test('Audit log records user lifecycle events', async ({ page }) => {
|
||||
await test.step('Perform workflow actions', async () => {
|
||||
// Create user
|
||||
await page.goto('/users', { waitUntil: 'networkidle' });
|
||||
|
||||
const addButton = page.getByRole('button', { name: /add|create/i }).first();
|
||||
await addButton.click();
|
||||
|
||||
await page.getByLabel(/email/i).fill(testUser.email);
|
||||
await page.getByLabel(/name/i).fill(testUser.name);
|
||||
await page.getByLabel(/password/i).first().fill(testUser.password);
|
||||
|
||||
const submit = page.getByRole('button', { name: /create|submit/i }).first();
|
||||
await submit.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await openInviteUserDialog(page);
|
||||
await createUserFromInviteDialog(page, testUser);
|
||||
});
|
||||
|
||||
await test.step('Check audit trail for user creation event', async () => {
|
||||
@@ -288,18 +318,8 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
// User cannot escalate own role
|
||||
test('User cannot promote self to admin', async ({ page }) => {
|
||||
await test.step('Create test user', async () => {
|
||||
await page.goto('/users', { waitUntil: 'networkidle' });
|
||||
|
||||
const addButton = page.getByRole('button', { name: /add|create/i }).first();
|
||||
await addButton.click();
|
||||
|
||||
await page.getByLabel(/email/i).fill(testUser.email);
|
||||
await page.getByLabel(/name/i).fill(testUser.name);
|
||||
await page.getByLabel(/password/i).first().fill(testUser.password);
|
||||
|
||||
const submitButton = page.getByRole('button', { name: /create|submit/i }).first();
|
||||
await submitButton.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await openInviteUserDialog(page);
|
||||
await createUserFromInviteDialog(page, testUser);
|
||||
});
|
||||
|
||||
await test.step('User attempts to modify own role', async () => {
|
||||
@@ -309,10 +329,7 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
await page.waitForURL(/login/);
|
||||
|
||||
// Login as user
|
||||
await page.getByLabel(/email/i).fill(testUser.email);
|
||||
await page.getByLabel(/password/i).fill(testUser.password);
|
||||
await page.getByRole('button', { name: /login/i }).click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await loginWithCredentials(page, testUser.email, testUser.password);
|
||||
|
||||
// Try to access user management
|
||||
await page.goto('/users', { waitUntil: 'networkidle' }).catch(() => {
|
||||
@@ -349,31 +366,13 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
};
|
||||
|
||||
await test.step('Create first user', async () => {
|
||||
await page.goto('/users', { waitUntil: 'networkidle' });
|
||||
|
||||
const addButton = page.getByRole('button', { name: /add|create/i }).first();
|
||||
await addButton.click();
|
||||
|
||||
await page.getByLabel(/email/i).fill(user1.email);
|
||||
await page.getByLabel(/name/i).fill(user1.name);
|
||||
await page.getByLabel(/password/i).first().fill(user1.password);
|
||||
|
||||
const submitButton = page.getByRole('button', { name: /create|submit/i }).first();
|
||||
await submitButton.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await openInviteUserDialog(page);
|
||||
await createUserFromInviteDialog(page, user1);
|
||||
});
|
||||
|
||||
await test.step('Create second user', async () => {
|
||||
const addButton = page.getByRole('button', { name: /add|create/i }).first();
|
||||
await addButton.click();
|
||||
|
||||
await page.getByLabel(/email/i).fill(user2.email);
|
||||
await page.getByLabel(/name/i).fill(user2.name);
|
||||
await page.getByLabel(/password/i).first().fill(user2.password);
|
||||
|
||||
const submitButton = page.getByRole('button', { name: /create|submit/i }).first();
|
||||
await submitButton.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await openInviteUserDialog(page);
|
||||
await createUserFromInviteDialog(page, user2);
|
||||
});
|
||||
|
||||
await test.step('User1 logs in and verifies data isolation', async () => {
|
||||
@@ -381,10 +380,7 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
await logoutButton.click();
|
||||
await page.waitForURL(/login/);
|
||||
|
||||
await page.getByLabel(/email/i).fill(user1.email);
|
||||
await page.getByLabel(/password/i).fill(user1.password);
|
||||
await page.getByRole('button', { name: /login/i }).click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await loginWithCredentials(page, user1.email, user1.password);
|
||||
|
||||
// User1 should see their profile but not User2's
|
||||
const user1Profile = page.getByText(user1.name).first();
|
||||
@@ -396,18 +392,14 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
|
||||
// User logout → login as different user → resources isolated
|
||||
test('Session isolation after logout and re-login', async ({ page }) => {
|
||||
await test.step('Create secondary user for session switch', async () => {
|
||||
await openInviteUserDialog(page);
|
||||
await createUserFromInviteDialog(page, testUser);
|
||||
});
|
||||
|
||||
await test.step('Login as first user', async () => {
|
||||
await page.goto('/', { waitUntil: 'networkidle' });
|
||||
|
||||
const emailInput = page.getByLabel(/email/i);
|
||||
const passwordInput = page.getByLabel(/password/i);
|
||||
|
||||
await emailInput.fill(adminEmail);
|
||||
await passwordInput.fill(TEST_PASSWORD);
|
||||
|
||||
const loginButton = page.getByRole('button', { name: /login/i });
|
||||
await loginButton.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await navigateToLogin(page);
|
||||
await loginWithCredentials(page, adminEmail, TEST_PASSWORD);
|
||||
});
|
||||
|
||||
await test.step('Note session storage', async () => {
|
||||
@@ -429,15 +421,7 @@ test.describe('Admin-User E2E Workflow', () => {
|
||||
});
|
||||
|
||||
await test.step('Login as different user', async () => {
|
||||
const emailInput = page.getByLabel(/email/i);
|
||||
const passwordInput = page.getByLabel(/password/i);
|
||||
|
||||
await emailInput.fill(testUser.email);
|
||||
await passwordInput.fill(testUser.password);
|
||||
|
||||
const loginButton = page.getByRole('button', { name: /login/i });
|
||||
await loginButton.click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
await loginWithCredentials(page, testUser.email, testUser.password);
|
||||
});
|
||||
|
||||
await test.step('Verify new session established', async () => {
|
||||
|
||||
Reference in New Issue
Block a user