mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
test: Migrate 1-workflows to Playwright (#17360)
This commit is contained in:
270
cypress-playwright-migration.md
Normal file
270
cypress-playwright-migration.md
Normal file
@@ -0,0 +1,270 @@
|
||||
# Cypress to Playwright Migration Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This guide outlines the systematic approach for migrating Cypress tests to Playwright in the n8n codebase, based on successful migrations and lessons learned.
|
||||
|
||||
## 🎯 Migration Principles
|
||||
|
||||
### 1. **Architecture First**
|
||||
- Follow the established 4-layer architecture: Tests → Composables → Page Objects → BasePage
|
||||
- Use existing composables and page objects before creating new ones
|
||||
- Maintain separation of concerns: business logic in composables, UI interactions in page objects
|
||||
|
||||
### 2. **Search Existing Patterns First**
|
||||
- **ALWAYS** search for existing Playwright patterns before implementing new functionality
|
||||
- Look for working examples in existing test files (e.g., `39-projects.spec.ts`)
|
||||
- Check composables and page objects for existing methods
|
||||
- Framework-specific patterns may differ (Cypress display names vs Playwright field names)
|
||||
|
||||
### 3. **Idempotent Test Design**
|
||||
- Design tests to work regardless of initial state
|
||||
- Use fresh project creation for tests that need empty states
|
||||
- Create test prerequisites within the test when needed
|
||||
- Avoid `@db:reset` dependencies in favor of project-based isolation
|
||||
|
||||
## 📋 Pre-Migration Checklist
|
||||
|
||||
### 1. **Environment Setup**
|
||||
```bash
|
||||
# Start isolated test environment
|
||||
cd packages/testing/playwright
|
||||
pnpm start:isolated
|
||||
|
||||
# Run tests with proper environment
|
||||
N8N_BASE_URL=http://localhost:5679 npx playwright test --reporter=list
|
||||
```
|
||||
|
||||
### 2. **Study Existing Patterns**
|
||||
- Review `CONTRIBUTING.md` for architecture guidelines
|
||||
- Examine working test files (e.g., `1-workflows.spec.ts`, `39-projects.spec.ts`)
|
||||
- Check available composables in `composables/` directory
|
||||
- Review page objects in `pages/` directory
|
||||
|
||||
### 3. **Understand Framework Differences**
|
||||
- **Cypress**: Uses display names (`'Internal Integration Secret'`)
|
||||
- **Playwright**: Uses field names (`'apiKey'`)
|
||||
- **Navigation**: Direct page navigation often more reliable than complex UI interactions
|
||||
- **Selectors**: Prefer `data-test-id` over text-based selectors
|
||||
|
||||
## 🔄 Migration Process
|
||||
|
||||
### Step 1: Scaffold the Test File
|
||||
```typescript
|
||||
// 1. Create test file with proper imports
|
||||
import { test, expect } from '../fixtures/base';
|
||||
import {
|
||||
// Import constants from existing patterns
|
||||
NOTION_NODE_NAME,
|
||||
NEW_NOTION_ACCOUNT_NAME,
|
||||
// ... other constants
|
||||
} from '../config/constants';
|
||||
|
||||
// 2. Add beforeEach setup if needed
|
||||
test.describe('Feature Name', () => {
|
||||
test.beforeEach(async ({ api, n8n }) => {
|
||||
await api.enableFeature('sharing');
|
||||
await api.enableFeature('folders');
|
||||
// ... other feature flags
|
||||
await n8n.goHome();
|
||||
});
|
||||
|
||||
// 3. Scaffold all tests from Cypress file
|
||||
test('should do something', async ({ n8n }) => {
|
||||
// TODO: Implement based on Cypress version
|
||||
console.log('Test scaffolded - ready for implementation');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Step 2: Research Existing Patterns
|
||||
```bash
|
||||
# Search for existing implementations
|
||||
grep -r "addCredentialToProject" packages/testing/playwright/
|
||||
grep -r "createProject" packages/testing/playwright/
|
||||
grep -r "workflowComposer" packages/testing/playwright/
|
||||
```
|
||||
|
||||
### Step 3: Implement Working Tests First
|
||||
- Start with tests that have clear existing patterns
|
||||
- Use composables for high-level operations (project creation, navigation)
|
||||
- Use direct DOM interactions for form filling when composables don't match
|
||||
- Implement one test at a time and verify it works
|
||||
|
||||
### Step 4: Handle Complex UI Interactions
|
||||
- **Node Creation Issues**: Close NDV after adding first node to prevent overlay blocking
|
||||
- **Universal Add Button**: Use direct navigation when button interactions fail
|
||||
- **Modal Overlays**: Use route interception for error testing
|
||||
- **Multiple Elements**: Use specific selectors to avoid strict mode violations
|
||||
|
||||
## 🛠️ Common Patterns
|
||||
|
||||
### Project-Based Testing
|
||||
```typescript
|
||||
// ✅ Good: Use existing composable
|
||||
const { projectName } = await n8n.projectComposer.createProject();
|
||||
await n8n.projectComposer.addCredentialToProject(
|
||||
projectName,
|
||||
'Notion API',
|
||||
'apiKey', // Use field name, not display name
|
||||
'test_value'
|
||||
);
|
||||
```
|
||||
|
||||
### Direct Navigation
|
||||
```typescript
|
||||
// ✅ Good: Direct navigation when UI interactions fail
|
||||
await n8n.page.goto('/home/credentials/create');
|
||||
await n8n.page.goto('/workflow/new');
|
||||
```
|
||||
|
||||
### Error Testing with Route Interception
|
||||
```typescript
|
||||
// ✅ Good: Force errors for notification testing
|
||||
await n8n.page.route('**/rest/credentials', route => {
|
||||
route.abort();
|
||||
});
|
||||
```
|
||||
|
||||
### Node Creation with NDV Handling
|
||||
```typescript
|
||||
// ✅ Good: Handle NDV auto-opening
|
||||
await n8n.canvas.addNode(SCHEDULE_TRIGGER_NODE_NAME);
|
||||
await n8n.ndv.close(); // Close NDV that opens automatically
|
||||
await n8n.canvas.addNode(NOTION_NODE_NAME);
|
||||
```
|
||||
|
||||
## 🚨 Common Pitfalls
|
||||
|
||||
### 1. **Not Checking Existing Patterns**
|
||||
```typescript
|
||||
// ❌ Bad: Implementing without checking existing patterns
|
||||
await n8n.page.getByText('Internal Integration Secret').fill('value');
|
||||
|
||||
// ✅ Good: Use existing composable with correct field name
|
||||
await n8n.projectComposer.addCredentialToProject(
|
||||
projectName, 'Notion API', 'apiKey', 'value'
|
||||
);
|
||||
```
|
||||
|
||||
### 2. **Ignoring Framework Differences**
|
||||
```typescript
|
||||
// ❌ Bad: Assuming Cypress patterns work in Playwright
|
||||
await n8n.credentialsModal.connectionParameter('Internal Integration Secret').fill('value');
|
||||
|
||||
// ✅ Good: Use Playwright field names
|
||||
await n8n.page.getByTestId('parameter-input-field').fill('value');
|
||||
```
|
||||
|
||||
### 3. **Complex UI Interactions When Simple Navigation Works**
|
||||
```typescript
|
||||
// ❌ Bad: Complex button clicking when direct navigation works
|
||||
await n8n.workflows.clickAddWorkflowButton();
|
||||
await n8n.page.waitForLoadState();
|
||||
|
||||
// ✅ Good: Direct navigation
|
||||
await n8n.page.goto('/workflow/new');
|
||||
await n8n.page.waitForLoadState('networkidle');
|
||||
```
|
||||
|
||||
### 4. **Not Handling UI Blocking**
|
||||
```typescript
|
||||
// ❌ Bad: Not handling NDV auto-opening
|
||||
await n8n.canvas.addNode(SCHEDULE_TRIGGER_NODE_NAME);
|
||||
await n8n.canvas.addNode(NOTION_NODE_NAME); // This will fail
|
||||
|
||||
// ✅ Good: Close NDV after first node
|
||||
await n8n.canvas.addNode(SCHEDULE_TRIGGER_NODE_NAME);
|
||||
await n8n.ndv.close();
|
||||
await n8n.canvas.addNode(NOTION_NODE_NAME);
|
||||
```
|
||||
|
||||
## 📝 Testing Strategy
|
||||
|
||||
### 1. **Start Simple**
|
||||
- Begin with basic navigation and page verification tests
|
||||
- Use existing composables for common operations
|
||||
- Verify each test works before moving to complex scenarios
|
||||
|
||||
### 2. **Incremental Implementation**
|
||||
- Scaffold all tests first with placeholders
|
||||
- Implement one test at a time
|
||||
- Use `console.log` for placeholder tests to maintain passing test suite
|
||||
|
||||
### 3. **Debugging Approach**
|
||||
```typescript
|
||||
// Add pauses for debugging
|
||||
await n8n.page.pause();
|
||||
|
||||
// Use headed mode for visual debugging
|
||||
SHOW_BROWSER=true npx playwright test
|
||||
|
||||
// Use specific test selection
|
||||
npx playwright test -g "test name" --reporter=list
|
||||
```
|
||||
|
||||
### 4. **Verification Strategy**
|
||||
- Run individual tests during development
|
||||
- Run full test suite after each major change
|
||||
- Use `--reporter=list` for clear output during development
|
||||
|
||||
## 🔧 Environment Configuration
|
||||
|
||||
### VS Code Settings
|
||||
```json
|
||||
{
|
||||
"playwright.env": {
|
||||
"N8N_BASE_URL": "http://localhost:5679",
|
||||
"SHOW_BROWSER": "true",
|
||||
"RESET_E2E_DB": "true"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Package.json Scripts
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"start:isolated": "cd ..; N8N_PORT=5679 N8N_USER_FOLDER=/tmp/n8n-test-$(date +%s) E2E_TESTS=true pnpm start",
|
||||
"test:local": "RESET_E2E_DB=true N8N_BASE_URL=http://localhost:5679 start-server-and-test 'pnpm start:isolated' http://localhost:5679/favicon.ico 'sleep 1 && pnpm test:standard --workers 4 --repeat-each 5'"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Success Metrics
|
||||
|
||||
### Migration Complete When:
|
||||
- [ ] All tests from Cypress file are scaffolded
|
||||
- [ ] All tests pass consistently
|
||||
- [ ] Tests use existing composables where appropriate
|
||||
- [ ] Tests follow established patterns
|
||||
- [ ] No `@db:reset` dependencies (unless absolutely necessary)
|
||||
- [ ] Tests are idempotent and can run in any order
|
||||
- [ ] Complex UI interactions are handled properly
|
||||
|
||||
### Quality Checklist:
|
||||
- [ ] Tests use proper error handling
|
||||
- [ ] Tests include appropriate assertions
|
||||
- [ ] Tests follow naming conventions
|
||||
- [ ] Tests include proper comments
|
||||
- [ ] Tests use constants for repeated values
|
||||
- [ ] Tests handle dynamic data properly
|
||||
|
||||
## 🎯 Best Practices Summary
|
||||
|
||||
1. **Search First**: Always look for existing patterns before implementing
|
||||
2. **Use Composables**: Leverage existing business logic composables
|
||||
3. **Direct Navigation**: Prefer direct page navigation over complex UI interactions
|
||||
4. **Handle UI Blocking**: Close modals/NDV when adding multiple nodes
|
||||
5. **Framework Awareness**: Understand differences between Cypress and Playwright
|
||||
6. **Incremental Approach**: Implement one test at a time
|
||||
7. **Idempotent Design**: Make tests work regardless of initial state
|
||||
8. **Proper Debugging**: Use pauses and headed mode for troubleshooting
|
||||
|
||||
## 📚 Resources
|
||||
|
||||
- [Playwright Test Documentation](https://playwright.dev/docs/intro)
|
||||
- [n8n Playwright Contributing Guide](./packages/testing/playwright/CONTRIBUTING.md)
|
||||
- [Existing Test Examples](./packages/testing/playwright/tests/)
|
||||
- [Composables Reference](./packages/testing/playwright/composables/)
|
||||
- [Page Objects Reference](./packages/testing/playwright/pages/)
|
||||
Reference in New Issue
Block a user