mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-19 19:21:15 -05:00
Compare commits
3 Commits
@formbrick
...
shubham/e2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ac68c9110 | ||
|
|
e19a82e2e4 | ||
|
|
aeefb6cbd8 |
@@ -1,17 +0,0 @@
|
|||||||
import { randomBytes } from "crypto";
|
|
||||||
|
|
||||||
let user: {
|
|
||||||
name: string;
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
} | null;
|
|
||||||
|
|
||||||
export const getUser = () => {
|
|
||||||
if (!user) {
|
|
||||||
const name = randomBytes(4).toString("hex");
|
|
||||||
const email = `${name}@gmail.com`;
|
|
||||||
const password = "Test@123";
|
|
||||||
user = { name, email, password };
|
|
||||||
}
|
|
||||||
return user;
|
|
||||||
};
|
|
||||||
45
apps/web/playwright/onboarding.spec.ts
Normal file
45
apps/web/playwright/onboarding.spec.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { getTeam, getUser, signUpAndLogin } from "./utils";
|
||||||
|
import { test, expect } from "@playwright/test";
|
||||||
|
|
||||||
|
const { role, productName, useCase } = getTeam();
|
||||||
|
|
||||||
|
test.describe("Onboarding Flow Test", async () => {
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
const { name, email, password } = getUser();
|
||||||
|
await signUpAndLogin(page, name, email, password);
|
||||||
|
await page.waitForURL("/onboarding");
|
||||||
|
await expect(page).toHaveURL("/onboarding");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Step by Step", async ({ page }) => {
|
||||||
|
await page.getByRole("button", { name: "Begin (1 min)" }).click();
|
||||||
|
await page.getByLabel(role).check();
|
||||||
|
await page.getByRole("button", { name: "Next" }).click();
|
||||||
|
|
||||||
|
await expect(page.getByLabel(useCase)).toBeVisible();
|
||||||
|
await page.getByLabel(useCase).check();
|
||||||
|
await page.getByRole("button", { name: "Next" }).click();
|
||||||
|
|
||||||
|
await expect(page.getByPlaceholder("e.g. Formbricks")).toBeVisible();
|
||||||
|
await page.getByPlaceholder("e.g. Formbricks").fill(productName);
|
||||||
|
|
||||||
|
await page.locator(".h-6").click();
|
||||||
|
await page.getByLabel("Hue").click();
|
||||||
|
|
||||||
|
await page.locator("div").filter({ hasText: "Create your team's product." }).nth(1).click();
|
||||||
|
await page.getByRole("button", { name: "Done" }).click();
|
||||||
|
|
||||||
|
await page.waitForURL(/\/environments\/[^/]+\/surveys/);
|
||||||
|
await expect(page).toHaveURL(/\/environments\/[^/]+\/surveys/);
|
||||||
|
await expect(page.getByText(productName)).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Skip", async ({ page }) => {
|
||||||
|
await page.getByRole("button", { name: "I'll do it later" }).click();
|
||||||
|
await page.getByRole("button", { name: "I'll do it later" }).click();
|
||||||
|
|
||||||
|
await page.waitForURL(/\/environments\/[^/]+\/surveys/);
|
||||||
|
await expect(page).toHaveURL(/\/environments\/[^/]+\/surveys/);
|
||||||
|
await expect(page.getByText("My Product")).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,95 +1,61 @@
|
|||||||
import { getUser } from "@/playwright/lib/user";
|
import { getUser } from "./utils";
|
||||||
import { test } from "@playwright/test";
|
import { test, expect } from "@playwright/test";
|
||||||
|
|
||||||
const { name, email, password } = getUser();
|
const { name, email, password } = getUser();
|
||||||
|
|
||||||
test.describe("Signup Flow Test", async () => {
|
test.describe("Email Signup Flow Test", async () => {
|
||||||
test.describe.configure({ mode: "serial" });
|
test.describe.configure({ mode: "serial" });
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
test("Valid User", async ({ page }) => {
|
|
||||||
await page.goto("/auth/signup");
|
await page.goto("/auth/signup");
|
||||||
await page.getByText("Continue with Email").click();
|
await page.getByText("Continue with Email").click();
|
||||||
|
});
|
||||||
|
|
||||||
await page.waitForSelector('input[name="name"]');
|
test("Valid User", async ({ page }) => {
|
||||||
await page.fill('input[name="name"]', name);
|
await page.fill('input[name="name"]', name);
|
||||||
await page.press('input[name="name"]', "Tab");
|
|
||||||
|
|
||||||
await page.fill('input[name="email"]', email);
|
await page.fill('input[name="email"]', email);
|
||||||
await page.press('input[name="email"]', "Tab");
|
|
||||||
|
|
||||||
await page.fill('input[name="password"]', password);
|
await page.fill('input[name="password"]', password);
|
||||||
await page.press('input[name="password"]', "Enter");
|
await page.press('input[name="password"]', "Enter");
|
||||||
|
|
||||||
await page.waitForURL("/auth/signup-without-verification-success");
|
await page.waitForURL("/auth/signup-without-verification-success");
|
||||||
|
await expect(page).toHaveURL("/auth/signup-without-verification-success");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Email is taken", async ({ page }) => {
|
test("Email is taken", async ({ page }) => {
|
||||||
await page.goto("/auth/signup");
|
|
||||||
await page.getByText("Continue with Email").click();
|
|
||||||
|
|
||||||
await page.waitForSelector('input[name="name"]');
|
|
||||||
await page.fill('input[name="name"]', name);
|
await page.fill('input[name="name"]', name);
|
||||||
await page.press('input[name="name"]', "Tab");
|
|
||||||
|
|
||||||
await page.fill('input[name="email"]', email);
|
await page.fill('input[name="email"]', email);
|
||||||
await page.press('input[name="email"]', "Tab");
|
|
||||||
|
|
||||||
await page.fill('input[name="password"]', password);
|
await page.fill('input[name="password"]', password);
|
||||||
await page.press('input[name="password"]', "Enter");
|
await page.press('input[name="password"]', "Enter");
|
||||||
|
|
||||||
let alertMessage = "user with this email address already exists";
|
let alertMessage = "user with this email address already exists";
|
||||||
|
|
||||||
await (await page.waitForSelector(`text=${alertMessage}`)).isVisible();
|
await (await page.waitForSelector(`text=${alertMessage}`)).isVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("No Name", async ({ page }) => {
|
test("No Name", async ({ page }) => {
|
||||||
await page.goto("/auth/signup");
|
|
||||||
await page.getByText("Continue with Email").click();
|
|
||||||
|
|
||||||
await page.waitForSelector('input[name="name"]');
|
|
||||||
await page.fill('input[name="name"]', "");
|
await page.fill('input[name="name"]', "");
|
||||||
await page.press('input[name="name"]', "Tab");
|
|
||||||
|
|
||||||
await page.fill('input[name="email"]', email);
|
await page.fill('input[name="email"]', email);
|
||||||
await page.press('input[name="email"]', "Tab");
|
|
||||||
|
|
||||||
await page.fill('input[name="password"]', password);
|
await page.fill('input[name="password"]', password);
|
||||||
await page.press('input[name="password"]', "Enter");
|
await page.press('input[name="password"]', "Enter");
|
||||||
|
|
||||||
await page.getByText("Continue with Email").isDisabled();
|
const button = page.getByText("Continue with Email");
|
||||||
|
await expect(button).toBeDisabled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Invalid Email", async ({ page }) => {
|
test("Invalid Email", async ({ page }) => {
|
||||||
await page.goto("/auth/signup");
|
|
||||||
await page.getByText("Continue with Email").click();
|
|
||||||
|
|
||||||
await page.waitForSelector('input[name="name"]');
|
|
||||||
await page.fill('input[name="name"]', name);
|
await page.fill('input[name="name"]', name);
|
||||||
await page.press('input[name="name"]', "Tab");
|
|
||||||
|
|
||||||
await page.fill('input[name="email"]', "invalid");
|
await page.fill('input[name="email"]', "invalid");
|
||||||
await page.press('input[name="email"]', "Tab");
|
|
||||||
|
|
||||||
await page.fill('input[name="password"]', password);
|
await page.fill('input[name="password"]', password);
|
||||||
await page.press('input[name="password"]', "Enter");
|
await page.press('input[name="password"]', "Enter");
|
||||||
|
|
||||||
await page.getByText("Continue with Email").isDisabled();
|
const button = page.getByText("Continue with Email");
|
||||||
|
await expect(button).toBeDisabled();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Invalid Password", async ({ page }) => {
|
test("Invalid Password", async ({ page }) => {
|
||||||
await page.goto("/auth/signup");
|
|
||||||
await page.getByText("Continue with Email").click();
|
|
||||||
|
|
||||||
await page.waitForSelector('input[name="name"]');
|
|
||||||
await page.fill('input[name="name"]', name);
|
await page.fill('input[name="name"]', name);
|
||||||
await page.press('input[name="name"]', "Tab");
|
|
||||||
|
|
||||||
await page.fill('input[name="email"]', email);
|
await page.fill('input[name="email"]', email);
|
||||||
await page.press('input[name="email"]', "Tab");
|
|
||||||
|
|
||||||
await page.fill('input[name="password"]', "invalid");
|
await page.fill('input[name="password"]', "invalid");
|
||||||
await page.press('input[name="password"]', "Enter");
|
await page.press('input[name="password"]', "Enter");
|
||||||
|
|
||||||
await page.getByText("Continue with Email").isDisabled();
|
const button = page.getByText("Continue with Email");
|
||||||
|
await expect(button).toBeDisabled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
98
apps/web/playwright/survey.spec.ts
Normal file
98
apps/web/playwright/survey.spec.ts
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import { getUser, login, signUpAndLogin, skipOnboarding } from "./utils";
|
||||||
|
import { test, expect } from "@playwright/test";
|
||||||
|
|
||||||
|
test.describe("Survey: Product Market Fit", async () => {
|
||||||
|
test.describe.configure({ mode: "serial" });
|
||||||
|
let url: string | null;
|
||||||
|
const { name, email, password } = getUser();
|
||||||
|
|
||||||
|
test("Create Survey", async ({ page }) => {
|
||||||
|
await signUpAndLogin(page, name, email, password);
|
||||||
|
await skipOnboarding(page);
|
||||||
|
|
||||||
|
await page.getByRole("heading", { name: "Product Market Fit (Superhuman)" }).click();
|
||||||
|
await page.getByRole("button", { name: "Continue to Settings" }).click();
|
||||||
|
await page.getByRole("button", { name: "Publish" }).click();
|
||||||
|
|
||||||
|
const regexPattern = /^http:\/\/localhost:3000\/s\//;
|
||||||
|
const urlElement = page.locator(`text=${regexPattern}`);
|
||||||
|
|
||||||
|
await expect(urlElement).toBeVisible();
|
||||||
|
url = await urlElement.textContent();
|
||||||
|
await page.getByRole("button", { name: "Close" }).click();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Submit Response: No", async ({ page }) => {
|
||||||
|
await page.goto(url!);
|
||||||
|
|
||||||
|
await expect(page.getByText("You are one of our power users! Do you have 5 minutes?")).toBeVisible();
|
||||||
|
await expect(page.getByText("Optional")).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByRole("button", { name: "No, thanks." }).click();
|
||||||
|
|
||||||
|
await expect(page.getByText("Thank you!")).toBeVisible();
|
||||||
|
await expect(page.getByText("We appreciate your feedback.")).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Submit Response: Yes", async ({ page }) => {
|
||||||
|
await page.goto(url!);
|
||||||
|
|
||||||
|
await expect(page.getByText("You are one of our power users! Do you have 5 minutes?")).toBeVisible();
|
||||||
|
await expect(page.getByText("Optional")).toBeVisible();
|
||||||
|
|
||||||
|
await page.getByRole("button", { name: "Happy to help!" }).click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText("How disappointed would you be if you could no longer use My Product?")
|
||||||
|
).toBeVisible();
|
||||||
|
let answers = ["Not at all disappointed", "Somewhat disappointed", "Very disappointed"];
|
||||||
|
let answer = answers[Math.floor(Math.random() * answers.length)];
|
||||||
|
await page.getByText(answer).click();
|
||||||
|
await page.getByRole("button", { name: "Next" }).click();
|
||||||
|
|
||||||
|
await expect(page.getByText("What is your role?")).toBeVisible();
|
||||||
|
answers = ["Founder", "Executive", "Product Manager", "Product Owner", "Software Engineer"];
|
||||||
|
answer = answers[Math.floor(Math.random() * answers.length)];
|
||||||
|
await page.getByText(answer).click();
|
||||||
|
await page.getByRole("button", { name: "Next" }).click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText("What type of people do you think would most benefit from My Product?")
|
||||||
|
).toBeVisible();
|
||||||
|
await page.getByLabel("").fill("Founders and Executives");
|
||||||
|
await page.getByRole("button", { name: "Next" }).click();
|
||||||
|
|
||||||
|
await expect(page.getByText("What is the main benefit you")).toBeVisible();
|
||||||
|
await page.getByLabel("").fill("Open Source and the UX!");
|
||||||
|
await page.getByRole("button", { name: "Next" }).click();
|
||||||
|
|
||||||
|
await expect(page.getByText("How can we improve My Product")).toBeVisible();
|
||||||
|
await page.getByLabel("").fill("More and more features, that's it! Keep shipping.");
|
||||||
|
await page.getByRole("button", { name: "Finish" }).click();
|
||||||
|
|
||||||
|
await expect(page.getByText("Thank you!")).toBeVisible();
|
||||||
|
await expect(page.getByText("We appreciate your feedback.")).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("View Responses", async ({ page }) => {
|
||||||
|
await login(page, email, password);
|
||||||
|
await page.waitForURL(/\/environments\/[^/]+\/surveys/);
|
||||||
|
await expect(page.getByText("Your Surveys")).toBeVisible();
|
||||||
|
await page.locator("li").filter({ hasText: "Link SurveyProduct Market Fit" }).getByRole("link").click();
|
||||||
|
await expect(page.getByText("Responses")).toBeVisible();
|
||||||
|
await expect(page.getByText("Product Market Fit (Superhuman)")).toBeVisible();
|
||||||
|
await expect(page.getByText("Displays2")).toBeVisible();
|
||||||
|
await page.getByRole("button", { name: "Responses100%" }).textContent();
|
||||||
|
await page.getByRole("link", { name: "Responses" }).click();
|
||||||
|
await page.waitForURL(/\/environments\/[^/]+\/surveys\/[^/]+\/responses/);
|
||||||
|
expect(await page.locator(".rounded-b-lg").count()).toEqual(2);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText("You are one of our power users! Do you have 5 minutes?dismissed")
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText("You are one of our power users! Do you have 5 minutes?clicked")
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
65
apps/web/playwright/utils.ts
Normal file
65
apps/web/playwright/utils.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import { randomBytes } from "crypto";
|
||||||
|
import { Page } from "playwright";
|
||||||
|
import { expect } from "@playwright/test";
|
||||||
|
|
||||||
|
export const getUser = () => {
|
||||||
|
const name = randomBytes(4).toString("hex");
|
||||||
|
const email = `${name}@gmail.com`;
|
||||||
|
const password = `Te${name}@123`;
|
||||||
|
return { name, email, password };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getTeam = () => {
|
||||||
|
let roles = ["Project Manager", "Engineer", "Founder", "Marketing Specialist"];
|
||||||
|
let useCases = [
|
||||||
|
"Increase conversion",
|
||||||
|
"Improve user retention",
|
||||||
|
"Increase user adoption",
|
||||||
|
"Sharpen marketing messaging",
|
||||||
|
"Support sales",
|
||||||
|
];
|
||||||
|
const productName = randomBytes(8).toString("hex");
|
||||||
|
const role = roles[Math.floor(Math.random() * roles.length)];
|
||||||
|
const useCase = useCases[Math.floor(Math.random() * useCases.length)];
|
||||||
|
return { role, useCase, productName };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const signUpAndLogin = async (
|
||||||
|
page: Page,
|
||||||
|
name: string,
|
||||||
|
email: string,
|
||||||
|
password: string
|
||||||
|
): Promise<void> => {
|
||||||
|
await page.goto("/auth/login");
|
||||||
|
await page.getByRole("link", { name: "Create an account" }).click();
|
||||||
|
await page.getByRole("button", { name: "Continue with Email" }).click();
|
||||||
|
await page.getByPlaceholder("Full Name").fill(name);
|
||||||
|
await page.getByPlaceholder("work@email.com").fill(email);
|
||||||
|
await page.getByPlaceholder("*******").fill(password);
|
||||||
|
await page.press('input[name="password"]', "Enter");
|
||||||
|
await page.getByRole("link", { name: "Login" }).click();
|
||||||
|
await page.getByRole("button", { name: "Login with Email" }).click();
|
||||||
|
await page.getByPlaceholder("work@email.com").fill(email);
|
||||||
|
await page.getByPlaceholder("*******").click();
|
||||||
|
await page.getByPlaceholder("*******").fill(password);
|
||||||
|
await page.getByRole("button", { name: "Login with Email" }).click();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const login = async (page: Page, email: string, password: string): Promise<void> => {
|
||||||
|
await page.goto("/auth/login");
|
||||||
|
await page.getByRole("button", { name: "Login with Email" }).click();
|
||||||
|
await page.getByPlaceholder("work@email.com").fill(email);
|
||||||
|
await page.getByPlaceholder("*******").click();
|
||||||
|
await page.getByPlaceholder("*******").fill(password);
|
||||||
|
await page.getByRole("button", { name: "Login with Email" }).click();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const skipOnboarding = async (page: Page): Promise<void> => {
|
||||||
|
await page.waitForURL("/onboarding");
|
||||||
|
await expect(page).toHaveURL("/onboarding");
|
||||||
|
await page.getByRole("button", { name: "I'll do it later" }).click();
|
||||||
|
await page.getByRole("button", { name: "I'll do it later" }).click();
|
||||||
|
await page.waitForURL(/\/environments\/[^/]+\/surveys/);
|
||||||
|
await expect(page).toHaveURL(/\/environments\/[^/]+\/surveys/);
|
||||||
|
await expect(page.getByText("My Product")).toBeVisible();
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user