Merge branch 'beta'
This commit is contained in:
commit
d45ae569d1
8 changed files with 3299 additions and 175 deletions
9
cypress.config.ts
Normal file
9
cypress.config.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { defineConfig } from "cypress";
|
||||
|
||||
export default defineConfig({
|
||||
e2e: {
|
||||
baseUrl: "http://localhost:5173",
|
||||
supportFile: false,
|
||||
specPattern: "cypress/e2e/**/*.cy.{js,jsx,ts,tsx}"
|
||||
},
|
||||
});
|
||||
3
cypress/downloads/seller_product_template.csv
Normal file
3
cypress/downloads/seller_product_template.csv
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Title,SKU,Category,Price,Stock,Description
|
||||
Silk Banarasi Saree,SAR-BAN-101,Apparel,120.00,15,Pure handloom zardozi border
|
||||
Wooden Carved Ganesha,GAN-302,Home Decor,85.00,5,Premium teak wood hand carved
|
||||
|
101
cypress/e2e/onboarding.cy.ts
Normal file
101
cypress/e2e/onboarding.cy.ts
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
describe('Supplier Portal Onboarding & Feature E2E Flow', () => {
|
||||
it('completes the registration, contact verification, document upload, location pinning, welcome tour, order acceptance, and barcode generation', () => {
|
||||
// 1. Visit Landing Page
|
||||
cy.visit('/');
|
||||
cy.contains('Sell Globally.').should('be.visible');
|
||||
|
||||
// 2. Registration Page
|
||||
cy.contains('Get Started Today').click();
|
||||
cy.get('input#reg-email').type('test_seller@example.com');
|
||||
cy.get('input#reg-phone').type('9876543210');
|
||||
cy.get('input#reg-pass').type('super_secure_pass_123');
|
||||
cy.get('button').contains('Register Business').click();
|
||||
|
||||
// 3. Step 1: Contact Verification
|
||||
cy.contains('Step 1 of 3: Contact Verification').should('be.visible');
|
||||
cy.contains('Send WhatsApp OTP').click();
|
||||
cy.get('input[placeholder="Enter 123456"]').first().type('123456');
|
||||
cy.contains('Verify Code').first().click();
|
||||
cy.contains('✓ Mobile & WhatsApp Verified').should('be.visible');
|
||||
|
||||
cy.contains('Send Email OTP').click();
|
||||
cy.get('input[placeholder="Enter 123456"]').last().type('123456');
|
||||
cy.contains('Verify Code').last().click();
|
||||
cy.contains('✓ Email Verified').should('be.visible');
|
||||
cy.contains('Next Step: Identity Verification').click();
|
||||
|
||||
// 4. Step 2: Tax & Identity Verification
|
||||
cy.contains('Step 2 of 3: Tax & Identity Verification').should('be.visible');
|
||||
cy.get('input#verify-gst').clear().type('29AAAAA1111A1Z1');
|
||||
cy.contains('Verify GSTIN').click();
|
||||
cy.contains('GSTIN successfully verified with government registry.').should('be.visible');
|
||||
|
||||
// Upload mock Aadhaar & PAN files
|
||||
cy.get('input#aadhar-upload').selectFile({
|
||||
contents: Cypress.Buffer.from('mock aadhaar pdf'),
|
||||
fileName: 'aadhar_card.pdf',
|
||||
mimeType: 'application/pdf',
|
||||
}, { force: true });
|
||||
cy.contains('Selected: aadhar_card.pdf').should('be.visible');
|
||||
|
||||
cy.get('input#pan-upload').selectFile({
|
||||
contents: Cypress.Buffer.from('mock pan pdf'),
|
||||
fileName: 'pan_card.pdf',
|
||||
mimeType: 'application/pdf',
|
||||
}, { force: true });
|
||||
cy.contains('Selected: pan_card.pdf').should('be.visible');
|
||||
|
||||
cy.contains('Next Step: Store & Location').click();
|
||||
|
||||
// 5. Step 3: Store & Pickup Location Setup
|
||||
cy.contains('Step 3 of 3: Store & Pickup Location').should('be.visible');
|
||||
cy.get('input#store-name').clear().type('Teak Wood Craft Store');
|
||||
cy.get('textarea#store-bio').clear().type('Teak wood hand-carved home decor elements.');
|
||||
|
||||
// Test interactive map coordinate pinning
|
||||
cy.contains('Store Location on Map *').should('be.visible');
|
||||
cy.get('span').contains('Click anywhere on the map grid to pin location').parent().click(100, 80);
|
||||
cy.contains('Coordinates: Lat').should('be.visible');
|
||||
|
||||
cy.get('input#location-text').should('not.have.value', '');
|
||||
cy.get('input#loc-city').clear().type('Bangalore');
|
||||
cy.get('input#loc-pincode').clear().type('560001');
|
||||
cy.contains('Submit Supplier Profile').click();
|
||||
|
||||
// 6. Setup Welcome Tour Stepper
|
||||
cy.contains('Welcome to Global Artisans Hub! 🎉').should('be.visible');
|
||||
cy.contains('Start Tour').click();
|
||||
cy.contains('📦 Products & Inventory Management').should('be.visible');
|
||||
cy.contains('Next: Order Management').click();
|
||||
cy.contains('🚚 Order Acceptance Control').should('be.visible');
|
||||
cy.contains('Next: Barcode Generation').click();
|
||||
cy.contains('🏷️ Barcode Identification & Tracking').should('be.visible');
|
||||
cy.contains('Next: Earnings & Wallet').click();
|
||||
cy.contains('💼 Wallet & Payout Withdrawals').should('be.visible');
|
||||
cy.contains('Launch Dashboard 🚀').click();
|
||||
|
||||
// 7. Check Active Dashboard Tab
|
||||
cy.contains('Performance Analytics').should('be.visible');
|
||||
|
||||
// 8. Manage Products tab & Bulk template download
|
||||
cy.contains('Manage Products').click();
|
||||
cy.contains('Active Inventory').should('be.visible');
|
||||
cy.contains('📥 Download Sample Excel Template').click();
|
||||
|
||||
// 9. Orders Acceptance Flow
|
||||
cy.contains('Orders & Transit').click();
|
||||
cy.contains('Active Orders & Payout status').should('be.visible');
|
||||
cy.contains('Pending Acceptance').should('be.visible');
|
||||
cy.get('button').contains('Accept').first().click();
|
||||
cy.contains('Ready to Ship').should('be.visible');
|
||||
|
||||
// 10. Barcode Generator
|
||||
cy.contains('Barcode Generator').click();
|
||||
cy.contains('Product Barcode Generator').should('be.visible');
|
||||
cy.get('select#barcode-product').select(1);
|
||||
cy.contains('Generate Barcode Graphic').click();
|
||||
cy.contains('Generated Barcode Preview').should('be.visible');
|
||||
cy.contains('Print Label').should('be.visible');
|
||||
cy.contains('Download SVG').should('be.visible');
|
||||
});
|
||||
});
|
||||
2132
package-lock.json
generated
2132
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -8,7 +8,9 @@
|
|||
"build": "tsc -b && vite build",
|
||||
"lint": "oxlint",
|
||||
"test": "vitest run",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"cypress:run": "cypress run --headed",
|
||||
"cypress:open": "cypress open"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^19.2.8",
|
||||
|
|
@ -22,6 +24,7 @@
|
|||
"@types/react": "^19.2.17",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.4",
|
||||
"cypress": "^15.20.0",
|
||||
"jsdom": "^30.0.1",
|
||||
"oxlint": "^1.75.0",
|
||||
"typescript": "~6.0.2",
|
||||
|
|
|
|||
|
|
@ -49,17 +49,60 @@ describe('Supplier Portal Onboarding & Active Dashboard Tests', () => {
|
|||
const emailInput = screen.getByLabelText(/Business Email \*/i)
|
||||
const phoneInput = screen.getByLabelText(/Mobile Number \*/i)
|
||||
const passInput = screen.getByLabelText(/Create Password \*/i)
|
||||
const taxInput = screen.getByLabelText(/GSTIN \/ Tax ID \*/i)
|
||||
|
||||
fireEvent.change(emailInput, { target: { value: 'seller@example.com' } })
|
||||
fireEvent.change(phoneInput, { target: { value: '9876543210' } })
|
||||
fireEvent.change(passInput, { target: { value: 'password123' } })
|
||||
fireEvent.change(taxInput, { target: { value: '29AAAAA1111A1Z1' } })
|
||||
|
||||
const alertMock = vi.spyOn(window, 'alert').mockImplementation(() => {})
|
||||
|
||||
const registerBtn = screen.getByRole('button', { name: /Register Business/i })
|
||||
fireEvent.click(registerBtn)
|
||||
|
||||
expect(screen.getByText('Step 2 of 3: Business Details')).toBeInTheDocument()
|
||||
// Step 1: Contact Verification
|
||||
expect(screen.getByText(/Step 1 of 3: Contact Verification/i)).toBeInTheDocument()
|
||||
|
||||
const sendWhatsappBtn = screen.getByText(/Send WhatsApp OTP/i)
|
||||
fireEvent.click(sendWhatsappBtn)
|
||||
|
||||
const whatsappCodeInput = screen.getByPlaceholderText(/Enter 123456/i)
|
||||
fireEvent.change(whatsappCodeInput, { target: { value: '123456' } })
|
||||
const verifyWhatsappBtn = screen.getByRole('button', { name: /Verify Code/i })
|
||||
fireEvent.click(verifyWhatsappBtn)
|
||||
|
||||
const sendEmailBtn = screen.getByText(/Send Email OTP/i)
|
||||
fireEvent.click(sendEmailBtn)
|
||||
|
||||
// There are now multiple placeholder elements with "Enter 123456". Let's fetch the visible inputs.
|
||||
const codeInputs = screen.getAllByPlaceholderText(/Enter 123456/i)
|
||||
fireEvent.change(codeInputs[codeInputs.length - 1], { target: { value: '123456' } })
|
||||
const verifyButtons = screen.getAllByRole('button', { name: /Verify Code/i })
|
||||
fireEvent.click(verifyButtons[verifyButtons.length - 1])
|
||||
|
||||
const nextStep1Btn = screen.getByRole('button', { name: /Next Step: Identity Verification/i })
|
||||
fireEvent.click(nextStep1Btn)
|
||||
|
||||
// Step 2: Tax & Identity Verification
|
||||
expect(screen.getByText(/Step 2 of 3: Tax & Identity Verification/i)).toBeInTheDocument()
|
||||
|
||||
const taxInput = screen.getByLabelText(/GSTIN Number \*/i)
|
||||
fireEvent.change(taxInput, { target: { value: '29AAAAA1111A1Z1' } })
|
||||
const verifyGstinBtn = screen.getByRole('button', { name: /Verify GSTIN/i })
|
||||
fireEvent.click(verifyGstinBtn)
|
||||
|
||||
// Upload files
|
||||
const aadharInput = screen.getByLabelText(/Aadhaar Card Upload \*/i)
|
||||
const panInput = screen.getByLabelText(/PAN Card Upload \*/i)
|
||||
|
||||
// Trigger file changes
|
||||
fireEvent.change(aadharInput, { target: { files: [{ name: 'aadhar_card.pdf' }] } })
|
||||
fireEvent.change(panInput, { target: { files: [{ name: 'pan_card.pdf' }] } })
|
||||
|
||||
const nextStep2Btn = screen.getByRole('button', { name: /Next Step: Store & Location/i })
|
||||
fireEvent.click(nextStep2Btn)
|
||||
|
||||
// Step 3: Store Details & Location Map
|
||||
expect(screen.getByText(/Step 3 of 3: Store & Pickup Location/i)).toBeInTheDocument()
|
||||
|
||||
const storeNameInput = screen.getByLabelText(/Store Display Name \*/i)
|
||||
fireEvent.change(storeNameInput, { target: { value: 'Crafty Store' } })
|
||||
|
|
@ -67,22 +110,41 @@ describe('Supplier Portal Onboarding & Active Dashboard Tests', () => {
|
|||
const bioText = screen.getByLabelText(/About Your Craft \/ Business \*/i)
|
||||
fireEvent.change(bioText, { target: { value: 'Handmade pottery.' } })
|
||||
|
||||
const streetInput = screen.getByPlaceholderText('Street Address')
|
||||
const cityInput = screen.getByPlaceholderText('City')
|
||||
const stateInput = screen.getByPlaceholderText('State')
|
||||
const pincodeInput = screen.getByPlaceholderText('Pincode')
|
||||
const streetInput = screen.getByLabelText(/Location in Text \(Address\) \*/i)
|
||||
const cityInput = screen.getByLabelText(/City \*/i)
|
||||
const pincodeInput = screen.getByLabelText(/Pincode \*/i)
|
||||
|
||||
fireEvent.change(streetInput, { target: { value: '123 Loom Lane' } })
|
||||
fireEvent.change(cityInput, { target: { value: 'Handloom City' } })
|
||||
fireEvent.change(stateInput, { target: { value: 'Karnataka' } })
|
||||
fireEvent.change(pincodeInput, { target: { value: '560001' } })
|
||||
|
||||
const saveBtn = screen.getByRole('button', { name: /Save & Continue/i })
|
||||
fireEvent.click(saveBtn)
|
||||
|
||||
// Redirects directly to Dashboard Page
|
||||
const submitBtn = screen.getByRole('button', { name: /Submit Supplier Profile/i })
|
||||
fireEvent.click(submitBtn)
|
||||
|
||||
// Welcome Page & Setup Tour
|
||||
expect(screen.getByText(/Welcome to Global Artisans Hub!/i)).toBeInTheDocument()
|
||||
|
||||
// Complete tour steps
|
||||
const startTourBtn = screen.getByRole('button', { name: /Start Tour/i })
|
||||
fireEvent.click(startTourBtn)
|
||||
|
||||
const next1 = screen.getByRole('button', { name: /Next: Order Management/i })
|
||||
fireEvent.click(next1)
|
||||
|
||||
const next2 = screen.getByRole('button', { name: /Next: Barcode Generation/i })
|
||||
fireEvent.click(next2)
|
||||
|
||||
const next3 = screen.getByRole('button', { name: /Next: Earnings & Wallet/i })
|
||||
fireEvent.click(next3)
|
||||
|
||||
const finishBtn = screen.getByRole('button', { name: /Launch Dashboard 🚀/i })
|
||||
fireEvent.click(finishBtn)
|
||||
|
||||
// Redirects to Dashboard Page
|
||||
expect(screen.getByText('Performance Analytics')).toBeInTheDocument()
|
||||
expect(screen.getByText(/Total Sales Volume/i)).toBeInTheDocument()
|
||||
|
||||
alertMock.mockRestore()
|
||||
})
|
||||
|
||||
it('logs in successfully and navigates dashboard tools', () => {
|
||||
|
|
|
|||
1084
src/App.tsx
1084
src/App.tsx
File diff suppressed because it is too large
Load diff
|
|
@ -1039,3 +1039,57 @@ body {
|
|||
.mock-chart-bar.active {
|
||||
background-color: var(--accent);
|
||||
}
|
||||
|
||||
/* Mobile Responsiveness Improvements */
|
||||
@media (max-width: 768px) {
|
||||
.app-header {
|
||||
flex-direction: column;
|
||||
gap: 1.25rem;
|
||||
padding: 1.25rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 1.25rem 1.5rem;
|
||||
}
|
||||
|
||||
.nav-buttons {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.dashboard-sidebar {
|
||||
padding: 1.25rem 1rem;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.sidebar-menu {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.sidebar-item-btn {
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: 0.85rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Tables horizontal scroll container */
|
||||
.dashboard-table-wrapper {
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* Forms padding & stacked inputs */
|
||||
.form-card {
|
||||
padding: 1.5rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue