fix(editor): Reintroduce user deletion actions in the members table in Users and Project settings page (#19604)

This commit is contained in:
Csaba Tuncsik
2025-09-18 17:15:05 +02:00
committed by GitHub
parent f0b48733ac
commit bcedf5c76f
22 changed files with 483 additions and 191 deletions

View File

@@ -18,4 +18,21 @@ export abstract class BasePage {
protected async clickButtonByName(name: string) {
await this.page.getByRole('button', { name }).click();
}
protected async waitForRestResponse(
url: string | RegExp,
method?: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE',
) {
if (typeof url === 'string') {
return await this.page.waitForResponse((res) => {
const matches = res.url().includes(url);
return matches && (method ? res.request().method() === method : true);
});
}
return await this.page.waitForResponse((res) => {
const matches = url.test(res.url());
return matches && (method ? res.request().method() === method : true);
});
}
}

View File

@@ -15,7 +15,10 @@ export class ProjectSettingsPage extends BasePage {
}
async clickSaveButton() {
await this.clickButtonByName('Save');
await Promise.all([
this.waitForRestResponse(/\/rest\/projects\/[^/]+$/, 'PATCH'),
this.clickButtonByName('Save'),
]);
}
async clickCancelButton() {
@@ -76,4 +79,8 @@ export class ProjectSettingsPage extends BasePage {
const select = this.page.getByTestId('project-members-select');
await expect(select).toBeVisible();
}
async waitForProjectSettingsRestResponse() {
await this.waitForRestResponse(/\/rest\/projects\/[^/]+$/, 'GET');
}
}

View File

@@ -112,7 +112,7 @@ test.describe('Projects', () => {
// Navigate to project settings
await n8n.page.goto(`/projects/${projectId}/settings`);
await n8n.page.waitForLoadState('domcontentloaded');
await n8n.projectSettings.waitForProjectSettingsRestResponse();
// Verify basic project settings form elements are visible (inner controls)
await expect(n8n.projectSettings.getNameInput()).toBeVisible();
@@ -137,7 +137,7 @@ test.describe('Projects', () => {
// Navigate to project settings
await n8n.page.goto(`/projects/${projectId}/settings`);
await n8n.page.waitForLoadState('domcontentloaded');
await n8n.projectSettings.waitForProjectSettingsRestResponse();
// Update project name
const newName = 'Updated Project Name';
@@ -166,7 +166,7 @@ test.describe('Projects', () => {
// Navigate to project settings
await n8n.page.goto(`/projects/${projectId}/settings`);
await n8n.page.waitForLoadState('domcontentloaded');
await n8n.projectSettings.waitForProjectSettingsRestResponse();
const table = n8n.projectSettings.getMembersTable();
@@ -192,7 +192,7 @@ test.describe('Projects', () => {
// Navigate to project settings
await n8n.page.goto(`/projects/${projectId}/settings`);
await n8n.page.waitForLoadState('domcontentloaded');
await n8n.projectSettings.waitForProjectSettingsRestResponse();
// Current user (owner) should not have a role dropdown
const currentUserRow = n8n.page.locator('tbody tr').first();
@@ -208,7 +208,7 @@ test.describe('Projects', () => {
// Navigate to project settings
await n8n.page.goto(`/projects/${projectId}/settings`);
await n8n.page.waitForLoadState('domcontentloaded');
await n8n.projectSettings.waitForProjectSettingsRestResponse();
// Verify search input is visible
const searchInput = n8n.page.getByTestId('project-members-search');
@@ -232,7 +232,7 @@ test.describe('Projects', () => {
// Navigate to project settings
await n8n.page.goto(`/projects/${projectId}/settings`);
await n8n.page.waitForLoadState('domcontentloaded');
await n8n.projectSettings.waitForProjectSettingsRestResponse();
// Clear the project name (required field)
await n8n.projectSettings.fillProjectName('');
@@ -254,7 +254,7 @@ test.describe('Projects', () => {
// Navigate to project settings
await n8n.page.goto(`/projects/${projectId}/settings`);
await n8n.page.waitForLoadState('domcontentloaded');
await n8n.projectSettings.waitForProjectSettingsRestResponse();
// Initially, save and cancel buttons should be disabled (no changes)
await expect(n8n.page.getByTestId('project-settings-save-button')).toBeDisabled();
@@ -284,7 +284,7 @@ test.describe('Projects', () => {
// Navigate to project settings
await n8n.page.goto(`/projects/${projectId}/settings`);
await n8n.page.waitForLoadState('domcontentloaded');
await n8n.projectSettings.waitForProjectSettingsRestResponse();
// Scroll to bottom to see delete section
await n8n.page
@@ -308,7 +308,7 @@ test.describe('Projects', () => {
// Navigate to project settings
await n8n.page.goto(`/projects/${projectId}/settings`);
await n8n.page.waitForLoadState('domcontentloaded');
await n8n.projectSettings.waitForProjectSettingsRestResponse();
// Update project details
const projectName = 'Persisted Project Name';
@@ -325,7 +325,7 @@ test.describe('Projects', () => {
// Reload the page
await n8n.page.reload();
await n8n.page.waitForLoadState('domcontentloaded');
await n8n.projectSettings.waitForProjectSettingsRestResponse();
// Verify data persisted
await n8n.projectSettings.expectProjectNameValue(projectName);