1import { expect, type Page } from "@playwright/test";
2import type { Api } from "./api";
3
4/** Open the agent ticket view and wait for the feed to render. */
5export async function openTicket(page: Page, name: string, hash = "") {
6 await page.goto(`/opendesk/tickets/${name}${hash}`);
7 await expect(page.getByRole("tab", { name: "Activity" })).toBeVisible();
8}
9
10/** The composer's editor; the last one on the page is the open reply or comment box. */
11export function composer(page: Page) {
12 return page.locator(".ProseMirror[contenteditable=true]").last();
13}
14
15/** Post a comment through the composer and wait for the server to store it. */
16export async function postComment(page: Page, text: string) {
17 await page.getByRole("button", { name: "Comment", exact: true }).click();
18 await composer(page).click();
19 await composer(page).pressSequentially(text);
20 const saved = page.waitForResponse(
21 (r) =>
22 r.url().endsWith("/api/method/run_doc_method") &&
23 (r.request().postData() || "").includes("new_comment")
24 );
25 await page.getByRole("button", { name: /^Comment \(/ }).click();
26 await saved;
27}
28
29/** Record the POST bodies of every call to one whitelisted method. */
30export function recordCalls(page: Page, method: string) {
31 const bodies: string[] = [];
32 page.on("request", (request) => {
33 if (request.url().endsWith(`/api/method/${method}`)) {
34 bodies.push(request.postData() || "");
35 }
36 });
37 return bodies;
38}
39
40/** Run a whitelisted OD Ticket method as whoever `api` is logged in as. */
41export function runTicketMethod(api: Api, ticket: string, method: string, args: object) {
42 return api.call("run_doc_method", { dt: "OD Ticket", dn: ticket, method, args });
43}
44
45/** Comment on a ticket as the agent `api` is logged in as; returns the Comment name. */
46export function addComment(api: Api, ticket: string, content: string) {
47 return runTicketMethod(api, ticket, "new_comment", { content: `<p>${content}</p>` });
48}
49
50/** Flip an OD Settings field and hand back a function that restores it. */
51export async function setOpendeskSetting(api: Api, field: string, value: unknown) {
52 const before = (await api.get("OD Settings", "OD Settings"))[field];
53 await api.update("OD Settings", "OD Settings", { [field]: value });
54 return () => api.update("OD Settings", "OD Settings", { [field]: before });
55}
56
57/** A team with members, so its assignment rule has someone to pick. */
58export async function createTeam(api: Api, name: string, users: string[]) {
59 return api.insert("OD Team", {
60 team_name: name,
61 users: users.map((user) => ({ user })),
62 });
63}
64
65export function comments(api: Api, ticket: string) {
66 return api.list("Comment", {
67 fields: ["name", "content", "comment_email", "owner"],
68 filters: { reference_doctype: "OD Ticket", reference_name: ticket, comment_type: "Comment" },
69 });
70}
71