bdd tests

This commit is contained in:
2026-01-21 23:46:48 +01:00
parent 5ed958281d
commit 959b99cb58
59 changed files with 17493 additions and 0 deletions

View File

@@ -0,0 +1,115 @@
# Onboarding BDD E2E Tests
This directory contains BDD (Behavior-Driven Development) E2E tests for the GridPilot onboarding flow.
## Overview
The onboarding flow guides new users through a two-step wizard process:
1. **Personal Information** - Collects user details (name, display name, country, timezone)
2. **Racing Avatar** - Generates an AI-powered racing avatar from a face photo
## Test Files
### [`onboarding-wizard.spec.ts`](onboarding-wizard.spec.ts)
Tests the complete onboarding wizard flow, including:
- User redirection after login
- Wizard structure and navigation
- Step progression and completion
- Help panel visibility
- Error states and retry logic
- Authentication and authorization flows
### [`onboarding-personal-info.spec.ts`](onboarding-personal-info.spec.ts)
Tests the personal information collection step, including:
- Form field visibility and interaction
- Input validation (required fields, length limits, character restrictions)
- Country and timezone selection
- Step navigation (next/back)
- Data persistence across steps
- Real-time validation feedback
### [`onboarding-avatar.spec.ts`](onboarding-avatar.spec.ts)
Tests the avatar creation step, including:
- Face photo upload and preview
- Suit color selection
- Avatar generation process
- Avatar selection from generated options
- File upload validation (format, size, dimensions)
- Generation error states and retry logic
### [`onboarding-validation.spec.ts`](onboarding-validation.spec.ts)
Tests validation rules and error handling throughout the flow:
- Form field validation (empty fields, invalid formats, length limits)
- File upload validation (corrupted files, wrong dimensions, inappropriate content)
- Network and server error handling
- Concurrent submission prevention
- Edge cases and boundary conditions
## Testing Philosophy
These tests follow the BDD E2E testing concept:
- **Focus on Outcomes**: Tests validate what the user sees and can verify, not visual implementation details
- **Gherkin Syntax**: Scenarios are described using Given/When/Then format
- **User-Centric**: Tests represent real user journeys and acceptance criteria
- **Placeholder Structure**: Each test file contains TODO comments indicating what needs to be implemented
## Test Structure
Each test file follows this pattern:
```typescript
test.describe('Feature Name', () => {
test.beforeEach(async ({ page }) => {
// TODO: Implement authentication and setup
});
test('User sees expected outcome', async ({ page }) => {
// TODO: Implement test
// Scenario: Description
// Given I am in a specific state
// When I perform an action
// Then I should see a specific outcome
});
});
```
## Key User Journeys Covered
### Driver Onboarding Journey
1. New user logs in for the first time
2. User is redirected to onboarding page
3. User completes personal information (Step 1)
4. User creates a racing avatar (Step 2)
5. User completes onboarding
6. User is redirected to dashboard
### Validation Journey
1. User attempts to proceed with invalid data
2. User sees validation errors
3. User corrects the data
4. User successfully proceeds
### Error Recovery Journey
1. User encounters a network error
2. User sees error message
3. User retries the operation
4. User successfully completes the operation
## Implementation Notes
- All tests are placeholders with TODO comments
- Tests should use Playwright's test and expect APIs
- Tests should focus on user-visible outcomes
- Tests should be independent and isolated
- Tests should use proper authentication setup
- Tests should handle both success and error scenarios
## Future Enhancements
- Add test data factories for consistent test data
- Add visual regression testing for critical UI elements
- Add performance testing for avatar generation
- Add accessibility testing for all interactive elements
- Add cross-browser compatibility testing

View File

