import type { Page, Route } from "@playwright/test"; import type { Api } from "../../../helpers/api"; import { ensureTemplate } from "../../../helpers/form-script"; import { expect, test, uid, usePersona } from "../../../helpers/fixtures"; import { personas } from "../../../helpers/personas"; const PIXEL = "e2e/fixtures/pixel.png"; const DEFAULTED_FIELDS = [ { fieldname: "e2e_frozen", read_only: 1 }, { fieldname: "e2e_answer", read_only: 0 }, ].map((field) => ({ ...field, fieldtype: "Select", options: "No\nYes", default: "No" })); usePersona("customer"); test.describe("raising a ticket", () => { test("with a custom field and an inline image", async ({ page, api }) => { const template = await api.get("OD Ticket Template", "Default"); await api.update("OD Ticket Template", "Default", { fields: [{ fieldname: "ticket_type", required: 0, visible_to: "Everyone" }], }); try { const subject = `E2E portal ${uid()}`; await page.goto("/help/my-tickets/new"); await page.getByRole("combobox", { name: "Ticket Type" }).click(); await page.getByRole("option", { name: "Question" }).click(); await page.getByPlaceholder("A short description").fill(subject); await page.locator(".ProseMirror").fill("Screenshot of the error"); await attachImage(page); await page.getByRole("button", { name: "Create ticket" }).click(); await expect(page).toHaveURL(/\/help\/my-tickets\/\d+$/); const [ticket] = await api.list("OD Ticket", { filters: { subject }, fields: ["description", "ticket_type", "raised_by"], }); expect(ticket.description).toContain(" { await page.goto("/help/my-tickets/new"); await page.getByPlaceholder("A short description").fill(`E2E image only ${uid()}`); await attachImage(page); await expect(page.getByRole("button", { name: "Create ticket" })).toBeEnabled(); }); test("keeps Create ticket disabled while an image is uploading", async ({ page }) => { let release: () => void = () => {}; const held = new Promise((resolve) => (release = resolve)); await page.route("**/api/method/upload_file", async (route: Route) => { await held; await route.continue(); }); await page.goto("/help/my-tickets/new"); await page.getByPlaceholder("A short description").fill(`E2E upload ${uid()}`); await page.locator(".ProseMirror").fill("See the screenshot"); const submit = page.getByRole("button", { name: "Create ticket" }); await expect(submit).toBeEnabled(); await chooseImage(page); await expect(submit).toBeDisabled(); release(); await expect(uploadedImage(page)).toBeVisible(); await expect(submit).toBeEnabled(); }); }); test.describe("the form", () => { test("a read-only field is disabled and untouched fields keep their defaults", async ({ page, api, }) => { await ensureDefaultedFields(api); const restore = await useTemplate(api, DEFAULTED_FIELDS); try { await page.goto("/help/my-tickets/new"); await expect(page.getByRole("combobox", { name: /^E2E frozen/ })).toBeDisabled(); await expect(page.getByRole("combobox", { name: /^E2E answer/ })).toBeEnabled(); const subject = await fillBasics(page); await page.getByRole("button", { name: "Create ticket" }).click(); await expect(page).toHaveURL(/\/help\/my-tickets\/\d+$/); const [ticket] = await api.list("OD Ticket", { filters: { subject }, fields: ["e2e_frozen", "e2e_answer"], }); expect(ticket).toEqual({ e2e_frozen: "No", e2e_answer: "No" }); } finally { await restore(); } }); test("about links open in a new tab", async ({ page, api }) => { const restore = await useTemplate(api, [], { about: '

Register your site

', }); try { await page.goto("/help/my-tickets/new"); const link = page.getByRole("link", { name: "Register your site" }); await expect(link).toHaveAttribute("target", "_blank"); await expect(link).toHaveAttribute("rel", "noopener noreferrer"); } finally { await restore(); } }); test("says what is still required on submit and ignores a blank subject", async ({ page }) => { let creates = 0; page.on("request", (request) => request.url().includes("od_ticket.api.new") && creates++); await page.goto("/help/my-tickets/new"); const hint = page.getByRole("alert").filter({ hasText: /^Required:/ }); const submit = page.getByRole("button", { name: "Create ticket" }); await expect(hint).toBeHidden(); await expect(submit).toBeEnabled(); await submit.click(); await expect(hint).toHaveText("Required: Subject, Description"); await page.getByPlaceholder("A short description").fill(" "); await page.locator(".ProseMirror").fill("Details"); await expect(hint).toHaveText("Required: Subject"); await submit.click(); expect(creates).toBe(0); await page.getByPlaceholder("A short description").fill(`E2E ${uid()}`); await expect(hint).toBeHidden(); }); test("a url_method field asks to select an option", async ({ page, api }) => { await ensureTemplate(api); const restore = await useTemplate(api, [ { fieldname: "e2e_needed", url_method: "opendesk.e2e_options" }, ]); await page.route("**/api/method/opendesk.e2e_options*", (route) => route.fulfill({ json: { message: ["Red"] } }) ); try { await page.goto("/help/my-tickets/new"); const picker = page.locator('[data-fieldname="e2e_needed"] button').first(); await expect(picker).toContainText("Select an option"); } finally { await restore(); } }); test("creating a ticket confirms with a toast", async ({ page }) => { await page.goto("/help/my-tickets/new"); await fillBasics(page); await page.getByRole("button", { name: "Create ticket" }).click(); await expect(page.getByText("Ticket created")).toBeVisible(); }); test("the editor does not offer Embed", async ({ page }) => { await page.goto("/help/my-tickets/new"); await expect(page.getByRole("button", { name: "Image", exact: true })).toBeVisible(); await expect(page.getByRole("button", { name: "Embed" })).toHaveCount(0); }); }); async function ensureDefaultedFields(api: Api) { for (const field of DEFAULTED_FIELDS) { if (await api.exists("Custom Field", { name: `OD Ticket-${field.fieldname}` })) continue; await api.insert("Custom Field", { dt: "OD Ticket", label: field.fieldname.replace("e2e_", "E2E "), insert_after: "description", ...field, }); } } async function useTemplate(api: Api, rows: Record[], extra: Record = {}) { const before = await api.get("OD Ticket Template", "Default"); await api.update("OD Ticket Template", "Default", { fields: rows.map(({ fieldname, url_method }) => ({ fieldname, url_method, visible_to: "Everyone", required: 0, })), ...extra, }); return () => api.update("OD Ticket Template", "Default", { fields: before.fields, about: before.about || "", }); } async function fillBasics(page: Page) { const subject = `E2E form ${uid()}`; await page.getByPlaceholder("A short description").fill(subject); await page.locator(".ProseMirror").fill("Details"); return subject; } async function chooseImage(page: Page) { const chooser = page.waitForEvent("filechooser"); await page.getByRole("button", { name: "Image", exact: true }).click(); await (await chooser).setFiles(PIXEL); } async function attachImage(page: Page) { await chooseImage(page); await expect(uploadedImage(page)).toBeVisible(); } function uploadedImage(page: Page) { return page.locator('.ProseMirror img[src*="/files/"]'); }