178 lines
9.5 KiB
TypeScript
178 lines
9.5 KiB
TypeScript
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()}_${Math.floor(Math.random() * 1000000)}@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').first()).toBeVisible();
|
|
await page.locator('button').filter({ hasText: 'Accept' }).first().click();
|
|
await expect(page.getByText('Ready to Ship')).toBeVisible();
|
|
|
|
// 10. Customer Address Printer
|
|
await page.locator('button, a').filter({ hasText: 'Customer Address Printer' }).click();
|
|
await expect(page.getByRole('heading', { name: 'Customer Address Printer' })).toBeVisible();
|
|
await page.locator('select#print-order').selectOption({ index: 1 });
|
|
await expect(page.getByText('Shipping Label Preview')).toBeVisible();
|
|
await expect(page.getByRole('button', { name: 'Print Address Label' })).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()}_${Math.floor(Math.random() * 1000000)}@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();
|
|
});
|
|
});
|