Ctrl K
ComunidadGuías…

e2e/helpers/list.ts

Rama develop · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { expect, type Page } from "@playwright/test";
import type { Api } from "./api";

/** The agent ticket list at /helpdesk/tickets. */
export class TicketList {
  constructor(private page: Page) {}

  async goto() {
    await this.page.goto("/helpdesk/tickets");
    await expect(this.page.getByRole("button", { name: "Filter", exact: true })).toBeVisible();
  }

  rows() {
    return this.page.locator("#list-rows a");
  }

  row(subject: string) {
    return this.rows().filter({ hasText: subject });
  }

  /** Narrow the list to this spec's tickets through the Subject quick filter. */
  async searchSubject(text: string) {
    const reloaded = this.page.waitForResponse(/get_list_data/);
    await this.page.getByRole("textbox", { name: "Subject" }).fill(text);
    await reloaded;
  }

  async select(...subjects: string[]) {
    for (const subject of subjects) {
      await this.row(subject).getByRole("checkbox").check();
    }
  }

  /** The floating bar that appears once rows are selected. */
  selectionBar() {
    return this.page
      .getByText(/\d+ rows? selected/)
      .locator("xpath=ancestor::div[contains(@class, 'shadow-2xl')]");
  }

  async selectionMenu(item: string) {
    await this.selectionBar().locator("[aria-haspopup=menu]").click();
    await this.page.getByRole("menuitem", { name: item }).click();
  }

  /** Save the current filters as a new view and return its HD View name. */
  async createView(api: Api, label: string) {
    await this.page.getByRole("button", { name: "List", exact: true }).click();
    await this.page.getByRole("menuitem", { name: "Create View" }).click();
    const dialog = this.page.getByRole("dialog", { name: "Create View" });
    await dialog.getByRole("textbox").first().fill(label);
    await dialog.getByRole("button", { name: "Create" }).click();
    await expect(this.page).toHaveURL(/\?view=/);
    await expect.poll(() => api.exists("HD View", { label })).toBeTruthy();
    return (await api.exists("HD View", { label }))!;
  }

  /** Run an action from a view's kebab menu in the breadcrumb dropdown. */
  async viewAction(label: string, action: string) {
    await this.page.getByRole("banner").locator("button[aria-haspopup=menu]").first().click();
    const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
    // standard views carry a "Standard" badge in their name
    const name = new RegExp(`^${escaped}( Standard)?$`);
    const item = this.page.getByRole("menuitem", { name });
    await item.hover();
    await item.getByRole("button").click();
    await this.page.getByRole("menuitem", { name: action }).click();
  }

  /** Clear every filter from the Filter popover, the way an agent resets the list. */
  async clearFilters() {
    await this.page.getByRole("button", { name: "Filter", exact: true }).click();
    await this.page.getByRole("dialog", { name: "Filter" }).getByRole("button", { name: "Clear all" }).click();
    await this.page.keyboard.press("Escape");
  }

  async addFilter(field: string, value: string) {
    await this.chooseFilterField(field);
    await this.page.getByRole("option", { name: value, exact: true }).click();
  }

  filterPopover() {
    return this.page.getByRole("dialog", { name: "Filter" });
  }

  /** Open the Filter popover and pick a field, leaving its value editor open. */
  async chooseFilterField(field: string) {
    await this.page.getByRole("button", { name: "Filter", exact: true }).click();
    const popover = this.filterPopover();
    await expect(popover).toBeVisible();
    const addFilter = popover.getByRole("button", { name: "Add filter" });
    if (await addFilter.isVisible()) await addFilter.click();
    await popover.getByRole("textbox").fill(field);
    await this.page.getByRole("option", { name: field, exact: true }).click();
  }

  async chooseFilterOperator(operator: string) {
    await this.filterPopover().locator("button[aria-haspopup]").click();
    await this.page.getByRole("menuitem", { name: operator, exact: true }).click();
  }
}

/** Drop the auto saved default view and any view a spec left behind. */
export async function resetDefaultTicketView(api: Api, user: string) {
  const views = await api.list("HD View", {
    filters: { user, dt: "HD Ticket", is_default: 1 },
  });
  views.push(...(await api.list("HD View", { filters: { label: ["like", "E2E view %"] } })));
  // the list may still be auto saving the default view, which locks it for a moment
  for (const view of views) {
    await expect(async () => {
      if (await api.exists("HD View", { name: view.name })) await api.delete("HD View", view.name);
    }).toPass();
  }
}