Skip to content

Commit 5fe4eaf

Browse files
hassoncsKilo Code
andauthored
Setup Playwright Testing (#832)
* test(vscode-e2e): Fix e2e tests Update e2e tests to reflect changes in registered commands and task output. - Removed outdated commands from the extension test. - Updated the task test to expect "Kilo" instead of "Roo" in the completion output. * 'chore: WIP' --------- Co-authored-by: Kilo Code <noreply@example.com>
1 parent e16aded commit 5fe4eaf

30 files changed

+1486
-111
lines changed

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ src/node_modules
7676
!pnpm-workspace.yaml
7777
!scripts/bootstrap.mjs
7878
!apps/web-evals/
79+
!apps/playwright-e2e/
7980
!src/
8081
!webview-ui/
8182
!packages/evals/.docker/entrypoints/runner.sh
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
const fs = require("fs")
2+
const path = require("path")
3+
4+
async function commentPlaywrightResults(github, context) {
5+
const commentIdentifier = "<!-- playwright-e2e-results -->"
6+
let comment = `${commentIdentifier}\n## 🎭 Playwright E2E Test Results\n\n`
7+
8+
const testResultsDir = "apps/playwright-e2e/test-results"
9+
const reportDir = "apps/playwright-e2e/playwright-report"
10+
11+
if (fs.existsSync(testResultsDir) && fs.readdirSync(testResultsDir).length > 0) {
12+
let hasFailures = false
13+
try {
14+
function scanDirectory(dir) {
15+
let items
16+
try {
17+
items = fs.readdirSync(dir, { withFileTypes: true })
18+
} catch (e) {
19+
return
20+
}
21+
22+
for (const item of items) {
23+
const fullPath = path.join(dir, item.name)
24+
if (item.isDirectory()) {
25+
// Skip vscode-logs directories which contain VSCode internal files
26+
if (item.name === 'vscode-logs') {
27+
continue
28+
}
29+
scanDirectory(fullPath)
30+
} else if (item.isFile() && item.name.endsWith(".json")) {
31+
try {
32+
const content = fs.readFileSync(fullPath, "utf8")
33+
if (content.includes('"status":"failed"')) {
34+
hasFailures = true
35+
return
36+
}
37+
} catch (e) {
38+
continue
39+
}
40+
}
41+
}
42+
}
43+
scanDirectory(testResultsDir)
44+
} catch (e) {
45+
console.log("Error checking test results:", e.message)
46+
}
47+
48+
if (hasFailures) {
49+
comment += "❌ **Some E2E tests failed**\n\n"
50+
comment += `- Check the [test results artifact](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${process.env.GITHUB_RUN_ID}) for details\n`
51+
comment += `- Review the [HTML report artifact](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${process.env.GITHUB_RUN_ID}) for visual debugging\n`
52+
} else {
53+
comment += "✅ **All E2E tests passed successfully!**\n\n"
54+
comment += "The extension works correctly in a Docker environment with full end-to-end functionality.\n"
55+
}
56+
} else {
57+
comment += "⚠️ **No test results found**\n\n"
58+
comment += `The E2E tests may not have run properly. Check the [workflow logs](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${process.env.GITHUB_RUN_ID}) for details.\n`
59+
}
60+
61+
comment += "\n---\n"
62+
comment += `*Workflow: [${context.workflow}](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${process.env.GITHUB_RUN_ID}) • Updated: ${new Date().toISOString()}*`
63+
64+
const { data: comments } = await github.rest.issues.listComments({
65+
issue_number: context.issue.number,
66+
owner: context.repo.owner,
67+
repo: context.repo.repo,
68+
})
69+
70+
const existingComment = comments.find((comment) => comment.body.includes(commentIdentifier))
71+
72+
if (existingComment) {
73+
await github.rest.issues.updateComment({
74+
comment_id: existingComment.id,
75+
owner: context.repo.owner,
76+
repo: context.repo.repo,
77+
body: comment,
78+
})
79+
console.log("Updated existing Playwright E2E comment")
80+
} else {
81+
await github.rest.issues.createComment({
82+
issue_number: context.issue.number,
83+
owner: context.repo.owner,
84+
repo: context.repo.repo,
85+
body: comment,
86+
})
87+
console.log("Created new Playwright E2E comment")
88+
}
89+
}
90+
91+
module.exports = { commentPlaywrightResults }

.github/workflows/code-qa.yml

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -109,43 +109,3 @@ jobs:
109109
steps:
110110
- name: NO-OP
111111
run: echo "All unit tests passed."
112-
113-
# check-openrouter-api-key:
114-
# runs-on: ubuntu-latest
115-
# outputs:
116-
# exists: ${{ steps.openrouter-api-key-check.outputs.defined }}
117-
# steps:
118-
# - name: Check if OpenRouter API key exists
119-
# id: openrouter-api-key-check
120-
# shell: bash
121-
# run: |
122-
# if [ "${{ secrets.OPENROUTER_API_KEY }}" != '' ]; then
123-
# echo "defined=true" >> $GITHUB_OUTPUT;
124-
# else
125-
# echo "defined=false" >> $GITHUB_OUTPUT;
126-
# fi
127-
128-
# integration-test:
129-
# runs-on: ubuntu-latest
130-
# needs: [check-openrouter-api-key]
131-
# if: needs.check-openrouter-api-key.outputs.exists == 'true'
132-
# steps:
133-
# - name: Checkout code
134-
# uses: actions/checkout@v4
135-
# - name: Install pnpm
136-
# uses: pnpm/action-setup@v4
137-
# with:
138-
# version: ${{ env.PNPM_VERSION }}
139-
# - name: Setup Node.js
140-
# uses: actions/setup-node@v4
141-
# with:
142-
# node-version: ${{ env.NODE_VERSION }}
143-
# cache: 'pnpm'
144-
# - name: Install dependencies
145-
# run: npx pnpm install
146-
# - name: Create .env.local file
147-
# working-directory: e2e
148-
# run: echo "OPENROUTER_API_KEY=${{ secrets.OPENROUTER_API_KEY }}" > .env.local
149-
# - name: Run integration tests
150-
# working-directory: e2e
151-
# run: xvfb-run -a pnpm ci

.github/workflows/playwright-e2e.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: Playwright E2E Tests
2+
3+
on:
4+
pull_request:
5+
types: [opened, reopened, ready_for_review, synchronize]
6+
branches: [main]
7+
push:
8+
branches: [main]
9+
workflow_dispatch:
10+
11+
# Cancel in-progress jobs when new workflow is triggered
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
14+
cancel-in-progress: true
15+
16+
env:
17+
DOCKER_BUILDKIT: 1
18+
COMPOSE_DOCKER_CLI_BUILD: 1
19+
NODE_VERSION: 20.19.2
20+
PNPM_VERSION: 10.8.1
21+
22+
jobs:
23+
playwright-e2e:
24+
runs-on: ubuntu-latest
25+
timeout-minutes: 30
26+
27+
steps:
28+
- name: Checkout repository
29+
uses: actions/checkout@v4
30+
31+
- name: Set up Node.js
32+
uses: actions/setup-node@v4
33+
with:
34+
node-version: ${{ env.NODE_VERSION }}
35+
36+
- name: Install pnpm
37+
uses: pnpm/action-setup@v4
38+
with:
39+
version: ${{ env.PNPM_VERSION }}
40+
41+
- name: Install dependencies
42+
run: pnpm install --frozen-lockfile
43+
44+
- name: Set up Docker Buildx
45+
uses: docker/setup-buildx-action@v3
46+
47+
- name: Cache Docker layers
48+
uses: actions/cache@v4
49+
with:
50+
path: /tmp/.buildx-cache
51+
key: ${{ runner.os }}-buildx-${{ hashFiles('apps/playwright-e2e/Dockerfile.playwright-ci') }}
52+
restore-keys: |
53+
${{ runner.os }}-buildx-
54+
55+
- name: Run Playwright E2E tests
56+
continue-on-error: true
57+
run: |
58+
cd apps/playwright-e2e
59+
node run-docker-playwright.js
60+
env:
61+
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
62+
WORKSPACE_ROOT: ${{ github.workspace }}
63+
64+
- name: Comment PR with test results
65+
if: always() && github.event_name == 'pull_request'
66+
uses: actions/github-script@v7
67+
with:
68+
script: |
69+
const { commentPlaywrightResults } = require('./.github/scripts/comment-playwright-results.js');
70+
await commentPlaywrightResults(github, context);

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ logs
3737
# kilocode_change
3838
.history/
3939
.aider*
40+
.docker-cache/
41+
4042
# Turborepo
4143
.turbo
4244

apps/playwright-e2e/.dockerignore

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Docker ignore file for simplified Playwright setup
2+
# Only include essential files for Docker build context
3+
4+
# Node modules (Docker will install minimal deps)
5+
node_modules/
6+
*/node_modules/
7+
**/node_modules/
8+
9+
# Test results and reports (will be generated in Docker)
10+
test-results/
11+
playwright-report/
12+
coverage/
13+
.nyc_output/
14+
15+
# Cache directories
16+
.turbo/
17+
.cache/
18+
.vite/
19+
.next/
20+
.nuxt/
21+
22+
# IDE and editor files
23+
.vscode/
24+
.vscode-test/
25+
.idea/
26+
*.swp
27+
*.swo
28+
*~
29+
30+
# OS generated files
31+
.DS_Store
32+
.DS_Store?
33+
._*
34+
.Spotlight-V100
35+
.Trashes
36+
ehthumbs.db
37+
Thumbs.db
38+
39+
# Logs
40+
*.log
41+
logs/
42+
npm-debug.log*
43+
pnpm-debug.log*
44+
45+
# Runtime data
46+
pids/
47+
*.pid
48+
*.seed
49+
*.pid.lock
50+
51+
# Temporary files
52+
tmp/
53+
temp/
54+
.tmp/
55+
56+
# Git
57+
.git/
58+
.gitignore
59+
60+
# Environment files (except sample)
61+
.env.local
62+
.env.*.local
63+
64+
# Package manager lock files (Docker uses npm for minimal deps)
65+
package-lock.json

apps/playwright-e2e/.env.local.sample

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Copy this file to .env.local and fill in your actual values
2+
3+
OPENROUTER_API_KEY=your_openrouter_api_key_here

apps/playwright-e2e/.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
node_modules/
2+
test-results/
3+
playwright-report/
4+
playwright/.cache/
5+
screenshots/
6+
*.log
7+
.env
8+
.env.local
9+
.build/
10+
.docker-cache/

apps/playwright-e2e/.pnpmrc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Docker-specific pnpm configuration
2+
# This ensures Docker and host use separate node_modules
3+
4+
# Use a different store location in Docker to avoid conflicts
5+
store-dir=/workspace/.pnpm-store
6+
7+
# Enable hoisting for better Docker layer caching
8+
hoist-pattern[]=*
9+
10+
# Disable symlinks for Docker compatibility
11+
symlink=false
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Streamlined Dockerfile for Playwright E2E Testing
2+
# Optimized for speed: builds app outside Docker, installs only Playwright deps inside
3+
# Cache-optimized: layers ordered by frequency of change
4+
5+
FROM mcr.microsoft.com/playwright:v1.53.1-noble
6+
7+
# Install system dependencies (rarely changes - good for caching)
8+
RUN apt-get update && apt-get install -y \
9+
# VSCode dependencies
10+
libasound2t64 \
11+
libatk-bridge2.0-0 \
12+
libdrm2 \
13+
libxkbcommon0 \
14+
libxcomposite1 \
15+
libxdamage1 \
16+
libxrandr2 \
17+
libgbm1 \
18+
libxss1 \
19+
# Additional Chrome dependencies
20+
fonts-liberation \
21+
libappindicator3-1 \
22+
libnss3 \
23+
lsb-release \
24+
xdg-utils \
25+
# Process management
26+
procps \
27+
# D-Bus for virtual display
28+
dbus-x11 \
29+
# VS Code secrets API support in Docker
30+
gnome-keyring \
31+
libsecret-1-0 \
32+
libsecret-1-dev \
33+
# Clean up
34+
&& rm -rf /var/lib/apt/lists/*
35+
36+
# Install pnpm globally (rarely changes - good for caching)
37+
RUN npm install -g pnpm@10.8.1
38+
39+
# Set environment variables (rarely changes - good for caching)
40+
ENV NODE_ENV=production \
41+
CI=true \
42+
DISPLAY=:99 \
43+
DOCKER_CONTAINER=true \
44+
ELECTRON_DISABLE_SANDBOX=false \
45+
ELECTRON_ENABLE_LOGGING=true
46+
47+
# Create workspace directory
48+
WORKDIR /workspace
49+
50+
# Copy entrypoint script (changes occasionally - separate layer for better caching)
51+
COPY apps/playwright-e2e/docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
52+
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
53+
54+
# Set entrypoint
55+
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]

0 commit comments

Comments
 (0)