import { test, expect } from '@playwright/test'; test.describe('Supplier Portal Onboarding & Feature E2E Flow', () => { test('completes the registration, contact verification, document upload, location pinning, welcome tour, order acceptance, and barcode generation', async ({ page }) => { // 1. Visit Landing Page await page.goto('/'); await expect(page.getByText('Sell Globally.')).toBeVisible(); // 2. Registration Page await page.locator('button, a').filter({ hasText: 'Get Started Today' }).first().click(); const randUser = `test_seller_${Date.now()}@example.com`; const randPhone = `9${Math.floor(100000000 + Math.random() * 900000000)}`; await page.locator('input#reg-email').fill(randUser); await page.locator('input#reg-phone').fill(randPhone); await page.locator('input#reg-pass').fill('Super_secure_pass_123!'); await page.locator('input#reg-confirm-pass').fill('Super_secure_pass_123!'); await page.locator('input#reg-policy').check(); await page.locator('button').filter({ hasText: 'Register Business' }).click(); // 3. Step 1: Contact Verification await expect(page.getByText('Step 1 of 3: Contact Verification')).toBeVisible(); await page.locator('button').filter({ hasText: 'Send WhatsApp OTP' }).click(); await page.locator('input[placeholder="Enter 123456"]').first().fill('123456'); await page.locator('button').filter({ hasText: 'Verify Code' }).first().click(); await expect(page.getByText('✓ Mobile & WhatsApp Verified')).toBeVisible(); await page.locator('button').filter({ hasText: 'Send Email OTP' }).click(); await page.locator('input[placeholder="Enter 123456"]').last().fill('123456'); await page.locator('button').filter({ hasText: 'Verify Code' }).last().click(); await expect(page.getByText('✓ Email Verified')).toBeVisible(); await page.locator('button').filter({ hasText: 'Next Step: Identity Verification' }).click(); // 4. Step 2: Tax & Identity Verification await expect(page.getByText('Step 2 of 3: Tax & Identity Verification')).toBeVisible(); await page.locator('input#verify-gst').clear(); await page.locator('input#verify-gst').fill('29AAAAA1111A1Z1'); await page.locator('button').filter({ hasText: 'Submit GSTIN' }).click(); await expect(page.getByText('verification will be completed within next 24 hrs')).toBeVisible(); // Upload mock Aadhaar & PAN files await page.setInputFiles('input#aadhar-upload', { name: 'aadhar_card.pdf', mimeType: 'application/pdf', buffer: Buffer.from('mock aadhaar pdf'), }); await expect(page.getByText('Selected: aadhar_card.pdf')).toBeVisible(); await page.setInputFiles('input#pan-upload', { name: 'pan_card.pdf', mimeType: 'application/pdf', buffer: Buffer.from('mock pan pdf'), }); await expect(page.getByText('Selected: pan_card.pdf')).toBeVisible(); await page.locator('button').filter({ hasText: 'Next Step: Store & Location' }).click(); // 5. Step 3: Store & Pickup Location Setup await expect(page.getByText('Step 3 of 3: Store & Pickup Location')).toBeVisible(); await page.locator('input#store-name').clear(); await page.locator('input#store-name').fill('Teak Wood Craft Store'); await page.locator('textarea#store-bio').clear(); await page.locator('textarea#store-bio').fill('Teak wood hand-carved home decor elements.'); // Test interactive map coordinate pinning await expect(page.getByText('Store Location on Map *')).toBeVisible(); const mapGridParent = page.locator('span').filter({ hasText: 'Click anywhere on the map grid to pin location' }).locator('..'); await mapGridParent.click({ position: { x: 100, y: 80 } }); await expect(page.getByText('Coordinates: Lat')).toBeVisible(); await expect(page.locator('input#location-text')).not.toHaveValue(''); await page.locator('input#loc-city').clear(); await page.locator('input#loc-city').fill('Bangalore'); await page.locator('input#loc-pincode').clear(); await page.locator('input#loc-pincode').fill('560001'); await page.locator('button').filter({ hasText: 'Submit Supplier Profile' }).click(); // 6. Setup Welcome Tour Stepper await expect(page.getByText('Supplier Account Under Review ⏳')).toBeVisible(); await page.locator('button').filter({ hasText: 'Start Guided Tour 🎬' }).click(); await expect(page.getByText('📦 Products & Inventory Management')).toBeVisible(); await page.locator('button').filter({ hasText: 'Next: Order Management' }).click(); await expect(page.getByText('🚚 Order Acceptance Control')).toBeVisible(); await page.locator('button').filter({ hasText: 'Next: Barcode Generation' }).click(); await expect(page.getByText('🏷️ Barcode Identification & Tracking')).toBeVisible(); await page.locator('button').filter({ hasText: 'Next: Earnings & Wallet' }).click(); await expect(page.getByText('💼 Wallet & Payout Withdrawals')).toBeVisible(); await page.locator('button').filter({ hasText: 'Explore Dashboard 🚀' }).click(); // 7. Check Active Dashboard Tab await expect(page.getByText('Performance Analytics')).toBeVisible(); // 8. Manage Products tab & Bulk template download await page.locator('button, a').filter({ hasText: 'Manage Products' }).click(); await expect(page.getByText('Active Inventory')).toBeVisible(); const downloadPromise = page.waitForEvent('download'); await page.locator('button, a').filter({ hasText: 'Download Sample Excel Template' }).click(); const download = await downloadPromise; expect(download.suggestedFilename()).toBeDefined(); // 9. Orders Acceptance Flow await page.locator('button, a').filter({ hasText: 'Orders & Transit' }).click(); await expect(page.getByText('Active Orders & Payout status')).toBeVisible(); await expect(page.getByText('Pending Acceptance')).toBeVisible(); await page.locator('button').filter({ hasText: 'Accept' }).first().click(); await expect(page.getByText('Ready to Ship')).toBeVisible(); // 10. Barcode Generator await page.locator('button, a').filter({ hasText: 'Barcode Generator' }).click(); await expect(page.getByText('Product Barcode Generator')).toBeVisible(); await page.locator('select#barcode-product').selectOption({ index: 1 }); await page.locator('button').filter({ hasText: 'Generate Barcode Graphic' }).click(); await expect(page.getByText('Generated Barcode Preview')).toBeVisible(); await expect(page.getByText('Print Label')).toBeVisible(); await expect(page.getByText('Download SVG')).toBeVisible(); }); test('enforces security constraints and validation rules (negative test cases)', async ({ page }) => { // 1. Visit Home and verify dashboard components are not in DOM (route guarding) await page.goto('/'); await expect(page.locator('.dashboard-container')).toBeHidden(); await expect(page.locator('.sidebar-menu')).toBeHidden(); // 2. Go to Registration await page.locator('button, a').filter({ hasText: 'Get Started Today' }).first().click(); const randSecurityUser = `security_test_${Date.now()}@example.com`; const randSecurityPhone = `9${Math.floor(100000000 + Math.random() * 900000000)}`; await page.locator('input#reg-email').fill(randSecurityUser); await page.locator('input#reg-phone').fill(randSecurityPhone); await page.locator('input#reg-pass').fill('Password123!'); await page.locator('input#reg-confirm-pass').fill('Password123!'); await page.locator('input#reg-policy').check(); await page.locator('button').filter({ hasText: 'Register Business' }).click(); // 3. Step 1: Negative OTP validations await expect(page.getByText('Step 1 of 3: Contact Verification')).toBeVisible(); // Proceed button must be disabled initially await expect(page.locator('button').filter({ hasText: 'Next Step: Identity Verification' })).toBeDisabled(); // Submit invalid WhatsApp OTP await page.locator('button').filter({ hasText: 'Send WhatsApp OTP' }).click(); await page.locator('input[placeholder="Enter 123456"]').first().fill('000000'); // Capture dialog let alertMessage = ''; page.once('dialog', async dialog => { alertMessage = dialog.message(); await dialog.accept(); }); await page.locator('button').filter({ hasText: 'Verify Code' }).first().click(); // Give brief time/event loop ticks to ensure dialog handler fires await page.waitForTimeout(500); expect(alertMessage).toBe('Incorrect code. Enter 123456'); await expect(page.getByText('✓ Mobile & WhatsApp Verified')).toBeHidden(); // Correct the code to enable proceed await page.locator('input[placeholder="Enter 123456"]').first().clear(); await page.locator('input[placeholder="Enter 123456"]').first().fill('123456'); await page.locator('button').filter({ hasText: 'Verify Code' }).first().click(); await expect(page.getByText('✓ Mobile & WhatsApp Verified')).toBeVisible(); // Submit invalid Email OTP await page.locator('button').filter({ hasText: 'Send Email OTP' }).click(); await page.locator('input[placeholder="Enter 123456"]').last().fill('999999'); page.once('dialog', async dialog => { alertMessage = dialog.message(); await dialog.accept(); }); await page.locator('button').filter({ hasText: 'Verify Code' }).last().click(); await page.waitForTimeout(500); expect(alertMessage).toBe('Incorrect code. Enter 123456'); await expect(page.getByText('✓ Email Verified')).toBeHidden(); await expect(page.locator('button').filter({ hasText: 'Next Step: Identity Verification' })).toBeDisabled(); }); });