@@ -0,0 +1,203 @@
/**
* BDD E2E Test: Onboarding Avatar Step
*
* Tests the avatar creation step of the onboarding wizard:
* - Face photo upload
* - Suit color selection
* - Avatar generation
* - Avatar selection
* - Avatar validation
* - Step completion
*
* Focus: Final user outcomes - what the driver sees and can verify
*/
import { test, expect } from '@playwright/test';
test.describe('Onboarding - Avatar Step', () => {
test.beforeEach(async ({ page }) => {
// TODO: Implement authentication setup
// - Navigate to login page
// - Enter credentials for a new user
// - Verify redirection to onboarding page
// - Complete step 1 with valid data
// - Verify step 2 is active
});
test('User sees avatar creation form', async ({ page }) => {
// TODO: Implement test
// Scenario: User sees avatar form
// Given I am on step 2 of onboarding
// Then I should see a face photo upload area
// And I should see suit color options
// And I should see a "Generate Avatars" button
});
test('User can upload face photo', async ({ page }) => {
// TODO: Implement test
// Scenario: User uploads face photo
// Given I am on step 2 of onboarding
// When I click the photo upload area
// And I select a face photo file
// Then the photo should be uploaded
// And I should see a preview of the photo
});
test('User can select suit color', async ({ page }) => {
// TODO: Implement test
// Scenario: User selects suit color
// Given I am on step 2 of onboarding
// When I click the suit color options
// And I select "Red"
// Then the "Red" option should be selected
});
test('User can generate avatars after uploading photo', async ({ page }) => {
// TODO: Implement test
// Scenario: Avatar generation
// Given I am on step 2 of onboarding
// And I have uploaded a face photo
// And I have selected a suit color
// When I click "Generate Avatars"
// Then I should see a loading indicator
// And I should see generated avatar options
});
test('User sees avatar generation progress', async ({ page }) => {
// TODO: Implement test
// Scenario: Avatar generation progress
// Given I am on step 2 of onboarding
// When I click "Generate Avatars"
// Then I should see a progress indicator
// And I should see "Generating..." text
});
test('User can select from generated avatars', async ({ page }) => {
// TODO: Implement test
// Scenario: Avatar selection
// Given I am on step 2 of onboarding
// And avatars have been generated
// When I click on one of the generated avatars
// Then it should be highlighted as selected
// And I should see a selection indicator
});
test('User sees validation error when no photo uploaded', async ({ page }) => {
// TODO: Implement test
// Scenario: Photo validation
// Given I am on step 2 of onboarding
// When I try to generate avatars without uploading a photo
// Then I should see "Please upload a photo of your face"
});
test('User sees validation error when no avatar selected', async ({ page }) => {
// TODO: Implement test
// Scenario: Avatar selection validation
// Given I am on step 2 of onboarding
// And avatars have been generated
// When I try to submit without selecting an avatar
// Then I should see "Please select one of the generated avatars"
});
test('User can regenerate avatars with different suit color', async ({ page }) => {
// TODO: Implement test
// Scenario: Regenerate avatars
// Given I am on step 2 of onboarding
// And I have generated avatars with one suit color
// When I select a different suit color
// And I click "Generate Avatars"
// Then I should see new avatars with the new color
});
test('User sees avatar preview before upload', async ({ page }) => {
// TODO: Implement test
// Scenario: Photo preview
// Given I am on step 2 of onboarding
// When I select a photo file
// Then I should see a preview of the photo
// And I should see the file name
});
test('User cannot upload invalid file format for photo', async ({ page }) => {
// TODO: Implement test
// Scenario: File format validation
// Given I am on step 2 of onboarding
// When I try to upload an invalid file format
// Then I should see an error message
// And the upload should be rejected
});
test('User cannot upload oversized photo file', async ({ page }) => {
// TODO: Implement test
// Scenario: File size validation
// Given I am on step 2 of onboarding
// When I try to upload a file exceeding size limit
// Then I should see an error message
// And the upload should be rejected
});
test('User sees avatar generation error state', async ({ page }) => {
// TODO: Implement test
// Scenario: Avatar generation error
// Given I am on step 2 of onboarding
// When avatar generation fails
// Then I should see an error message
// And I should see an option to retry
});
test('User can retry failed avatar generation', async ({ page }) => {
// TODO: Implement test
// Scenario: Retry avatar generation
// Given I am on step 2 of onboarding
// And avatar generation failed
// When I click "Retry"
// Then the generation should be attempted again
});
test('User can proceed to submit with valid avatar selection', async ({ page }) => {
// TODO: Implement test
// Scenario: Valid avatar submission
// Given I am on step 2 of onboarding
// And I have uploaded a face photo
// And I have generated avatars
// And I have selected an avatar
// When I click "Complete Onboarding"
// Then the form should be submitted
// And I should be redirected to dashboard
});
test('User sees help text for avatar generation', async ({ page }) => {
// TODO: Implement test
// Scenario: Avatar help text
// Given I am on step 2 of onboarding
// Then I should see help text about avatar generation
// And I should see tips for taking a good photo
});
test('User sees avatar generation requirements', async ({ page }) => {
// TODO: Implement test
// Scenario: Avatar requirements
// Given I am on step 2 of onboarding
// Then I should see photo requirements
// And I should see supported file formats
// And I should see maximum file size
});
test('User can cancel avatar generation', async ({ page }) => {
// TODO: Implement test
// Scenario: Cancel generation
// Given I am on step 2 of onboarding
// When I click "Generate Avatars"
// And I see a loading indicator
// Then I should be able to cancel the generation
});
test('User sees avatar in different contexts after onboarding', async ({ page }) => {
// TODO: Implement test
// Scenario: Avatar visibility
// Given I have completed onboarding
// When I navigate to different pages
// Then I should see my avatar in the header
// And I should see my avatar in my profile
});
});

View File

@@ -0,0 +1,186 @@
/**
* BDD E2E Test: Onboarding Personal Information Step
*
* Tests the personal information collection step of the onboarding wizard:
* - First name input
* - Last name input
* - Display name input
* - Country selection
* - Timezone selection
* - Step validation and navigation
*
* Focus: Final user outcomes - what the driver sees and can verify
*/
import { test, expect } from '@playwright/test';
test.describe('Onboarding - Personal Information Step', () => {
test.beforeEach(async ({ page }) => {
// TODO: Implement authentication setup
// - Navigate to login page
// - Enter credentials for a new user
// - Verify redirection to onboarding page
// - Verify step 1 is active
});
test('User sees personal information form fields', async ({ page }) => {
// TODO: Implement test
// Scenario: User sees form fields
// Given I am on step 1 of onboarding
// Then I should see a "First Name" input field
// And I should see a "Last Name" input field
// And I should see a "Display Name" input field
// And I should see a "Country" dropdown
// And I should see a "Timezone" dropdown
});
test('User can enter first name', async ({ page }) => {
// TODO: Implement test
// Scenario: User enters first name
// Given I am on step 1 of onboarding
// When I enter "John" in the first name field
// Then the first name field should contain "John"
});
test('User can enter last name', async ({ page }) => {
// TODO: Implement test
// Scenario: User enters last name
// Given I am on step 1 of onboarding
// When I enter "Doe" in the last name field
// Then the last name field should contain "Doe"
});
test('User can enter display name', async ({ page }) => {
// TODO: Implement test
// Scenario: User enters display name
// Given I am on step 1 of onboarding
// When I enter "RacerJohn" in the display name field
// Then the display name field should contain "RacerJohn"
});
test('User can select country from dropdown', async ({ page }) => {
// TODO: Implement test
// Scenario: User selects country
// Given I am on step 1 of onboarding
// When I click the country dropdown
// And I select "United States"
// Then the country dropdown should show "United States"
});
test('User can select timezone from dropdown', async ({ page }) => {
// TODO: Implement test
// Scenario: User selects timezone
// Given I am on step 1 of onboarding
// When I click the timezone dropdown
// And I select "UTC-05:00"
// Then the timezone dropdown should show "UTC-05:00"
});
test('User sees validation error for empty first name', async ({ page }) => {
// TODO: Implement test
// Scenario: First name validation
// Given I am on step 1 of onboarding
// When I leave the first name field empty
// And I try to proceed to step 2
// Then I should see "First name is required"
});
test('User sees validation error for empty last name', async ({ page }) => {
// TODO: Implement test
// Scenario: Last name validation
// Given I am on step 1 of onboarding
// When I leave the last name field empty
// And I try to proceed to step 2
// Then I should see "Last name is required"
});
test('User sees validation error for empty display name', async ({ page }) => {
// TODO: Implement test
// Scenario: Display name validation
// Given I am on step 1 of onboarding
// When I leave the display name field empty
// And I try to proceed to step 2
// Then I should see "Display name is required"
});
test('User sees validation error for short display name', async ({ page }) => {
// TODO: Implement test
// Scenario: Display name length validation
// Given I am on step 1 of onboarding
// When I enter "AB" in the display name field
// And I try to proceed to step 2
// Then I should see "Display name must be at least 3 characters"
});
test('User sees validation error for empty country', async ({ page }) => {
// TODO: Implement test
// Scenario: Country validation
// Given I am on step 1 of onboarding
// When I leave the country field empty
// And I try to proceed to step 2
// Then I should see "Please select your country"
});
test('User can proceed to step 2 with valid data', async ({ page }) => {
// TODO: Implement test
// Scenario: Valid data allows progression
// Given I am on step 1 of onboarding
// When I enter "John" in first name
// And I enter "Doe" in last name
// And I enter "RacerJohn" in display name
// And I select "United States" in country
// And I click "Next"
// Then I should see step 2 of onboarding
});
test('User can go back from step 1', async ({ page }) => {
// TODO: Implement test
// Scenario: Back button on step 1
// Given I am on step 1 of onboarding
// When I click "Back"
// Then I should see the onboarding welcome screen
// Or the back button should be disabled
});
test('User sees entered data preserved when going back and forth', async ({ page }) => {
// TODO: Implement test
// Scenario: Data persistence
// Given I am on step 1 of onboarding
// When I enter "John" in first name
// And I enter "Doe" in last name
// And I enter "RacerJohn" in display name
// And I select "United States" in country
// And I click "Next"
// And I click "Back"
// Then the first name field should still contain "John"
// And the last name field should still contain "Doe"
// And the display name field should still contain "RacerJohn"
// And the country field should still show "United States"
});
test('User sees help text for personal information', async ({ page }) => {
// TODO: Implement test
// Scenario: Help text visibility
// Given I am on step 1 of onboarding
// Then I should see help text explaining what information is needed
// And I should see any requirements or hints
});
test('User cannot proceed with invalid display name characters', async ({ page }) => {
// TODO: Implement test
// Scenario: Display name character validation
// Given I am on step 1 of onboarding
// When I enter special characters in display name
// And I try to proceed to step 2
// Then I should see validation errors
});
test('User sees real-time validation feedback', async ({ page }) => {
// TODO: Implement test
// Scenario: Real-time validation
// Given I am on step 1 of onboarding
// When I type in the display name field
// Then I should see validation feedback as I type
// And I should see if the name meets requirements
});
});

View File

@@ -0,0 +1,230 @@
/**
* BDD E2E Test: Onboarding Validation and Error States
*
* Tests validation rules and error handling throughout the onboarding flow:
* - Form field validation
* - File upload validation
* - Network error handling
* - Server error handling
* - Edge cases and boundary conditions
*
* Focus: Final user outcomes - what the driver sees and can verify
*/
import { test, expect } from '@playwright/test';
test.describe('Onboarding - Validation and Error States', () => {
test.beforeEach(async ({ page }) => {
// TODO: Implement authentication setup
// - Navigate to login page
// - Enter credentials for a new user
// - Verify redirection to onboarding page
});
test('User sees validation errors for all empty fields', async ({ page }) => {
// TODO: Implement test
// Scenario: All fields empty validation
// Given I am on step 1 of onboarding
// When I try to proceed without entering any data
// Then I should see validation errors for all required fields
// And I should not be able to proceed
});
test('User sees validation error for display name with spaces only', async ({ page }) => {
// TODO: Implement test
// Scenario: Display name whitespace validation
// Given I am on step 1 of onboarding
// When I enter only spaces in display name
// And I try to proceed to step 2
// Then I should see "Display name is required"
});
test('User sees validation error for display name with special characters', async ({ page }) => {
// TODO: Implement test
// Scenario: Display name character validation
// Given I am on step 1 of onboarding
// When I enter "John@#$%" in display name
// And I try to proceed to step 2
// Then I should see validation errors
});
test('User sees validation error for display name exceeding maximum length', async ({ page }) => {
// TODO: Implement test
// Scenario: Display name length validation
// Given I am on step 1 of onboarding
// When I enter a display name exceeding 50 characters
// And I try to proceed to step 2
// Then I should see validation errors
});
test('User sees validation error for first name with numbers', async ({ page }) => {
// TODO: Implement test
// Scenario: First name validation
// Given I am on step 1 of onboarding
// When I enter "John123" in first name
// And I try to proceed to step 2
// Then I should see validation errors
});
test('User sees validation error for last name with numbers', async ({ page }) => {
// TODO: Implement test
// Scenario: Last name validation
// Given I am on step 1 of onboarding
// When I enter "Doe456" in last name
// And I try to proceed to step 2
// Then I should see validation errors
});
test('User sees validation error for photo with wrong dimensions', async ({ page }) => {
// TODO: Implement test
// Scenario: Photo dimension validation
// Given I am on step 2 of onboarding
// When I upload a photo with invalid dimensions
// Then I should see an error message
// And the upload should be rejected
});
test('User sees validation error for photo with wrong aspect ratio', async ({ page }) => {
// TODO: Implement test
// Scenario: Photo aspect ratio validation
// Given I am on step 2 of onboarding
// When I upload a photo with extreme aspect ratio
// Then I should see an error message
// And the upload should be rejected
});
test('User sees validation error for corrupted photo file', async ({ page }) => {
// TODO: Implement test
// Scenario: Corrupted file validation
// Given I am on step 2 of onboarding
// When I upload a corrupted image file
// Then I should see an error message
// And the upload should be rejected
});
test('User sees network error state during avatar generation', async ({ page }) => {
// TODO: Implement test
// Scenario: Network error during generation
// Given I am on step 2 of onboarding
// When I click "Generate Avatars"
// And a network error occurs
// Then I should see a network error message
// And I should see an option to retry
});
test('User sees server error state during onboarding submission', async ({ page }) => {
// TODO: Implement test
// Scenario: Server error during submission
// Given I am on step 2 of onboarding
// When I submit the onboarding form
// And the server returns an error
// Then I should see a server error message
// And I should be able to retry
});
test('User sees timeout error state during avatar generation', async ({ page }) => {
// TODO: Implement test
// Scenario: Timeout during generation
// Given I am on step 2 of onboarding
// When I click "Generate Avatars"
// And the request times out
// Then I should see a timeout error message
// And I should see an option to retry
});
test('User sees concurrent submission prevention', async ({ page }) => {
// TODO: Implement test
// Scenario: Concurrent submission prevention
// Given I am on step 2 of onboarding
// When I submit the form
// And I try to submit again before completion
// Then the second submission should be prevented
// And I should see a processing indicator
});
test('User sees validation error for empty country selection', async ({ page }) => {
// TODO: Implement test
// Scenario: Country selection validation
// Given I am on step 1 of onboarding
// When I leave country unselected
// And I try to proceed to step 2
// Then I should see "Please select your country"
});
test('User sees validation error for invalid email format in display name', async ({ page }) => {
// TODO: Implement test
// Scenario: Email format in display name
// Given I am on step 1 of onboarding
// When I enter an email in display name field
// And I try to proceed to step 2
// Then I should see validation errors
});
test('User sees validation error for display name with leading/trailing spaces', async ({ page }) => {
// TODO: Implement test
// Scenario: Display name whitespace trimming
// Given I am on step 1 of onboarding
// When I enter " John " in display name
// And I try to proceed to step 2
// Then the display name should be trimmed
// And I should see validation if trimmed name is too short
});
test('User sees validation error for photo upload during network issues', async ({ page }) => {
// TODO: Implement test
// Scenario: Photo upload network error
// Given I am on step 2 of onboarding
// When I try to upload a photo
// And a network error occurs
// Then I should see an upload error message
// And I should see an option to retry
});
test('User sees validation error for avatar generation with invalid parameters', async ({ page }) => {
// TODO: Implement test
// Scenario: Invalid generation parameters
// Given I am on step 2 of onboarding
// When I try to generate avatars with invalid parameters
// Then I should see a validation error
// And I should be able to correct the parameters
});
test('User sees error state when avatar generation service is unavailable', async ({ page }) => {
// TODO: Implement test
// Scenario: Service unavailable
// Given I am on step 2 of onboarding
// When I click "Generate Avatars"
// And the service is unavailable
// Then I should see a service unavailable message
// And I should see an option to retry later
});
test('User sees validation error for duplicate display name', async ({ page }) => {
// TODO: Implement test
// Scenario: Duplicate display name
// Given I am on step 1 of onboarding
// When I enter a display name that already exists
// And I try to proceed to step 2
// Then I should see a duplicate name error
// And I should be prompted to choose a different name
});
test('User sees validation error for display name with profanity', async ({ page }) => {
// TODO: Implement test
// Scenario: Profanity filter
// Given I am on step 1 of onboarding
// When I enter a display name with profanity
// And I try to proceed to step 2
// Then I should see a profanity filter error
// And I should be prompted to choose a different name
});
test('User sees validation error for photo with inappropriate content', async ({ page }) => {
// TODO: Implement test
// Scenario: Content moderation
// Given I am on step 2 of onboarding
// When I upload a photo with inappropriate content
// Then I should see a content moderation error
// And the upload should be rejected
});
});

