Skip to content

Commit 782a07b

Browse files
committed
ci: move all e2e vscode tests to run in ci
1 parent aeeaa62 commit 782a07b

24 files changed

+1093
-883
lines changed

.github/workflows/pr.yaml

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ concurrency:
1010
cancel-in-progress: true
1111
jobs:
1212
test-vscode:
13+
runs-on: ubuntu-latest
1314
env:
1415
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
15-
runs-on: ubuntu-latest
1616
steps:
1717
- uses: actions/checkout@v4
1818
- uses: actions/setup-node@v4
@@ -26,7 +26,9 @@ jobs:
2626
- name: Run CI
2727
run: pnpm run ci
2828
test-vscode-e2e:
29-
runs-on: ubuntu-latest
29+
runs-on:
30+
group: ubuntu-runners
31+
labels: ubuntu-2404-8
3032
steps:
3133
- uses: actions/checkout@v4
3234
- uses: actions/setup-node@v4
@@ -41,22 +43,43 @@ jobs:
4143
uses: actions/setup-python@v5
4244
with:
4345
python-version: '3.12'
46+
- name: Cache pip dependencies
47+
uses: actions/cache@v4
48+
with:
49+
path: ~/.cache/pip
50+
key:
51+
${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt',
52+
'**/pyproject.toml', '**/setup.py') }}
53+
restore-keys: |
54+
${{ runner.os }}-pip-
55+
- name: Cache virtual environment
56+
uses: actions/cache@v4
57+
with:
58+
path: .venv
59+
key:
60+
${{ runner.os }}-venv-${{ hashFiles('**/requirements*.txt',
61+
'**/pyproject.toml', '**/setup.py') }}
62+
restore-keys: |
63+
${{ runner.os }}-venv-
4464
- name: Install python dependencies
4565
run: |
4666
python -m venv .venv
4767
source .venv/bin/activate
4868
make install-dev
49-
- name: Fetch VS Code
50-
working-directory: ./vscode/extension
51-
run: pnpm run fetch-vscode
52-
5369
- name: Install code-server
5470
run: curl -fsSL https://code-server.dev/install.sh | sh
5571
- name: Install Playwright browsers
5672
working-directory: ./vscode/extension
5773
run: pnpm exec playwright install
5874
- name: Run e2e tests
5975
working-directory: ./vscode/extension
76+
timeout-minutes: 90
6077
run: |
6178
source ../../.venv/bin/activate
62-
pnpm run test:e2e tests/stop.spec.ts
79+
pnpm run test:e2e
80+
- uses: actions/upload-artifact@v4
81+
if: ${{ !cancelled() }}
82+
with:
83+
name: playwright-report
84+
path: vscode/extension/playwright-report/
85+
retention-days: 30

.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ vscode/extension/out
2020
vscode/extension/src_react
2121
vscode/extension/tsconfig.tsbuildinfo
2222
vscode/extension/.vscode-test/
23+
vscode/extension/playwright-report/
24+
vscode/extension/test-results/
25+
vscode/extension/.test_setup
2326

2427
sqlmesh
2528
docs

vscode/extension/.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ node_modules
22
dist
33
out
44
.vscode-test
5+
.test_setup
56
*.vsix
67
LICENSE
78
src_react
8-
!src_react/.gitkeep
9+
!src_react/.gitkeep
10+
playwright-report

