test: Clean up dead code and selector-purity violations (no-changelog) (#30308)

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Declan Carroll 2026-05-13 07:54:20 +01:00 committed by GitHub
parent 94dbc3e54b
commit b41d8aab81
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 52 additions and 116 deletions

View File

@ -1,7 +1,7 @@
{
"version": 1,
"generated": "2026-05-12T08:06:17.170Z",
"totalViolations": 416,
"generated": "2026-05-12T11:24:54.376Z",
"totalViolations": 410,
"violations": {
"pages/AIAssistantPage.ts": [
{
@ -82,13 +82,7 @@
},
{
"rule": "scope-lockdown",
"line": 274,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 323,
"line": 278,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
@ -106,7 +100,7 @@
},
{
"rule": "scope-lockdown",
"line": 351,
"line": 335,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
@ -136,31 +130,25 @@
},
{
"rule": "scope-lockdown",
"line": 373,
"line": 371,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 399,
"line": 377,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 435,
"line": 403,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 463,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 467,
"line": 439,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
@ -176,6 +164,12 @@
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 471,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 475,
@ -184,7 +178,7 @@
},
{
"rule": "scope-lockdown",
"line": 493,
"line": 479,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
@ -196,49 +190,43 @@
},
{
"rule": "scope-lockdown",
"line": 497,
"line": 501,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 508,
"line": 501,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 517,
"line": 512,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 579,
"line": 521,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 624,
"line": 583,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 630,
"line": 628,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 654,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 654,
"line": 634,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
@ -250,19 +238,25 @@
},
{
"rule": "scope-lockdown",
"line": 765,
"line": 658,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 810,
"line": 662,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 864,
"line": 769,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 814,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
@ -274,13 +268,19 @@
},
{
"rule": "scope-lockdown",
"line": 877,
"line": 872,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 883,
"line": 885,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
},
{
"rule": "scope-lockdown",
"line": 891,
"message": "NodeDetailsViewPage: Unscoped locator - use this.container instead of this.page",
"hash": "4087a9cf20cb"
}
@ -1547,20 +1547,6 @@
"hash": "e286b40da00e"
}
],
"tests/e2e/workflows/editor/expressions/transformation.spec.ts": [
{
"rule": "selector-purity",
"line": 114,
"message": "Chained locator call in test: n8n.ndv.getOutputDataContainer().locator('[class*=value_]')",
"hash": "5ce9a307e353"
},
{
"rule": "selector-purity",
"line": 134,
"message": "Chained locator call in test: n8n.ndv.getOutputDataContainer().locator('[class*=value_]')",
"hash": "5ce9a307e353"
}
],
"tests/e2e/workflows/editor/ndv/io-filter.spec.ts": [
{
"rule": "selector-purity",
@ -1853,14 +1839,6 @@
"hash": "6ccf615ddb0b"
}
],
"tests/e2e/workflows/editor/subworkflows/workflow-selector.spec.ts": [
{
"rule": "selector-purity",
"line": 92,
"message": "Chained locator call in test: addResourceItem.getByText(/Create a/)",
"hash": "46294c103c93"
}
],
"tests/e2e/workflows/editor/tags.spec.ts": [
{
"rule": "selector-purity",
@ -2471,26 +2449,6 @@
"hash": "0acea681877b"
}
],
"utils/benchmark/instance-ai-driver.ts": [
{
"rule": "dead-code",
"line": 263,
"message": "Unused method: InstanceAiDriver.deleteAllThreads()",
"hash": "84fa4accc8fa"
},
{
"rule": "dead-code",
"line": 302,
"message": "Unused method: InstanceAiDriver.measureHeap()",
"hash": "40ed597f87ba"
},
{
"rule": "dead-code",
"line": 307,
"message": "Unused method: InstanceAiDriver.snapshot()",
"hash": "70bd4d633512"
}
],
"pages/ChatHubSettingsPage.ts": [
{
"rule": "deduplication",

View File

@ -143,6 +143,10 @@ export class NodeDetailsViewPage extends BasePage {
return this.getOutputPanel().getByTestId('ndv-data-container');
}
getOutputDataValues() {
return this.getOutputDataContainer().locator('[class*=value_]');
}
async setPinnedData(data: object | string) {
const pinnedData = typeof data === 'string' ? data : JSON.stringify(data);
await this.getEditPinnedDataButton().click();
@ -868,6 +872,10 @@ export class NodeDetailsViewPage extends BasePage {
return this.page.getByTestId('rlc-item-add-resource');
}
getAddResourceCreateOption() {
return this.getAddResourceItem().getByText(/Create a/);
}
getExpressionModeToggle(index: number = 1) {
return this.container.getByTestId('radio-button-expression').nth(index);
}

View File

@ -111,7 +111,7 @@ test.describe(
await expect(n8n.ndv.getInlineExpressionEditorOutput()).toContainText(output);
await n8n.ndv.execute();
const valueElements = n8n.ndv.getOutputDataContainer().locator('[class*=value_]');
const valueElements = n8n.ndv.getOutputDataValues();
await expect(valueElements).toBeVisible();
await expect(valueElements).toContainText(output);
});
@ -131,7 +131,7 @@ test.describe(
await expect(n8n.ndv.getInlineExpressionEditorOutput()).toContainText(output);
await n8n.ndv.execute();
const valueElements = n8n.ndv.getOutputDataContainer().locator('[class*=value_]');
const valueElements = n8n.ndv.getOutputDataValues();
await expect(valueElements).toBeVisible();
await expect(valueElements).toContainText(output);
});

View File

@ -89,7 +89,7 @@ test.describe(
const addResourceItem = n8n.ndv.getAddResourceItem();
await expect(addResourceItem).toHaveCount(1);
await expect(addResourceItem.getByText(/Create a/)).toBeVisible();
await expect(n8n.ndv.getAddResourceCreateOption()).toBeVisible();
const secondPage = await n8n.start.fromNewPage(async () => {
await n8n.ndvComposer.createNewSubworkflow('workflowId');

View File

@ -17,11 +17,10 @@ export const instanceAiTestConfig = {
} as const;
export const test = base.extend<InstanceAiMemoryFixtures>({
instanceAiDriver: async ({ n8n, backendUrl, services }, use) => {
instanceAiDriver: async ({ n8n, backendUrl }, use) => {
const config: InstanceAiDriverConfig = {
n8n,
baseUrl: backendUrl,
metrics: services.observability.metrics,
};
const driver = new InstanceAiDriver(config);

View File

@ -1,14 +1,7 @@
import type { Page, TestInfo } from '@playwright/test';
import type { MetricsHelper } from 'n8n-containers';
import type { Page } from '@playwright/test';
import { InstanceAiPage } from '../../pages/InstanceAiPage';
import type { n8nPage } from '../../pages/n8nPage';
import {
getStableHeap,
takeHeapSnapshot,
type StableHeapOptions,
type StableHeapResult,
} from '../performance-helper';
/** Lightweight prompt for warmup — exercises the instance-ai path without building a workflow. */
export const WARMUP_PROMPT = 'List my current credentials.';
@ -42,8 +35,6 @@ export interface InstanceAiDriverConfig {
n8n: n8nPage;
/** Backend base URL for REST API calls (GC, snapshots, thread management) */
baseUrl: string;
/** VictoriaMetrics helper for heap queries */
metrics: MetricsHelper;
}
export interface RunParallelOptions {
@ -74,14 +65,12 @@ export interface TabRunResult {
export class InstanceAiDriver {
private readonly n8n: n8nPage;
private readonly baseUrl: string;
private readonly metrics: MetricsHelper;
private createdThreadIds: string[] = [];
private openedPages: Page[] = [];
constructor(config: InstanceAiDriverConfig) {
this.n8n = config.n8n;
this.baseUrl = config.baseUrl;
this.metrics = config.metrics;
}
/**
@ -259,14 +248,6 @@ export class InstanceAiDriver {
this.createdThreadIds = this.createdThreadIds.filter((id) => id !== threadId);
}
/** Delete all threads created by this driver instance. */
async deleteAllThreads(): Promise<void> {
const threadIds = [...this.createdThreadIds];
for (const threadId of threadIds) {
await this.deleteThread(threadId);
}
}
/** Delete all workflows via the REST API to prevent cross-round interference. */
async deleteAllWorkflows(): Promise<void> {
const cookies = await this.n8n.page.context().cookies();
@ -298,16 +279,6 @@ export class InstanceAiDriver {
await this.deleteAllWorkflows();
}
/** Take a stable server-side heap measurement (triggers GC + polls VictoriaMetrics). */
async measureHeap(options?: StableHeapOptions): Promise<StableHeapResult> {
return await getStableHeap(this.baseUrl, this.metrics, options);
}
/** Trigger a V8 heap snapshot on the server. */
async snapshot(testInfo: TestInfo, label: string): Promise<void> {
await takeHeapSnapshot(this.baseUrl, testInfo, label);
}
private extractThreadId(page: Page): string {
const url = new URL(page.url());
const match = url.pathname.match(/\/instance-ai\/([0-9a-f-]+)/);