fix: Implement comprehensive edit event button functionality and resolve authentication issues
Major fixes and improvements: - Fixed edit event button functionality with proper event handlers and DOM ready state checking - Added status column to tickets table via Supabase migration to resolve 500 API errors - Updated stats API to correctly calculate revenue from decimal price values - Resolved authentication redirect loops by fixing cookie configuration for Docker environment - Fixed Permissions-Policy header syntax errors - Added comprehensive debugging and error handling for event management - Implemented modal-based event editing with form validation and API integration - Enhanced event data loading with proper error handling and user feedback 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
237
tests/auth/auth-api.spec.ts
Normal file
237
tests/auth/auth-api.spec.ts
Normal file
@@ -0,0 +1,237 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Auth API Integration', () => {
|
||||
test('should handle successful login API call', async ({ page }) => {
|
||||
await page.route('**/api/auth/login', async route => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
user: {
|
||||
id: '1',
|
||||
email: 'test@example.com',
|
||||
roleType: 'user'
|
||||
},
|
||||
session: {
|
||||
accessToken: 'mock-token',
|
||||
refreshToken: 'mock-refresh-token',
|
||||
expiresAt: Math.floor(Date.now() / 1000) + 3600
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
await page.goto('/login')
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page).toHaveURL(/.*dashboard/)
|
||||
})
|
||||
|
||||
test('should handle failed login API call', async ({ page }) => {
|
||||
await page.route('**/api/auth/login', async route => {
|
||||
await route.fulfill({
|
||||
status: 401,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
error: {
|
||||
code: 'invalid_credentials',
|
||||
message: 'Invalid email or password'
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
await page.goto('/login')
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.fill('input[name="password"]', 'wrongpassword')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page.locator('.text-red-600')).toContainText('Invalid email or password')
|
||||
})
|
||||
|
||||
test('should handle session refresh', async ({ page }) => {
|
||||
let refreshCalled = false
|
||||
|
||||
await page.route('**/api/auth/refresh', async route => {
|
||||
refreshCalled = true
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
session: {
|
||||
accessToken: 'new-mock-token',
|
||||
refreshToken: 'new-mock-refresh-token',
|
||||
expiresAt: Math.floor(Date.now() / 1000) + 3600
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
await page.goto('/login')
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await page.evaluate(() => {
|
||||
const session = {
|
||||
accessToken: 'expiring-token',
|
||||
refreshToken: 'mock-refresh-token',
|
||||
expiresAt: Math.floor(Date.now() / 1000) + 60,
|
||||
user: { id: '1', email: 'test@example.com' }
|
||||
}
|
||||
localStorage.setItem('bct_auth_session', JSON.stringify(session))
|
||||
})
|
||||
|
||||
await page.reload()
|
||||
await page.waitForTimeout(1000)
|
||||
|
||||
expect(refreshCalled).toBe(true)
|
||||
})
|
||||
|
||||
test('should handle logout API call', async ({ page }) => {
|
||||
await page.route('**/api/auth/logout', async route => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ success: true })
|
||||
})
|
||||
})
|
||||
|
||||
await page.goto('/login')
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await page.click('[data-testid="user-menu-button"]')
|
||||
await page.click('button:has-text("Sign Out")')
|
||||
|
||||
await expect(page).toHaveURL(/.*login/)
|
||||
})
|
||||
|
||||
test('should handle password reset API call', async ({ page }) => {
|
||||
await page.route('**/api/auth/reset-password', async route => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ message: 'Reset email sent' })
|
||||
})
|
||||
})
|
||||
|
||||
await page.goto('/reset-password')
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page.locator('.text-green-600')).toContainText('Reset email sent')
|
||||
})
|
||||
|
||||
test('should handle signup API call', async ({ page }) => {
|
||||
await page.route('**/api/auth/signup', async route => {
|
||||
await route.fulfill({
|
||||
status: 201,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
user: {
|
||||
id: '2',
|
||||
email: 'newuser@example.com',
|
||||
roleType: 'user'
|
||||
},
|
||||
message: 'Account created successfully'
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
await page.goto('/signup')
|
||||
await page.fill('input[name="email"]', 'newuser@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.fill('input[name="confirmPassword"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page.locator('.text-green-600')).toContainText('Account created successfully')
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Protected API Routes', () => {
|
||||
test('should include auth headers in API requests', async ({ page }) => {
|
||||
let authHeaderReceived = false
|
||||
|
||||
await page.route('**/api/dashboard/stats', async route => {
|
||||
const headers = route.request().headers()
|
||||
if (headers.authorization?.startsWith('Bearer ')) {
|
||||
authHeaderReceived = true
|
||||
}
|
||||
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ stats: { events: 5, revenue: 1000 } })
|
||||
})
|
||||
})
|
||||
|
||||
await page.goto('/login')
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await page.goto('/dashboard')
|
||||
await page.waitForTimeout(1000)
|
||||
|
||||
expect(authHeaderReceived).toBe(true)
|
||||
})
|
||||
|
||||
test('should handle 401 responses by refreshing token', async ({ page }) => {
|
||||
let refreshCalled = false
|
||||
let retrySuccessful = false
|
||||
|
||||
await page.route('**/api/dashboard/stats', async route => {
|
||||
const headers = route.request().headers()
|
||||
|
||||
if (headers.authorization === 'Bearer expiring-token') {
|
||||
await route.fulfill({
|
||||
status: 401,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ error: 'Token expired' })
|
||||
})
|
||||
} else if (headers.authorization === 'Bearer new-mock-token') {
|
||||
retrySuccessful = true
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ stats: { events: 5, revenue: 1000 } })
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
await page.route('**/api/auth/refresh', async route => {
|
||||
refreshCalled = true
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
session: {
|
||||
accessToken: 'new-mock-token',
|
||||
refreshToken: 'new-mock-refresh-token',
|
||||
expiresAt: Math.floor(Date.now() / 1000) + 3600
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
await page.evaluate(() => {
|
||||
const session = {
|
||||
accessToken: 'expiring-token',
|
||||
refreshToken: 'mock-refresh-token',
|
||||
expiresAt: Math.floor(Date.now() / 1000) + 3600,
|
||||
user: { id: '1', email: 'test@example.com' }
|
||||
}
|
||||
localStorage.setItem('bct_auth_session', JSON.stringify(session))
|
||||
})
|
||||
|
||||
await page.goto('/dashboard')
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
expect(refreshCalled).toBe(true)
|
||||
expect(retrySuccessful).toBe(true)
|
||||
})
|
||||
})
|
||||
172
tests/auth/auth-components.spec.ts
Normal file
172
tests/auth/auth-components.spec.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Auth Components', () => {
|
||||
test.describe('SignInForm', () => {
|
||||
test('should render sign in form with all fields', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await expect(page.locator('input[name="email"]')).toBeVisible()
|
||||
await expect(page.locator('input[name="password"]')).toBeVisible()
|
||||
await expect(page.locator('button[type="submit"]')).toBeVisible()
|
||||
await expect(page.locator('label[for="email"]')).toContainText('Email')
|
||||
await expect(page.locator('label[for="password"]')).toContainText('Password')
|
||||
})
|
||||
|
||||
test('should validate email format', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await page.fill('input[name="email"]', 'invalid-email')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
const emailField = page.locator('input[name="email"]')
|
||||
const validationMessage = await emailField.getAttribute('validationMessage')
|
||||
expect(validationMessage).toBeTruthy()
|
||||
})
|
||||
|
||||
test('should disable submit button when loading', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
|
||||
const submitButton = page.locator('button[type="submit"]')
|
||||
await submitButton.click()
|
||||
|
||||
await expect(submitButton).toBeDisabled()
|
||||
await expect(submitButton).toContainText('Signing in...')
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('SignUpForm', () => {
|
||||
test('should render sign up form with all fields', async ({ page }) => {
|
||||
await page.goto('/signup')
|
||||
|
||||
await expect(page.locator('input[name="email"]')).toBeVisible()
|
||||
await expect(page.locator('input[name="password"]')).toBeVisible()
|
||||
await expect(page.locator('input[name="confirmPassword"]')).toBeVisible()
|
||||
await expect(page.locator('button[type="submit"]')).toBeVisible()
|
||||
})
|
||||
|
||||
test('should validate password confirmation', async ({ page }) => {
|
||||
await page.goto('/signup')
|
||||
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.fill('input[name="confirmPassword"]', 'different')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page.locator('.text-red-600')).toContainText('Passwords do not match')
|
||||
})
|
||||
|
||||
test('should show loading state during signup', async ({ page }) => {
|
||||
await page.goto('/signup')
|
||||
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.fill('input[name="confirmPassword"]', 'password123')
|
||||
|
||||
const submitButton = page.locator('button[type="submit"]')
|
||||
await submitButton.click()
|
||||
|
||||
await expect(submitButton).toBeDisabled()
|
||||
await expect(submitButton).toContainText('Creating account...')
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('UserMenu', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
await expect(page).toHaveURL(/.*dashboard/)
|
||||
})
|
||||
|
||||
test('should show user avatar and email', async ({ page }) => {
|
||||
const userMenu = page.locator('[data-testid="user-menu-button"]')
|
||||
await expect(userMenu).toBeVisible()
|
||||
await expect(userMenu).toContainText('test@example.com')
|
||||
})
|
||||
|
||||
test('should show dropdown menu when clicked', async ({ page }) => {
|
||||
await page.click('[data-testid="user-menu-button"]')
|
||||
|
||||
await expect(page.locator('div:has-text("test@example.com")')).toBeVisible()
|
||||
await expect(page.locator('a:has-text("Profile")')).toBeVisible()
|
||||
await expect(page.locator('a:has-text("Settings")')).toBeVisible()
|
||||
await expect(page.locator('button:has-text("Sign Out")')).toBeVisible()
|
||||
})
|
||||
|
||||
test('should navigate to profile page', async ({ page }) => {
|
||||
await page.click('[data-testid="user-menu-button"]')
|
||||
await page.click('a:has-text("Profile")')
|
||||
|
||||
await expect(page).toHaveURL(/.*profile/)
|
||||
})
|
||||
|
||||
test('should sign out when clicked', async ({ page }) => {
|
||||
await page.click('[data-testid="user-menu-button"]')
|
||||
await page.click('button:has-text("Sign Out")')
|
||||
|
||||
await expect(page).toHaveURL(/.*login/)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Auth Guards', () => {
|
||||
test('should show loading spinner initially', async ({ page }) => {
|
||||
await page.goto('/dashboard')
|
||||
|
||||
await expect(page.locator('.animate-spin')).toBeVisible()
|
||||
})
|
||||
|
||||
test('should redirect to login for unauthenticated users', async ({ page }) => {
|
||||
await page.goto('/dashboard')
|
||||
|
||||
await expect(page).toHaveURL(/.*login/)
|
||||
})
|
||||
|
||||
test('should show access denied for insufficient permissions', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
await page.fill('input[name="email"]', 'user@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await page.goto('/admin/dashboard')
|
||||
await expect(page.locator('h2:has-text("Access Denied")')).toBeVisible()
|
||||
})
|
||||
|
||||
test('should allow access for authorized users', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
await page.fill('input[name="email"]', 'admin@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await page.goto('/admin/dashboard')
|
||||
await expect(page.locator('h1:has-text("Admin Dashboard")')).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Error Handling', () => {
|
||||
test('should display error messages for failed auth', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await page.fill('input[name="email"]', 'invalid@example.com')
|
||||
await page.fill('input[name="password"]', 'wrongpassword')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page.locator('.text-red-600')).toContainText('Invalid email or password')
|
||||
})
|
||||
|
||||
test('should handle network errors gracefully', async ({ page }) => {
|
||||
await page.route('**/api/auth/login', route => route.abort())
|
||||
|
||||
await page.goto('/login')
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page.locator('.text-red-600')).toBeVisible()
|
||||
})
|
||||
})
|
||||
181
tests/auth/auth-flow.spec.ts
Normal file
181
tests/auth/auth-flow.spec.ts
Normal file
@@ -0,0 +1,181 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Authentication Flow', () => {
|
||||
const testUser = {
|
||||
email: 'test@example.com',
|
||||
password: 'password123',
|
||||
}
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/')
|
||||
})
|
||||
|
||||
test('should redirect to login when accessing protected route', async ({ page }) => {
|
||||
await page.goto('/dashboard')
|
||||
await expect(page).toHaveURL(/.*login/)
|
||||
})
|
||||
|
||||
test('should show sign in form', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await expect(page.locator('input[name="email"]')).toBeVisible()
|
||||
await expect(page.locator('input[name="password"]')).toBeVisible()
|
||||
await expect(page.locator('button[type="submit"]')).toContainText('Sign In')
|
||||
})
|
||||
|
||||
test('should handle invalid credentials', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await page.fill('input[name="email"]', 'invalid@example.com')
|
||||
await page.fill('input[name="password"]', 'wrongpassword')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page.locator('.text-red-600')).toBeVisible()
|
||||
})
|
||||
|
||||
test('should sign in successfully', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await page.fill('input[name="email"]', testUser.email)
|
||||
await page.fill('input[name="password"]', testUser.password)
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page).toHaveURL(/.*dashboard/)
|
||||
})
|
||||
|
||||
test('should persist session on page reload', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await page.fill('input[name="email"]', testUser.email)
|
||||
await page.fill('input[name="password"]', testUser.password)
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page).toHaveURL(/.*dashboard/)
|
||||
|
||||
await page.reload()
|
||||
await expect(page).toHaveURL(/.*dashboard/)
|
||||
})
|
||||
|
||||
test('should sign out successfully', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await page.fill('input[name="email"]', testUser.email)
|
||||
await page.fill('input[name="password"]', testUser.password)
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page).toHaveURL(/.*dashboard/)
|
||||
|
||||
await page.click('[data-testid="user-menu-button"]')
|
||||
await page.click('button:has-text("Sign Out")')
|
||||
|
||||
await expect(page).toHaveURL(/.*login/)
|
||||
})
|
||||
|
||||
test('should handle session expiration', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await page.fill('input[name="email"]', testUser.email)
|
||||
await page.fill('input[name="password"]', testUser.password)
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page).toHaveURL(/.*dashboard/)
|
||||
|
||||
await page.evaluate(() => {
|
||||
localStorage.removeItem('bct_auth_session')
|
||||
})
|
||||
|
||||
await page.reload()
|
||||
await expect(page).toHaveURL(/.*login/)
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Role-based Access Control', () => {
|
||||
test('should show admin panel for admin users', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await page.fill('input[name="email"]', 'admin@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page).toHaveURL(/.*dashboard/)
|
||||
|
||||
await page.click('[data-testid="user-menu-button"]')
|
||||
await expect(page.locator('a:has-text("Admin Dashboard")')).toBeVisible()
|
||||
})
|
||||
|
||||
test('should hide admin panel for regular users', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await page.fill('input[name="email"]', 'user@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page).toHaveURL(/.*dashboard/)
|
||||
|
||||
await page.click('[data-testid="user-menu-button"]')
|
||||
await expect(page.locator('a:has-text("Admin Dashboard")')).not.toBeVisible()
|
||||
})
|
||||
|
||||
test('should deny access to admin routes for regular users', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await page.fill('input[name="email"]', 'user@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await page.goto('/admin/dashboard')
|
||||
await expect(page.locator('h2:has-text("Access Denied")')).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Password Reset', () => {
|
||||
test('should show reset password form', async ({ page }) => {
|
||||
await page.goto('/login')
|
||||
|
||||
await page.click('a:has-text("Forgot password?")')
|
||||
await expect(page.locator('input[name="email"]')).toBeVisible()
|
||||
await expect(page.locator('button[type="submit"]')).toContainText('Send Reset Email')
|
||||
})
|
||||
|
||||
test('should handle password reset request', async ({ page }) => {
|
||||
await page.goto('/reset-password')
|
||||
|
||||
await page.fill('input[name="email"]', 'test@example.com')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page.locator('.text-green-600')).toContainText('Reset email sent')
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Sign Up Flow', () => {
|
||||
test('should show sign up form', async ({ page }) => {
|
||||
await page.goto('/signup')
|
||||
|
||||
await expect(page.locator('input[name="email"]')).toBeVisible()
|
||||
await expect(page.locator('input[name="password"]')).toBeVisible()
|
||||
await expect(page.locator('input[name="confirmPassword"]')).toBeVisible()
|
||||
await expect(page.locator('button[type="submit"]')).toContainText('Sign Up')
|
||||
})
|
||||
|
||||
test('should handle password mismatch', async ({ page }) => {
|
||||
await page.goto('/signup')
|
||||
|
||||
await page.fill('input[name="email"]', 'newuser@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.fill('input[name="confirmPassword"]', 'differentpassword')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page.locator('.text-red-600')).toContainText('Passwords do not match')
|
||||
})
|
||||
|
||||
test('should create new account successfully', async ({ page }) => {
|
||||
await page.goto('/signup')
|
||||
|
||||
await page.fill('input[name="email"]', 'newuser@example.com')
|
||||
await page.fill('input[name="password"]', 'password123')
|
||||
await page.fill('input[name="confirmPassword"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
await expect(page.locator('.text-green-600')).toContainText('Account created successfully')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user