vscode/extension/.vscodeignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@ tsconfig.test.json
2424
tsconfig.build.json
2525
src/test/**
2626
tests/**
27-
.claude
27+
.claude
28+
.idea
29+
.test_setup

vscode/extension/E2E_TESTING.md

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,9 @@ This directory contains end-to-end tests for the SQLMesh VS Code extension using
99
pnpm install
1010
```
1111

12-
2. **Download VS Code executable (one-time setup):**
12+
2. **Install Playwright browsers:**
1313
```bash
14-
pnpm run fetch-vscode
15-
```
16-
17-
This downloads VS Code and caches it in `.vscode-test/` directory. The paths are saved to `.vscode-test/paths.json` for Playwright to use.
18-
19-
3. **Install Playwright browsers:**
20-
```bash
21-
npx playwright install
14+
pnpm run playwright:install
2215
```
2316

2417
## Running Tests

vscode/extension/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@
124124
"test:e2e": "pnpm run vscode:package && playwright test",
125125
"test:e2e:ui": "pnpm run vscode:package && playwright test --ui",
126126
"test:e2e:headed": "pnpm run vscode:package && playwright test --headed",
127-
"fetch-vscode": "tsx scripts/fetch-vscode.ts",
128127
"compile": "pnpm run check-types && node esbuild.js",
129128
"check-types": "tsc --noEmit -p ./tsconfig.build.json",
130129
"watch": "node esbuild.js --watch",

vscode/extension/playwright.config.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,22 @@ import { defineConfig } from '@playwright/test'
33
export default defineConfig({
44
testDir: 'tests',
55
timeout: 60_000,
6-
retries: process.env.CI ? 1 : 0,
7-
workers: 1,
6+
// TODO: When stable, allow retries in CI
7+
retries: process.env.CI ? 0 : 0,
8+
workers: process.env.CI ? 1 : 4,
9+
reporter: [['html', { outputFolder: 'playwright-report' }], ['list']],
10+
globalSetup: './tests/global-setup.ts',
811
projects: [
912
{
1013
name: 'electron-vscode',
1114
use: {
12-
// ⭢ we'll launch Electron ourselves – no browser needed
1315
browserName: 'chromium',
14-
headless: true, // headless mode for tests
16+
headless: true,
1517
launchOptions: {
1618
slowMo: process.env.CI ? 0 : 100,
1719
},
20+
viewport: { width: 1512, height: 944 },
21+
video: 'retain-on-failure',
1822
},
1923
},
2024
],

vscode/extension/tests/bad_setup.spec.ts

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@ import os from 'os'
44
import path from 'path'
55
import {
66
createVirtualEnvironment,
7+
openFile,
78
openLineageView,
89
pipInstall,
910
REPO_ROOT,
10-
startVSCode,
1111
SUSHI_SOURCE_PATH,
1212
} from './utils'
13+
import { startCodeServer, stopCodeServer } from './utils_code_server'
1314

14-
test('missing LSP dependencies shows install prompt', async ({}, testInfo) => {
15+
test('missing LSP dependencies shows install prompt', async ({
16+
page,
17+
}, testInfo) => {
1518
testInfo.setTimeout(120_000) // 2 minutes for venv creation and package installation
1619
const tempDir = await fs.mkdtemp(
1720
path.join(os.tmpdir(), 'vscode-test-tcloud-'),
@@ -26,6 +29,11 @@ test('missing LSP dependencies shows install prompt', async ({}, testInfo) => {
2629
const sqlmeshWithExtras = `${REPO_ROOT}[bigquery]`
2730
await pipInstall(pythonDetails, [sqlmeshWithExtras, custom_materializations])
2831

32+
// Start VS Code
33+
const context = await startCodeServer({
34+
tempDir,
35+
})
36+
2937
try {
3038
// Copy sushi project
3139
await fs.copy(SUSHI_SOURCE_PATH, tempDir)
@@ -42,45 +50,45 @@ test('missing LSP dependencies shows install prompt', async ({}, testInfo) => {
4250
{ spaces: 2 },
4351
)
4452

45-
// Start VS Code
46-
const { window, close } = await startVSCode(tempDir)
53+
await page.goto(`http://127.0.0.1:${context.codeServerPort}`)
4754

4855
// Open a SQL file to trigger SQLMesh activation
4956
// Wait for the models folder to be visible
50-
await window.waitForSelector('text=models')
57+
await page.waitForSelector('text=models')
5158

5259
// Click on the models folder
53-
await window
60+
await page
5461
.getByRole('treeitem', { name: 'models', exact: true })
5562
.locator('a')
5663
.click()
5764

5865
// Open the top_waiters model
59-
await window
66+
await page
6067
.getByRole('treeitem', { name: 'customers.sql', exact: true })
6168
.locator('a')
6269
.click()
6370

6471
// Wait for the message to show that LSP extras need to be installed
65-
await window.waitForSelector('text=LSP dependencies missing')
66-
expect(await window.locator('text=Install').count()).toBeGreaterThanOrEqual(
67-
1,
68-
)
69-
70-
await close()
72+
await page.waitForSelector('text=LSP dependencies missing')
73+
expect(await page.locator('text=Install').count()).toBeGreaterThanOrEqual(1)
7174
} finally {
72-
// Clean up
73-
await fs.remove(tempDir)
75+
await stopCodeServer(context)
7476
}
7577
})
7678

77-
test('lineage, no sqlmesh found', async ({}) => {
79+
test('lineage, no sqlmesh found', async ({ page }, testInfo) => {
80+
testInfo.setTimeout(120_000) // 2 minutes for venv creation and package installation
81+
7882
const tempDir = await fs.mkdtemp(
7983
path.join(os.tmpdir(), 'vscode-test-tcloud-'),
8084
)
8185
const pythonEnvDir = path.join(tempDir, '.venv')
8286
const pythonDetails = await createVirtualEnvironment(pythonEnvDir)
8387

88+
const context = await startCodeServer({
89+
tempDir,
90+
})
91+
8492
try {
8593
// Copy sushi project
8694
await fs.copy(SUSHI_SOURCE_PATH, tempDir)
@@ -97,25 +105,28 @@ test('lineage, no sqlmesh found', async ({}) => {
97105
{ spaces: 2 },
98106
)
99107

100-
const { window, close } = await startVSCode(tempDir)
108+
// navigate to code-server instance
109+
await page.goto(`http://127.0.0.1:${context.codeServerPort}`)
110+
await page.waitForLoadState('networkidle')
101111

102112
// Open lineage view
103-
await openLineageView(window)
113+
await openLineageView(page)
104114

105115
// Assert shows that sqlmesh is not installed
106-
await window.waitForSelector('text=SQLMesh LSP not found')
107-
108-
await close()
116+
await page.waitForSelector('text=SQLMesh LSP not found')
109117
} finally {
110118
// Clean up
111-
await fs.remove(tempDir)
119+
await stopCodeServer(context)
112120
}
113121
})
114122

115123
// Checks that if you have another file open like somewhere else, it still checks the workspace first for a successful context
116124
// it's very flaky but runs when debugging
117125
// - the typing in of the file name is very flaky
118-
test('check that the LSP runs correctly by opening lineage when looking at another file before not in workspace', async ({}) => {
126+
test('check that the LSP runs correctly by opening lineage when looking at another file before not in workspace', async ({
127+
page,
128+
}, testInfo) => {
129+
testInfo.setTimeout(120_000) // 2 minutes for venv creation and package installation
119130
const tempDir = await fs.mkdtemp(
120131
path.join(os.tmpdir(), 'vscode-test-tcloud-'),
121132
)
@@ -133,7 +144,7 @@ test('check that the LSP runs correctly by opening lineage when looking at anoth
133144
// Configure VS Code settings to use our Python environment
134145
const settings = {
135146
'python.defaultInterpreterPath': pythonDetails.pythonPath,
136-
'sqlmesh.environmentPath': pythonEnvDir,
147+
'sqlmesh.environmentPath': tempDir,
137148
}
138149
await fs.ensureDir(path.join(tempDir, '.vscode'))
139150
await fs.writeJson(path.join(tempDir, '.vscode', 'settings.json'), settings, {
@@ -148,19 +159,18 @@ test('check that the LSP runs correctly by opening lineage when looking at anoth
148159
await fs.ensureDir(path.dirname(sqlFile))
149160
await fs.writeFile(sqlFile, 'SELECT 1')
150161

151-
const { window, close } = await startVSCode(tempDir)
162+
const context = await startCodeServer({
163+
tempDir,
164+
})
152165
try {
166+
await page.goto(`http://127.0.0.1:${context.codeServerPort}`)
167+
await page.waitForLoadState('networkidle')
168+
153169
// Open the SQL file from the other directory
154-
await window.keyboard.press('Meta+P')
155-
await window.waitForTimeout(100)
156-
await window.keyboard.type(sqlFile.toString(), { delay: 10 })
157-
await window.waitForTimeout(100)
158-
await window.keyboard.press('Enter')
159-
await window.waitForTimeout(100)
160-
161-
await window.waitForSelector('text=Loaded SQLMesh context')
170+
await openFile(page, sqlFile)
171+
172+
await page.waitForSelector('text=Loaded SQLMesh context')
162173
} finally {
163-
await close()
164-
await fs.remove(tempDir)
174+
await stopCodeServer(context)
165175
}
166176
})

0 commit comments

Comments
 (0)