import type { GitCommitInfo, SourceControlledFile } from '@n8n/api-types'; import type { Locator, Page } from '@playwright/test'; export interface PushResult { files: SourceControlledFile[]; commit: GitCommitInfo | null; } export class SourceControlPushModal { constructor(private readonly page: Page) {} get container() { return this.page.getByTestId('sourceControlPush-modal'); } getSubmitButton(): Locator { return this.container.getByTestId('source-control-push-modal-submit'); } async push(commitMessage: string): Promise { await this.container.getByTestId('source-control-push-modal-commit').fill(commitMessage); const responsePromise = this.page.waitForResponse( (response) => response.url().includes('/rest/source-control/push-workfolder') && response.status() === 200, ); await this.getSubmitButton().click(); const response = await responsePromise; const json = await response.json(); return json.data as PushResult; } // Tabs getWorkflowsTab(): Locator { return this.container.getByTestId('source-control-push-modal-tab-workflow'); } getCredentialsTab(): Locator { return this.container.getByTestId('source-control-push-modal-tab-credential'); } async selectWorkflowsTab(): Promise { await this.getWorkflowsTab().click(); } async selectCredentialsTab(): Promise { await this.getCredentialsTab().click(); } isWorkflowsTabSelected(): Promise { return this.getWorkflowsTab() .getAttribute('class') .then((classList) => classList?.includes('tabActive') ?? false); } // File items getFileInModal(fileName: string): Locator { return this.container.getByTestId('push-modal-item').filter({ hasText: fileName }).first(); } getFileCheckboxByName(fileName: string): Locator { return this.container .locator('[data-test-id="source-control-push-modal-file-checkbox"]') .filter({ has: this.container.getByText(fileName, { exact: true }) }); } async selectAllFilesInModal(): Promise { const toggleAll = this.container.getByTestId('source-control-push-modal-toggle-all'); const isChecked = await toggleAll.isChecked(); if (!isChecked) { await toggleAll.click(); } } getNotice(): Locator { return this.container.locator('#source-control-push-modal-notice.notice[role="alert"]'); } getStatusBadge(fileName: string, status: 'New' | 'Modified' | 'Deleted'): Locator { return this.getFileCheckboxByName(fileName).getByText(status); } async selectFile(fileName: string): Promise { const checkbox = this.getFileCheckboxByName(fileName); const isChecked = await checkbox.isChecked(); if (!isChecked) { await checkbox.click(); } } }