mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
test: Migrate NPS from Cypress -> Playwright (#18535)
This commit is contained in:
@@ -1,149 +0,0 @@
|
|||||||
import { INSTANCE_ADMIN } from '../constants';
|
|
||||||
import { clearNotifications } from '../pages/notifications';
|
|
||||||
import {
|
|
||||||
getNpsSurvey,
|
|
||||||
getNpsSurveyClose,
|
|
||||||
getNpsSurveyFeedback,
|
|
||||||
getNpsSurveyRatings,
|
|
||||||
getNpsSurveySubmit,
|
|
||||||
} from '../pages/npsSurvey';
|
|
||||||
import { WorkflowPage } from '../pages/workflow';
|
|
||||||
|
|
||||||
const workflowPage = new WorkflowPage();
|
|
||||||
|
|
||||||
const NOW = Date.now();
|
|
||||||
const ONE_DAY = 24 * 60 * 60 * 1000;
|
|
||||||
const THREE_DAYS = ONE_DAY * 3;
|
|
||||||
const SEVEN_DAYS = ONE_DAY * 7;
|
|
||||||
const ABOUT_SIX_MONTHS = ONE_DAY * 30 * 6 + ONE_DAY;
|
|
||||||
|
|
||||||
// eslint-disable-next-line n8n-local-rules/no-skipped-tests
|
|
||||||
describe.skip('NpsSurvey', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.resetDatabase();
|
|
||||||
cy.signin(INSTANCE_ADMIN);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows nps survey to recently activated user and can submit feedback ', () => {
|
|
||||||
cy.intercept('/rest/settings', { middleware: true }, (req) => {
|
|
||||||
req.on('response', (res) => {
|
|
||||||
if (res.body.data) {
|
|
||||||
res.body.data.telemetry = {
|
|
||||||
enabled: true,
|
|
||||||
config: {
|
|
||||||
key: 'test',
|
|
||||||
url: 'https://telemetry-test.n8n.io',
|
|
||||||
proxy: 'http://localhost:5678/rest/telemetry/proxy',
|
|
||||||
sourceConfig: 'http://localhost:5678/rest/telemetry/rudderstack',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
cy.intercept('/rest/login', { middleware: true }, (req) => {
|
|
||||||
req.on('response', (res) => {
|
|
||||||
if (res.body.data) {
|
|
||||||
res.body.data.settings = res.body.data.settings || {};
|
|
||||||
res.body.data.settings.userActivated = true;
|
|
||||||
res.body.data.settings.userActivatedAt = NOW - THREE_DAYS - 1000;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
workflowPage.actions.visit(true, NOW);
|
|
||||||
|
|
||||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
|
||||||
getNpsSurvey().should('be.visible');
|
|
||||||
getNpsSurveyRatings().find('button').should('have.length', 11);
|
|
||||||
getNpsSurveyRatings().find('button').first().click();
|
|
||||||
|
|
||||||
getNpsSurveyFeedback().find('textarea').type('n8n is the best');
|
|
||||||
getNpsSurveySubmit().find('button').click();
|
|
||||||
|
|
||||||
// test that modal does not show up again until 6 months later
|
|
||||||
workflowPage.actions.visit(true, NOW + ONE_DAY);
|
|
||||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
|
||||||
getNpsSurvey().should('not.be.visible');
|
|
||||||
|
|
||||||
// 6 months later
|
|
||||||
workflowPage.actions.visit(true, NOW + ABOUT_SIX_MONTHS);
|
|
||||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
|
||||||
getNpsSurvey().should('be.visible');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('allows user to ignore survey 3 times before stopping to show until 6 months later', () => {
|
|
||||||
cy.intercept('/rest/settings', { middleware: true }, (req) => {
|
|
||||||
req.on('response', (res) => {
|
|
||||||
if (res.body.data) {
|
|
||||||
res.body.data.telemetry = {
|
|
||||||
enabled: true,
|
|
||||||
config: {
|
|
||||||
key: 'test',
|
|
||||||
url: 'https://telemetry-test.n8n.io',
|
|
||||||
proxy: 'http://localhost:5678/rest/telemetry/proxy',
|
|
||||||
sourceConfig: 'http://localhost:5678/rest/telemetry/rudderstack',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
cy.intercept('/rest/login', { middleware: true }, (req) => {
|
|
||||||
req.on('response', (res) => {
|
|
||||||
if (res.body.data) {
|
|
||||||
res.body.data.settings = res.body.data.settings || {};
|
|
||||||
res.body.data.settings.userActivated = true;
|
|
||||||
res.body.data.settings.userActivatedAt = NOW - THREE_DAYS - 1000;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// can ignore survey and it won't show up again
|
|
||||||
workflowPage.actions.visit(true, NOW);
|
|
||||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
|
||||||
clearNotifications();
|
|
||||||
|
|
||||||
getNpsSurvey().should('be.visible');
|
|
||||||
getNpsSurveyClose().click();
|
|
||||||
getNpsSurvey().should('not.be.visible');
|
|
||||||
|
|
||||||
workflowPage.actions.visit(true, NOW + ONE_DAY);
|
|
||||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
|
||||||
getNpsSurvey().should('not.be.visible');
|
|
||||||
|
|
||||||
// shows up seven days later to ignore again
|
|
||||||
workflowPage.actions.visit(true, NOW + SEVEN_DAYS + 10000);
|
|
||||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
|
||||||
clearNotifications();
|
|
||||||
getNpsSurvey().should('be.visible');
|
|
||||||
getNpsSurveyClose().click();
|
|
||||||
getNpsSurvey().should('not.be.visible');
|
|
||||||
|
|
||||||
workflowPage.actions.visit(true, NOW + SEVEN_DAYS + 10000);
|
|
||||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
|
||||||
getNpsSurvey().should('not.be.visible');
|
|
||||||
|
|
||||||
// shows up after at least seven days later to ignore again
|
|
||||||
workflowPage.actions.visit(true, NOW + (SEVEN_DAYS + 10000) * 2 + ONE_DAY);
|
|
||||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
|
||||||
clearNotifications();
|
|
||||||
getNpsSurvey().should('be.visible');
|
|
||||||
getNpsSurveyClose().click();
|
|
||||||
getNpsSurvey().should('not.be.visible');
|
|
||||||
|
|
||||||
workflowPage.actions.visit(true, NOW + (SEVEN_DAYS + 10000) * 2 + ONE_DAY * 2);
|
|
||||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
|
||||||
getNpsSurvey().should('not.be.visible');
|
|
||||||
|
|
||||||
// does not show up again after at least 7 days
|
|
||||||
workflowPage.actions.visit(true, NOW + (SEVEN_DAYS + 10000) * 3 + ONE_DAY * 3);
|
|
||||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
|
||||||
getNpsSurvey().should('not.be.visible');
|
|
||||||
|
|
||||||
// shows up 6 months later
|
|
||||||
workflowPage.actions.visit(true, NOW + (SEVEN_DAYS + 10000) * 3 + ABOUT_SIX_MONTHS);
|
|
||||||
workflowPage.actions.saveWorkflowOnButtonClick();
|
|
||||||
getNpsSurvey().should('be.visible');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -423,4 +423,15 @@ export class CanvasPage extends BasePage {
|
|||||||
await this.canvasPane().focus();
|
await this.canvasPane().focus();
|
||||||
await this.page.keyboard.press(keyMap[direction]);
|
await this.page.keyboard.press(keyMap[direction]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visit the workflow page with a specific timestamp for NPS survey testing.
|
||||||
|
* Uses Playwright's clock API to set a fixed time.
|
||||||
|
*/
|
||||||
|
async visitWithTimestamp(timestamp: number): Promise<void> {
|
||||||
|
// Set fixed time using Playwright's clock API
|
||||||
|
await this.page.clock.setFixedTime(timestamp);
|
||||||
|
|
||||||
|
await this.page.goto('/workflow/new');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
57
packages/testing/playwright/pages/NpsSurveyPage.ts
Normal file
57
packages/testing/playwright/pages/NpsSurveyPage.ts
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import type { Locator, Page } from '@playwright/test';
|
||||||
|
|
||||||
|
import { BasePage } from './BasePage';
|
||||||
|
|
||||||
|
export class NpsSurveyPage extends BasePage {
|
||||||
|
constructor(page: Page) {
|
||||||
|
super(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
getNpsSurveyModal(): Locator {
|
||||||
|
return this.page.getByTestId('nps-survey-modal');
|
||||||
|
}
|
||||||
|
|
||||||
|
getNpsSurveyRatings(): Locator {
|
||||||
|
return this.page.getByTestId('nps-survey-ratings');
|
||||||
|
}
|
||||||
|
|
||||||
|
getNpsSurveyFeedback(): Locator {
|
||||||
|
return this.page.getByTestId('nps-survey-feedback');
|
||||||
|
}
|
||||||
|
|
||||||
|
getNpsSurveySubmitButton(): Locator {
|
||||||
|
return this.page.getByTestId('nps-survey-feedback-button');
|
||||||
|
}
|
||||||
|
|
||||||
|
getNpsSurveyCloseButton(): Locator {
|
||||||
|
return this.getNpsSurveyModal().locator('button.el-drawer__close-btn');
|
||||||
|
}
|
||||||
|
|
||||||
|
getRatingButton(rating: number): Locator {
|
||||||
|
return this.getNpsSurveyRatings().locator('button').nth(rating);
|
||||||
|
}
|
||||||
|
|
||||||
|
getFeedbackTextarea(): Locator {
|
||||||
|
return this.getNpsSurveyFeedback().locator('textarea');
|
||||||
|
}
|
||||||
|
|
||||||
|
async clickRating(rating: number): Promise<void> {
|
||||||
|
await this.getRatingButton(rating).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fillFeedback(feedback: string): Promise<void> {
|
||||||
|
await this.getFeedbackTextarea().fill(feedback);
|
||||||
|
}
|
||||||
|
|
||||||
|
async clickSubmitButton(): Promise<void> {
|
||||||
|
await this.getNpsSurveySubmitButton().click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async closeSurvey(): Promise<void> {
|
||||||
|
await this.getNpsSurveyCloseButton().click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRatingButtonCount(): Promise<number> {
|
||||||
|
return await this.getNpsSurveyRatings().locator('button').count();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import { ExecutionsPage } from './ExecutionsPage';
|
|||||||
import { IframePage } from './IframePage';
|
import { IframePage } from './IframePage';
|
||||||
import { NodeDisplayViewPage } from './NodeDisplayViewPage';
|
import { NodeDisplayViewPage } from './NodeDisplayViewPage';
|
||||||
import { NotificationsPage } from './NotificationsPage';
|
import { NotificationsPage } from './NotificationsPage';
|
||||||
|
import { NpsSurveyPage } from './NpsSurveyPage';
|
||||||
import { ProjectSettingsPage } from './ProjectSettingsPage';
|
import { ProjectSettingsPage } from './ProjectSettingsPage';
|
||||||
import { SettingsPage } from './SettingsPage';
|
import { SettingsPage } from './SettingsPage';
|
||||||
import { SidebarPage } from './SidebarPage';
|
import { SidebarPage } from './SidebarPage';
|
||||||
@@ -31,6 +32,7 @@ export class n8nPage {
|
|||||||
|
|
||||||
readonly iframe: IframePage;
|
readonly iframe: IframePage;
|
||||||
readonly ndv: NodeDisplayViewPage;
|
readonly ndv: NodeDisplayViewPage;
|
||||||
|
readonly npsSurvey: NpsSurveyPage;
|
||||||
readonly projectSettings: ProjectSettingsPage;
|
readonly projectSettings: ProjectSettingsPage;
|
||||||
readonly settings: SettingsPage;
|
readonly settings: SettingsPage;
|
||||||
readonly versions: VersionsPage;
|
readonly versions: VersionsPage;
|
||||||
@@ -60,6 +62,7 @@ export class n8nPage {
|
|||||||
|
|
||||||
this.iframe = new IframePage(page);
|
this.iframe = new IframePage(page);
|
||||||
this.ndv = new NodeDisplayViewPage(page);
|
this.ndv = new NodeDisplayViewPage(page);
|
||||||
|
this.npsSurvey = new NpsSurveyPage(page);
|
||||||
this.projectSettings = new ProjectSettingsPage(page);
|
this.projectSettings = new ProjectSettingsPage(page);
|
||||||
this.settings = new SettingsPage(page);
|
this.settings = new SettingsPage(page);
|
||||||
this.versions = new VersionsPage(page);
|
this.versions = new VersionsPage(page);
|
||||||
|
|||||||
144
packages/testing/playwright/tests/ui/42-nps-survey.spec.ts
Normal file
144
packages/testing/playwright/tests/ui/42-nps-survey.spec.ts
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
import { test, expect } from '../../fixtures/base';
|
||||||
|
import type { TestRequirements } from '../../Types';
|
||||||
|
|
||||||
|
const NOW = Date.now();
|
||||||
|
const ONE_DAY = 24 * 60 * 60 * 1000;
|
||||||
|
const THREE_DAYS = ONE_DAY * 3;
|
||||||
|
const SEVEN_DAYS = ONE_DAY * 7;
|
||||||
|
const ABOUT_SIX_MONTHS = ONE_DAY * 30 * 6 + ONE_DAY;
|
||||||
|
|
||||||
|
const ACTIVATED_USER_SETTINGS = {
|
||||||
|
userActivated: true,
|
||||||
|
userActivatedAt: NOW - THREE_DAYS - 1000,
|
||||||
|
};
|
||||||
|
|
||||||
|
const getNpsTestRequirements: TestRequirements = {
|
||||||
|
config: {
|
||||||
|
settings: {
|
||||||
|
telemetry: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
intercepts: {
|
||||||
|
npsSurveyApi: {
|
||||||
|
url: '**/rest/user-settings/nps-survey',
|
||||||
|
response: { success: true },
|
||||||
|
},
|
||||||
|
telemetryTest: {
|
||||||
|
url: '**/test/telemetry',
|
||||||
|
response: { status: 'ok' },
|
||||||
|
},
|
||||||
|
telemetryProxy: {
|
||||||
|
url: '**/rest/telemetry/proxy',
|
||||||
|
response: { status: 'ok' },
|
||||||
|
},
|
||||||
|
telemetryRudderstack: {
|
||||||
|
url: '**/rest/telemetry/rudderstack',
|
||||||
|
response: { status: 'ok' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
test.describe('NPS Survey', () => {
|
||||||
|
test.beforeEach(async ({ n8n }) => {
|
||||||
|
await n8n.page.route('**/rest/login', async (route) => {
|
||||||
|
const response = await route.fetch();
|
||||||
|
const originalJson = await response.json();
|
||||||
|
|
||||||
|
const modifiedData = {
|
||||||
|
...originalJson,
|
||||||
|
data: {
|
||||||
|
...originalJson.data,
|
||||||
|
settings: {
|
||||||
|
...originalJson.data?.settings,
|
||||||
|
...ACTIVATED_USER_SETTINGS,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await route.fulfill({
|
||||||
|
status: response.status(),
|
||||||
|
headers: response.headers(),
|
||||||
|
contentType: 'application/json',
|
||||||
|
body: JSON.stringify(modifiedData),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await n8n.goHome();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('shows nps survey to recently activated user and can submit feedback', async ({
|
||||||
|
n8n,
|
||||||
|
setupRequirements,
|
||||||
|
}) => {
|
||||||
|
await setupRequirements(getNpsTestRequirements);
|
||||||
|
await n8n.canvas.visitWithTimestamp(NOW);
|
||||||
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
|
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeVisible();
|
||||||
|
expect(await n8n.npsSurvey.getRatingButtonCount()).toBe(11);
|
||||||
|
|
||||||
|
await n8n.npsSurvey.clickRating(0);
|
||||||
|
await n8n.npsSurvey.fillFeedback('n8n is the best');
|
||||||
|
await n8n.npsSurvey.clickSubmitButton();
|
||||||
|
|
||||||
|
await n8n.canvas.visitWithTimestamp(NOW + ONE_DAY);
|
||||||
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeHidden();
|
||||||
|
|
||||||
|
await n8n.canvas.visitWithTimestamp(NOW + ABOUT_SIX_MONTHS);
|
||||||
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('allows user to ignore survey 3 times before stopping to show until 6 months later', async ({
|
||||||
|
n8n,
|
||||||
|
setupRequirements,
|
||||||
|
}) => {
|
||||||
|
await setupRequirements(getNpsTestRequirements);
|
||||||
|
await n8n.canvas.visitWithTimestamp(NOW);
|
||||||
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
|
await n8n.notifications.quickCloseAll();
|
||||||
|
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeVisible();
|
||||||
|
await n8n.npsSurvey.closeSurvey();
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeHidden();
|
||||||
|
|
||||||
|
await n8n.canvas.visitWithTimestamp(NOW + ONE_DAY);
|
||||||
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeHidden();
|
||||||
|
|
||||||
|
await n8n.canvas.visitWithTimestamp(NOW + SEVEN_DAYS + 10000);
|
||||||
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
|
await n8n.notifications.quickCloseAll();
|
||||||
|
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeVisible();
|
||||||
|
await n8n.npsSurvey.closeSurvey();
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeHidden();
|
||||||
|
|
||||||
|
await n8n.canvas.visitWithTimestamp(NOW + SEVEN_DAYS + 10000);
|
||||||
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeHidden();
|
||||||
|
|
||||||
|
await n8n.canvas.visitWithTimestamp(NOW + (SEVEN_DAYS + 10000) * 2 + ONE_DAY);
|
||||||
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
|
await n8n.notifications.quickCloseAll();
|
||||||
|
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeVisible();
|
||||||
|
await n8n.npsSurvey.closeSurvey();
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeHidden();
|
||||||
|
|
||||||
|
await n8n.canvas.visitWithTimestamp(NOW + (SEVEN_DAYS + 10000) * 2 + ONE_DAY * 2);
|
||||||
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeHidden();
|
||||||
|
|
||||||
|
await n8n.canvas.visitWithTimestamp(NOW + (SEVEN_DAYS + 10000) * 3 + ONE_DAY * 3);
|
||||||
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeHidden();
|
||||||
|
|
||||||
|
await n8n.canvas.visitWithTimestamp(NOW + (SEVEN_DAYS + 10000) * 3 + ABOUT_SIX_MONTHS);
|
||||||
|
await n8n.canvas.clickSaveWorkflowButton();
|
||||||
|
await expect(n8n.npsSurvey.getNpsSurveyModal()).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user