View File

@@ -0,0 +1,125 @@
/**
* BDD E2E Test: Onboarding Wizard Flow
*
* Tests the complete onboarding wizard flow that guides new users through:
* - Personal information collection (Step 1)
* - Racing avatar creation (Step 2)
* - Profile completion and redirection to dashboard
*
* Focus: Final user outcomes - what the driver sees and can verify
*/
import { test, expect } from '@playwright/test';
test.describe('Onboarding Wizard Flow', () => {
test.beforeEach(async ({ page }) => {
// TODO: Implement authentication setup
// - Navigate to login page
// - Enter credentials for a new user (not yet onboarded)
// - Verify successful login
// - Verify redirection to onboarding page
});
test('New user is redirected to onboarding after login', async ({ page }) => {
// TODO: Implement test
// Scenario: New user is redirected to onboarding
// Given I am a new registered user "John Doe"
// And I have not completed onboarding
// When I log in
// Then I should be redirected to the onboarding page
// And I should see the onboarding wizard
});
test('User sees onboarding wizard with two steps', async ({ page }) => {
// TODO: Implement test
// Scenario: User sees onboarding wizard structure
// Given I am on the onboarding page
// Then I should see the "Personal Info" step
// And I should see the "Racing Avatar" step
// And I should see a progress indicator
});
test('User can navigate between onboarding steps', async ({ page }) => {
// TODO: Implement test
// Scenario: User navigates between steps
// Given I am on the onboarding page
// When I complete step 1
// And I click "Next"
// Then I should see step 2
// When I click "Back"
// Then I should see step 1 again
});
test('User completes onboarding and is redirected to dashboard', async ({ page }) => {
// TODO: Implement test
// Scenario: User completes onboarding
// Given I am on the onboarding page
// When I complete step 1 with valid data
// And I complete step 2 with a valid avatar
// And I submit the onboarding form
// Then I should be redirected to the dashboard
// And I should see my profile information
});
test('User sees onboarding help panel', async ({ page }) => {
// TODO: Implement test
// Scenario: User sees help information
// Given I am on the onboarding page
// Then I should see the onboarding help panel
// And I should see instructions for the current step
});
test('User sees avatar generation help on step 2', async ({ page }) => {
// TODO: Implement test
// Scenario: User sees avatar generation help
// Given I am on step 2 of onboarding
// Then I should see avatar generation help
// And I should see tips for taking a good photo
});
test('User cannot skip required onboarding steps', async ({ page }) => {
// TODO: Implement test
// Scenario: User cannot skip steps
// Given I am on the onboarding page
// When I try to navigate to step 2 without completing step 1
// Then I should see validation errors
// And I should not be able to proceed
});
test('User sees processing state during submission', async ({ page }) => {
// TODO: Implement test
// Scenario: User sees processing indicator
// Given I am on the onboarding page
// When I submit the onboarding form
// Then I should see a loading/processing indicator
// And I should not be able to submit again
});
test('User sees error state when submission fails', async ({ page }) => {
// TODO: Implement test
// Scenario: User sees submission error
// Given I am on the onboarding page
// When I submit the onboarding form
// And the submission fails
// Then I should see an error message
// And I should be able to retry
});
test('User sees already onboarded redirect', async ({ page }) => {
// TODO: Implement test
// Scenario: Already onboarded user is redirected
// Given I am a user who has already completed onboarding
// When I navigate to the onboarding page
// Then I should be redirected to the dashboard
// And I should not see the onboarding wizard
});
test('User sees unauthorized redirect when not logged in', async ({ page }) => {
// TODO: Implement test
// Scenario: Unauthorized user is redirected
// Given I am not logged in
// When I navigate to the onboarding page
// Then I should be redirected to the login page
// And I should see a login prompt
});
});