mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-05 08:10:14 +00:00
Add VSCode Webview Integration Tests (#1373)
* update ci/cd * ci: more git actions * remove duplicitive git actions file * remove duplicative git actions file * add default permissions * chore: sync package-lock.json with main * ci: Fix job name to match branch protection rule * ci: Remove test file with formatting issues * style: Fix formatting in modified files * ci: Remove warning mode, keep webview tests * fixed npm build issue * fix formatting again * Add webview tests * fix formatting * remove temporary docs * remove unecessary auth and types * move tmp in gitignore * spare line * restore prior comments in vscode-test * remove redundant infrastructure * prettier * removed vestigial webviews --------- Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
This commit is contained in:
parent
29725445cc
commit
26ee05dd07
8 changed files with 206 additions and 6 deletions
9
.github/workflows/test.yml
vendored
9
.github/workflows/test.yml
vendored
|
|
@ -6,6 +6,12 @@ on:
|
|||
branches:
|
||||
- main
|
||||
|
||||
# Set default permissions for all jobs
|
||||
permissions:
|
||||
contents: read # Needed to check out code
|
||||
checks: write # Needed to report test results
|
||||
pull-requests: write # Needed to add comments/annotations to PRs
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -51,6 +57,5 @@ jobs:
|
|||
- name: Prettier / Format Check
|
||||
run: npm run format
|
||||
|
||||
- name: Tests
|
||||
- name: Extension Tests
|
||||
run: xvfb-run -a npm run test
|
||||
if: runner.os == 'Linux'
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,6 +1,7 @@
|
|||
out
|
||||
dist
|
||||
node_modules
|
||||
tmp
|
||||
.vscode-test/
|
||||
*.vsix
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
import { defineConfig } from "@vscode/test-cli"
|
||||
import path from "path"
|
||||
|
||||
export default defineConfig({
|
||||
files: "out/**/*.test.js",
|
||||
files: "out/test/**/*.test.js",
|
||||
mocha: {
|
||||
ui: "bdd",
|
||||
timeout: 20000, // Maximum time (in ms) that a test can run before failing
|
||||
},
|
||||
workspaceFolder: "test-workspace",
|
||||
version: "stable",
|
||||
extensionDevelopmentPath: path.resolve("./"),
|
||||
launchArgs: ["--disable-extensions"],
|
||||
})
|
||||
|
|
|
|||
1
package-lock.json
generated
1
package-lock.json
generated
|
|
@ -60,6 +60,7 @@
|
|||
"@vscode/test-electron": "^2.4.0",
|
||||
"esbuild": "^0.21.5",
|
||||
"eslint": "^8.57.0",
|
||||
"glob": "^10.3.10",
|
||||
"husky": "^9.1.7",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.3.3",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import path from "path"
|
|||
import "should"
|
||||
import * as vscode from "vscode"
|
||||
|
||||
const packagePath = path.join(__dirname, "..", "..", "..", "package.json")
|
||||
const packagePath = path.join(__dirname, "..", "..", "package.json")
|
||||
|
||||
describe("Cline Extension", () => {
|
||||
after(() => {
|
||||
|
|
@ -23,4 +23,69 @@ describe("Cline Extension", () => {
|
|||
await new Promise((resolve) => setTimeout(resolve, 400))
|
||||
await vscode.commands.executeCommand("cline.plusButtonClicked")
|
||||
})
|
||||
|
||||
// New test to verify xvfb and webview functionality
|
||||
it("should create and display a webview panel", async () => {
|
||||
// Create a webview panel
|
||||
const panel = vscode.window.createWebviewPanel("testWebview", "CI/CD Test", vscode.ViewColumn.One, {
|
||||
enableScripts: true,
|
||||
})
|
||||
|
||||
// Set some HTML content
|
||||
panel.webview.html = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>xvfb Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="test">Testing xvfb display server</div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
// Verify panel exists
|
||||
should.exist(panel)
|
||||
panel.visible.should.be.true()
|
||||
|
||||
// Clean up
|
||||
panel.dispose()
|
||||
})
|
||||
|
||||
// Test webview message passing
|
||||
it("should handle webview messages", async () => {
|
||||
const panel = vscode.window.createWebviewPanel("testWebview", "Message Test", vscode.ViewColumn.One, {
|
||||
enableScripts: true,
|
||||
})
|
||||
|
||||
// Set up message handling
|
||||
const messagePromise = new Promise<string>((resolve) => {
|
||||
panel.webview.onDidReceiveMessage((message) => resolve(message.text), undefined)
|
||||
})
|
||||
|
||||
// Add message sending script
|
||||
panel.webview.html = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Message Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
vscode.postMessage({ text: 'test-message' });
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
// Wait for message
|
||||
const message = await messagePromise
|
||||
message.should.equal("test-message")
|
||||
|
||||
// Clean up
|
||||
panel.dispose()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
116
src/test/webview/chat-native.test.ts
Normal file
116
src/test/webview/chat-native.test.ts
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import * as vscode from "vscode"
|
||||
import { describe, it, beforeEach, afterEach } from "mocha"
|
||||
import { strict as assert } from "assert"
|
||||
import { join } from "path"
|
||||
describe("Chat Integration Tests", () => {
|
||||
let panel: vscode.WebviewPanel
|
||||
let disposables: vscode.Disposable[] = []
|
||||
|
||||
beforeEach(async () => {
|
||||
// Create VSCode webview panel
|
||||
panel = vscode.window.createWebviewPanel("testWebview", "Chat Test", vscode.ViewColumn.One, {
|
||||
enableScripts: true,
|
||||
retainContextWhenHidden: true,
|
||||
})
|
||||
|
||||
// Set up minimal test webview
|
||||
panel.webview.html = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
window.addEventListener('message', event => {
|
||||
const message = event.data;
|
||||
switch (message.type) {
|
||||
case 'sendMessage':
|
||||
vscode.postMessage({ type: 'newTask', text: message.text });
|
||||
break;
|
||||
case 'toggleMode':
|
||||
vscode.postMessage({ type: 'chatSettings', chatSettings: { mode: 'act' } });
|
||||
break;
|
||||
case 'invoke':
|
||||
if (message.invoke === 'primaryButtonClick') {
|
||||
vscode.postMessage({ type: 'askResponse', askResponse: 'yesButtonClicked' });
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="test-webview"></div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
panel.dispose()
|
||||
disposables.forEach((d) => d.dispose())
|
||||
disposables = []
|
||||
})
|
||||
|
||||
it("should send chat messages", async () => {
|
||||
// Set up message listener
|
||||
const messagePromise = new Promise<any>((resolve) => {
|
||||
panel.webview.onDidReceiveMessage((message) => {
|
||||
if (message.type === "newTask") {
|
||||
resolve(message)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Trigger send message
|
||||
await panel.webview.postMessage({
|
||||
type: "sendMessage",
|
||||
text: "Create a hello world app",
|
||||
})
|
||||
|
||||
// Verify message was sent
|
||||
const message = await messagePromise
|
||||
assert.equal(message.type, "newTask")
|
||||
assert.equal(message.text, "Create a hello world app")
|
||||
})
|
||||
|
||||
it("should toggle between plan and act modes", async () => {
|
||||
// Set up state change listener
|
||||
const stateChangePromise = new Promise<any>((resolve) => {
|
||||
panel.webview.onDidReceiveMessage((message) => {
|
||||
if (message.type === "chatSettings") {
|
||||
resolve(message)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Trigger mode toggle
|
||||
await panel.webview.postMessage({ type: "toggleMode" })
|
||||
|
||||
// Verify mode changed
|
||||
const stateChange = await stateChangePromise
|
||||
assert.equal(stateChange.chatSettings.mode, "act")
|
||||
})
|
||||
|
||||
it("should handle tool approval flow", async () => {
|
||||
// Set up approval listener
|
||||
const approvalPromise = new Promise<any>((resolve) => {
|
||||
panel.webview.onDidReceiveMessage((message) => {
|
||||
if (message.type === "askResponse") {
|
||||
resolve(message)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Trigger tool approval
|
||||
await panel.webview.postMessage({
|
||||
type: "invoke",
|
||||
invoke: "primaryButtonClick",
|
||||
})
|
||||
|
||||
// Verify approval was sent
|
||||
const response = await approvalPromise
|
||||
assert.equal(response.type, "askResponse")
|
||||
assert.equal(response.askResponse, "yesButtonClicked")
|
||||
})
|
||||
})
|
||||
|
|
@ -8,7 +8,9 @@
|
|||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"types": ["node", "mocha", "should", "vscode"]
|
||||
"types": ["node", "mocha", "should", "vscode"],
|
||||
"outDir": "out",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src/**/*.test.ts"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -803,6 +803,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
}}
|
||||
/>
|
||||
<DynamicTextArea
|
||||
data-testid="chat-input"
|
||||
ref={(el) => {
|
||||
if (typeof ref === "function") {
|
||||
ref(el)
|
||||
|
|
@ -909,6 +910,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
}}
|
||||
/> */}
|
||||
<div
|
||||
data-testid="send-button"
|
||||
className={`input-icon-button ${textAreaDisabled ? "disabled" : ""} codicon codicon-send`}
|
||||
onClick={() => {
|
||||
if (!textAreaDisabled) {
|
||||
|
|
@ -923,6 +925,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
<ControlsContainer>
|
||||
<ButtonGroup>
|
||||
<VSCodeButton
|
||||
data-testid="context-button"
|
||||
appearance="icon"
|
||||
aria-label="Add Context"
|
||||
disabled={textAreaDisabled}
|
||||
|
|
@ -935,6 +938,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
</VSCodeButton>
|
||||
|
||||
<VSCodeButton
|
||||
data-testid="images-button"
|
||||
appearance="icon"
|
||||
aria-label="Add Images"
|
||||
disabled={shouldDisableImages}
|
||||
|
|
@ -985,7 +989,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
|||
</ModelContainer>
|
||||
</ButtonGroup>
|
||||
|
||||
<SwitchContainer disabled={textAreaDisabled} onClick={onModeToggle}>
|
||||
<SwitchContainer data-testid="mode-switch" disabled={textAreaDisabled} onClick={onModeToggle}>
|
||||
<Slider isAct={chatSettings.mode === "act"} />
|
||||
<SwitchOption isActive={chatSettings.mode === "plan"}>Plan</SwitchOption>
|
||||
<SwitchOption isActive={chatSettings.mode === "act"}>Act</SwitchOption>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue