snapshot of https://github.com/marmelab/atomic-crm.git (main, 2026-09-18; blobs > 131072B omitted)
Some checks failed
✅ Check / 🔬 ESLint (push) Failing after 21s
✅ Check / 🏷️ Typecheck (push) Failing after 11s
✅ Check / 🔎 Test (push) Failing after 11s
✅ Check / e2e-test (push) Failing after 11s
✅ Check / 🔨 Build (push) Failing after 11s
🚀 Deploy / 🚀 Deploy (doc) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (demo) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (supabase) (push) Failing after 18s
Some checks failed
✅ Check / 🔬 ESLint (push) Failing after 21s
✅ Check / 🏷️ Typecheck (push) Failing after 11s
✅ Check / 🔎 Test (push) Failing after 11s
✅ Check / e2e-test (push) Failing after 11s
✅ Check / 🔨 Build (push) Failing after 11s
🚀 Deploy / 🚀 Deploy (doc) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (demo) (push) Failing after 12s
🚀 Deploy / 🚀 Deploy (supabase) (push) Failing after 18s
This commit is contained in:
100
e2e/adminAccountManagerFilter.spec.ts
Normal file
100
e2e/adminAccountManagerFilter.spec.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { expect, test } from "./fixtures";
|
||||
|
||||
test.describe("admin filtering by account manager", () => {
|
||||
test.beforeEach(async ({ createSales, createCompany, createContact }) => {
|
||||
const admin = await createSales({
|
||||
administrator: true,
|
||||
email: "john@doe.com",
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
password: "password",
|
||||
});
|
||||
|
||||
const teammate = await createSales({
|
||||
email: "marie@curie.com",
|
||||
first_name: "Marie",
|
||||
last_name: "Curie",
|
||||
password: "password",
|
||||
});
|
||||
|
||||
const company = await createCompany({
|
||||
name: "Smith Corp",
|
||||
salesId: admin.id,
|
||||
});
|
||||
|
||||
await createContact({
|
||||
company_id: company.id,
|
||||
first_name: "Ada",
|
||||
last_name: "Lovelace",
|
||||
sales_id: admin.id,
|
||||
title: "CTO",
|
||||
});
|
||||
|
||||
await createContact({
|
||||
company_id: company.id,
|
||||
first_name: "Grace",
|
||||
last_name: "Hopper",
|
||||
sales_id: teammate.id,
|
||||
title: "Rear Admiral",
|
||||
});
|
||||
});
|
||||
|
||||
test("admin narrows the contact list down to a teammate's contacts", async ({
|
||||
page,
|
||||
isMobile,
|
||||
menu,
|
||||
}) => {
|
||||
await page.goto("/");
|
||||
await page.getByLabel("Email").fill("john@doe.com");
|
||||
await page.getByLabel("Password").fill("password");
|
||||
await page.getByRole("button", { name: "Sign in" }).click();
|
||||
|
||||
await menu.goToContacts();
|
||||
await expect(page.getByText("Ada Lovelace")).toBeVisible();
|
||||
await expect(page.getByText("Grace Hopper")).toBeVisible();
|
||||
|
||||
if (isMobile) {
|
||||
await page.getByRole("button", { name: "Add filter" }).click();
|
||||
}
|
||||
await page.getByRole("button", { name: "Marie Curie" }).click();
|
||||
if (isMobile) {
|
||||
await page.getByRole("button", { name: "Confirm" }).click();
|
||||
}
|
||||
|
||||
await expect(page.getByText("Grace Hopper")).toBeVisible();
|
||||
await expect(page.getByText("Ada Lovelace")).toBeHidden();
|
||||
|
||||
if (isMobile) {
|
||||
await page.getByRole("button", { name: "Add filter" }).click();
|
||||
}
|
||||
await page.getByRole("button", { name: "Marie Curie" }).click();
|
||||
if (isMobile) {
|
||||
await page.getByRole("button", { name: "Confirm" }).click();
|
||||
}
|
||||
|
||||
await expect(page.getByText("Ada Lovelace")).toBeVisible();
|
||||
await expect(page.getByText("Grace Hopper")).toBeVisible();
|
||||
});
|
||||
|
||||
test("a non-admin user gets no account manager list", async ({
|
||||
page,
|
||||
isMobile,
|
||||
menu,
|
||||
}) => {
|
||||
await page.goto("/");
|
||||
await page.getByLabel("Email").fill("marie@curie.com");
|
||||
await page.getByLabel("Password").fill("password");
|
||||
await page.getByRole("button", { name: "Sign in" }).click();
|
||||
|
||||
await menu.goToContacts();
|
||||
await expect(page.getByText("Grace Hopper")).toBeVisible();
|
||||
|
||||
if (isMobile) {
|
||||
await page.getByRole("button", { name: "Add filter" }).click();
|
||||
}
|
||||
await expect(
|
||||
page.getByRole("button", { name: "Me", exact: true }),
|
||||
).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "John Doe" })).toBeHidden();
|
||||
});
|
||||
});
|
||||
63
e2e/bulkContactTags.spec.ts
Normal file
63
e2e/bulkContactTags.spec.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { test, expect } from "./fixtures";
|
||||
|
||||
test("user adds a tag to several contacts", async ({
|
||||
page,
|
||||
isMobile,
|
||||
createContact,
|
||||
createSales,
|
||||
menu,
|
||||
dismissToast,
|
||||
}) => {
|
||||
test.skip(isMobile, "Bulk tag is only available on desktop");
|
||||
|
||||
const sales = await createSales({
|
||||
email: "john@doe.com",
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
password: "password",
|
||||
});
|
||||
|
||||
await createContact({
|
||||
first_name: "Ada",
|
||||
last_name: "Lovelace",
|
||||
sales_id: sales.id,
|
||||
title: "CTO",
|
||||
});
|
||||
await createContact({
|
||||
first_name: "Grace",
|
||||
last_name: "Hopper",
|
||||
sales_id: sales.id,
|
||||
title: "Rear Admiral",
|
||||
});
|
||||
|
||||
await page.goto("/");
|
||||
|
||||
await page.getByLabel("Email").fill("john@doe.com");
|
||||
await page.getByLabel("Password").fill("password");
|
||||
await page.getByRole("button", { name: "Sign in" }).click();
|
||||
|
||||
await expect(page).toHaveTitle(/Atomic CRM/);
|
||||
await expect(page.getByRole("link", { name: "Contacts" })).toBeVisible();
|
||||
|
||||
await menu.goToContacts();
|
||||
await expect(page.getByText("Ada Lovelace")).toBeVisible();
|
||||
await expect(page.getByText("Grace Hopper")).toBeVisible();
|
||||
|
||||
const checkboxes = page.getByRole("checkbox");
|
||||
await checkboxes.nth(1).click();
|
||||
await page.getByRole("button", { name: /select all/i }).click();
|
||||
|
||||
await page.getByRole("button", { name: /^Tag$/ }).click();
|
||||
await page.getByRole("button", { name: "Create new tag" }).click();
|
||||
await page.getByLabel("Tag name").fill("Prospect");
|
||||
await page.getByRole("button", { name: "Save" }).click();
|
||||
|
||||
await dismissToast("Tag added to 2 contacts");
|
||||
|
||||
await expect(
|
||||
page.getByText("Grace Hopper").locator("xpath=ancestor::a[1]"),
|
||||
).toContainText("Prospect");
|
||||
await expect(
|
||||
page.getByText("Ada Lovelace").locator("xpath=ancestor::a[1]"),
|
||||
).toContainText("Prospect");
|
||||
});
|
||||
264
e2e/fixtures.ts
Normal file
264
e2e/fixtures.ts
Normal file
@@ -0,0 +1,264 @@
|
||||
import { test as base, expect, type Page } from "@playwright/test";
|
||||
import { createClient } from "@supabase/supabase-js";
|
||||
|
||||
const adminSupabase = createClient(
|
||||
process.env.VITE_SUPABASE_URL ?? "http://127.0.0.1:54341",
|
||||
process.env.SERVICE_ROLE_KEY!,
|
||||
{ auth: { autoRefreshToken: false, persistSession: false } },
|
||||
);
|
||||
|
||||
// Tables in FK-safe deletion order (children before parents)
|
||||
const TABLES = [
|
||||
"tasks",
|
||||
"contact_notes",
|
||||
"deal_notes",
|
||||
"deals",
|
||||
"contacts",
|
||||
"companies",
|
||||
"tags",
|
||||
"favicons_excluded_domains",
|
||||
"configuration",
|
||||
"sales",
|
||||
];
|
||||
|
||||
async function resetDb() {
|
||||
for (const table of TABLES) {
|
||||
// Supabase client delete need a where clause to get executed, so we use one that will match on all rows (id is not null)
|
||||
await adminSupabase.from(table).delete().not("id", "is", null);
|
||||
}
|
||||
|
||||
// Delete all auth users (cascades to sales via DB trigger)
|
||||
const { data } = await adminSupabase.auth.admin.listUsers();
|
||||
await Promise.all(
|
||||
data.users.map((user) => adminSupabase.auth.admin.deleteUser(user.id)),
|
||||
);
|
||||
}
|
||||
|
||||
async function createUser({
|
||||
email,
|
||||
password,
|
||||
}: {
|
||||
email: string;
|
||||
password: string;
|
||||
}) {
|
||||
const { data, error } = await adminSupabase.auth.admin.createUser({
|
||||
email,
|
||||
password,
|
||||
email_confirm: true,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw new Error(`Failed to create user: ${error.message}`);
|
||||
}
|
||||
|
||||
return data.user;
|
||||
}
|
||||
|
||||
async function createSales({
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
password,
|
||||
administrator = false,
|
||||
}: {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
email: string;
|
||||
password: string;
|
||||
administrator?: boolean;
|
||||
}) {
|
||||
const { data: userData, error: userError } =
|
||||
await adminSupabase.auth.admin.createUser({
|
||||
email,
|
||||
password,
|
||||
email_confirm: true,
|
||||
});
|
||||
|
||||
if (userError) {
|
||||
throw new Error(`Failed to create sales: ${userError.message}`);
|
||||
}
|
||||
|
||||
const { data, error } = await adminSupabase
|
||||
.from("sales")
|
||||
.update({ first_name, last_name, administrator })
|
||||
.eq("user_id", userData.user?.id)
|
||||
.select()
|
||||
.single();
|
||||
|
||||
if (error) {
|
||||
throw new Error(`Failed to create sales: ${error.message}`);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async function createNotes({
|
||||
contactId,
|
||||
salesId,
|
||||
notes,
|
||||
}: {
|
||||
contactId: string | number;
|
||||
salesId: string | number;
|
||||
notes: {
|
||||
text: string;
|
||||
date?: string;
|
||||
status?: "cold" | "warm" | "hot";
|
||||
}[];
|
||||
}) {
|
||||
if (notes.length === 0) return;
|
||||
|
||||
const { error } = await adminSupabase.from("contact_notes").insert(
|
||||
notes.map(({ text, date, status = "cold" }) => ({
|
||||
contact_id: contactId,
|
||||
sales_id: salesId,
|
||||
text,
|
||||
date,
|
||||
status,
|
||||
})),
|
||||
);
|
||||
|
||||
if (error) {
|
||||
throw new Error(`Failed to create notes: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function createCompany({
|
||||
name,
|
||||
salesId,
|
||||
}: {
|
||||
name: string;
|
||||
salesId: string | number;
|
||||
}) {
|
||||
const { data, error } = await adminSupabase
|
||||
.from("companies")
|
||||
.insert({ name, sales_id: salesId })
|
||||
.select("id")
|
||||
.single();
|
||||
|
||||
if (error) {
|
||||
throw new Error(`Failed to create company: ${error.message}`);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async function createContact({
|
||||
first_name,
|
||||
last_name,
|
||||
title = "",
|
||||
company_id = null,
|
||||
sales_id,
|
||||
notes = [],
|
||||
}: {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
title?: string;
|
||||
company_id?: string | number | null;
|
||||
sales_id: string | number;
|
||||
notes?: {
|
||||
text: string;
|
||||
date?: string;
|
||||
status?: "cold" | "warm" | "hot";
|
||||
}[];
|
||||
}) {
|
||||
const { data, error } = await adminSupabase
|
||||
.from("contacts")
|
||||
.insert({
|
||||
first_name,
|
||||
last_name,
|
||||
title,
|
||||
company_id,
|
||||
sales_id,
|
||||
first_seen: new Date().toISOString(),
|
||||
last_seen: new Date().toISOString(),
|
||||
has_newsletter: false,
|
||||
tags: [],
|
||||
gender: "unknown",
|
||||
status: "cold",
|
||||
background: "",
|
||||
email_jsonb: [],
|
||||
phone_jsonb: [],
|
||||
})
|
||||
.select("id")
|
||||
.single();
|
||||
|
||||
if (error) {
|
||||
throw new Error(`Failed to create contact: ${error.message}`);
|
||||
}
|
||||
|
||||
await createNotes({
|
||||
contactId: data.id,
|
||||
salesId: sales_id,
|
||||
notes,
|
||||
});
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
const getMenuMethod = ({ page }: { page: Page; isMobile: boolean }) => ({
|
||||
goToDashboard: async () => {
|
||||
await page.getByRole("link", { name: "Dashboard" }).click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
},
|
||||
goToContacts: async () => {
|
||||
await page.getByRole("link", { name: "Contacts" }).click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
},
|
||||
});
|
||||
|
||||
const dismissToast = async (page: Page, content: string) => {
|
||||
await expect(page.getByText(content)).toBeVisible();
|
||||
await page.getByLabel("Close toast").first().click();
|
||||
// Since we are in optimistic UI, dismissing the toast trigger the request to the api linked to the toast message
|
||||
await page.waitForLoadState("networkidle");
|
||||
};
|
||||
|
||||
export const test = base.extend<{
|
||||
resetDb: void;
|
||||
createUser: typeof createUser;
|
||||
createSales: typeof createSales;
|
||||
createCompany: typeof createCompany;
|
||||
createContact: typeof createContact;
|
||||
createNotes: typeof createNotes;
|
||||
menu: ReturnType<typeof getMenuMethod>;
|
||||
dismissToast: (content: string) => Promise<void>;
|
||||
}>({
|
||||
resetDb: [
|
||||
// The first argument to a Playwright fixture function must use object destructuring ({}) — _ is not allowed.
|
||||
// Playwright uses this to statically analyze which fixtures are requested.
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
async ({}, use) => {
|
||||
await resetDb();
|
||||
await use();
|
||||
},
|
||||
{ auto: true },
|
||||
],
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
createUser: async ({}, cb) => {
|
||||
await cb(createUser);
|
||||
},
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
createSales: async ({}, cb) => {
|
||||
await cb(createSales);
|
||||
},
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
createCompany: async ({}, cb) => {
|
||||
await cb(createCompany);
|
||||
},
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
createContact: async ({}, cb) => {
|
||||
await cb(createContact);
|
||||
},
|
||||
// eslint-disable-next-line no-empty-pattern
|
||||
createNotes: async ({}, cb) => {
|
||||
await cb(createNotes);
|
||||
},
|
||||
menu: async ({ page, isMobile }, cb) => {
|
||||
await cb(getMenuMethod({ page, isMobile }));
|
||||
},
|
||||
dismissToast: async ({ page }, cb) => {
|
||||
await cb((content: string) => dismissToast(page, content));
|
||||
},
|
||||
});
|
||||
|
||||
export { expect };
|
||||
110
e2e/onboarding.spec.ts
Normal file
110
e2e/onboarding.spec.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { test, expect } from "./fixtures";
|
||||
|
||||
test("user onboarding", async ({ page, isMobile, menu, dismissToast }) => {
|
||||
await page.goto("/");
|
||||
|
||||
// Expect a title "to contain" a substring.
|
||||
await expect(page).toHaveTitle(/Atomic CRM/);
|
||||
await expect(page.getByText("Welcome to Atomic CRM")).toBeVisible();
|
||||
|
||||
await page.getByLabel("First name").fill("John");
|
||||
await page.getByLabel("Last name").fill("Doe");
|
||||
await page.getByLabel("Email").fill("john@doe.com");
|
||||
await page.getByLabel("Password").fill("password");
|
||||
await page.getByRole("button", { name: "Create account" }).click();
|
||||
|
||||
await expect(page.getByText("What's next?")).toBeVisible();
|
||||
await expect(page.getByText("1/3 done")).toBeVisible();
|
||||
await expect(page.getByText("Install Atomic CRM")).toBeVisible();
|
||||
await expect(page.getByText("Add your first contact")).toBeVisible();
|
||||
await expect(page.getByText("Add your first note")).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Import data" })).toBeVisible();
|
||||
|
||||
await page
|
||||
.getByRole(isMobile ? "button" : "link", { name: "Add contact" })
|
||||
.click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
await page.getByLabel("She/Her").click();
|
||||
await page.getByLabel("First name").fill("Jane");
|
||||
await page.getByLabel("Last name").fill("Smith");
|
||||
await page.getByLabel("Title").fill("CEO");
|
||||
await page.getByLabel("Company").click();
|
||||
await page.getByPlaceholder("Search").fill("Smith Corp");
|
||||
await page.getByText("Create Smith Corp").click();
|
||||
await page
|
||||
.getByRole("group", { name: "Email addresses" })
|
||||
.getByRole("textbox", { name: "Email" })
|
||||
.fill("jane@smithcorp.com");
|
||||
await page
|
||||
.getByRole("group", { name: "Email addresses" })
|
||||
.getByRole("button", { name: "Add" })
|
||||
.click();
|
||||
|
||||
await page
|
||||
.getByRole("group", { name: "Phone numbers" })
|
||||
.getByRole("textbox", { name: "Phone number" })
|
||||
.fill("+1234567890");
|
||||
await page
|
||||
.getByRole("group", { name: "Phone numbers" })
|
||||
.getByRole("button", { name: "Add" })
|
||||
.click();
|
||||
|
||||
await page
|
||||
.getByLabel("LinkedIn URL")
|
||||
.fill("https://www.linkedin.com/in/jane-smith");
|
||||
|
||||
await page
|
||||
.getByLabel("Background info (bio, how you met, etc)")
|
||||
.fill("Met at a conference.");
|
||||
|
||||
await page.getByLabel("Has newsletter").check();
|
||||
|
||||
await expect(page.getByLabel("Account manager *")).toHaveText("John Doe");
|
||||
|
||||
await page.getByRole("button", { name: "Save" }).click();
|
||||
|
||||
await dismissToast("Element created");
|
||||
|
||||
await expect(page.locator(isMobile ? "h2" : "h5")).toHaveText("Jane Smith");
|
||||
await expect(page.getByText("CEO at Smith Corp")).toBeVisible();
|
||||
|
||||
await menu.goToDashboard();
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(page.getByText("2/3 done")).toBeVisible();
|
||||
|
||||
await page
|
||||
.getByRole(isMobile ? "button" : "link", { name: "Add note" })
|
||||
.click();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.getByPlaceholder("Add a note").fill("This is a note about Jane.");
|
||||
await page
|
||||
.getByRole("button", { name: isMobile ? "Save" : "Add this note" })
|
||||
.click();
|
||||
|
||||
await dismissToast("Note added");
|
||||
|
||||
await expect(
|
||||
page.getByText(isMobile ? "Me" : "You added a note", { exact: false }),
|
||||
).toBeVisible();
|
||||
await expect(page.getByText("This is a note about Jane.")).toBeVisible();
|
||||
|
||||
await menu.goToDashboard();
|
||||
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await expect(page.getByText("Latest Activity")).toBeVisible();
|
||||
await expect(
|
||||
page.getByText("Latest Activity").locator("xpath=../.."),
|
||||
).toHaveText(/You added company Smith Corp today at/);
|
||||
|
||||
await expect(
|
||||
page.getByText("Latest Activity").locator("xpath=../.."),
|
||||
).toHaveText(/You added Jane Smith to Smith Corp today at/);
|
||||
|
||||
await expect(
|
||||
page.getByText("Latest Activity").locator("xpath=../.."),
|
||||
).toHaveText(/You added a note about Jane Smith today at/);
|
||||
});
|
||||
97
e2e/userAddingATask.spec.ts
Normal file
97
e2e/userAddingATask.spec.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import { expect, test } from "./fixtures";
|
||||
|
||||
test.describe("user adding a task", () => {
|
||||
test.beforeEach(async ({ createSales, createContact, createCompany }) => {
|
||||
const sales = await createSales({
|
||||
first_name: "John",
|
||||
last_name: "Doe",
|
||||
email: "john@doe.com",
|
||||
password: "password",
|
||||
});
|
||||
|
||||
const company = await createCompany({
|
||||
name: "Smith Corp",
|
||||
salesId: sales.id,
|
||||
});
|
||||
|
||||
await createContact({
|
||||
first_name: "Jane",
|
||||
last_name: "Smith",
|
||||
title: "CEO",
|
||||
sales_id: sales.id,
|
||||
company_id: company.id,
|
||||
notes: [{ text: "Met at a conference." }],
|
||||
});
|
||||
|
||||
await createContact({
|
||||
first_name: "Bob",
|
||||
last_name: "Johnson",
|
||||
title: "CTO",
|
||||
sales_id: sales.id,
|
||||
company_id: company.id,
|
||||
});
|
||||
|
||||
await createContact({
|
||||
first_name: "Alice",
|
||||
last_name: "Williams",
|
||||
title: "CFO",
|
||||
sales_id: sales.id,
|
||||
company_id: company.id,
|
||||
});
|
||||
});
|
||||
test("user adding a task", async ({ page, isMobile, menu, dismissToast }) => {
|
||||
await page.goto("/");
|
||||
await page.getByLabel("Email").fill("john@doe.com");
|
||||
await page.getByLabel("Password").fill("password");
|
||||
await page.getByRole("button", { name: "Sign in" }).click();
|
||||
|
||||
await expect(page).toHaveTitle(/Atomic CRM/);
|
||||
await expect(page.getByText("Latest Activity")).toBeVisible();
|
||||
|
||||
await menu.goToContacts();
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
await page.getByText("Jane Smith").click();
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
if (isMobile) {
|
||||
await page.getByRole("button", { name: "Create" }).click();
|
||||
await page.getByRole("menuitem", { name: "Task" }).click();
|
||||
} else {
|
||||
await page.getByRole("button", { name: "Add Task" }).click();
|
||||
}
|
||||
await page.getByLabel("Description *").fill("Follow up with Jane");
|
||||
await page.getByLabel("Due date").fill("2026-04-11T21:00");
|
||||
await page.getByLabel("Type").click();
|
||||
await page.getByRole("option", { name: "Call" }).click();
|
||||
|
||||
await page.getByRole("button", { name: "Save" }).click();
|
||||
|
||||
await dismissToast("Task added");
|
||||
|
||||
if (isMobile) {
|
||||
await expect(page.getByText("1 task")).toBeVisible();
|
||||
await page.getByText("1 task").click();
|
||||
|
||||
await expect(page.getByText("Follow up with Jane")).toBeVisible();
|
||||
await expect(page.getByText("due 4/11/2026, 9:00:00 PM")).toBeVisible();
|
||||
} else {
|
||||
await expect(page.getByText("Tasks")).toBeVisible();
|
||||
|
||||
await expect(page.getByText("Tasks").locator("..")).toHaveText(
|
||||
/Follow up with Jane/,
|
||||
);
|
||||
await menu.goToDashboard();
|
||||
|
||||
await expect(page.getByText("Upcoming Tasks")).toBeVisible();
|
||||
await expect(
|
||||
page.getByText("Upcoming Tasks").locator("../.."),
|
||||
).toHaveText(/Follow up with Jane/);
|
||||
await expect(
|
||||
page.getByText("Follow up with Jane").locator(".."),
|
||||
).toHaveText(
|
||||
"Call Follow up with Janedue 4/11/2026, 9:00:00 PM (Re: Jane Smith)",
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user