fix type mismatch in order printer comparison
This commit is contained in:
parent
3a5b5f50c5
commit
dfdbf2b1d5
19 changed files with 223 additions and 612 deletions
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB |
|
|
@ -14,14 +14,14 @@
|
|||
```
|
||||
Error: expect(locator).toBeVisible() failed
|
||||
|
||||
Locator: getByText('Step 1 of 3: Contact Verification')
|
||||
Locator: getByText('Shipping Label Preview')
|
||||
Expected: visible
|
||||
Timeout: 5000ms
|
||||
Error: element(s) not found
|
||||
|
||||
Call log:
|
||||
- Expect "toBeVisible" with timeout 5000ms
|
||||
- waiting for getByText('Step 1 of 3: Contact Verification')
|
||||
- waiting for getByText('Shipping Label Preview')
|
||||
|
||||
```
|
||||
|
||||
|
|
@ -33,39 +33,33 @@ Call log:
|
|||
- button "Pricing"
|
||||
- button "Success Stories"
|
||||
- button "Support"
|
||||
- button "Login"
|
||||
- button "Get Started"
|
||||
- main:
|
||||
- button "Login"
|
||||
- button "Register"
|
||||
- heading "Create Your Supplier Account" [level=2]
|
||||
- text: Business Email *
|
||||
- textbox "Business Email *":
|
||||
- /placeholder: Enter email address
|
||||
- text: test_seller_1786700927358@example.com
|
||||
- text: Mobile Number *
|
||||
- textbox "Mobile Number *":
|
||||
- /placeholder: Enter 10-digit number
|
||||
- text: "9118192284"
|
||||
- text: Create Password *
|
||||
- textbox "Create Password *":
|
||||
- /placeholder: Minimum 8 characters
|
||||
- text: Super_secure_pass_123!
|
||||
- button "🙈"
|
||||
- text: Confirm Password *
|
||||
- textbox "Confirm Password *":
|
||||
- /placeholder: Re-enter password
|
||||
- text: Super_secure_pass_123!
|
||||
- button "🙈"
|
||||
- checkbox "I accept the Terms of Service and Privacy Policy *" [checked]
|
||||
- text: I accept the
|
||||
- link "Terms of Service":
|
||||
- /url: "#terms"
|
||||
- text: and
|
||||
- link "Privacy Policy":
|
||||
- /url: "#privacy"
|
||||
- text: "*"
|
||||
- button "Register Business"
|
||||
- button "Logout"
|
||||
- complementary:
|
||||
- text: SELLER PANEL
|
||||
- heading "Teak Wood Craft Store" [level=4]
|
||||
- list:
|
||||
- listitem:
|
||||
- button "📊 Overview & Analytics"
|
||||
- listitem:
|
||||
- button "📦 Manage Products"
|
||||
- listitem:
|
||||
- button "🚚 Orders & Transit"
|
||||
- listitem:
|
||||
- button "🔄 Returns Management"
|
||||
- listitem:
|
||||
- button "💼 Wallet & Payouts"
|
||||
- listitem:
|
||||
- button "🖨️ Customer Address Printer"
|
||||
- listitem:
|
||||
- button "⚙️ Store Settings"
|
||||
- heading "Customer Address Printer" [level=2]
|
||||
- paragraph: Select an accepted order to view and print the shipping address label for the customer.
|
||||
- heading "Print Configuration" [level=3]
|
||||
- text: Select Accepted Order *
|
||||
- combobox "Select Accepted Order *":
|
||||
- option "-- Choose an accepted order --"
|
||||
- option "22 - Alice Smith (Handmade Wool Blanket)" [selected]
|
||||
- button "Print Address Label"
|
||||
- contentinfo:
|
||||
- text: Global Artisans Hub
|
||||
- link "About Us":
|
||||
|
|
@ -84,17 +78,6 @@ Call log:
|
|||
# Test source
|
||||
|
||||
```ts
|
||||
1 | import { test, expect } from '@playwright/test';
|
||||
2 |
|
||||
3 | test.describe('Supplier Portal Onboarding & Feature E2E Flow', () => {
|
||||
4 | test('completes the registration, contact verification, document upload, location pinning, welcome tour, order acceptance, and barcode generation', async ({ page }) => {
|
||||
5 | // 1. Visit Landing Page
|
||||
6 | await page.goto('/');
|
||||
7 | await expect(page.getByText('Sell Globally.')).toBeVisible();
|
||||
8 |
|
||||
9 | // 2. Registration Page
|
||||
10 | await page.locator('button, a').filter({ hasText: 'Get Started Today' }).first().click();
|
||||
11 | const randUser = `test_seller_${Date.now()}@example.com`;
|
||||
12 | const randPhone = `9${Math.floor(100000000 + Math.random() * 900000000)}`;
|
||||
13 | await page.locator('input#reg-email').fill(randUser);
|
||||
14 | await page.locator('input#reg-phone').fill(randPhone);
|
||||
|
|
@ -104,8 +87,7 @@ Call log:
|
|||
18 | await page.locator('button').filter({ hasText: 'Register Business' }).click();
|
||||
19 |
|
||||
20 | // 3. Step 1: Contact Verification
|
||||
> 21 | await expect(page.getByText('Step 1 of 3: Contact Verification')).toBeVisible();
|
||||
| ^ Error: expect(locator).toBeVisible() failed
|
||||
21 | await expect(page.getByText('Step 1 of 3: Contact Verification')).toBeVisible();
|
||||
22 | await page.locator('button').filter({ hasText: 'Send WhatsApp OTP' }).click();
|
||||
23 | await page.locator('input[placeholder="Enter 123456"]').first().fill('123456');
|
||||
24 | await page.locator('button').filter({ hasText: 'Verify Code' }).first().click();
|
||||
|
|
@ -188,22 +170,81 @@ Call log:
|
|||
101 | // 9. Orders Acceptance Flow
|
||||
102 | await page.locator('button, a').filter({ hasText: 'Orders & Transit' }).click();
|
||||
103 | await expect(page.getByText('Active Orders & Payout status')).toBeVisible();
|
||||
104 | await expect(page.getByText('Pending Acceptance')).toBeVisible();
|
||||
104 | await expect(page.getByText('Pending Acceptance').first()).toBeVisible();
|
||||
105 | await page.locator('button').filter({ hasText: 'Accept' }).first().click();
|
||||
106 | await expect(page.getByText('Ready to Ship')).toBeVisible();
|
||||
107 |
|
||||
108 | // 10. Barcode Generator
|
||||
109 | await page.locator('button, a').filter({ hasText: 'Barcode Generator' }).click();
|
||||
110 | await expect(page.getByText('Product Barcode Generator')).toBeVisible();
|
||||
111 | await page.locator('select#barcode-product').selectOption({ index: 1 });
|
||||
112 | await page.locator('button').filter({ hasText: 'Generate Barcode Graphic' }).click();
|
||||
113 | await expect(page.getByText('Generated Barcode Preview')).toBeVisible();
|
||||
114 | await expect(page.getByText('Print Label')).toBeVisible();
|
||||
115 | await expect(page.getByText('Download SVG')).toBeVisible();
|
||||
116 | });
|
||||
117 |
|
||||
118 | test('enforces security constraints and validation rules (negative test cases)', async ({ page }) => {
|
||||
119 | // 1. Visit Home and verify dashboard components are not in DOM (route guarding)
|
||||
120 | await page.goto('/');
|
||||
121 | await expect(page.locator('.dashboard-container')).toBeHidden();
|
||||
108 | // 10. Customer Address Printer
|
||||
109 | await page.locator('button, a').filter({ hasText: 'Customer Address Printer' }).click();
|
||||
110 | await expect(page.getByRole('heading', { name: 'Customer Address Printer' })).toBeVisible();
|
||||
111 | await page.locator('select#print-order').selectOption({ index: 1 });
|
||||
> 112 | await expect(page.getByText('Shipping Label Preview')).toBeVisible();
|
||||
| ^ Error: expect(locator).toBeVisible() failed
|
||||
113 | await expect(page.getByRole('button', { name: 'Print Address Label' })).toBeVisible();
|
||||
114 | });
|
||||
115 |
|
||||
116 | test('enforces security constraints and validation rules (negative test cases)', async ({ page }) => {
|
||||
117 | // 1. Visit Home and verify dashboard components are not in DOM (route guarding)
|
||||
118 | await page.goto('/');
|
||||
119 | await expect(page.locator('.dashboard-container')).toBeHidden();
|
||||
120 | await expect(page.locator('.sidebar-menu')).toBeHidden();
|
||||
121 |
|
||||
122 | // 2. Go to Registration
|
||||
123 | await page.locator('button, a').filter({ hasText: 'Get Started Today' }).first().click();
|
||||
124 | const randSecurityUser = `security_test_${Date.now()}_${Math.floor(Math.random() * 1000000)}@example.com`;
|
||||
125 | const randSecurityPhone = `9${Math.floor(100000000 + Math.random() * 900000000)}`;
|
||||
126 | await page.locator('input#reg-email').fill(randSecurityUser);
|
||||
127 | await page.locator('input#reg-phone').fill(randSecurityPhone);
|
||||
128 | await page.locator('input#reg-pass').fill('Password123!');
|
||||
129 | await page.locator('input#reg-confirm-pass').fill('Password123!');
|
||||
130 | await page.locator('input#reg-policy').check();
|
||||
131 | await page.locator('button').filter({ hasText: 'Register Business' }).click();
|
||||
132 |
|
||||
133 | // 3. Step 1: Negative OTP validations
|
||||
134 | await expect(page.getByText('Step 1 of 3: Contact Verification')).toBeVisible();
|
||||
135 |
|
||||
136 | // Proceed button must be disabled initially
|
||||
137 | await expect(page.locator('button').filter({ hasText: 'Next Step: Identity Verification' })).toBeDisabled();
|
||||
138 |
|
||||
139 | // Submit invalid WhatsApp OTP
|
||||
140 | await page.locator('button').filter({ hasText: 'Send WhatsApp OTP' }).click();
|
||||
141 | await page.locator('input[placeholder="Enter 123456"]').first().fill('000000');
|
||||
142 |
|
||||
143 | // Capture dialog
|
||||
144 | let alertMessage = '';
|
||||
145 | page.once('dialog', async dialog => {
|
||||
146 | alertMessage = dialog.message();
|
||||
147 | await dialog.accept();
|
||||
148 | });
|
||||
149 |
|
||||
150 | await page.locator('button').filter({ hasText: 'Verify Code' }).first().click();
|
||||
151 |
|
||||
152 | // Give brief time/event loop ticks to ensure dialog handler fires
|
||||
153 | await page.waitForTimeout(500);
|
||||
154 | expect(alertMessage).toBe('Incorrect code. Enter 123456');
|
||||
155 | await expect(page.getByText('✓ Mobile & WhatsApp Verified')).toBeHidden();
|
||||
156 |
|
||||
157 | // Correct the code to enable proceed
|
||||
158 | await page.locator('input[placeholder="Enter 123456"]').first().clear();
|
||||
159 | await page.locator('input[placeholder="Enter 123456"]').first().fill('123456');
|
||||
160 | await page.locator('button').filter({ hasText: 'Verify Code' }).first().click();
|
||||
161 | await expect(page.getByText('✓ Mobile & WhatsApp Verified')).toBeVisible();
|
||||
162 |
|
||||
163 | // Submit invalid Email OTP
|
||||
164 | await page.locator('button').filter({ hasText: 'Send Email OTP' }).click();
|
||||
165 | await page.locator('input[placeholder="Enter 123456"]').last().fill('999999');
|
||||
166 |
|
||||
167 | page.once('dialog', async dialog => {
|
||||
168 | alertMessage = dialog.message();
|
||||
169 | await dialog.accept();
|
||||
170 | });
|
||||
171 |
|
||||
172 | await page.locator('button').filter({ hasText: 'Verify Code' }).last().click();
|
||||
173 | await page.waitForTimeout(500);
|
||||
174 | expect(alertMessage).toBe('Incorrect code. Enter 123456');
|
||||
175 | await expect(page.getByText('✓ Email Verified')).toBeHidden();
|
||||
176 | await expect(page.locator('button').filter({ hasText: 'Next Step: Identity Verification' })).toBeDisabled();
|
||||
177 | });
|
||||
178 | });
|
||||
179 |
|
||||
```
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB |
|
|
@ -1,234 +0,0 @@
|
|||
# Instructions
|
||||
|
||||
- Following Playwright test failed.
|
||||
- Explain why, be concise, respect Playwright best practices.
|
||||
- Provide a snippet of code with the fix, if possible.
|
||||
|
||||
# Test info
|
||||
|
||||
- Name: onboarding.spec.ts >> Supplier Portal Onboarding & Feature E2E Flow >> enforces security constraints and validation rules (negative test cases)
|
||||
- Location: playwright/e2e/onboarding.spec.ts:118:3
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: expect(locator).toBeVisible() failed
|
||||
|
||||
Locator: getByText('Step 1 of 3: Contact Verification')
|
||||
Expected: visible
|
||||
Timeout: 5000ms
|
||||
Error: element(s) not found
|
||||
|
||||
Call log:
|
||||
- Expect "toBeVisible" with timeout 5000ms
|
||||
- waiting for getByText('Step 1 of 3: Contact Verification')
|
||||
|
||||
```
|
||||
|
||||
```yaml
|
||||
- banner:
|
||||
- text: A Global Artisans Hub
|
||||
- navigation:
|
||||
- button "Platform"
|
||||
- button "Pricing"
|
||||
- button "Success Stories"
|
||||
- button "Support"
|
||||
- button "Login"
|
||||
- button "Get Started"
|
||||
- main:
|
||||
- button "Login"
|
||||
- button "Register"
|
||||
- heading "Create Your Supplier Account" [level=2]
|
||||
- text: Business Email *
|
||||
- textbox "Business Email *":
|
||||
- /placeholder: Enter email address
|
||||
- text: security_test_1786700927306@example.com
|
||||
- text: Mobile Number *
|
||||
- textbox "Mobile Number *":
|
||||
- /placeholder: Enter 10-digit number
|
||||
- text: "9358500184"
|
||||
- text: Create Password *
|
||||
- textbox "Create Password *":
|
||||
- /placeholder: Minimum 8 characters
|
||||
- text: Password123!
|
||||
- button "🙈"
|
||||
- text: Confirm Password *
|
||||
- textbox "Confirm Password *":
|
||||
- /placeholder: Re-enter password
|
||||
- text: Password123!
|
||||
- button "🙈"
|
||||
- checkbox "I accept the Terms of Service and Privacy Policy *" [checked]
|
||||
- text: I accept the
|
||||
- link "Terms of Service":
|
||||
- /url: "#terms"
|
||||
- text: and
|
||||
- link "Privacy Policy":
|
||||
- /url: "#privacy"
|
||||
- text: "*"
|
||||
- button "Register Business"
|
||||
- contentinfo:
|
||||
- text: Global Artisans Hub
|
||||
- link "About Us":
|
||||
- /url: "#about"
|
||||
- link "Careers":
|
||||
- /url: "#careers"
|
||||
- link "Press":
|
||||
- /url: "#press"
|
||||
- link "Terms":
|
||||
- /url: "#terms"
|
||||
- link "Privacy":
|
||||
- /url: "#privacy"
|
||||
- text: © 2026 Global Artisans Hub. All rights reserved.
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
36 | await page.locator('input#verify-gst').fill('29AAAAA1111A1Z1');
|
||||
37 | await page.locator('button').filter({ hasText: 'Submit GSTIN' }).click();
|
||||
38 | await expect(page.getByText('verification will be completed within next 24 hrs')).toBeVisible();
|
||||
39 |
|
||||
40 | // Upload mock Aadhaar & PAN files
|
||||
41 | await page.setInputFiles('input#aadhar-upload', {
|
||||
42 | name: 'aadhar_card.pdf',
|
||||
43 | mimeType: 'application/pdf',
|
||||
44 | buffer: Buffer.from('mock aadhaar pdf'),
|
||||
45 | });
|
||||
46 | await expect(page.getByText('Selected: aadhar_card.pdf')).toBeVisible();
|
||||
47 |
|
||||
48 | await page.setInputFiles('input#pan-upload', {
|
||||
49 | name: 'pan_card.pdf',
|
||||
50 | mimeType: 'application/pdf',
|
||||
51 | buffer: Buffer.from('mock pan pdf'),
|
||||
52 | });
|
||||
53 | await expect(page.getByText('Selected: pan_card.pdf')).toBeVisible();
|
||||
54 |
|
||||
55 | await page.locator('button').filter({ hasText: 'Next Step: Store & Location' }).click();
|
||||
56 |
|
||||
57 | // 5. Step 3: Store & Pickup Location Setup
|
||||
58 | await expect(page.getByText('Step 3 of 3: Store & Pickup Location')).toBeVisible();
|
||||
59 | await page.locator('input#store-name').clear();
|
||||
60 | await page.locator('input#store-name').fill('Teak Wood Craft Store');
|
||||
61 | await page.locator('textarea#store-bio').clear();
|
||||
62 | await page.locator('textarea#store-bio').fill('Teak wood hand-carved home decor elements.');
|
||||
63 |
|
||||
64 | // Test interactive map coordinate pinning
|
||||
65 | await expect(page.getByText('Store Location on Map *')).toBeVisible();
|
||||
66 | const mapGridParent = page.locator('span').filter({ hasText: 'Click anywhere on the map grid to pin location' }).locator('..');
|
||||
67 | await mapGridParent.click({ position: { x: 100, y: 80 } });
|
||||
68 | await expect(page.getByText('Coordinates: Lat')).toBeVisible();
|
||||
69 |
|
||||
70 | await expect(page.locator('input#location-text')).not.toHaveValue('');
|
||||
71 | await page.locator('input#loc-city').clear();
|
||||
72 | await page.locator('input#loc-city').fill('Bangalore');
|
||||
73 | await page.locator('input#loc-pincode').clear();
|
||||
74 | await page.locator('input#loc-pincode').fill('560001');
|
||||
75 | await page.locator('button').filter({ hasText: 'Submit Supplier Profile' }).click();
|
||||
76 |
|
||||
77 | // 6. Setup Welcome Tour Stepper
|
||||
78 | await expect(page.getByText('Supplier Account Under Review ⏳')).toBeVisible();
|
||||
79 | await page.locator('button').filter({ hasText: 'Start Guided Tour 🎬' }).click();
|
||||
80 | await expect(page.getByText('📦 Products & Inventory Management')).toBeVisible();
|
||||
81 | await page.locator('button').filter({ hasText: 'Next: Order Management' }).click();
|
||||
82 | await expect(page.getByText('🚚 Order Acceptance Control')).toBeVisible();
|
||||
83 | await page.locator('button').filter({ hasText: 'Next: Barcode Generation' }).click();
|
||||
84 | await expect(page.getByText('🏷️ Barcode Identification & Tracking')).toBeVisible();
|
||||
85 | await page.locator('button').filter({ hasText: 'Next: Earnings & Wallet' }).click();
|
||||
86 | await expect(page.getByText('💼 Wallet & Payout Withdrawals')).toBeVisible();
|
||||
87 | await page.locator('button').filter({ hasText: 'Explore Dashboard 🚀' }).click();
|
||||
88 |
|
||||
89 | // 7. Check Active Dashboard Tab
|
||||
90 | await expect(page.getByText('Performance Analytics')).toBeVisible();
|
||||
91 |
|
||||
92 | // 8. Manage Products tab & Bulk template download
|
||||
93 | await page.locator('button, a').filter({ hasText: 'Manage Products' }).click();
|
||||
94 | await expect(page.getByText('Active Inventory')).toBeVisible();
|
||||
95 |
|
||||
96 | const downloadPromise = page.waitForEvent('download');
|
||||
97 | await page.locator('button, a').filter({ hasText: 'Download Sample Excel Template' }).click();
|
||||
98 | const download = await downloadPromise;
|
||||
99 | expect(download.suggestedFilename()).toBeDefined();
|
||||
100 |
|
||||
101 | // 9. Orders Acceptance Flow
|
||||
102 | await page.locator('button, a').filter({ hasText: 'Orders & Transit' }).click();
|
||||
103 | await expect(page.getByText('Active Orders & Payout status')).toBeVisible();
|
||||
104 | await expect(page.getByText('Pending Acceptance')).toBeVisible();
|
||||
105 | await page.locator('button').filter({ hasText: 'Accept' }).first().click();
|
||||
106 | await expect(page.getByText('Ready to Ship')).toBeVisible();
|
||||
107 |
|
||||
108 | // 10. Barcode Generator
|
||||
109 | await page.locator('button, a').filter({ hasText: 'Barcode Generator' }).click();
|
||||
110 | await expect(page.getByText('Product Barcode Generator')).toBeVisible();
|
||||
111 | await page.locator('select#barcode-product').selectOption({ index: 1 });
|
||||
112 | await page.locator('button').filter({ hasText: 'Generate Barcode Graphic' }).click();
|
||||
113 | await expect(page.getByText('Generated Barcode Preview')).toBeVisible();
|
||||
114 | await expect(page.getByText('Print Label')).toBeVisible();
|
||||
115 | await expect(page.getByText('Download SVG')).toBeVisible();
|
||||
116 | });
|
||||
117 |
|
||||
118 | test('enforces security constraints and validation rules (negative test cases)', async ({ page }) => {
|
||||
119 | // 1. Visit Home and verify dashboard components are not in DOM (route guarding)
|
||||
120 | await page.goto('/');
|
||||
121 | await expect(page.locator('.dashboard-container')).toBeHidden();
|
||||
122 | await expect(page.locator('.sidebar-menu')).toBeHidden();
|
||||
123 |
|
||||
124 | // 2. Go to Registration
|
||||
125 | await page.locator('button, a').filter({ hasText: 'Get Started Today' }).first().click();
|
||||
126 | const randSecurityUser = `security_test_${Date.now()}@example.com`;
|
||||
127 | const randSecurityPhone = `9${Math.floor(100000000 + Math.random() * 900000000)}`;
|
||||
128 | await page.locator('input#reg-email').fill(randSecurityUser);
|
||||
129 | await page.locator('input#reg-phone').fill(randSecurityPhone);
|
||||
130 | await page.locator('input#reg-pass').fill('Password123!');
|
||||
131 | await page.locator('input#reg-confirm-pass').fill('Password123!');
|
||||
132 | await page.locator('input#reg-policy').check();
|
||||
133 | await page.locator('button').filter({ hasText: 'Register Business' }).click();
|
||||
134 |
|
||||
135 | // 3. Step 1: Negative OTP validations
|
||||
> 136 | await expect(page.getByText('Step 1 of 3: Contact Verification')).toBeVisible();
|
||||
| ^ Error: expect(locator).toBeVisible() failed
|
||||
137 |
|
||||
138 | // Proceed button must be disabled initially
|
||||
139 | await expect(page.locator('button').filter({ hasText: 'Next Step: Identity Verification' })).toBeDisabled();
|
||||
140 |
|
||||
141 | // Submit invalid WhatsApp OTP
|
||||
142 | await page.locator('button').filter({ hasText: 'Send WhatsApp OTP' }).click();
|
||||
143 | await page.locator('input[placeholder="Enter 123456"]').first().fill('000000');
|
||||
144 |
|
||||
145 | // Capture dialog
|
||||
146 | let alertMessage = '';
|
||||
147 | page.once('dialog', async dialog => {
|
||||
148 | alertMessage = dialog.message();
|
||||
149 | await dialog.accept();
|
||||
150 | });
|
||||
151 |
|
||||
152 | await page.locator('button').filter({ hasText: 'Verify Code' }).first().click();
|
||||
153 |
|
||||
154 | // Give brief time/event loop ticks to ensure dialog handler fires
|
||||
155 | await page.waitForTimeout(500);
|
||||
156 | expect(alertMessage).toBe('Incorrect code. Enter 123456');
|
||||
157 | await expect(page.getByText('✓ Mobile & WhatsApp Verified')).toBeHidden();
|
||||
158 |
|
||||
159 | // Correct the code to enable proceed
|
||||
160 | await page.locator('input[placeholder="Enter 123456"]').first().clear();
|
||||
161 | await page.locator('input[placeholder="Enter 123456"]').first().fill('123456');
|
||||
162 | await page.locator('button').filter({ hasText: 'Verify Code' }).first().click();
|
||||
163 | await expect(page.getByText('✓ Mobile & WhatsApp Verified')).toBeVisible();
|
||||
164 |
|
||||
165 | // Submit invalid Email OTP
|
||||
166 | await page.locator('button').filter({ hasText: 'Send Email OTP' }).click();
|
||||
167 | await page.locator('input[placeholder="Enter 123456"]').last().fill('999999');
|
||||
168 |
|
||||
169 | page.once('dialog', async dialog => {
|
||||
170 | alertMessage = dialog.message();
|
||||
171 | await dialog.accept();
|
||||
172 | });
|
||||
173 |
|
||||
174 | await page.locator('button').filter({ hasText: 'Verify Code' }).last().click();
|
||||
175 | await page.waitForTimeout(500);
|
||||
176 | expect(alertMessage).toBe('Incorrect code. Enter 123456');
|
||||
177 | await expect(page.getByText('✓ Email Verified')).toBeHidden();
|
||||
178 | await expect(page.locator('button').filter({ hasText: 'Next Step: Identity Verification' })).toBeDisabled();
|
||||
179 | });
|
||||
180 | });
|
||||
181 |
|
||||
```
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -2,10 +2,10 @@ import { defineConfig, devices } from '@playwright/test';
|
|||
|
||||
export default defineConfig({
|
||||
testDir: './playwright/e2e',
|
||||
fullyParallel: true,
|
||||
fullyParallel: false,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
workers: 1,
|
||||
reporter: 'html',
|
||||
use: {
|
||||
baseURL: 'https://betasuppliers.tipro.in/',
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ test.describe('Supplier Portal Onboarding & Feature E2E Flow', () => {
|
|||
|
||||
// 2. Registration Page
|
||||
await page.locator('button, a').filter({ hasText: 'Get Started Today' }).first().click();
|
||||
const randUser = `test_seller_${Date.now()}@example.com`;
|
||||
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);
|
||||
|
|
@ -101,18 +101,16 @@ test.describe('Supplier Portal Onboarding & Feature E2E Flow', () => {
|
|||
// 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 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. 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();
|
||||
// 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 }) => {
|
||||
|
|
@ -123,7 +121,7 @@ test.describe('Supplier Portal Onboarding & Feature E2E Flow', () => {
|
|||
|
||||
// 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 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);
|
||||
|
|
|
|||
|
|
@ -2235,7 +2235,7 @@ export default function App() {
|
|||
style={{ width: '100%', marginTop: '1.5rem' }}
|
||||
disabled={!barcodeProductSku}
|
||||
onClick={() => {
|
||||
const order = orders.find(o => o.id === barcodeProductSku);
|
||||
const order = orders.find(o => String(o.id) === String(barcodeProductSku));
|
||||
if (order) {
|
||||
alert(`Printing shipping label for order: ${order.id}\nCustomer: ${order.customer}\nDestination: 12 Weaver Lane, Kanchipuram, Tamil Nadu 631502`);
|
||||
}
|
||||
|
|
@ -2248,7 +2248,7 @@ export default function App() {
|
|||
<div className="chart-card" style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textAlign: 'center', minHeight: '300px' }}>
|
||||
{barcodeGenerated && barcodeProductSku ? (
|
||||
(() => {
|
||||
const selectedOrder = orders.find(o => o.id === barcodeProductSku);
|
||||
const selectedOrder = orders.find(o => String(o.id) === String(barcodeProductSku));
|
||||
return selectedOrder ? (
|
||||
<div>
|
||||
<h4 style={{ marginBottom: '1.5rem', color: 'var(--primary)' }}>Shipping Label Preview</h4>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
"status": "failed",
|
||||
"failedTests": [
|
||||
"fe534f0825407f213faa-eae28aa470cee3dd351a",
|
||||
"fe534f0825407f213faa-178b974dec5b4368ccdd"
|
||||
"fe534f0825407f213faa-eae28aa470cee3dd351a"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
# Instructions
|
||||
|
||||
- Following Playwright test failed.
|
||||
- Explain why, be concise, respect Playwright best practices.
|
||||
- Provide a snippet of code with the fix, if possible.
|
||||
|
||||
# Test info
|
||||
|
||||
- Name: onboarding.spec.ts >> Supplier Portal Onboarding & Feature E2E Flow >> enforces security constraints and validation rules (negative test cases)
|
||||
- Location: playwright/e2e/onboarding.spec.ts:118:3
|
||||
|
||||
# Error details
|
||||
|
||||
```
|
||||
Error: expect(locator).toBeVisible() failed
|
||||
|
||||
Locator: getByText('Step 1 of 3: Contact Verification')
|
||||
Expected: visible
|
||||
Timeout: 5000ms
|
||||
Error: element(s) not found
|
||||
|
||||
Call log:
|
||||
- Expect "toBeVisible" with timeout 5000ms
|
||||
- waiting for getByText('Step 1 of 3: Contact Verification')
|
||||
|
||||
```
|
||||
|
||||
```yaml
|
||||
- banner:
|
||||
- text: A Global Artisans Hub
|
||||
- navigation:
|
||||
- button "Platform"
|
||||
- button "Pricing"
|
||||
- button "Success Stories"
|
||||
- button "Support"
|
||||
- button "Login"
|
||||
- button "Get Started"
|
||||
- main:
|
||||
- button "Login"
|
||||
- button "Register"
|
||||
- heading "Create Your Supplier Account" [level=2]
|
||||
- text: Business Email *
|
||||
- textbox "Business Email *":
|
||||
- /placeholder: Enter email address
|
||||
- text: security_test_1786700927306@example.com
|
||||
- text: Mobile Number *
|
||||
- textbox "Mobile Number *":
|
||||
- /placeholder: Enter 10-digit number
|
||||
- text: "9358500184"
|
||||
- text: Create Password *
|
||||
- textbox "Create Password *":
|
||||
- /placeholder: Minimum 8 characters
|
||||
- text: Password123!
|
||||
- button "🙈"
|
||||
- text: Confirm Password *
|
||||
- textbox "Confirm Password *":
|
||||
- /placeholder: Re-enter password
|
||||
- text: Password123!
|
||||
- button "🙈"
|
||||
- checkbox "I accept the Terms of Service and Privacy Policy *" [checked]
|
||||
- text: I accept the
|
||||
- link "Terms of Service":
|
||||
- /url: "#terms"
|
||||
- text: and
|
||||
- link "Privacy Policy":
|
||||
- /url: "#privacy"
|
||||
- text: "*"
|
||||
- button "Register Business"
|
||||
- contentinfo:
|
||||
- text: Global Artisans Hub
|
||||
- link "About Us":
|
||||
- /url: "#about"
|
||||
- link "Careers":
|
||||
- /url: "#careers"
|
||||
- link "Press":
|
||||
- /url: "#press"
|
||||
- link "Terms":
|
||||
- /url: "#terms"
|
||||
- link "Privacy":
|
||||
- /url: "#privacy"
|
||||
- text: © 2026 Global Artisans Hub. All rights reserved.
|
||||
```
|
||||
|
||||
# Test source
|
||||
|
||||
```ts
|
||||
36 | await page.locator('input#verify-gst').fill('29AAAAA1111A1Z1');
|
||||
37 | await page.locator('button').filter({ hasText: 'Submit GSTIN' }).click();
|
||||
38 | await expect(page.getByText('verification will be completed within next 24 hrs')).toBeVisible();
|
||||
39 |
|
||||
40 | // Upload mock Aadhaar & PAN files
|
||||
41 | await page.setInputFiles('input#aadhar-upload', {
|
||||
42 | name: 'aadhar_card.pdf',
|
||||
43 | mimeType: 'application/pdf',
|
||||
44 | buffer: Buffer.from('mock aadhaar pdf'),
|
||||
45 | });
|
||||
46 | await expect(page.getByText('Selected: aadhar_card.pdf')).toBeVisible();
|
||||
47 |
|
||||
48 | await page.setInputFiles('input#pan-upload', {
|
||||
49 | name: 'pan_card.pdf',
|
||||
50 | mimeType: 'application/pdf',
|
||||
51 | buffer: Buffer.from('mock pan pdf'),
|
||||
52 | });
|
||||
53 | await expect(page.getByText('Selected: pan_card.pdf')).toBeVisible();
|
||||
54 |
|
||||
55 | await page.locator('button').filter({ hasText: 'Next Step: Store & Location' }).click();
|
||||
56 |
|
||||
57 | // 5. Step 3: Store & Pickup Location Setup
|
||||
58 | await expect(page.getByText('Step 3 of 3: Store & Pickup Location')).toBeVisible();
|
||||
59 | await page.locator('input#store-name').clear();
|
||||
60 | await page.locator('input#store-name').fill('Teak Wood Craft Store');
|
||||
61 | await page.locator('textarea#store-bio').clear();
|
||||
62 | await page.locator('textarea#store-bio').fill('Teak wood hand-carved home decor elements.');
|
||||
63 |
|
||||
64 | // Test interactive map coordinate pinning
|
||||
65 | await expect(page.getByText('Store Location on Map *')).toBeVisible();
|
||||
66 | const mapGridParent = page.locator('span').filter({ hasText: 'Click anywhere on the map grid to pin location' }).locator('..');
|
||||
67 | await mapGridParent.click({ position: { x: 100, y: 80 } });
|
||||
68 | await expect(page.getByText('Coordinates: Lat')).toBeVisible();
|
||||
69 |
|
||||
70 | await expect(page.locator('input#location-text')).not.toHaveValue('');
|
||||
71 | await page.locator('input#loc-city').clear();
|
||||
72 | await page.locator('input#loc-city').fill('Bangalore');
|
||||
73 | await page.locator('input#loc-pincode').clear();
|
||||
74 | await page.locator('input#loc-pincode').fill('560001');
|
||||
75 | await page.locator('button').filter({ hasText: 'Submit Supplier Profile' }).click();
|
||||
76 |
|
||||
77 | // 6. Setup Welcome Tour Stepper
|
||||
78 | await expect(page.getByText('Supplier Account Under Review ⏳')).toBeVisible();
|
||||
79 | await page.locator('button').filter({ hasText: 'Start Guided Tour 🎬' }).click();
|
||||
80 | await expect(page.getByText('📦 Products & Inventory Management')).toBeVisible();
|
||||
81 | await page.locator('button').filter({ hasText: 'Next: Order Management' }).click();
|
||||
82 | await expect(page.getByText('🚚 Order Acceptance Control')).toBeVisible();
|
||||
83 | await page.locator('button').filter({ hasText: 'Next: Barcode Generation' }).click();
|
||||
84 | await expect(page.getByText('🏷️ Barcode Identification & Tracking')).toBeVisible();
|
||||
85 | await page.locator('button').filter({ hasText: 'Next: Earnings & Wallet' }).click();
|
||||
86 | await expect(page.getByText('💼 Wallet & Payout Withdrawals')).toBeVisible();
|
||||
87 | await page.locator('button').filter({ hasText: 'Explore Dashboard 🚀' }).click();
|
||||
88 |
|
||||
89 | // 7. Check Active Dashboard Tab
|
||||
90 | await expect(page.getByText('Performance Analytics')).toBeVisible();
|
||||
91 |
|
||||
92 | // 8. Manage Products tab & Bulk template download
|
||||
93 | await page.locator('button, a').filter({ hasText: 'Manage Products' }).click();
|
||||
94 | await expect(page.getByText('Active Inventory')).toBeVisible();
|
||||
95 |
|
||||
96 | const downloadPromise = page.waitForEvent('download');
|
||||
97 | await page.locator('button, a').filter({ hasText: 'Download Sample Excel Template' }).click();
|
||||
98 | const download = await downloadPromise;
|
||||
99 | expect(download.suggestedFilename()).toBeDefined();
|
||||
100 |
|
||||
101 | // 9. Orders Acceptance Flow
|
||||
102 | await page.locator('button, a').filter({ hasText: 'Orders & Transit' }).click();
|
||||
103 | await expect(page.getByText('Active Orders & Payout status')).toBeVisible();
|
||||
104 | await expect(page.getByText('Pending Acceptance')).toBeVisible();
|
||||
105 | await page.locator('button').filter({ hasText: 'Accept' }).first().click();
|
||||
106 | await expect(page.getByText('Ready to Ship')).toBeVisible();
|
||||
107 |
|
||||
108 | // 10. Barcode Generator
|
||||
109 | await page.locator('button, a').filter({ hasText: 'Barcode Generator' }).click();
|
||||
110 | await expect(page.getByText('Product Barcode Generator')).toBeVisible();
|
||||
111 | await page.locator('select#barcode-product').selectOption({ index: 1 });
|
||||
112 | await page.locator('button').filter({ hasText: 'Generate Barcode Graphic' }).click();
|
||||
113 | await expect(page.getByText('Generated Barcode Preview')).toBeVisible();
|
||||
114 | await expect(page.getByText('Print Label')).toBeVisible();
|
||||
115 | await expect(page.getByText('Download SVG')).toBeVisible();
|
||||
116 | });
|
||||
117 |
|
||||
118 | test('enforces security constraints and validation rules (negative test cases)', async ({ page }) => {
|
||||
119 | // 1. Visit Home and verify dashboard components are not in DOM (route guarding)
|
||||
120 | await page.goto('/');
|
||||
121 | await expect(page.locator('.dashboard-container')).toBeHidden();
|
||||
122 | await expect(page.locator('.sidebar-menu')).toBeHidden();
|
||||
123 |
|
||||
124 | // 2. Go to Registration
|
||||
125 | await page.locator('button, a').filter({ hasText: 'Get Started Today' }).first().click();
|
||||
126 | const randSecurityUser = `security_test_${Date.now()}@example.com`;
|
||||
127 | const randSecurityPhone = `9${Math.floor(100000000 + Math.random() * 900000000)}`;
|
||||
128 | await page.locator('input#reg-email').fill(randSecurityUser);
|
||||
129 | await page.locator('input#reg-phone').fill(randSecurityPhone);
|
||||
130 | await page.locator('input#reg-pass').fill('Password123!');
|
||||
131 | await page.locator('input#reg-confirm-pass').fill('Password123!');
|
||||
132 | await page.locator('input#reg-policy').check();
|
||||
133 | await page.locator('button').filter({ hasText: 'Register Business' }).click();
|
||||
134 |
|
||||
135 | // 3. Step 1: Negative OTP validations
|
||||
> 136 | await expect(page.getByText('Step 1 of 3: Contact Verification')).toBeVisible();
|
||||
| ^ Error: expect(locator).toBeVisible() failed
|
||||
137 |
|
||||
138 | // Proceed button must be disabled initially
|
||||
139 | await expect(page.locator('button').filter({ hasText: 'Next Step: Identity Verification' })).toBeDisabled();
|
||||
140 |
|
||||
141 | // Submit invalid WhatsApp OTP
|
||||
142 | await page.locator('button').filter({ hasText: 'Send WhatsApp OTP' }).click();
|
||||
143 | await page.locator('input[placeholder="Enter 123456"]').first().fill('000000');
|
||||
144 |
|
||||
145 | // Capture dialog
|
||||
146 | let alertMessage = '';
|
||||
147 | page.once('dialog', async dialog => {
|
||||
148 | alertMessage = dialog.message();
|
||||
149 | await dialog.accept();
|
||||
150 | });
|
||||
151 |
|
||||
152 | await page.locator('button').filter({ hasText: 'Verify Code' }).first().click();
|
||||
153 |
|
||||
154 | // Give brief time/event loop ticks to ensure dialog handler fires
|
||||
155 | await page.waitForTimeout(500);
|
||||
156 | expect(alertMessage).toBe('Incorrect code. Enter 123456');
|
||||
157 | await expect(page.getByText('✓ Mobile & WhatsApp Verified')).toBeHidden();
|
||||
158 |
|
||||
159 | // Correct the code to enable proceed
|
||||
160 | await page.locator('input[placeholder="Enter 123456"]').first().clear();
|
||||
161 | await page.locator('input[placeholder="Enter 123456"]').first().fill('123456');
|
||||
162 | await page.locator('button').filter({ hasText: 'Verify Code' }).first().click();
|
||||
163 | await expect(page.getByText('✓ Mobile & WhatsApp Verified')).toBeVisible();
|
||||
164 |
|
||||
165 | // Submit invalid Email OTP
|
||||
166 | await page.locator('button').filter({ hasText: 'Send Email OTP' }).click();
|
||||
167 | await page.locator('input[placeholder="Enter 123456"]').last().fill('999999');
|
||||
168 |
|
||||
169 | page.once('dialog', async dialog => {
|
||||
170 | alertMessage = dialog.message();
|
||||
171 | await dialog.accept();
|
||||
172 | });
|
||||
173 |
|
||||
174 | await page.locator('button').filter({ hasText: 'Verify Code' }).last().click();
|
||||
175 | await page.waitForTimeout(500);
|
||||
176 | expect(alertMessage).toBe('Incorrect code. Enter 123456');
|
||||
177 | await expect(page.getByText('✓ Email Verified')).toBeHidden();
|
||||
178 | await expect(page.locator('button').filter({ hasText: 'Next Step: Identity Verification' })).toBeDisabled();
|
||||
179 | });
|
||||
180 | });
|
||||
181 |
|
||||
```
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB |
Binary file not shown.
|
|
@ -14,14 +14,14 @@
|
|||
```
|
||||
Error: expect(locator).toBeVisible() failed
|
||||
|
||||
Locator: getByText('Step 1 of 3: Contact Verification')
|
||||
Locator: getByText('Shipping Label Preview')
|
||||
Expected: visible
|
||||
Timeout: 5000ms
|
||||
Error: element(s) not found
|
||||
|
||||
Call log:
|
||||
- Expect "toBeVisible" with timeout 5000ms
|
||||
- waiting for getByText('Step 1 of 3: Contact Verification')
|
||||
- waiting for getByText('Shipping Label Preview')
|
||||
|
||||
```
|
||||
|
||||
|
|
@ -33,39 +33,33 @@ Call log:
|
|||
- button "Pricing"
|
||||
- button "Success Stories"
|
||||
- button "Support"
|
||||
- button "Login"
|
||||
- button "Get Started"
|
||||
- main:
|
||||
- button "Login"
|
||||
- button "Register"
|
||||
- heading "Create Your Supplier Account" [level=2]
|
||||
- text: Business Email *
|
||||
- textbox "Business Email *":
|
||||
- /placeholder: Enter email address
|
||||
- text: test_seller_1786700927358@example.com
|
||||
- text: Mobile Number *
|
||||
- textbox "Mobile Number *":
|
||||
- /placeholder: Enter 10-digit number
|
||||
- text: "9118192284"
|
||||
- text: Create Password *
|
||||
- textbox "Create Password *":
|
||||
- /placeholder: Minimum 8 characters
|
||||
- text: Super_secure_pass_123!
|
||||
- button "🙈"
|
||||
- text: Confirm Password *
|
||||
- textbox "Confirm Password *":
|
||||
- /placeholder: Re-enter password
|
||||
- text: Super_secure_pass_123!
|
||||
- button "🙈"
|
||||
- checkbox "I accept the Terms of Service and Privacy Policy *" [checked]
|
||||
- text: I accept the
|
||||
- link "Terms of Service":
|
||||
- /url: "#terms"
|
||||
- text: and
|
||||
- link "Privacy Policy":
|
||||
- /url: "#privacy"
|
||||
- text: "*"
|
||||
- button "Register Business"
|
||||
- button "Logout"
|
||||
- complementary:
|
||||
- text: SELLER PANEL
|
||||
- heading "Teak Wood Craft Store" [level=4]
|
||||
- list:
|
||||
- listitem:
|
||||
- button "📊 Overview & Analytics"
|
||||
- listitem:
|
||||
- button "📦 Manage Products"
|
||||
- listitem:
|
||||
- button "🚚 Orders & Transit"
|
||||
- listitem:
|
||||
- button "🔄 Returns Management"
|
||||
- listitem:
|
||||
- button "💼 Wallet & Payouts"
|
||||
- listitem:
|
||||
- button "🖨️ Customer Address Printer"
|
||||
- listitem:
|
||||
- button "⚙️ Store Settings"
|
||||
- heading "Customer Address Printer" [level=2]
|
||||
- paragraph: Select an accepted order to view and print the shipping address label for the customer.
|
||||
- heading "Print Configuration" [level=3]
|
||||
- text: Select Accepted Order *
|
||||
- combobox "Select Accepted Order *":
|
||||
- option "-- Choose an accepted order --"
|
||||
- option "22 - Alice Smith (Handmade Wool Blanket)" [selected]
|
||||
- button "Print Address Label"
|
||||
- contentinfo:
|
||||
- text: Global Artisans Hub
|
||||
- link "About Us":
|
||||
|
|
@ -84,17 +78,6 @@ Call log:
|
|||
# Test source
|
||||
|
||||
```ts
|
||||
1 | import { test, expect } from '@playwright/test';
|
||||
2 |
|
||||
3 | test.describe('Supplier Portal Onboarding & Feature E2E Flow', () => {
|
||||
4 | test('completes the registration, contact verification, document upload, location pinning, welcome tour, order acceptance, and barcode generation', async ({ page }) => {
|
||||
5 | // 1. Visit Landing Page
|
||||
6 | await page.goto('/');
|
||||
7 | await expect(page.getByText('Sell Globally.')).toBeVisible();
|
||||
8 |
|
||||
9 | // 2. Registration Page
|
||||
10 | await page.locator('button, a').filter({ hasText: 'Get Started Today' }).first().click();
|
||||
11 | const randUser = `test_seller_${Date.now()}@example.com`;
|
||||
12 | const randPhone = `9${Math.floor(100000000 + Math.random() * 900000000)}`;
|
||||
13 | await page.locator('input#reg-email').fill(randUser);
|
||||
14 | await page.locator('input#reg-phone').fill(randPhone);
|
||||
|
|
@ -104,8 +87,7 @@ Call log:
|
|||
18 | await page.locator('button').filter({ hasText: 'Register Business' }).click();
|
||||
19 |
|
||||
20 | // 3. Step 1: Contact Verification
|
||||
> 21 | await expect(page.getByText('Step 1 of 3: Contact Verification')).toBeVisible();
|
||||
| ^ Error: expect(locator).toBeVisible() failed
|
||||
21 | await expect(page.getByText('Step 1 of 3: Contact Verification')).toBeVisible();
|
||||
22 | await page.locator('button').filter({ hasText: 'Send WhatsApp OTP' }).click();
|
||||
23 | await page.locator('input[placeholder="Enter 123456"]').first().fill('123456');
|
||||
24 | await page.locator('button').filter({ hasText: 'Verify Code' }).first().click();
|
||||
|
|
@ -188,22 +170,81 @@ Call log:
|
|||
101 | // 9. Orders Acceptance Flow
|
||||
102 | await page.locator('button, a').filter({ hasText: 'Orders & Transit' }).click();
|
||||
103 | await expect(page.getByText('Active Orders & Payout status')).toBeVisible();
|
||||
104 | await expect(page.getByText('Pending Acceptance')).toBeVisible();
|
||||
104 | await expect(page.getByText('Pending Acceptance').first()).toBeVisible();
|
||||
105 | await page.locator('button').filter({ hasText: 'Accept' }).first().click();
|
||||
106 | await expect(page.getByText('Ready to Ship')).toBeVisible();
|
||||
107 |
|
||||
108 | // 10. Barcode Generator
|
||||
109 | await page.locator('button, a').filter({ hasText: 'Barcode Generator' }).click();
|
||||
110 | await expect(page.getByText('Product Barcode Generator')).toBeVisible();
|
||||
111 | await page.locator('select#barcode-product').selectOption({ index: 1 });
|
||||
112 | await page.locator('button').filter({ hasText: 'Generate Barcode Graphic' }).click();
|
||||
113 | await expect(page.getByText('Generated Barcode Preview')).toBeVisible();
|
||||
114 | await expect(page.getByText('Print Label')).toBeVisible();
|
||||
115 | await expect(page.getByText('Download SVG')).toBeVisible();
|
||||
116 | });
|
||||
117 |
|
||||
118 | test('enforces security constraints and validation rules (negative test cases)', async ({ page }) => {
|
||||
119 | // 1. Visit Home and verify dashboard components are not in DOM (route guarding)
|
||||
120 | await page.goto('/');
|
||||
121 | await expect(page.locator('.dashboard-container')).toBeHidden();
|
||||
108 | // 10. Customer Address Printer
|
||||
109 | await page.locator('button, a').filter({ hasText: 'Customer Address Printer' }).click();
|
||||
110 | await expect(page.getByRole('heading', { name: 'Customer Address Printer' })).toBeVisible();
|
||||
111 | await page.locator('select#print-order').selectOption({ index: 1 });
|
||||
> 112 | await expect(page.getByText('Shipping Label Preview')).toBeVisible();
|
||||
| ^ Error: expect(locator).toBeVisible() failed
|
||||
113 | await expect(page.getByRole('button', { name: 'Print Address Label' })).toBeVisible();
|
||||
114 | });
|
||||
115 |
|
||||
116 | test('enforces security constraints and validation rules (negative test cases)', async ({ page }) => {
|
||||
117 | // 1. Visit Home and verify dashboard components are not in DOM (route guarding)
|
||||
118 | await page.goto('/');
|
||||
119 | await expect(page.locator('.dashboard-container')).toBeHidden();
|
||||
120 | await expect(page.locator('.sidebar-menu')).toBeHidden();
|
||||
121 |
|
||||
122 | // 2. Go to Registration
|
||||
123 | await page.locator('button, a').filter({ hasText: 'Get Started Today' }).first().click();
|
||||
124 | const randSecurityUser = `security_test_${Date.now()}_${Math.floor(Math.random() * 1000000)}@example.com`;
|
||||
125 | const randSecurityPhone = `9${Math.floor(100000000 + Math.random() * 900000000)}`;
|
||||
126 | await page.locator('input#reg-email').fill(randSecurityUser);
|
||||
127 | await page.locator('input#reg-phone').fill(randSecurityPhone);
|
||||
128 | await page.locator('input#reg-pass').fill('Password123!');
|
||||
129 | await page.locator('input#reg-confirm-pass').fill('Password123!');
|
||||
130 | await page.locator('input#reg-policy').check();
|
||||
131 | await page.locator('button').filter({ hasText: 'Register Business' }).click();
|
||||
132 |
|
||||
133 | // 3. Step 1: Negative OTP validations
|
||||
134 | await expect(page.getByText('Step 1 of 3: Contact Verification')).toBeVisible();
|
||||
135 |
|
||||
136 | // Proceed button must be disabled initially
|
||||
137 | await expect(page.locator('button').filter({ hasText: 'Next Step: Identity Verification' })).toBeDisabled();
|
||||
138 |
|
||||
139 | // Submit invalid WhatsApp OTP
|
||||
140 | await page.locator('button').filter({ hasText: 'Send WhatsApp OTP' }).click();
|
||||
141 | await page.locator('input[placeholder="Enter 123456"]').first().fill('000000');
|
||||
142 |
|
||||
143 | // Capture dialog
|
||||
144 | let alertMessage = '';
|
||||
145 | page.once('dialog', async dialog => {
|
||||
146 | alertMessage = dialog.message();
|
||||
147 | await dialog.accept();
|
||||
148 | });
|
||||
149 |
|
||||
150 | await page.locator('button').filter({ hasText: 'Verify Code' }).first().click();
|
||||
151 |
|
||||
152 | // Give brief time/event loop ticks to ensure dialog handler fires
|
||||
153 | await page.waitForTimeout(500);
|
||||
154 | expect(alertMessage).toBe('Incorrect code. Enter 123456');
|
||||
155 | await expect(page.getByText('✓ Mobile & WhatsApp Verified')).toBeHidden();
|
||||
156 |
|
||||
157 | // Correct the code to enable proceed
|
||||
158 | await page.locator('input[placeholder="Enter 123456"]').first().clear();
|
||||
159 | await page.locator('input[placeholder="Enter 123456"]').first().fill('123456');
|
||||
160 | await page.locator('button').filter({ hasText: 'Verify Code' }).first().click();
|
||||
161 | await expect(page.getByText('✓ Mobile & WhatsApp Verified')).toBeVisible();
|
||||
162 |
|
||||
163 | // Submit invalid Email OTP
|
||||
164 | await page.locator('button').filter({ hasText: 'Send Email OTP' }).click();
|
||||
165 | await page.locator('input[placeholder="Enter 123456"]').last().fill('999999');
|
||||
166 |
|
||||
167 | page.once('dialog', async dialog => {
|
||||
168 | alertMessage = dialog.message();
|
||||
169 | await dialog.accept();
|
||||
170 | });
|
||||
171 |
|
||||
172 | await page.locator('button').filter({ hasText: 'Verify Code' }).last().click();
|
||||
173 | await page.waitForTimeout(500);
|
||||
174 | expect(alertMessage).toBe('Incorrect code. Enter 123456');
|
||||
175 | await expect(page.getByText('✓ Email Verified')).toBeHidden();
|
||||
176 | await expect(page.locator('button').filter({ hasText: 'Next Step: Identity Verification' })).toBeDisabled();
|
||||
177 | });
|
||||
178 | });
|
||||
179 |
|
||||
```
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 61 KiB |
Binary file not shown.
Loading…
Reference in a new issue