Skip to content

Instantly share code, notes, and snippets.

@pksorensen
Created June 3, 2025 06:07
Show Gist options
  • Save pksorensen/239471b329a1b5e29193460a6e661281 to your computer and use it in GitHub Desktop.
Save pksorensen/239471b329a1b5e29193460a6e661281 to your computer and use it in GitHub Desktop.
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