Created
June 3, 2025 06:07
-
-
Save pksorensen/239471b329a1b5e29193460a6e661281 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { test, expect } from '@playwright/test'; | |
import { SignupPage } from '../../page-helpers/signup-page'; | |
import { generateSignupTestData } from './fixtures'; | |
import { generateTestUser } from '../../utils/auth-helpers'; | |
import { | |
initializeSpeechRecording, | |
addSpeech, | |
generateSubtitleFiles, | |
resetSpeechRecording, | |
} from '../../utils/speech-narration'; | |
test.describe('User Signup Flow', () => { | |
let signupPage: SignupPage; | |
let testData: ReturnType<typeof generateSignupTestData>; | |
test.beforeEach(async ({ page }) => { | |
signupPage = new SignupPage(page); | |
testData = generateSignupTestData(); // This now generates a TestUser with all fields | |
page.on('console', msg => console.log(msg.text())); | |
// Navigate to signup page before each test | |
await signupPage.goto(); | |
}); | |
test.describe('Successful Signup', () => { | |
test('should successfully create account for a normal user with valid information', { | |
tag: '@documentation', | |
annotation: { | |
type: 'documentation', | |
description: | |
'Shows how to successfully create a normal user account with valid information through the multi-step signup form.', | |
}, | |
}, async ({ page }) => { | |
initializeSpeechRecording('Normal User Signup Flow'); | |
try { | |
const user = generateTestUser(false); // Generate a normal user | |
await addSpeech( | |
page, | |
'Welcome to the CommuteConnects car sharing platform. Let\'s begin by creating a new user account.', | |
4000 | |
); | |
// Fill and submit signup form for normal user | |
await addSpeech( | |
page, | |
'First, we\'ll fill in the personal information, including your name, email, and a secure password. Watch as the fields are populated with a realistic typing effect.', | |
6000 | |
); | |
// The signupAsNormalUser method now encapsulates all the filling and clicking with visual helpers | |
await signupPage.signupAsNormalUser(user); | |
// Verify signup was successful | |
const isSuccessful = await signupPage.isSignupSuccessful(); | |
expect(isSuccessful).toBe(true); | |
await addSpeech( | |
page, | |
'The signup process is now complete, and your account has been successfully created. You will be redirected to your personal dashboard.', | |
6000 | |
); | |
// Verify we're redirected to appropriate page | |
const currentUrl = signupPage.page.url(); | |
expect(currentUrl).toMatch(/\/(account)/); | |
} finally { | |
await generateSubtitleFiles({ | |
format: 'srt', | |
filename: 'normal_user_signup_demo', | |
}); | |
resetSpeechRecording(); | |
} | |
}); | |
test('should successfully create account for an organization administrator', async () => { | |
const user = generateTestUser(true); // Generate an organization admin user | |
// Fill and submit signup form for org admin | |
await signupPage.signupAsOrgAdmin(user); | |
// Verify signup was successful | |
const isSuccessful = await signupPage.isSignupSuccessful(); | |
expect(isSuccessful).toBe(true); | |
// Verify we're redirected to appropriate page | |
const currentUrl = signupPage.page.url(); | |
expect(currentUrl).toMatch(/\/(account)/); | |
}); | |
test('should handle signup with special characters in name (normal user)', async () => { | |
const user = generateTestUser(false); | |
user.firstName = 'José'; | |
user.lastName = 'O\'Connor-Smith'; | |
await signupPage.signupAsNormalUser(user); | |
const isSuccessful = await signupPage.isSignupSuccessful(); | |
expect(isSuccessful).toBe(true); | |
}); | |
test('should handle signup with plus sign in email (normal user)', async () => { | |
const user = generateTestUser(false); | |
user.email = `test+signup+${Date.now()}@example.com`; | |
await signupPage.signupAsNormalUser(user); | |
const isSuccessful = await signupPage.isSignupSuccessful(); | |
expect(isSuccessful).toBe(true); | |
}); | |
}); | |
test.describe('Form Validation', () => { | |
test('should show error for empty first name field (Step 1)', async () => { | |
const user = generateTestUser(false); | |
user.firstName = ''; | |
await signupPage.fillPersonalInfo(user); // Only fill step 1 | |
const hasErrors = await signupPage.hasValidationErrors(); | |
expect(hasErrors).toBe(true); | |
const errors = await signupPage.getErrorMessages(); | |
expect(errors.some(error => error.toLowerCase().includes('first name'))).toBe(true); | |
}); | |
test('should show error for empty email field (Step 1)', async () => { | |
const user = generateTestUser(false); | |
user.email = ''; | |
await signupPage.fillPersonalInfo(user); | |
const hasErrors = await signupPage.hasValidationErrors(); | |
expect(hasErrors).toBe(true); | |
const errors = await signupPage.getErrorMessages(); | |
expect(errors.some(error => error.toLowerCase().includes('email'))).toBe(true); | |
}); | |
test('should show error for empty password field (Step 1)', async () => { | |
const user = generateTestUser(false); | |
user.password = ''; | |
await signupPage.fillPersonalInfo(user); | |
const hasErrors = await signupPage.hasValidationErrors(); | |
expect(hasErrors).toBe(true); | |
const errors = await signupPage.getErrorMessages(); | |
expect(errors.some(error => error.toLowerCase().includes('password'))).toBe(true); | |
}); | |
test('should show error for invalid email format (Step 1)', async () => { | |
const user = generateTestUser(false); | |
user.email = 'invalid-email'; | |
await signupPage.fillPersonalInfo(user); | |
const hasErrors = await signupPage.hasValidationErrors(); | |
expect(hasErrors).toBe(true); | |
const errors = await signupPage.getErrorMessages(); | |
expect(errors.some(error => | |
error.toLowerCase().includes('email') || | |
error.toLowerCase().includes('invalid') | |
)).toBe(true); | |
}); | |
test('should show error for weak password (Step 1)', async () => { | |
const user = generateTestUser(false); | |
user.password = 'short'; // Too short and no special chars | |
await signupPage.fillPersonalInfo(user); | |
const hasErrors = await signupPage.hasValidationErrors(); | |
expect(hasErrors).toBe(true); | |
const errors = await signupPage.getErrorMessages(); | |
expect(errors.some(error => error.toLowerCase().includes('password'))).toBe(true); | |
}); | |
test('should show error for empty street field (Step 2)', async () => { | |
const user = generateTestUser(false); | |
user.address.street = ''; | |
await signupPage.fillPersonalInfo(user); | |
await signupPage.fillAddressInfo(user); // This will trigger validation for step 2 | |
const hasErrors = await signupPage.hasValidationErrors(); | |
expect(hasErrors).toBe(true); | |
const errors = await signupPage.getErrorMessages(); | |
expect(errors.some(error => error.toLowerCase().includes('street'))).toBe(true); | |
}); | |
test('should show error for empty license number (Step 3 - normal user)', async () => { | |
const user = generateTestUser(false); | |
user.license.licenseNumber = ''; | |
await signupPage.fillPersonalInfo(user); | |
await signupPage.fillAddressInfo(user); | |
await signupPage.fillLicenseInfo(user); // This will trigger validation for step 3 | |
const hasErrors = await signupPage.hasValidationErrors(); | |
expect(hasErrors).toBe(true); | |
const errors = await signupPage.getErrorMessages(); | |
expect(errors.some(error => error.toLowerCase().includes('license number'))).toBe(true); | |
}); | |
test('should show error for empty CVR number (Step 3 - org admin)', async () => { | |
const user = generateTestUser(true); | |
user.organization.cvrNumber = ''; | |
await signupPage.fillPersonalInfo(user); | |
await signupPage.fillAddressInfo(user); | |
await signupPage.fillOrgAdminInfo(user); // This will trigger validation for step 3 | |
const hasErrors = await signupPage.hasValidationErrors(); | |
expect(hasErrors).toBe(true); | |
const errors = await signupPage.getErrorMessages(); | |
expect(errors.some(error => error.toLowerCase().includes('cvr number'))).toBe(true); | |
}); | |
test('should retain form data after validation error (Step 1)', async () => { | |
const user = generateTestUser(false); | |
user.email = 'invalid-email'; | |
await signupPage.fillPersonalInfo(user); | |
// Verify form retains valid data | |
expect(await signupPage.firstNameInput.inputValue()).toBe(user.firstName); | |
expect(await signupPage.emailInput.inputValue()).toBe(user.email); | |
}); | |
}); | |
test.describe('Edge Cases', () => { | |
test('should handle very long first name (normal user)', async () => { | |
const user = generateTestUser(false); | |
user.firstName = 'VeryLongFirstNameThatShouldStillWorkFineInMostCasesButTestsEdgeCaseHandling'; | |
await signupPage.signupAsNormalUser(user); | |
const isSuccessful = await signupPage.isSignupSuccessful(); | |
expect(isSuccessful).toBe(true); | |
}); | |
test('should handle minimum valid password (normal user)', async () => { | |
const user = generateTestUser(false); | |
user.password = 'Abcd123!'; // Minimum valid password | |
await signupPage.signupAsNormalUser(user); | |
const isSuccessful = await signupPage.isSignupSuccessful(); | |
expect(isSuccessful).toBe(true); | |
}); | |
test('should handle duplicate email gracefully (normal user)', async ({ page }) => { | |
// First, create a user programmatically to ensure it exists | |
const firstUser = generateTestUser(false); | |
await SignupPage.completeSignupFlow(page, firstUser); // Use the helper to create the first user | |
// Navigate back to signup for duplicate test | |
await signupPage.goto(); | |
// Try to signup with same email | |
const duplicateUser = generateTestUser(false); | |
duplicateUser.email = firstUser.email; | |
await signupPage.signupAsNormalUser(duplicateUser); | |
const hasErrors = await signupPage.hasValidationErrors(); | |
expect(hasErrors).toBe(true); | |
const errors = await signupPage.getErrorMessages(); | |
expect(errors.some(error => | |
error.toLowerCase().includes('email') || | |
error.toLowerCase().includes('exists') || | |
error.toLowerCase().includes('already') | |
)).toBe(true); | |
}); | |
}); | |
test.describe('Form Interaction', () => { | |
test('should be able to clear and refill form (Step 1)', async () => { | |
const user = generateTestUser(false); | |
// Fill form initially | |
await signupPage.fillPersonalInfo(user); | |
// Clear form | |
await signupPage.clearForm(); | |
// Verify fields are empty (only checking step 1 fields for simplicity) | |
expect(await signupPage.firstNameInput.inputValue()).toBe(''); | |
expect(await signupPage.emailInput.inputValue()).toBe(''); | |
expect(await signupPage.passwordInput.inputValue()).toBe(''); | |
// Refill and submit | |
await signupPage.signupAsNormalUser(user); | |
const isSuccessful = await signupPage.isSignupSuccessful(); | |
expect(isSuccessful).toBe(true); | |
}); | |
test('should focus on first error field after validation (Step 1)', async () => { | |
const user = generateTestUser(false); | |
user.firstName = ''; // Make first name invalid | |
await signupPage.fillPersonalInfo(user); | |
// Check if first name field is focused | |
const activeElement = await signupPage.page.evaluate(() => document.activeElement?.getAttribute('name')); | |
expect(activeElement).toBe('firstName'); | |
}); | |
}); | |
test.describe('Mobile and Desktop Views', () => { | |
test('should work correctly on mobile viewport (normal user)', async ({ page }) => { | |
await page.setViewportSize({ width: 375, height: 667 }); | |
const user = generateTestUser(false); | |
await signupPage.signupAsNormalUser(user); | |
const isSuccessful = await signupPage.isSignupSuccessful(); | |
expect(isSuccessful).toBe(true); | |
}); | |
test('should work correctly on tablet viewport (normal user)', async ({ page }) => { | |
await page.setViewportSize({ width: 768, height: 1024 }); | |
const user = generateTestUser(false); | |
await signupPage.signupAsNormalUser(user); | |
const isSuccessful = await signupPage.isSignupSuccessful(); | |
expect(isSuccessful).toBe(true); | |
}); | |
}); | |
test.describe('Performance and Loading', () => { | |
test('should show loading state during submission', async () => { | |
const user = generateTestUser(false); | |
await signupPage.fillPersonalInfo(user); | |
await signupPage.fillAddressInfo(user); | |
await signupPage.fillLicenseInfo(user); | |
// Submit and immediately check for loading state | |
await signupPage.completeRegistrationButton.click(); | |
// Check if submit button is disabled during processing | |
const isDisabled = await signupPage.isSubmitButtonDisabled(); | |
expect(isDisabled).toBe(true); | |
await signupPage.waitForSubmissionComplete(); | |
}); | |
test('should complete signup within reasonable time (normal user)', async () => { | |
const user = generateTestUser(false); | |
const startTime = Date.now(); | |
await signupPage.signupAsNormalUser(user); | |
const endTime = Date.now(); | |
const duration = endTime - startTime; | |
expect(duration).toBeLessThan(20000); // Increased timeout for multi-step form | |
const isSuccessful = await signupPage.isSignupSuccessful(); | |
expect(isSuccessful).toBe(true); | |
}); | |
test('should complete signup within reasonable time (org admin)', async () => { | |
const user = generateTestUser(true); | |
const startTime = Date.now(); | |
await signupPage.signupAsOrgAdmin(user); | |
const endTime = Date.now(); | |
const duration = endTime - startTime; | |
expect(duration).toBeLessThan(20000); // Increased timeout for multi-step form | |
const isSuccessful = await signupPage.isSignupSuccessful(); | |
expect(isSuccessful).toBe(true); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment