import type { Locator, Page } from '@playwright/test'; import { MessageBox } from './messageBoxLocators'; /** * Workflow menu on the editor header (`workflow-menu` trigger) plus the * teleported (Element Plus) dropdown items and confirmation surfaces it opens. * * Lives on the editor header, not inside `workflow-settings-dialog`. The * teleport-popper items render at the document root, so they're resolved * through the `Page` rather than scoped to a container. * * @example * // Inside a test * await n8n.workflowMenu.openSettings(); * await n8n.workflowMenu.clickArchive(); * await n8n.workflowMenu.confirmArchiveModal(); */ export class WorkflowMenu { constructor(private readonly page: Page) {} // Trigger getTrigger(): Locator { return this.page.getByTestId('workflow-menu'); } async open(): Promise { await this.getTrigger().click(); } // Menu items (teleported) getSettingsItem(): Locator { return this.page.getByTestId('workflow-menu-item-settings'); } getDuplicateItem(): Locator { return this.page.getByTestId('workflow-menu-item-duplicate'); } getDeleteItem(): Locator { return this.page.getByTestId('workflow-menu-item-delete'); } getArchiveItem(): Locator { return this.page.getByTestId('workflow-menu-item-archive'); } getArchiveItemWrapper(): Locator { return this.getArchiveItem(); } getUnarchiveItem(): Locator { return this.page.getByTestId('workflow-menu-item-unarchive'); } getPushToGitItem(): Locator { return this.page.getByTestId('workflow-menu-item-push'); } getUnpublishItem(): Locator { return this.page.getByTestId('workflow-menu-item-unpublish'); } // Open + click compound actions async openSettings(): Promise { await this.open(); await this.getSettingsItem().click(); } async openDuplicate(): Promise { await this.open(); await this.getDuplicateItem().click(); } async clickDelete(): Promise { await this.getDeleteItem().click(); } async clickArchive(): Promise { await this.getArchiveItem().click(); } async clickUnarchive(): Promise { await this.getUnarchiveItem().click(); } async clickUnpublish(): Promise { await this.getUnpublishItem().click(); } // Confirmation surfaces opened by the menu items getUnpublishModal(): Locator { return this.page.getByTestId('workflow-history-version-unpublish-modal'); } async confirmUnpublishModal(): Promise { await this.getUnpublishModal().getByRole('button', { name: 'Unpublish' }).click(); } async confirmDeleteModal(): Promise { await this.page.getByRole('button', { name: 'delete' }).click(); } async confirmArchiveModal(): Promise { await new MessageBox(this.page).confirmButton.click(); } // Duplicate modal (opened by openDuplicate) getDuplicateModal(): Locator { return this.page.getByTestId('duplicate-modal'); } getDuplicateNameInput(): Locator { return this.getDuplicateModal().locator('input').first(); } getDuplicateTagsInput(): Locator { return this.getDuplicateModal().locator('.el-select__tags input'); } getDuplicateSaveButton(): Locator { return this.getDuplicateModal().getByRole('button', { name: /duplicate|save/i }); } }