/** * 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 { expect } from '@playwright/test'; import { testWithAuth } from '../../shared/auth-fixture'; import * as path from 'path'; testWithAuth.describe('Onboarding - Avatar Step', () => { testWithAuth('User sees avatar creation form', async ({ unonboardedDriver }) => { await unonboardedDriver.goto('/onboarding/avatar'); await unonboardedDriver.waitForLoadState('networkidle'); await expect(unonboardedDriver.getByTestId('avatar-creation-form')).toBeVisible(); await expect(unonboardedDriver.getByTestId('photo-upload-area')).toBeVisible(); await expect(unonboardedDriver.getByTestId('suit-color-options')).toBeVisible(); await expect(unonboardedDriver.getByTestId('generate-avatars-btn')).toBeVisible(); }); testWithAuth('User can upload face photo', async ({ unonboardedDriver }) => { await unonboardedDriver.goto('/onboarding/avatar'); const uploadInput = unonboardedDriver.getByTestId('photo-upload-input'); const filePath = path.resolve(__dirname, '../../assets/test-photo.jpg'); await uploadInput.setInputFiles(filePath); await expect(unonboardedDriver.getByTestId('photo-preview')).toBeVisible(); }); testWithAuth('User can select suit color', async ({ unonboardedDriver }) => { await unonboardedDriver.goto('/onboarding/avatar'); await unonboardedDriver.getByTestId('suit-color-red').click(); await expect(unonboardedDriver.getByTestId('suit-color-red')).toHaveAttribute('data-selected', 'true'); }); testWithAuth('User can generate avatars after uploading photo', async ({ unonboardedDriver }) => { await unonboardedDriver.goto('/onboarding'); await unonboardedDriver.getByTestId('first-name-input').fill('Demo'); await unonboardedDriver.getByTestId('last-name-input').fill('Driver'); await unonboardedDriver.getByTestId('display-name-input').fill('DemoDriver'); await unonboardedDriver.getByTestId('country-select').selectOption('US'); await unonboardedDriver.getByTestId('next-btn').click(); const uploadInput = unonboardedDriver.getByTestId('photo-upload-input'); const filePath = path.resolve(__dirname, '../../assets/test-photo.jpg'); await uploadInput.setInputFiles(filePath); await unonboardedDriver.getByTestId('suit-color-red').click(); await unonboardedDriver.getByTestId('generate-avatars-btn').click(); await expect(unonboardedDriver.getByTestId('generate-avatars-btn')).toBeDisabled(); await expect(unonboardedDriver.locator('button:has(img[alt*="Avatar option"])').first()).toBeVisible({ timeout: 15000 }); }); testWithAuth('User sees avatar generation progress', async () => { // 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 }); testWithAuth('User can select from generated avatars', async () => { // 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 }); testWithAuth('User sees validation error when no photo uploaded', async () => { // 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" }); testWithAuth('User sees validation error when no avatar selected', async () => { // 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" }); testWithAuth('User can regenerate avatars with different suit color', async () => { // 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 }); testWithAuth('User sees avatar preview before upload', async () => { // 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 }); testWithAuth('User cannot upload invalid file format for photo', async () => { // 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 }); testWithAuth('User cannot upload oversized photo file', async () => { // 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 }); testWithAuth('User sees avatar generation error state', async () => { // 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 }); testWithAuth('User can retry failed avatar generation', async () => { // 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 }); testWithAuth('User can proceed to submit with valid avatar selection', async () => { // 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 }); testWithAuth('User sees help text for avatar generation', async () => { // 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 }); testWithAuth('User sees avatar generation requirements', async () => { // 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 }); testWithAuth('User can cancel avatar generation', async () => { // 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 }); testWithAuth('User sees avatar in different contexts after onboarding', async () => { // 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 }); });