IKHSAN
EN Read in EnglishID

opendesk

Publik
Branch
main
Commit terakhir
08d9f3328 Oktober 2026

field-permissions.spec.ts

Buka raw
import type { Api } from "../../helpers/api";
import { expect, test } from "../../helpers/fixtures";
import { FormScripts } from "../../helpers/form-script";
import { snapshotSettings } from "../../helpers/settings";
import { openTicket } from "../../helpers/ticket";

test.describe("field permission notice", () => {
  const NOTICE = "show_ticket_field_permission_notice";
  let restoreSettings: () => Promise<unknown>;

  test.beforeEach(async ({ api }) => {
    restoreSettings = await snapshotSettings(api, [
      NOTICE,
      "show_customer_portal_permission_notice",
    ]);
    // the customer portal notice has its own Learn more button
    await api.update("OD Settings", "OD Settings", {
      [NOTICE]: 1,
      show_customer_portal_permission_notice: 0,
    });
  });

  test.afterEach(async () => {
    await restoreSettings();
  });

  test("a manager sees it until they dismiss it in any tab", async ({ api, pageAs }) => {
    const text = "Some fields are now hidden from customers";
    const otherTab = await pageAs("manager");
    await otherTab.goto("/opendesk/tickets");
    await expect(otherTab.getByText(text)).toBeVisible();
    const page = await pageAs("manager");
    await page.goto("/opendesk/tickets");
    const banner = page.getByText(text);
    await expect(banner).toBeVisible();

    await page.getByRole("button", { name: "Learn more" }).click();
    const dialog = page.getByRole("dialog", { name: "Ticket fields have changed" });
    await expect(dialog.getByRole("link", { name: "See how" })).toHaveAttribute(
      "href",
      /perm-levels-in-opendesk/
    );
    await dialog.getByRole("button", { name: "Got it" }).click();
    await expect(dialog).toHaveCount(0);
    await expect(banner).toHaveCount(0);
    expect((await api.get("OD Settings", "OD Settings"))[NOTICE]).toBe(0);
    await expect(otherTab.getByText(text)).toHaveCount(0);

    await page.reload();
    await page.waitForLoadState("networkidle");
    await expect(banner).toHaveCount(0);
  });

  test("agents and customers never see it", async ({ pageAs }) => {
    for (const [persona, url] of [
      ["agent", "/opendesk/tickets"],
      ["customer", "/help/my-tickets"],
    ] as const) {
      const page = await pageAs(persona);
      await page.goto(url);
      await page.waitForLoadState("networkidle");
      await expect(page.getByText("Ticket fields update")).toHaveCount(0);
    }
  });
});

test.describe("Default template rows", () => {
  let restoreTemplate: () => Promise<unknown>;

  test.afterEach(async () => {
    await restoreTemplate?.();
  });

  test("a row visible to Agents shows on the agent pages only", async ({
    api,
    pageAs,
    ticket,
  }) => {
    restoreTemplate = await setTemplateRows(api, [
      { fieldname: "priority", visible_to: "Everyone" },
      { fieldname: "ticket_type", visible_to: "Agents" },
    ]);
    await api.update("OD Ticket", ticket.name, { priority: "High", ticket_type: "Bug" });

    const customer = await pageAs("customer");
    await customer.goto("/help/my-tickets/new");
    await expect(customer.getByText("Priority", { exact: true })).toBeVisible();
    await expect(customer.getByText("Ticket Type", { exact: true })).toHaveCount(0);

    await customer.goto(`/help/my-tickets/${ticket.name}`);
    await expect(customer.getByText("High", { exact: true })).toBeVisible();
    await expect(customer.getByText("Bug", { exact: true })).toHaveCount(0);

    const agent = await pageAs("agent");
    await openTicket(agent, ticket.name);
    await expect(agent.getByRole("combobox", { name: "Set Ticket Type..." })).toHaveValue("Bug");
    await agent.goto("/opendesk/tickets/new");
    await expect(agent.getByText("Ticket Type", { exact: true })).toBeVisible();
  });

  test("a portal script changes only the fields editable after creation", async ({
    api,
    pageAs,
    ticket,
  }) => {
    restoreTemplate = await setTemplateRows(api, [
      { fieldname: "priority", visible_to: "Everyone", editable_after_creation: 1 },
      { fieldname: "ticket_type", visible_to: "Everyone", editable_after_creation: 0 },
    ]);
    await api.update("OD Ticket", ticket.name, { priority: "High", ticket_type: "Question" });
    const scripts = new FormScripts(api);
    await scripts.create(
      `return { actions: [
        { label: "E2E Set Priority", onClick: () => ctx.updateField("priority", "Low") },
        { label: "E2E Set Type", onClick: () => ctx.updateField("ticket_type", "Bug") },
      ] };`,
      { portal: true }
    );
    try {
      const page = await pageAs("customer");
      await page.goto(`/help/my-tickets/${ticket.name}`);
      await page.getByRole("button", { name: "E2E Set Priority" }).click();
      await expect.poll(async () => (await api.get("OD Ticket", ticket.name)).priority).toBe("Low");

      // Only the type's save: the priority save's response may still be in flight.
      const refused = page.waitForResponse(
        (r) =>
          r.url().endsWith("/api/method/frappe.client.set_value") &&
          (r.request().postData() || "").includes("ticket_type")
      );
      await page.getByRole("button", { name: "E2E Set Type" }).click();
      expect((await refused).status()).toBe(403);
      expect((await api.get("OD Ticket", ticket.name)).ticket_type).toBe("Question");
    } finally {
      await scripts.removeAll();
    }
  });
});

/** Replace the Default template's rows; returns a function that puts them back. */
async function setTemplateRows(api: Api, rows: Record<string, unknown>[]) {
  const { fields } = await api.get("OD Ticket Template", "Default");
  await api.update("OD Ticket Template", "Default", { fields: rows });
  return () => api.update("OD Ticket Template", "Default", { fields });
}
byte
5.754
baris
146
Jenis
ts
Commit terakhir
28 Oktober 2026