chore: added tests for users and minor refactor (#41279)

* added tests for users and minor refactor

* fix helpers

* addressed PR feedback

* remove before await

* missed the await
This commit is contained in:
Ali Waseem
2025-12-11 13:31:43 -07:00
committed by GitHub
parent 39e21ebef6
commit fef1f043ad
5 changed files with 173 additions and 12 deletions

View File

@@ -0,0 +1,74 @@
import { expect, Page } from '@playwright/test'
import { test } from '../utils/test.js'
import { toUrl } from '../utils/to-url.js'
import { waitForApiResponse } from '../utils/wait-for-response.js'
import { createUserViaUI, deleteUserViaUI, navigateToAuthUsers } from '../utils/auth-helpers.js'
test.describe('auth users list refresh', () => {
test.beforeEach(async ({ page, ref }) => {
await navigateToAuthUsers(page, ref)
})
test('should automatically refresh users list after creating a user', async ({ page, ref }) => {
const testEmail = `test-create-${Date.now()}@example.com`
const testPassword = 'testpassword123'
// Create user via UI
await createUserViaUI(page, ref, testEmail, testPassword)
// Verify the user appears in the table WITHOUT manually refreshing the page
const userRow = page.getByRole('row').filter({ hasText: testEmail })
await expect(
userRow,
'User should appear in the table immediately after creation without manual refresh'
).toBeVisible({ timeout: 10_000 })
// Verify the user details are correct
await expect(userRow.getByText(testEmail)).toBeVisible()
await expect(userRow.getByText('Email')).toBeVisible()
// Clean up: delete the user
await deleteUserViaUI(page, ref, testEmail)
// Verify the user is removed from the table
await expect
.poll(async () => {
return await page.getByRole('row').filter({ hasText: testEmail }).count()
}, 'User should be removed from the table after deletion')
.toBe(0)
})
test('should automatically refresh users list after creating multiple users', async ({
page,
ref,
}) => {
const testUsers = [
{ email: `test-multi-1-${Date.now()}@example.com`, password: 'testpassword123' },
{ email: `test-multi-2-${Date.now()}@example.com`, password: 'testpassword123' },
{ email: `test-multi-3-${Date.now()}@example.com`, password: 'testpassword123' },
]
// Create multiple users
for (const user of testUsers) {
await createUserViaUI(page, ref, user.email, user.password)
// Verify each user appears in the table
await expect(
page.getByRole('row').filter({ hasText: user.email }),
`User ${user.email} should appear in the table after creation`
).toBeVisible()
}
// Clean up: delete all test users
for (const user of testUsers) {
await deleteUserViaUI(page, ref, user.email)
// Verify each user is removed
await expect
.poll(async () => {
return await page.getByRole('row').filter({ hasText: user.email }).count()
}, `User ${user.email} should be removed from the table after deletion`)
.toBe(0)
}
})
})

View File

@@ -8,12 +8,12 @@ import {
deleteAllBuckets,
deleteBucket,
deleteItem,
dismissToastsIfAny,
downloadFile,
navigateToBucket,
renameItem,
uploadFile,
} from '../utils/storage-helpers.js'
import { dismissToastsIfAny } from '../utils/dismiss-toast.js'
const bucketNamePrefix = 'pw_bucket'

View File

@@ -0,0 +1,89 @@
import { expect, Page } from '@playwright/test'
import { waitForApiResponse } from './wait-for-response.js'
import { dismissToastsIfAny } from './dismiss-toast.js'
import { toUrl } from './to-url.js'
export const createUserViaUI = async (page: Page, ref: string, email: string, password: string) => {
await dismissToastsIfAny(page)
// Open the Add user dropdown
await page.getByRole('button', { name: 'Add user' }).click()
// Click "Create new user"
await page.getByRole('menuitem', { name: 'Create new user' }).click()
// Wait for dialog to be visible
await expect(page.getByRole('dialog', { name: 'Create a new user' })).toBeVisible()
// Fill in email
await page.getByRole('textbox', { name: 'user@example.com' }).fill(email)
// Fill in password
await page.getByRole('textbox', { name: '••••••••' }).fill(password)
// Verify that "Auto Confirm User?" is checked by default
await expect(page.getByRole('checkbox', { name: 'Auto Confirm User?' })).toBeChecked()
// Set up API waiters BEFORE clicking the button to avoid race conditions
const createUserPromise = waitForApiResponse(page, 'platform/auth', ref, 'users', {
method: 'POST',
})
const usersListPromise = waitForApiResponse(page, 'platform/pg-meta', ref, 'query?key=')
// Click "Create user"
await page.getByRole('button', { name: 'Create user' }).click()
// Wait for both API calls to complete
await Promise.all([createUserPromise, usersListPromise])
// Wait for success toast
await expect(
page.getByText(`Successfully created user: ${email}`),
'Success toast should be visible after user creation'
).toBeVisible({ timeout: 10_000 })
}
export const deleteUserViaUI = async (page: Page, ref: string, email: string) => {
await dismissToastsIfAny(page)
// Find the user row by email and click the checkbox
const userRow = page.getByRole('row').filter({ hasText: email })
await expect(userRow, `User row with email ${email} should be visible`).toBeVisible()
// Click the checkbox to select the user
await userRow.getByRole('checkbox').first().click()
// Click "Delete 1 users" button
await page.getByRole('button', { name: 'Delete 1 users' }).click()
// Wait for confirmation dialog
await expect(page.getByRole('dialog', { name: 'Confirm to delete 1 user' })).toBeVisible()
// Set up API waiters BEFORE clicking the delete button
const deleteUserPromise = waitForApiResponse(page, 'platform/auth', ref, 'users/', {
method: 'DELETE',
})
const usersListPromise = waitForApiResponse(page, 'platform/pg-meta', ref, 'query?key=')
// Confirm deletion
await page.getByRole('button', { name: 'Delete' }).click()
// Wait for both API calls to complete
await Promise.all([deleteUserPromise, usersListPromise])
// Wait for success toast
await expect(
page.getByText('Successfully deleted the selected 1 user'),
'Success toast should be visible after user deletion'
).toBeVisible({ timeout: 10_000 })
}
export const navigateToAuthUsers = async (page: Page, ref: string) => {
await page.goto(toUrl(`/project/${ref}/auth/users`))
// Wait for the page to load by checking for the "Users" heading
await expect(page.getByRole('heading', { name: 'Users', level: 3 })).toBeVisible()
// Wait for initial users list to load
await waitForApiResponse(page, 'platform/pg-meta', ref, 'query?key=')
}

View File

@@ -9,3 +9,11 @@ export const dismissToast = async (page: Page) => {
}
export const toKebabCase = (str: string) => str.replace(/([A-Z])/g, '-$1').toLowerCase()
export const dismissToastsIfAny = async (page: Page) => {
const closeButtons = page.getByRole('button', { name: 'Close toast' })
const count = await closeButtons.count()
for (let i = 0; i < count; i++) {
await closeButtons.nth(i).click()
}
}

View File

@@ -1,17 +1,7 @@
import { expect, Page } from '@playwright/test'
import { waitForApiResponse } from './wait-for-response.js'
import { toUrl } from './to-url.js'
/**
* Dismisses any visible toast notifications
*/
export const dismissToastsIfAny = async (page: Page) => {
const closeButtons = page.getByRole('button', { name: 'Close toast' })
const count = await closeButtons.count()
for (let i = 0; i < count; i++) {
await closeButtons.nth(i).click()
}
}
import { dismissToastsIfAny } from './dismiss-toast.js'
/**
* Navigates to a the storage home view