test: Migrate sticky test from Cypress -> Playwright (#19185)

This commit is contained in:
shortstacked
2025-09-04 14:16:42 +01:00
committed by GitHub
parent 026da46d0d
commit 85cfe6cff8
4 changed files with 138 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
# Cypress to Playwright Migration Guide
## Migration Process
### 1. Review Original Test
- Examine the Cypress test file to understand what functionality it's testing
- Note the test structure, assertions, and user interactions
- Identify any special setup or teardown requirements
### 2. Scaffold New Test
- Create Playwright test file with exact same test names as Cypress
- Add commented descriptions of what each test is trying to achieve
- Keep the same test structure and organization
### 3. Analyze Dependencies
- Review what page models, composables, and helpers the Cypress test uses
- Check existing Playwright infrastructure in `composables/`, `helpers/`, `pages/`
- Identify which components are already available vs need to be created
### 4. Study Building Blocks
- Review existing Playwright tests to understand correct patterns
- Check how similar functionality is implemented in other migrated tests
- Follow established conventions for page objects and test structure
### 5. Plan Migration Approach
- Determine the best strategy for translating Cypress commands to Playwright
- Plan any new page objects or helpers needed
- Consider test data requirements and setup
### 6. Execute Migration
- Migrate tests one at a time
- Maintain original test intent and coverage
- Follow Playwright best practices and n8n conventions
### 7. Verify Results
- Test using `pnpm test:local --grep "test-name" --reporter=line`
- Ensure all assertions pass and behavior matches original
- Validate test runs reliably and consistently
## Key Differences: Cypress vs Playwright
- **Selectors**: Cypress uses `cy.get()` → Playwright uses `page.locator()`
- **Assertions**: Cypress auto-waits → Playwright uses `expect()` with built-in waiting
- **Page Navigation**: `cy.visit()``page.goto()`
- **Element Interaction**: `cy.click()``locator.click()`
- **Text Content**: `cy.contains()``expect(locator).toContainText()`
## Testing Commands
```bash
# Run specific test with grep
pnpm --filter n8n-playwright test:local --grep "test-name" --reporter=line
# Run full test suite in directory
pnpm --filter n8n-playwright test:local --reporter=line
```

View File

@@ -4,8 +4,11 @@ import { nanoid } from 'nanoid';
import { BasePage } from './BasePage';
import { ROUTES } from '../config/constants';
import { resolveFromRoot } from '../utils/path-helper';
import { StickyComponent } from './components/StickyComponent';
export class CanvasPage extends BasePage {
readonly sticky = new StickyComponent(this.page);
saveWorkflowButton(): Locator {
return this.page.getByRole('button', { name: 'Save' });
}

View File

@@ -0,0 +1,50 @@
import type { Locator, Page } from '@playwright/test';
import { BasePage } from '../BasePage';
/**
* Sticky note component for canvas interactions.
* Used within CanvasPage as `n8n.canvas.sticky.*`
*
* @example
* // Access via canvas page
* await n8n.canvas.sticky.addSticky();
* await expect(n8n.canvas.sticky.getStickies()).toHaveCount(1);
*/
export class StickyComponent extends BasePage {
constructor(page: Page) {
super(page);
}
getAddButton(): Locator {
return this.page.getByTestId('add-sticky-button');
}
getStickies(): Locator {
return this.page.getByTestId('sticky');
}
getStickyByIndex(index: number): Locator {
return this.getStickies().nth(index);
}
async addSticky(): Promise<void> {
await this.getAddButton().click();
}
/**
* Add a sticky from the context menu, targets top left corner of canvas, so could fail if it's covered
* @param canvasPane - The canvas pane locator
*/
async addFromContextMenu(canvasPane: Locator): Promise<void> {
await canvasPane.click({
button: 'right',
position: { x: 10, y: 10 },
});
await this.page.getByText('Add sticky note').click();
}
getDefaultStickyGuideLink(): Locator {
return this.getStickies().first().getByRole('link', { name: 'Guide' });
}
}

View File

@@ -0,0 +1,29 @@
import { test, expect } from '../../fixtures/base';
test.describe('Canvas Actions', () => {
test('adds sticky to canvas with default text and position', async ({ n8n }) => {
await n8n.start.fromBlankCanvas();
await expect(n8n.canvas.sticky.getAddButton()).toBeVisible();
await n8n.canvas.sticky.addSticky();
const firstSticky = n8n.canvas.sticky.getStickies().first();
await expect(firstSticky).toHaveCSS('height', '160px');
await expect(firstSticky).toHaveCSS('width', '240px');
await n8n.canvas.deselectAll();
await n8n.canvas.sticky.addFromContextMenu(n8n.canvas.canvasPane());
await n8n.page.keyboard.press('Shift+s');
await expect(n8n.canvas.sticky.getStickies()).toHaveCount(3);
await n8n.page.keyboard.press('ControlOrMeta+Shift+s');
await expect(n8n.canvas.sticky.getStickies()).toHaveCount(3);
await expect(n8n.canvas.sticky.getStickies().first()).toHaveText(
'Im a note\nDouble click to edit me. Guide\n',
);
const guideLink = n8n.canvas.sticky.getDefaultStickyGuideLink();
await expect(guideLink).toHaveAttribute('href');
});
});