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
39 changes: 38 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches: [main, release/**]
pull_request:
branches: [main, release/**]
workflow_dispatch:

# Least-privilege default: CI only needs to read the repository.
Expand Down Expand Up @@ -58,6 +57,44 @@ jobs:
- name: Tests
run: pnpm exec jest --selectProjects ${{ matrix.project }} --runInBand

e2e:
name: Test (web e2e)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: pnpm/action-setup@v6.0.9
with:
version: 10
- name: Set up Node
uses: actions/setup-node@v7
with:
node-version: '24'
cache: 'pnpm'
- name: Install Packages
run: pnpm run ci:install
- name: Install Chromium
run: pnpm exec playwright install --with-deps chromium
- name: Tests
run: pnpm run test:e2e:web
- name: Upload Playwright HTML report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report-web
path: lana/playwright-report/web
if-no-files-found: ignore
retention-days: 14
- name: Upload Playwright test results
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-test-results-web
path: lana/test-results/web
if-no-files-found: ignore
retention-days: 14

build:
name: Verify VSCode Package Build
runs-on: ubuntu-latest
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ build/
out/
coverage/
*.tsbuildinfo
/.vscode-test-web
/lana/test-results
/lana/playwright-report
2 changes: 2 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export default defineConfig(
'**/out/',
'**/coverage/',
'**/.docusaurus/',
'**/.vscode-test-web/',
'**/playwright-report/',
// only TypeScript is linted; without this, `eslint .` selects js/mjs/cjs
// by default and scans them with no rules
'**/*.js',
Expand Down
6 changes: 5 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ const defaultConfig = {
},
],
},
testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/out/'],
testPathIgnorePatterns: [
'<rootDir>/node_modules/',
'<rootDir>/out/',
'<rootDir>/test/playwright/',
],
testMatch: ['**/?(*.)+(spec|test).ts'],
extensionsToTreatAsEsm: ['.ts', '.tsx'],
};
Expand Down
11 changes: 11 additions & 0 deletions lana/test/playwright/playwright.config.web.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createWebConfig } from '@salesforce/playwright-vscode-ext';
import type { PlaywrightTestConfig } from '@playwright/test';

const config: PlaywrightTestConfig = {
...createWebConfig({ testDir: './specs', workers: 1, fullyParallel: false }),
outputDir: '../../test-results/web',
reporter: [['html', { open: 'never', outputFolder: '../../playwright-report/web' }]],
testMatch: '**/*.web.spec.ts',
};

export default config;
18 changes: 18 additions & 0 deletions lana/test/playwright/specs/logAnalysis.web.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { test } from '@playwright/test';
import {
closeWelcomeTabs,
waitForExtensionsActivated,
waitForVSCodeWorkbench,
waitForWorkspaceReady,
} from '@salesforce/playwright-vscode-ext';

import { assertLogAnalysisRenders, openLogAnalysis } from '../support/logAnalysis';

test('opens a sample log and renders its analysis in VS Code Web', async ({ page }) => {
await waitForVSCodeWorkbench(page);
await waitForWorkspaceReady(page);
await closeWelcomeTabs(page);
await waitForExtensionsActivated(page);
await openLogAnalysis(page);
await assertLogAnalysisRenders(page);
});
28 changes: 28 additions & 0 deletions lana/test/playwright/support/logAnalysis.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { expect, type Page } from '@playwright/test';
import {
executeCommandWithCommandPalette,
hasContent,
openFileFromExplorerTree,
webviewActiveFrame,
} from '@salesforce/playwright-vscode-ext';

import { SAMPLE_LOG_NAME } from './logWorkspace';

export const assertLogAnalysisRenders = async (page: Page): Promise<void> => {
const analysis = await webviewActiveFrame(page, hasContent('log-viewer'), {
timeout: 60_000,
});

const flameChart = analysis.locator('timeline-flame-chart');
await expect(flameChart).toBeVisible({ timeout: 120_000 });

await analysis.locator('vscode-tab-header').filter({ hasText: 'Call Tree' }).click();
const callTree = analysis.locator('call-tree-view');
await expect(callTree).toBeVisible();
await expect(callTree.locator('.tabulator-row').first()).toBeVisible({ timeout: 120_000 });
};

