Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cursor/rules/ts-rules.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ The application we are working on uses the following tech stack:
- Include elaborate details in the body of the commit message
- Always follow the conventional commit message format
- Add two newlines after the commit message title
- Do not ever commit and push without asking for consent from the user

## When to create a class

Expand Down
67 changes: 67 additions & 0 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: E2E Tests

on:
push:
branches: [main, kyledev/e2eTests]
pull_request:
branches: [main]
workflow_dispatch:

jobs:
e2e-tests:
name: End-to-End Tests
runs-on: ubuntu-latest
timeout-minutes: 15

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Build all packages and extension
run: |
npm run compile
npm run bundle
npm run build -w packages/apex-lsp-vscode-extension

- name: Verify extension build
run: |
if [ ! -f "packages/apex-lsp-vscode-extension/dist/package.json" ]; then
echo "❌ package.json not found in dist"
exit 1
fi
if [ ! -f "packages/apex-lsp-vscode-extension/dist/extension.js" ]; then
echo "❌ extension.js not found in dist"
exit 1
fi
if [ ! -f "packages/apex-lsp-vscode-extension/dist/extension.web.js" ]; then
echo "❌ extension.web.js not found in dist"
exit 1
fi

- name: Install Playwright browsers
run: npx playwright install --with-deps chromium

- name: Run E2E tests
run: npm run test -w e2e-tests
env:
CI: true

- name: Upload test results and artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-results-${{ github.run_number }}
path: |
e2e-tests/playwright-report/
e2e-tests/test-results/
retention-days: 30
if-no-files-found: warn
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,10 @@ grammars/

# Language server bundle copied into the VS Code extension package
packages/apex-lsp-vscode-extension/server-bundle/

# E2E Testing artifacts
e2e-tests/test-results/
e2e-tests/playwright-report/
e2e-tests/.playwright/
test-results/
playwright-report/
23 changes: 10 additions & 13 deletions build-config/tsup.shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const COMMON_EXTERNAL = [
'vscode',
'vscode-languageserver',
'vscode-languageserver/node',
'vscode-languageserver/browser',
'vscode-languageserver/browser',
'vscode-languageserver-protocol',
'vscode-jsonrpc',
'vscode-jsonrpc/node',
Expand Down Expand Up @@ -45,17 +45,14 @@ export const nodeBaseConfig: Partial<Options> = {
minify: false,
dts: false,
splitting: false,
external: [
...COMMON_EXTERNAL,
'crypto', 'fs', 'path', 'url', 'os', 'stream',
],
external: [...COMMON_EXTERNAL, 'crypto', 'fs', 'path', 'url', 'os', 'stream'],
};

/**
* Base configuration for browser/web builds
*/
export const browserBaseConfig: Partial<Options> = {
platform: 'browser',
platform: 'browser',
target: 'es2022',
format: ['cjs'],
sourcemap: true,
Expand All @@ -70,11 +67,11 @@ export const browserBaseConfig: Partial<Options> = {
* Browser polyfill aliases - simplified from complex esbuild setup
*/
export const BROWSER_ALIASES = {
'path': 'path-browserify',
'crypto': 'crypto-browserify',
'stream': 'stream-browserify',
'fs': 'memfs',
'url': 'url-browserify',
'os': 'os-browserify/browser',
path: 'path-browserify',
crypto: 'crypto-browserify',
stream: 'stream-browserify',
fs: 'memfs',
url: 'url-browserify',
os: 'os-browserify/browser',
'vscode-languageclient/node': 'vscode-languageclient/browser',
};
};
97 changes: 97 additions & 0 deletions e2e-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# E2E Tests for Apex Language Server Extension

This package provides comprehensive end-to-end testing for the Apex Language Server Extension in VS Code Web environments. The test suite validates that the extension correctly integrates with VS Code's language server protocol and provides essential Apex language features.

## Purpose

The e2e test suite ensures the Apex Language Server Extension works correctly in real-world browser environments by testing:

- **Extension Activation**: Verifies the extension properly activates when Apex files are opened
- **Language Server Integration**: Confirms the LSP worker starts and initializes without errors
- **Symbol Parsing**: Validates that Apex code is correctly parsed and symbols are identified
- **Outline View**: Tests that the VS Code outline view displays Apex class structure
- **Workspace Integration**: Ensures Apex files are recognized and handled in the workspace
- **Stability**: Confirms the extension doesn't cause VS Code crashes or performance issues

## Test Philosophy

These tests focus on critical user-facing functionality rather than internal implementation details. They simulate real user interactions with the extension in a browser environment, providing confidence that the extension will work correctly when published.

The test suite prioritizes:

- **Reliability**: Tests are designed to be stable across different environments
- **Performance**: Fast execution with parallel test runs where possible
- **Maintainability**: Clean abstractions and reusable utilities
- **Comprehensive Coverage**: Core functionality is thoroughly validated

## Prerequisites

- Node.js >= 20.0.0
- Extension must be built before running tests
- VS Code Web test server capability

## Running Tests

```bash
# Run all tests (recommended)
npm run test:e2e

# Debug mode with browser UI
npm run test:e2e:debug

# Visual mode for test development
npm run test:e2e:visual
```

## Test Environment

The tests run against a real VS Code Web instance with the extension pre-loaded. This provides high confidence that the extension will work correctly in production browser environments.

**Supported Browsers**: Chromium (primary testing target)

**Environment Support**:

- Local development with detailed debugging
- CI/CD with stability optimizations
- Debug modes for test development

## Architecture

The test suite uses Playwright for browser automation and is structured with:

- **Utilities**: Reusable functions for common test operations
- **Test Helpers**: Specialized functions for extension-specific testing
- **Configuration**: Centralized settings and selectors
- **Type Safety**: Full TypeScript support throughout

## Debugging and Development

The test suite includes comprehensive debugging capabilities:

- Console error monitoring with intelligent filtering
- Network failure tracking
- Screenshot and video capture on failures
- Detailed logging for test analysis

For manual debugging, tests can be run against a standalone VS Code Web server with full developer tools access.

## CI/CD Integration

Tests are configured for continuous integration with:

- Retry logic for flaky test handling
- Environment-specific timeouts and worker configuration
- Comprehensive reporting and artifact collection
- Headless execution with debugging artifact generation

## Contributing

When adding new tests:

1. Use existing test utilities and patterns
2. Focus on user-facing functionality
3. Ensure tests are reliable across environments
4. Include proper error handling and logging
5. Follow TypeScript best practices

The test suite is designed to grow with the extension while maintaining reliability and performance.
17 changes: 17 additions & 0 deletions e2e-tests/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "e2e-tests",
"version": "1.0.0",
"private": true,
"description": "End-to-end tests for Apex Language Server Extension",
"scripts": {
"test": "playwright test",
"test:debug": "playwright test --debug --headed",
"test:visual": "DEBUG_MODE=1 playwright test --headed",
"server": "node test-server.js"
},
"devDependencies": {
"@playwright/test": "^1.55.0",
"@types/node": "^20.11.30",
"typescript": "^5.8.2"
}
}
73 changes: 73 additions & 0 deletions e2e-tests/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright (c) 2025, salesforce.com, inc.
* All rights reserved.
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the
* repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { defineConfig, devices } from '@playwright/test';

/**
* Playwright configuration for Apex Language Server Extension e2e tests.
*
* Configures test execution for VS Code Web environment with proper
* browser settings, timeouts, and CI/CD integration.
*/
export default defineConfig({
testDir: './tests',

fullyParallel: !process.env.DEBUG_MODE,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI || process.env.DEBUG_MODE ? 1 : undefined,
reporter: process.env.CI
? [['html'], ['line'], ['junit', { outputFile: 'test-results/junit.xml' }]]
: 'html',

use: {
baseURL: 'http://localhost:3000',
trace: process.env.CI ? 'retain-on-failure' : 'on-first-retry',
screenshot: process.env.CI ? 'on' : 'only-on-failure',
video: process.env.CI ? 'on' : 'retain-on-failure',
actionTimeout: 15000,
},

projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
launchOptions: {
args: [
'--disable-web-security',
'--disable-features=VizDisplayCompositor',
'--enable-logging=stderr',
'--log-level=0',
'--v=1',
...(process.env.CI || process.env.DEBUG_MODE
? [
'--no-sandbox',
'--disable-dev-shm-usage',
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-renderer-backgrounding',
]
: []),
],
headless: process.env.CI || !process.env.DEBUG_MODE ? true : false,
slowMo: process.env.DEBUG_MODE ? 300 : 0,
},
},
},
],

webServer: {
command: 'npm run test:e2e:server',
port: 3000,
reuseExistingServer: !process.env.CI,
timeout: 120_000,
cwd: process.cwd().endsWith('e2e-tests') ? '..' : '.',
},

timeout: process.env.CI ? 120_000 : 60_000,
});
Loading