import { expect, test } from "@playwright/test"; type SignupScenario = { name: string; signupUrl: string; dashboardRole: string; }; const portfolioPrefixByRole: Record = { PHOTOGRAPHER: "photographers", MAKEUP_ARTIST: "makeup-artists", TUTOR: "tutors", DEVELOPER: "developers", VIDEO_EDITOR: "video-editors", UGC_CONTENT_CREATOR: "ugc-content-creators", GRAPHIC_DESIGNER: "graphic-designers", SOCIAL_MEDIA_MANAGER: "social-media-managers", FITNESS_TRAINER: "fitness-trainers", CATERING_SERVICES: "catering-services", }; const scenarios: SignupScenario[] = [ { name: "company", signupUrl: "/signup?intent=company", dashboardRole: "COMPANY" }, { name: "customer", signupUrl: "/signup?intent=customer", dashboardRole: "CUSTOMER" }, { name: "job seeker", signupUrl: "/signup?intent=job_seeker", dashboardRole: "JOB_SEEKER" }, { name: "photographer", signupUrl: "/signup?intent=professional&role=photographer", dashboardRole: "PHOTOGRAPHER" }, { name: "makeup artist", signupUrl: "/signup?intent=professional&role=makeup_artist", dashboardRole: "MAKEUP_ARTIST" }, { name: "tutor", signupUrl: "/signup?intent=professional&role=tutor", dashboardRole: "TUTOR" }, { name: "developer", signupUrl: "/signup?intent=professional&role=developer", dashboardRole: "DEVELOPER" }, { name: "video editor", signupUrl: "/signup?intent=professional&role=video_editor", dashboardRole: "VIDEO_EDITOR" }, { name: "ugc content creator", signupUrl: "/signup?intent=professional&role=ugc_content_creator", dashboardRole: "UGC_CONTENT_CREATOR" }, { name: "graphic designer", signupUrl: "/signup?intent=professional&role=graphic_designer", dashboardRole: "GRAPHIC_DESIGNER" }, { name: "social media manager", signupUrl: "/signup?intent=professional&role=social_media_manager", dashboardRole: "SOCIAL_MEDIA_MANAGER" }, { name: "fitness trainer", signupUrl: "/signup?intent=professional&role=fitness_trainer", dashboardRole: "FITNESS_TRAINER" }, { name: "catering services", signupUrl: "/signup?intent=professional&role=catering_services", dashboardRole: "CATERING_SERVICES" }, ]; const profileSeedComplete: Record = { first_name: "Ari", last_name: "Tester", email: "ari.tester@nxtgauge.test", phone: "9999999999", location: "Chennai", city: "Chennai", area: "Anna Nagar", state: "Tamil Nadu", address_line_1: "No 12, Lake View", company_name: "Nxtgauge QA Labs", business_name: "Nxtgauge Catering", owner_name: "Ari Tester", company_email: "ops@nxtgauge.test", registration_doc: "company-registration.pdf", aadhar_doc: "id-proof.pdf", address_proof: "address-proof.pdf", portfolio_ownership_proof: "portfolio-proof.pdf", qualification_proof: "qualification-proof.pdf", professional_certifications: "certifications.pdf", certification_doc: "trainer-certification.pdf", fssai_license: "fssai.pdf", gst_doc: "gst-certificate.pdf", }; const requiredDocKeyByRole: Record = { COMPANY: "registration_doc", PHOTOGRAPHER: "aadhar_doc", MAKEUP_ARTIST: "aadhar_doc", TUTOR: "aadhar_doc", FITNESS_TRAINER: "aadhar_doc", CATERING_SERVICES: "aadhar_doc", CUSTOMER: "aadhar_doc", JOB_SEEKER: "aadhar_doc", }; function missingDocProfile(role: string): Record { const next = { ...profileSeedComplete }; const key = requiredDocKeyByRole[role] || "aadhar_doc"; delete next[key]; return next; } async function wireApiMock( page: any, scenario: SignupScenario, unique: number, profileData: Record, submitRef: { count: number }, portfolioReady: boolean ) { const portfolioPrefix = portfolioPrefixByRole[scenario.dashboardRole]; await page.route("**/api/**", async (route: any) => { const url = new URL(route.request().url()); const path = url.pathname; if (path.endsWith("/api/auth/check-email")) { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ exists: false }) }); return; } if (path.endsWith("/api/auth/register")) { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ success: true, user: { id: `${scenario.dashboardRole}-${unique}` } }), }); return; } if (path.endsWith("/api/auth/verify-email")) { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ success: true }) }); return; } if (path.includes("/runtime-config")) { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ role: scenario.dashboardRole, dashboard_config: { sidebar_items: ["My Dashboard", "My Profile", "Verification Status", "Help Center"], }, }), }); return; } if (path.includes("/api/me/verification-status")) { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ status: "NOT_SUBMITTED", document_request: null }), }); return; } if (path.includes("/api/profile/submit-for-verification")) { submitRef.count += 1; await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ ok: true }) }); return; } if (path.includes("/api/profile") && route.request().method() === "GET") { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ profile_data: profileData }), }); return; } if (path.includes("/api/profile") && route.request().method() === "PATCH") { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ ok: true }) }); return; } if (path.includes("/api/jobseeker/profile/me") && route.request().method() === "GET") { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ custom_data: { job_seeker_portfolio: portfolioReady ? { headline: "Frontend Engineer", summary: "Builds product-grade web apps", education: "B.Tech CSE", workExperience: "3 years in SaaS", skills: "SolidJS, TypeScript", } : {}, }, }), }); return; } if (portfolioPrefix && path.includes(`/api/${portfolioPrefix}/portfolio/me`)) { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify( portfolioReady ? [{ id: `portfolio-${unique}`, title: "Showcase Project", description: "Media sample" }] : [] ), }); return; } await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify({ data: [] }) }); }); } async function runSignup(page: any, scenario: SignupScenario, email: string) { await page.goto(`http://localhost:3000${scenario.signupUrl}`); await page.fill("#first-name", "Ari"); await page.fill("#last-name", "Tester"); await page.fill("#email", email); await page.fill("#password", "TestPassword123!"); await page.fill("#confirm-password", "TestPassword123!"); await page.fill("#captcha", "AAAAAA"); await page.check('input[type="checkbox"]'); await page.click("button.auth-submit-btn"); await expect(page.getByText("Verify Email")).toBeVisible(); await page.fill("#otp-0", "1"); await page.fill("#otp-1", "2"); await page.fill("#otp-2", "3"); await page.fill("#otp-3", "4"); await page.fill("#otp-4", "5"); await page.fill("#otp-5", "6"); await page.click("button.auth-submit-btn"); await page.waitForURL("**/login?verified=1"); } async function seedSession(page: any, scenario: SignupScenario, email: string) { await page.evaluate( ({ role, mail }) => { sessionStorage.setItem("nxtgauge_access_token", "pw-test-token"); const payload = { email: mail, roleKey: role, role: role, selectedProfessionalRole: role, fullName: "Ari Tester", name: "Ari Tester", }; localStorage.setItem("nxtgauge_signup_profile_v1", JSON.stringify(payload)); localStorage.setItem("nxtgauge_auth_user", JSON.stringify(payload)); localStorage.setItem("nxtgauge_user", JSON.stringify(payload)); const professionalRoles = [ "PHOTOGRAPHER", "MAKEUP_ARTIST", "TUTOR", "DEVELOPER", "VIDEO_EDITOR", "UGC_CONTENT_CREATOR", "GRAPHIC_DESIGNER", "SOCIAL_MEDIA_MANAGER", "FITNESS_TRAINER", "CATERING_SERVICES", ]; if (professionalRoles.includes(role)) { localStorage.setItem( `nxtgauge_portfolio_meta_${String(role).toLowerCase()}`, JSON.stringify({ about: "Experienced professional with strong delivery track record.", services: [{ name: "Core Service", pricingType: "Fixed", amount: "₹10,000", details: "End-to-end delivery" }], experience: [{ year: "2024", description: "Handled projects across multiple clients" }], faqs: [{ question: "Do you provide revisions?", answer: "Yes, revisions are included." }], tools: ["Industry Tool"], }) ); } }, { role: scenario.dashboardRole, mail: email } ); } test.describe("Signup and verification submission by role", () => { test.beforeEach(async ({ page }) => { await page.addInitScript(() => { Math.random = () => 0; window.__testMode = true; }); }); for (const scenario of scenarios) { test(`complete profile submits verification for ${scenario.name}`, async ({ page }) => { const unique = Date.now(); const email = `qa_${scenario.dashboardRole.toLowerCase()}_${unique}@nxtgauge.test`; const submitRef = { count: 0 }; await wireApiMock(page, scenario, unique, profileSeedComplete, submitRef, true); await runSignup(page, scenario, email); await seedSession(page, scenario, email); await page.goto(`http://localhost:3000/dashboard?role=${scenario.dashboardRole}`); await page.getByRole("button", { name: /my profile/i }).click(); const submitButton = page.getByRole("button", { name: /submit for verification/i }); await expect(submitButton).toBeVisible(); await expect(submitButton).toBeEnabled(); await submitButton.click(); await expect(page.getByText(/Submitted! We will review your profile/i)).toBeVisible(); expect(submitRef.count).toBe(1); }); test(`missing document blocks verification submit for ${scenario.name}`, async ({ page }) => { const unique = Date.now() + 1000; const email = `qa_${scenario.dashboardRole.toLowerCase()}_missing_${unique}@nxtgauge.test`; const submitRef = { count: 0 }; await wireApiMock(page, scenario, unique, missingDocProfile(scenario.dashboardRole), submitRef, false); await runSignup(page, scenario, email); await seedSession(page, scenario, email); await page.goto(`http://localhost:3000/dashboard?role=${scenario.dashboardRole}`); await page.getByRole("button", { name: /my profile/i }).click(); const submitButton = page.getByRole("button", { name: /submit for verification/i }); await expect(submitButton).toBeVisible(); await expect(submitButton).toBeDisabled(); await expect(page.getByRole("button", { name: /go to documents/i })).toBeVisible(); expect(submitRef.count).toBe(0); }); } });