export const openLogAnalysis = async (page: Page): Promise<void> => {
await openFileFromExplorerTree(page, SAMPLE_LOG_NAME);
await executeCommandWithCommandPalette(page, 'Log: Show Apex Log Analysis');
};
14 changes: 14 additions & 0 deletions lana/test/playwright/support/logWorkspace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import fs from 'node:fs/promises';
import path from 'node:path';

import { createTestWorkspace } from '@salesforce/playwright-vscode-ext';

import { sampleLogPath } from './paths';

export const SAMPLE_LOG_NAME = 'sample-log.log';

export const createLogWorkspace = async (): Promise<string> => {
const workspaceDir = await createTestWorkspace();
await fs.copyFile(sampleLogPath, path.join(workspaceDir, SAMPLE_LOG_NAME));
return workspaceDir;
};
6 changes: 6 additions & 0 deletions lana/test/playwright/support/paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import path from 'node:path';

export const repoRoot = path.resolve(__dirname, '../../../..');
export const extensionRoot = path.join(repoRoot, 'lana');
export const sampleLogPath = path.join(repoRoot, 'sample-app', 'debug-logs', 'sample-log.log');
export const vscodeWebTestPath = path.join(repoRoot, '.vscode-test-web');
7 changes: 7 additions & 0 deletions lana/test/playwright/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"types": ["node"]
},
"include": ["./**/*.ts"]
}
35 changes: 35 additions & 0 deletions lana/test/playwright/web/headlessServer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import fs from 'node:fs/promises';

import { open } from '@vscode/test-web';

import { createLogWorkspace } from '../support/logWorkspace';
import { extensionRoot, vscodeWebTestPath } from '../support/paths';

// Lana declares Salesforce Services as an extension dependency, but VS Code Web
// needs the test server to explicitly provision it for a development extension.
const SERVICES_EXTENSION_ID = 'salesforce.salesforcedx-vscode-services';

const start = async (): Promise<void> => {
const workspaceDir = await createLogWorkspace();
const server = await open({
browserType: 'none',
quality: 'stable',
commit: process.env.PLAYWRIGHT_WEB_VSCODE_COMMIT,
port: Number(process.env.PORT) || 3001,
printServerLog: true,
verbose: true,
extensionDevelopmentPath: extensionRoot,
extensionIds: [{ id: SERVICES_EXTENSION_ID }],
folderPath: workspaceDir,
testRunnerDataDir: vscodeWebTestPath,
});

const shutdown = (): void => {
server.dispose();
void fs.rm(workspaceDir, { recursive: true, force: true }).finally(() => process.exit(0));
};
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
};

void start();
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@
"private": true,
"devDependencies": {
"@eslint/js": "^10.0.1",
"@playwright/test": "^1.60.0",
"@prettier/plugin-oxc": "^0.2.2",
"@rolldown/plugin-node-polyfills": "^1.0.3",
"@rollup/plugin-alias": "^6.0.0",
"@rollup/plugin-commonjs": "^29.0.3",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^16.0.3",
"@salesforce/playwright-vscode-ext": "^1.3.10",
"@swc/core": "^1.15.47",
"@swc/helpers": "^0.5.23",
"@swc/jest": "^0.2.39",
"@types/jest": "^30.0.0",
"@vscode/test-web": "^0.0.81",
"concurrently": "^10.0.4",
"eslint": "^10.8.0",
"eslint-config-prettier": "^10.1.8",
Expand All @@ -26,6 +29,7 @@
"rollup-plugin-copy": "^3.5.0",
"rollup-plugin-polyfill-node": "^0.13.0",
"rollup-plugin-swc3": "^0.12.1",
"tsx": "^4.21.0",
"typescript": "npm:@typescript/typescript6@^6.0.2",
"typescript-7": "npm:typescript@^7.0.2",
"typescript-eslint": "^8.65.0"
Expand All @@ -46,6 +50,8 @@
"lint": "concurrently -r -g 'eslint . --cache --cache-location node_modules/.cache/eslint/' 'prettier --cache **/*.{ts,css,md,mdx,scss} --check --experimental-cli' 'pnpm run typecheck'",
"test": "jest",
"test:ci": "jest --runInBand",
"test:e2e:web": "pnpm build && playwright test --config=lana/test/playwright/playwright.config.web.ts",
"serve:web": "pnpm build && tsx lana/test/playwright/web/headlessServer.ts",
"ci:install": "pnpm install --frozen-lockfile --prefer-offline --ignore-scripts",
"prettier-format": "prettier '**/*.ts' --cache --write --experimental-cli"
},
Expand Down
Loading
Loading