chore: Adopt ActionToggle component across page objects (#32933)

Co-authored-by: n8n-cat-bot[bot] <n8n-cat-bot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
n8n-cat-bot[bot]
2026-06-25 08:10:22 +00:00
committed by GitHub
parent d7460db4f1
commit 37bc8230d8
8 changed files with 37 additions and 31 deletions
@@ -1,7 +1,7 @@
{
"version": 1,
"generated": "2026-06-23T20:38:55.035Z",
"totalViolations": 141,
"generated": "2026-06-24T10:26:20.816Z",
"totalViolations": 139,
"violations": {
"pages/AIAssistantPage.ts": [
{
@@ -76,13 +76,7 @@
"pages/NodeDetailsViewPage.ts": [
{
"rule": "scope-lockdown",
"line": 350,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 430,
"line": 352,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
}
@@ -865,12 +859,6 @@
"line": 38,
"message": "Duplicate locator: this.page.getByTestId(\"project-name\") in pages scope",
"hash": "206b89bd1594"
},
{
"rule": "deduplication",
"line": 52,
"message": "Duplicate locator: this.page.getByTestId(\"action-delete\") in pages scope",
"hash": "2f37cf533810"
}
],
"pages/WorkerViewPage.ts": [
@@ -1,8 +1,11 @@
import type { Locator } from '@playwright/test';
import { BasePage } from './BasePage';
import { ActionToggle } from './components/ActionToggle';
export class CommunityNodesPage extends BasePage {
readonly actionToggle = new ActionToggle(this.page);
async goto(): Promise<void> {
await this.page.goto('/settings/community-nodes');
}
@@ -49,7 +52,7 @@ export class CommunityNodesPage extends BasePage {
}
getUninstallAction(): Locator {
return this.page.getByTestId('action-uninstall');
return this.actionToggle.getAction('uninstall');
}
getUpdateButton(): Locator {
@@ -4,6 +4,7 @@ import { expect } from '@playwright/test';
import { BasePage } from './BasePage';
import { ClipboardHelper } from '../helpers/ClipboardHelper';
import { NodeParameterHelper } from '../helpers/NodeParameterHelper';
import { ActionToggle } from './components/ActionToggle';
import { CodeNodeEditor } from './components/CodeNodeEditor';
import { dialogCloseIconIn, dialogRootIn } from './components/dialogLocators';
import { InlineExpressionEditor } from './components/InlineExpressionEditor';
@@ -25,6 +26,7 @@ export class NodeDetailsViewPage extends BasePage {
readonly resourceLocator = new ResourceLocator(this.container);
readonly codeNodeEditor = new CodeNodeEditor(this.container);
readonly nodeCreator = new NodeCreator(this.page);
readonly actionToggle = new ActionToggle(this.page);
constructor(page: Page) {
super(page);
@@ -427,15 +429,15 @@ export class NodeDetailsViewPage extends BasePage {
}
getResourceMapperRemoveAllFieldsOption() {
return this.page.getByTestId('action-removeAllFields');
return this.actionToggle.getAction('removeAllFields');
}
async refreshResourceMapperColumns() {
const selectColumn = this.getResourceMapperSelectColumn();
await selectColumn.hover();
await selectColumn.getByTestId('action-toggle').getByRole('button').click();
await expect(this.getVisiblePopper().getByTestId('action-refreshFieldList')).toBeVisible();
await this.getVisiblePopper().getByTestId('action-refreshFieldList').click();
await this.actionToggle.open(selectColumn);
await expect(this.actionToggle.getAction('refreshFieldList')).toBeVisible();
await this.actionToggle.getAction('refreshFieldList').click();
}
getAddValueButton() {
@@ -136,11 +136,7 @@ export class SettingsLogStreamingPage extends BasePage {
}
async clickDestinationCardDropdown(index: number): Promise<void> {
await this.getDestinationCards()
.nth(index)
.getByTestId('action-toggle')
.getByRole('button')
.click();
await this.actionToggle.open(this.getDestinationCards().nth(index));
}
async clickDropdownMenuItem(index: number): Promise<void> {
@@ -1,8 +1,11 @@
import type { Locator } from '@playwright/test';
import { BasePage } from './BasePage';
import { ActionToggle } from './components/ActionToggle';
export class SettingsUsersPage extends BasePage {
readonly actionToggle = new ActionToggle(this.page);
async goto(): Promise<void> {
await this.page.goto('/settings/users');
}
@@ -77,11 +80,11 @@ export class SettingsUsersPage extends BasePage {
}
async openActions(email: string) {
await this.getRow(email).getByTestId('action-toggle').getByRole('button').click();
await this.actionToggle.open(this.getRow(email));
}
async clickDeleteUser(email: string) {
await this.openActions(email);
await this.page.getByTestId('action-delete').filter({ visible: true }).click();
await this.actionToggle.getAction('delete').filter({ visible: true }).click();
}
}
@@ -49,7 +49,7 @@ export class WorkflowsPage extends BasePage {
async deleteWorkflow(workflowItem: Locator) {
await this.openWorkflowCardActions(workflowItem);
await this.page.getByTestId('action-delete').click();
await this.actionToggle.getAction('delete').click();
await this.page.getByRole('button', { name: 'delete' }).click();
}
@@ -13,6 +13,14 @@ export class ActionToggle {
return this.page.getByTestId('action-toggle-dropdown');
}
/**
* Opens the action toggle nested inside the given row/resource trigger
* (the card, table row, or cell that hosts the `action-toggle` button).
*/
async open(trigger: Locator): Promise<void> {
await trigger.getByTestId('action-toggle').getByRole('button').click();
}
/** Action item scoped inside the toggle, e.g. `action-delete`. */
getAction(name: string): Locator {
return this.root.getByTestId(`action-${name}`);
@@ -1,5 +1,7 @@
import type { Locator, Page } from '@playwright/test';
import { ActionToggle } from './ActionToggle';
/**
* AddResource component for creating workflows, credentials, folders, and data tables.
* Represents the "add resource" functionality in the project header.
@@ -12,7 +14,11 @@ import type { Locator, Page } from '@playwright/test';
* await n8n.workflows.addResource.dataTable();
*/
export class AddResource {
constructor(private page: Page) {}
private readonly actionToggle: ActionToggle;
constructor(private page: Page) {
this.actionToggle = new ActionToggle(this.page);
}
getWorkflowButton(): Locator {
return this.page.getByTestId('add-resource-workflow');
@@ -28,7 +34,7 @@ export class AddResource {
async folder(): Promise<void> {
await this.page.getByTestId('add-resource').click();
await this.page.getByTestId('action-folder').click();
await this.actionToggle.getAction('folder').click();
}
async dataTable(fromDataTableTab: boolean = true): Promise<void> {
@@ -36,7 +42,7 @@ export class AddResource {
await this.page.getByTestId('add-resource-dataTable').click();
} else {
await this.page.getByTestId('add-resource').click();
await this.page.getByTestId('action-dataTable').click();
await this.actionToggle.getAction('dataTable').click();
}
}
}