This document describes the end-to-end testing strategy for the docgen project, focusing on the docgenButton Lightning Web Component.
The E2E testing suite uses Playwright to test the docgenButton LWC component in a real Salesforce environment (scratch org). Tests verify UI behavior, user interactions, and Salesforce record creation without requiring the Node.js document generation service to be running.
- Framework: Playwright Test (
@playwright/test) - Language: TypeScript
- Browser: Chromium
- Salesforce: Ephemeral scratch orgs (local) or CI-created orgs
- Authentication: Access token-based (session cookies)
- Test Data: Created/deleted per test via Salesforce CLI
e2e/
├── playwright.config.ts # Playwright configuration
├── tsconfig.json # TypeScript config (extends root)
├── tests/
│ └── docgen-button.spec.ts # Test specifications
├── fixtures/
│ └── salesforce.fixture.ts # Test fixtures (setup/teardown)
├── pages/
│ ├── AccountRecordPage.ts # Page Object Model for Account
│ └── DocgenButtonComponent.ts # Component Object Model
└── utils/
└── scratch-org.ts # Scratch org CLI utilities
Decision: Focus on UI behavior and Salesforce integration; skip end-to-end document generation.
Rationale:
- Node.js service may not be running during local development
- Backend testing covered by separate integration tests
- UI tests can run faster without HTTP callouts
- Easier to test error scenarios (mock responses)
Trade-offs:
- Don't verify actual PDF generation
- Don't test Node API integration
- Don't verify ContentVersion upload
Future: Add backend integration tests separately with proper service mocking.
Decision: Use Salesforce access tokens from sf org display to authenticate Playwright.
Rationale:
- No interactive login required (headless mode)
- Works in CI/CD pipelines
- Fast and reliable
- Reuses existing SF CLI authentication
Implementation:
await page.context().addCookies([{
name: 'sid',
value: orgInfo.accessToken,
domain: domain,
path: '/',
httpOnly: true,
secure: true,
sameSite: 'None',
}]);Decision: Create test data before each test, delete after each test.
Rationale:
- Ensures clean state for each test
- Avoids test pollution and flakiness
- Allows tests to run in any order
- Scratch orgs are ephemeral (no long-term data concerns)
Implementation:
- Setup: Create Account + Template via
sf data create record - Teardown: Delete Generated_Document__c, Account, Template via
sf data delete record
Decision: Use Page Object Model (POM) to encapsulate page interactions.
Rationale:
- Improves test maintainability
- Reduces code duplication
- Makes tests more readable
- Isolates locator changes to page objects
Example:
const accountPage = new AccountRecordPage(page);
await accountPage.goto(accountId);
const button = new DocgenButtonComponent(page);
await button.click();Local Development:
- Developer creates scratch org once:
npm run e2e:setup - Runs tests multiple times:
npm run test:e2e - Deletes org when done:
npm run e2e:teardown - Scratch org lasts 7 days
CI/CD:
- GitHub Actions creates ephemeral scratch org
- Runs tests once
- Deletes org immediately after
- Scratch org lasts 1 day (minimum)
Decision: Run tests sequentially (workers: 1) instead of parallel.
Rationale:
- Avoid race conditions in scratch org (single database)
- Prevent test data conflicts
- Salesforce API rate limits
- More predictable test behavior
Trade-off: Slower test execution, but more reliable.
✅ Component rendering and visibility ✅ Button label and initial state ✅ Spinner appearance during processing ✅ Button disabled state during processing ✅ Success toast after completion ✅ Spinner disappearance after completion ✅ Button re-enabling after completion ✅ Generated_Document__c record creation ✅ Account page loading
❌ Actual PDF/DOCX generation (requires Node service) ❌ ContentVersion file upload verification ❌ ContentDocumentLink creation ❌ Download URL validity ❌ Node API error responses (requires mocking) ❌ Template validation errors ❌ Idempotency (RequestHash caching)
⏭️ Missing template error handling (needs invalid templateId config) ⏭️ Server error handling (needs HttpCalloutMock or test mode) ⏭️ Idempotency verification (needs backend to complete first request)
Purpose: Authenticate to Salesforce and manage test data lifecycle.
Responsibilities:
- Get scratch org credentials via
sf org display - Set Salesforce session cookies in Playwright
- Create test Account and Template records
- Clean up Generated_Document__c records after test
- Delete test data after test
Usage:
test('test name', async ({ salesforce }) => {
// salesforce.orgInfo: Instance URL, access token, username
// salesforce.testData: Account ID, Template ID
// salesforce.authenticatedPage: Page with SF session cookies
});Purpose: Interact with Salesforce via CLI commands.
Functions:
getScratchOrgInfo(): Get instance URL and access tokencreateRecord(): Create Salesforce record via CLIdeleteRecords(): Delete records via CLIquerySalesforce(): Execute SOQL queryexecuteAnonymousApex(): Run Apex code (for test mode setup)
File: .github/workflows/e2e-tests.yml
Steps:
- Checkout code
- Setup Node.js + cache dependencies
- Install npm dependencies
- Install Salesforce CLI
- Install Playwright browsers
- Authenticate to Dev Hub (using
SFDX_AUTH_URLsecret) - Create scratch org (1-day duration)
- Deploy main metadata
- Deploy test metadata
- Get org credentials (instance URL, access token)
- Run Playwright tests
- Upload test results and reports as artifacts
- Delete scratch org (cleanup)
- Comment on PR with test summary
Triggers:
- Pull requests to
main - Manual workflow dispatch
Secrets Required:
SFDX_AUTH_URL: Dev Hub authentication URL
Symptom: Failed to get scratch org info
Causes:
- No default org set
- Scratch org expired
- SF CLI not installed
Fix:
sf org list
sf org set default --org docgen-e2eSymptom: Locator 'c-docgen-button' not found
Causes:
- Test metadata not deployed
- Flexipage not assigned to Account record
- Component not on page
Fix:
sf project deploy start --source-dir force-app/test
sf org open # Manually verify component is visibleSymptom: Test timeout of 60000ms exceeded
Causes:
- Salesforce org is slow
- Element selector incorrect
- Component not loading
Fix:
- Increase timeout in
playwright.config.ts - Run in headed mode:
npm run test:e2e:headed - Check browser console for errors
1. Headed Mode:
npm run test:e2e:headed- Watch browser execute tests
- See UI state changes
- Inspect network requests
2. UI Mode:
npm run test:e2e:ui- Interactive test runner
- Step through tests
- Time travel debugging
3. Debug Mode:
npm run test:e2e:debug- Opens Playwright Inspector
- Pause on failures
- Inspect element locators
4. Screenshots and Traces:
- Automatic on failure:
screenshot: 'only-on-failure' - View in HTML report:
npm run test:e2e:report - Download from CI artifacts
Add tests that verify full end-to-end flow:
- Deploy Node service to test environment
- Configure Named Credential to point to test service
- Verify PDF generation, upload, and download
Add mock mode to skip HTTP callouts:
@TestVisible
private static Boolean isTestMode = false;
@AuraEnabled
public static String generate(...) {
if (isTestMode) {
// Return mock response
return 'https://mock.salesforce.com/download/MOCK_CV_ID';
}
// Real implementation...
}Enable via Anonymous Apex before tests:
await executeAnonymousApex(`DocgenController.isTestMode = true;`);Add screenshot comparison tests:
- Capture component baseline screenshots
- Compare against baselines on each run
- Detect unintended UI changes
Add performance metrics:
- Measure time from click to completion
- Track spinner duration
- Verify toast appears within SLA
Expand browser coverage:
- Firefox
- WebKit (Safari)
- Mobile viewports
- Use Page Objects: Encapsulate selectors and interactions
- Clear Test Names: Describe expected behavior
- One Assertion Per Test: Focus on single behavior
- Independent Tests: No dependencies between tests
- Clean Test Data: Create/delete data per test
- Update Selectors: Keep page objects in sync with component changes
- Review Skipped Tests: Periodically revisit and enable
- Monitor Flakiness: Investigate and fix flaky tests
- Update Documentation: Keep README and this doc current
- Fast Feedback: Run tests on every PR
- Artifact Preservation: Upload screenshots and reports
- Fail Fast: Stop on first failure in CI
- Notification: Comment on PR with results