nxtgauge-frontend-solid/tests/e2e/signup-verification-submission.spec.ts

305 lines
11 KiB
TypeScript

import { expect, test } from "@playwright/test";
type SignupScenario = {
name: string;
signupUrl: string;
dashboardRole: string;
};
const portfolioPrefixByRole: Record<string, string> = {
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<string, string> = {
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<string, string> = {
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<string, string> {
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<string, string>,
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);
});
}
});