chore: remove integration tests (#11598)

* chore: remove integration test files

* chore: remove integration test job from CI workflow

---------

Co-authored-by: Roo Code <roomote@roocode.com>
Co-authored-by: Hannes Rudolph <hrudolph@gmail.com>
This commit is contained in:
roomote[bot] 2026-02-19 01:16:40 -07:00 committed by GitHub
parent 00c35e691f
commit aff46b14e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 0 additions and 746 deletions

View file

@ -58,66 +58,3 @@ jobs:
uses: ./.github/actions/setup-node-pnpm
- name: Run unit tests
run: pnpm test
check-openrouter-api-key:
runs-on: ubuntu-latest
outputs:
exists: ${{ steps.openrouter-api-key-check.outputs.defined }}
steps:
- name: Check if OpenRouter API key exists
id: openrouter-api-key-check
shell: bash
run: |
if [ "${{ secrets.OPENROUTER_API_KEY }}" != '' ]; then
echo "defined=true" >> $GITHUB_OUTPUT;
else
echo "defined=false" >> $GITHUB_OUTPUT;
fi
integration-test:
runs-on: ubuntu-latest
needs: [check-openrouter-api-key]
if: needs.check-openrouter-api-key.outputs.exists == 'true'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js and pnpm
uses: ./.github/actions/setup-node-pnpm
- name: Create .env.local file
working-directory: apps/vscode-e2e
run: echo "OPENROUTER_API_KEY=${{ secrets.OPENROUTER_API_KEY }}" > .env.local
- name: Set VS Code test version
run: echo "VSCODE_VERSION=1.101.2" >> $GITHUB_ENV
- name: Cache VS Code test runtime
uses: actions/cache@v4
with:
path: apps/vscode-e2e/.vscode-test
key: ${{ runner.os }}-vscode-test-${{ env.VSCODE_VERSION }}
- name: Pre-download VS Code test runtime with retry
working-directory: apps/vscode-e2e
run: |
for attempt in 1 2 3; do
echo "Download attempt $attempt of 3..."
node -e "
const { downloadAndUnzipVSCode } = require('@vscode/test-electron');
downloadAndUnzipVSCode({ version: process.env.VSCODE_VERSION || '1.101.2' })
.then(() => {
console.log('✅ VS Code test runtime downloaded successfully');
process.exit(0);
})
.catch(err => {
console.error('❌ Failed to download VS Code (attempt $attempt):', err);
process.exit(1);
});
" && break || {
if [ $attempt -eq 3 ]; then
echo "All download attempts failed"
exit 1
fi
echo "Retrying in 5 seconds..."
sleep 5
}
done
- name: Run integration tests
working-directory: apps/vscode-e2e
run: xvfb-run -a pnpm test:ci

View file

@ -1,147 +0,0 @@
// npx vitest run src/__tests__/CloudService.integration.test.ts
import type { ExtensionContext } from "vscode"
import { CloudService } from "../CloudService.js"
import { StaticSettingsService } from "../StaticSettingsService.js"
import { CloudSettingsService } from "../CloudSettingsService.js"
vi.mock("vscode", () => ({
ExtensionContext: vi.fn(),
window: {
showInformationMessage: vi.fn(),
showErrorMessage: vi.fn(),
},
env: {
openExternal: vi.fn(),
},
Uri: {
parse: vi.fn(),
},
}))
describe("CloudService Integration - Settings Service Selection", () => {
let mockContext: ExtensionContext
beforeEach(() => {
CloudService.resetInstance()
mockContext = {
subscriptions: [],
workspaceState: {
get: vi.fn(),
update: vi.fn(),
keys: vi.fn().mockReturnValue([]),
},
secrets: {
get: vi.fn(),
store: vi.fn(),
delete: vi.fn(),
onDidChange: vi.fn().mockReturnValue({ dispose: vi.fn() }),
},
globalState: {
get: vi.fn(),
update: vi.fn(),
setKeysForSync: vi.fn(),
keys: vi.fn().mockReturnValue([]),
},
extensionUri: { scheme: "file", path: "/mock/path" },
extensionPath: "/mock/path",
extensionMode: 1,
asAbsolutePath: vi.fn((relativePath: string) => `/mock/path/${relativePath}`),
storageUri: { scheme: "file", path: "/mock/storage" },
extension: {
packageJSON: {
version: "1.0.0",
},
},
} as unknown as ExtensionContext
})
afterEach(() => {
CloudService.resetInstance()
delete process.env.ROO_CODE_CLOUD_ORG_SETTINGS
delete process.env.ROO_CODE_CLOUD_TOKEN
})
it("should use CloudSettingsService when no environment variable is set", async () => {
// Ensure no environment variables are set
delete process.env.ROO_CODE_CLOUD_ORG_SETTINGS
delete process.env.ROO_CODE_CLOUD_TOKEN
const cloudService = await CloudService.createInstance(mockContext)
// Access the private settingsService to check its type
const settingsService = (cloudService as unknown as { settingsService: unknown }).settingsService
expect(settingsService).toBeInstanceOf(CloudSettingsService)
})
it("should use StaticSettingsService when ROO_CODE_CLOUD_ORG_SETTINGS is set", async () => {
const validSettings = {
version: 1,
cloudSettings: {
recordTaskMessages: true,
enableTaskSharing: true,
taskShareExpirationDays: 30,
},
defaultSettings: {
enableCheckpoints: true,
},
allowList: {
allowAll: true,
providers: {},
},
}
// Set the environment variable
process.env.ROO_CODE_CLOUD_ORG_SETTINGS = Buffer.from(JSON.stringify(validSettings)).toString("base64")
const cloudService = await CloudService.createInstance(mockContext)
// Access the private settingsService to check its type
const settingsService = (cloudService as unknown as { settingsService: unknown }).settingsService
expect(settingsService).toBeInstanceOf(StaticSettingsService)
// Verify the settings are correctly loaded
expect(cloudService.getAllowList()).toEqual(validSettings.allowList)
})
it("should throw error when ROO_CODE_CLOUD_ORG_SETTINGS contains invalid data", async () => {
// Set invalid environment variable
process.env.ROO_CODE_CLOUD_ORG_SETTINGS = "invalid-base64-data"
await expect(CloudService.createInstance(mockContext)).rejects.toThrow("Failed to initialize CloudService")
})
it("should prioritize static token auth when both environment variables are set", async () => {
const validSettings = {
version: 1,
cloudSettings: {
recordTaskMessages: true,
enableTaskSharing: true,
taskShareExpirationDays: 30,
},
defaultSettings: {
enableCheckpoints: true,
},
allowList: {
allowAll: true,
providers: {},
},
}
// Set both environment variables
process.env.ROO_CODE_CLOUD_TOKEN = "test-token"
process.env.ROO_CODE_CLOUD_ORG_SETTINGS = Buffer.from(JSON.stringify(validSettings)).toString("base64")
const cloudService = await CloudService.createInstance(mockContext)
// Should use StaticSettingsService for settings
const settingsService = (cloudService as unknown as { settingsService: unknown }).settingsService
expect(settingsService).toBeInstanceOf(StaticSettingsService)
// Should use StaticTokenAuthService for auth (from the existing logic)
expect(cloudService.isAuthenticated()).toBe(true)
expect(cloudService.hasActiveSession()).toBe(true)
})
})

View file

@ -1,406 +0,0 @@
// Integration tests for command execution timeout functionality
// npx vitest run src/core/tools/__tests__/executeCommandTimeout.integration.spec.ts
import * as vscode from "vscode"
import * as fs from "fs/promises"
import { executeCommandInTerminal, executeCommandTool, ExecuteCommandOptions } from "../ExecuteCommandTool"
import { Task } from "../../task/Task"
import { TerminalRegistry } from "../../../integrations/terminal/TerminalRegistry"
// Mock dependencies
vitest.mock("vscode", () => ({
workspace: {
getConfiguration: vitest.fn(),
},
}))
vitest.mock("fs/promises")
vitest.mock("../../../integrations/terminal/TerminalRegistry")
vitest.mock("../../task/Task")
vitest.mock("../../prompts/responses", () => ({
formatResponse: {
toolError: vitest.fn((msg) => `Tool Error: ${msg}`),
rooIgnoreError: vitest.fn((msg) => `RooIgnore Error: ${msg}`),
},
}))
vitest.mock("../../../utils/text-normalization", () => ({
unescapeHtmlEntities: vitest.fn((text) => text),
}))
vitest.mock("../../../shared/package", () => ({
Package: {
name: "roo-cline",
},
}))
describe("Command Execution Timeout Integration", () => {
let mockTask: any
let mockTerminal: any
let mockProcess: any
beforeEach(() => {
vitest.clearAllMocks()
// Mock fs.access to resolve successfully for working directory
;(fs.access as any).mockResolvedValue(undefined)
// Mock task
mockTask = {
cwd: "/test/directory",
terminalProcess: undefined,
providerRef: {
deref: vitest.fn().mockResolvedValue({
postMessageToWebview: vitest.fn(),
}),
},
say: vitest.fn().mockResolvedValue(undefined),
}
// Mock terminal process
mockProcess = {
abort: vitest.fn(),
then: vitest.fn(),
catch: vitest.fn(),
}
// Mock terminal
mockTerminal = {
runCommand: vitest.fn().mockReturnValue(mockProcess),
getCurrentWorkingDirectory: vitest.fn().mockReturnValue("/test/directory"),
}
// Mock TerminalRegistry
;(TerminalRegistry.getOrCreateTerminal as any).mockResolvedValue(mockTerminal)
// Mock VSCode configuration
const mockGetConfiguration = vitest.fn().mockReturnValue({
get: vitest.fn().mockReturnValue(0), // Default 0 (no timeout)
})
;(vscode.workspace.getConfiguration as any).mockReturnValue(mockGetConfiguration())
})
it("should pass timeout configuration to executeCommand", async () => {
const customTimeoutMs = 15000 // 15 seconds in milliseconds
const options: ExecuteCommandOptions = {
executionId: "test-execution",
command: "echo test",
commandExecutionTimeout: customTimeoutMs,
}
// Mock a quick-completing process
const quickProcess = Promise.resolve()
mockTerminal.runCommand.mockReturnValue(quickProcess)
await executeCommandInTerminal(mockTask as Task, options)
// Verify that the terminal was called with the command
expect(mockTerminal.runCommand).toHaveBeenCalledWith("echo test", expect.any(Object))
})
it("should handle timeout scenario", async () => {
const shortTimeoutMs = 100 // Very short timeout in milliseconds
const options: ExecuteCommandOptions = {
executionId: "test-execution",
command: "sleep 10",
commandExecutionTimeout: shortTimeoutMs,
}
// Create a process that never resolves but has an abort method
const longRunningProcess = new Promise(() => {
// Never resolves to simulate a hanging command
})
// Add abort method to the promise
;(longRunningProcess as any).abort = vitest.fn()
mockTerminal.runCommand.mockReturnValue(longRunningProcess)
// Execute with timeout
const result = await executeCommandInTerminal(mockTask as Task, options)
// Should return timeout error
expect(result[0]).toBe(false) // Not rejected by user
expect(result[1]).toContain("terminated after exceeding")
expect(result[1]).toContain("0.1s") // Should show seconds in error message
}, 10000) // Increase test timeout to 10 seconds
it("should abort process on timeout", async () => {
const shortTimeoutMs = 50 // Short timeout in milliseconds
const options: ExecuteCommandOptions = {
executionId: "test-execution",
command: "sleep 10",
commandExecutionTimeout: shortTimeoutMs,
}
// Create a process that can be aborted
const abortSpy = vitest.fn()
// Mock the process to never resolve but be abortable
const neverResolvingPromise = new Promise(() => {})
;(neverResolvingPromise as any).abort = abortSpy
mockTerminal.runCommand.mockReturnValue(neverResolvingPromise)
await executeCommandInTerminal(mockTask as Task, options)
// Verify abort was called
expect(abortSpy).toHaveBeenCalled()
}, 5000) // Increase test timeout to 5 seconds
it("should clean up timeout on successful completion", async () => {
const options: ExecuteCommandOptions = {
executionId: "test-execution",
command: "echo test",
commandExecutionTimeout: 5000,
}
// Mock a process that completes quickly
const quickProcess = Promise.resolve()
mockTerminal.runCommand.mockReturnValue(quickProcess)
const result = await executeCommandInTerminal(mockTask as Task, options)
// Should complete successfully without timeout
expect(result[0]).toBe(false) // Not rejected
expect(result[1]).not.toContain("terminated after exceeding")
})
it("should use default timeout when not specified (0 = no timeout)", async () => {
const options: ExecuteCommandOptions = {
executionId: "test-execution",
command: "echo test",
// commandExecutionTimeout not specified, should use default (0)
}
const quickProcess = Promise.resolve()
mockTerminal.runCommand.mockReturnValue(quickProcess)
await executeCommandInTerminal(mockTask as Task, options)
// Should complete without issues using default (no timeout)
expect(mockTerminal.runCommand).toHaveBeenCalled()
})
it("should not timeout when commandExecutionTimeout is 0", async () => {
const options: ExecuteCommandOptions = {
executionId: "test-execution",
command: "sleep 10",
commandExecutionTimeout: 0, // No timeout
}
// Create a process that resolves after a delay to simulate a long-running command
const longRunningProcess = new Promise((resolve) => {
setTimeout(resolve, 200) // 200ms delay
})
mockTerminal.runCommand.mockReturnValue(longRunningProcess)
const result = await executeCommandInTerminal(mockTask as Task, options)
// Should complete successfully without timeout
expect(result[0]).toBe(false) // Not rejected
expect(result[1]).not.toContain("terminated after exceeding")
})
describe("Command Timeout Allowlist", () => {
let mockBlock: any
let mockAskApproval: any
let mockHandleError: any
let mockPushToolResult: any
beforeEach(() => {
// Reset mocks for allowlist tests
vitest.clearAllMocks()
;(fs.access as any).mockResolvedValue(undefined)
;(TerminalRegistry.getOrCreateTerminal as any).mockResolvedValue(mockTerminal)
// Mock the executeCommandTool parameters
mockBlock = {
type: "tool_use",
name: "execute_command",
params: {
command: "",
cwd: undefined,
},
nativeArgs: {
command: "",
cwd: undefined,
},
partial: false,
}
mockAskApproval = vitest.fn().mockResolvedValue(true) // Always approve
mockHandleError = vitest.fn()
mockPushToolResult = vitest.fn()
// Mock task with additional properties needed by executeCommandTool
mockTask = {
cwd: "/test/directory",
terminalProcess: undefined,
providerRef: {
deref: vitest.fn().mockResolvedValue({
postMessageToWebview: vitest.fn(),
getState: vitest.fn().mockResolvedValue({
terminalOutputLineLimit: 500,
terminalShellIntegrationDisabled: false,
}),
}),
},
say: vitest.fn().mockResolvedValue(undefined),
consecutiveMistakeCount: 0,
recordToolError: vitest.fn(),
sayAndCreateMissingParamError: vitest.fn(),
rooIgnoreController: {
validateCommand: vitest.fn().mockReturnValue(null),
},
lastMessageTs: Date.now(),
ask: vitest.fn(),
didRejectTool: false,
}
})
it("should skip timeout for commands in allowlist", async () => {
// Mock VSCode configuration with timeout and allowlist
const mockGetConfiguration = vitest.fn().mockReturnValue({
get: vitest.fn().mockImplementation((key: string) => {
if (key === "commandExecutionTimeout") return 1 // 1 second timeout
if (key === "commandTimeoutAllowlist") return ["npm", "git"]
return undefined
}),
})
;(vscode.workspace.getConfiguration as any).mockReturnValue(mockGetConfiguration())
mockBlock.params.command = "npm install"
mockBlock.nativeArgs.command = "npm install"
// Create a process that would timeout if not allowlisted
const longRunningProcess = new Promise((resolve) => {
setTimeout(resolve, 2000) // 2 seconds, longer than 1 second timeout
})
mockTerminal.runCommand.mockReturnValue(longRunningProcess)
await executeCommandTool.handle(mockTask as Task, mockBlock, {
askApproval: mockAskApproval,
handleError: mockHandleError,
pushToolResult: mockPushToolResult,
})
// Should complete successfully without timeout because "npm" is in allowlist
expect(mockPushToolResult).toHaveBeenCalled()
const result = mockPushToolResult.mock.calls[0][0]
expect(result).not.toContain("terminated after exceeding")
}, 3000)
it("should apply timeout for commands not in allowlist", async () => {
// Mock VSCode configuration with timeout and allowlist
const mockGetConfiguration = vitest.fn().mockReturnValue({
get: vitest.fn().mockImplementation((key: string) => {
if (key === "commandExecutionTimeout") return 1 // 1 second timeout
if (key === "commandTimeoutAllowlist") return ["npm", "git"]
return undefined
}),
})
;(vscode.workspace.getConfiguration as any).mockReturnValue(mockGetConfiguration())
mockBlock.params.command = "sleep 10" // Not in allowlist
mockBlock.nativeArgs.command = "sleep 10"
// Create a process that never resolves
const neverResolvingProcess = new Promise(() => {})
;(neverResolvingProcess as any).abort = vitest.fn()
mockTerminal.runCommand.mockReturnValue(neverResolvingProcess)
await executeCommandTool.handle(mockTask as Task, mockBlock, {
askApproval: mockAskApproval,
handleError: mockHandleError,
pushToolResult: mockPushToolResult,
})
// Should timeout because "sleep" is not in allowlist
expect(mockPushToolResult).toHaveBeenCalled()
const result = mockPushToolResult.mock.calls[0][0]
expect(result).toContain("terminated after exceeding")
}, 3000)
it("should handle empty allowlist", async () => {
// Mock VSCode configuration with timeout and empty allowlist
const mockGetConfiguration = vitest.fn().mockReturnValue({
get: vitest.fn().mockImplementation((key: string) => {
if (key === "commandExecutionTimeout") return 1 // 1 second timeout
if (key === "commandTimeoutAllowlist") return []
return undefined
}),
})
;(vscode.workspace.getConfiguration as any).mockReturnValue(mockGetConfiguration())
mockBlock.params.command = "npm install"
mockBlock.nativeArgs.command = "npm install"
// Create a process that never resolves
const neverResolvingProcess = new Promise(() => {})
;(neverResolvingProcess as any).abort = vitest.fn()
mockTerminal.runCommand.mockReturnValue(neverResolvingProcess)
await executeCommandTool.handle(mockTask as Task, mockBlock, {
askApproval: mockAskApproval,
handleError: mockHandleError,
pushToolResult: mockPushToolResult,
})
// Should timeout because allowlist is empty
expect(mockPushToolResult).toHaveBeenCalled()
const result = mockPushToolResult.mock.calls[0][0]
expect(result).toContain("terminated after exceeding")
}, 3000)
it("should match command prefixes correctly", async () => {
// Mock VSCode configuration with timeout and allowlist
const mockGetConfiguration = vitest.fn().mockReturnValue({
get: vitest.fn().mockImplementation((key: string) => {
if (key === "commandExecutionTimeout") return 1 // 1 second timeout
if (key === "commandTimeoutAllowlist") return ["git log", "npm run"]
return undefined
}),
})
;(vscode.workspace.getConfiguration as any).mockReturnValue(mockGetConfiguration())
const longRunningProcess = new Promise((resolve) => {
setTimeout(resolve, 2000) // 2 seconds
})
const neverResolvingProcess = new Promise(() => {})
;(neverResolvingProcess as any).abort = vitest.fn()
// Test exact prefix match - should not timeout
mockBlock.params.command = "git log --oneline"
mockBlock.nativeArgs.command = "git log --oneline"
mockTerminal.runCommand.mockReturnValueOnce(longRunningProcess)
await executeCommandTool.handle(mockTask as Task, mockBlock, {
askApproval: mockAskApproval,
handleError: mockHandleError,
pushToolResult: mockPushToolResult,
})
expect(mockPushToolResult).toHaveBeenCalled()
const result1 = mockPushToolResult.mock.calls[0][0]
expect(result1).not.toContain("terminated after exceeding")
// Reset mocks for second test
mockPushToolResult.mockClear()
// Test partial prefix match (should not match) - should timeout
mockBlock.params.command = "git status" // "git" alone is not in allowlist, only "git log"
mockBlock.nativeArgs.command = "git status"
mockTerminal.runCommand.mockReturnValueOnce(neverResolvingProcess)
await executeCommandTool.handle(mockTask as Task, mockBlock, {
askApproval: mockAskApproval,
handleError: mockHandleError,
pushToolResult: mockPushToolResult,
})
expect(mockPushToolResult).toHaveBeenCalled()
const result2 = mockPushToolResult.mock.calls[0][0]
expect(result2).toContain("terminated after exceeding")
}, 5000)
})
})

View file

@ -1,130 +0,0 @@
import * as fs from "fs/promises"
import * as path from "path"
import * as os from "os"
// Must mock dependencies before importing the handler module.
vi.mock("../../../api/providers/fetchers/modelCache")
import { webviewMessageHandler } from "../webviewMessageHandler"
import type { ClineProvider } from "../ClineProvider"
vi.mock("vscode", () => ({
window: {
showInformationMessage: vi.fn(),
showErrorMessage: vi.fn(),
},
workspace: {
workspaceFolders: [{ uri: { fsPath: "/mock/workspace" } }],
},
}))
// Mock imageHelpers - use actual implementations for functions that need real file access
vi.mock("../../tools/helpers/imageHelpers", async (importOriginal) => {
const actual = await importOriginal<typeof import("../../tools/helpers/imageHelpers")>()
return {
...actual,
validateImageForProcessing: vi.fn().mockResolvedValue({ isValid: true, sizeInMB: 0.001 }),
ImageMemoryTracker: vi.fn().mockImplementation(() => ({
getTotalMemoryUsed: vi.fn().mockReturnValue(0),
addMemoryUsage: vi.fn(),
})),
}
})
describe("webviewMessageHandler - image mentions (integration)", () => {
it("resolves image mentions for newTask and passes images to createTask", async () => {
const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), "roo-image-mentions-"))
try {
const imgBytes = Buffer.from("png-bytes")
await fs.writeFile(path.join(tmpRoot, "cat.png"), imgBytes)
const mockProvider = {
cwd: tmpRoot,
getCurrentTask: vi.fn().mockReturnValue(undefined),
createTask: vi.fn().mockResolvedValue(undefined),
postMessageToWebview: vi.fn().mockResolvedValue(undefined),
getState: vi.fn().mockResolvedValue({
maxImageFileSize: 5,
maxTotalImageSize: 20,
}),
} as unknown as ClineProvider
await webviewMessageHandler(mockProvider, {
type: "newTask",
text: "Please look at @/cat.png",
images: [],
} as any)
expect(mockProvider.createTask).toHaveBeenCalledWith("Please look at @/cat.png", [
`data:image/png;base64,${imgBytes.toString("base64")}`,
])
} finally {
await fs.rm(tmpRoot, { recursive: true, force: true })
}
})
it("resolves image mentions for askResponse and passes images to handleWebviewAskResponse", async () => {
const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), "roo-image-mentions-"))
try {
const imgBytes = Buffer.from("jpg-bytes")
await fs.writeFile(path.join(tmpRoot, "cat.jpg"), imgBytes)
const handleWebviewAskResponse = vi.fn()
const mockProvider = {
cwd: tmpRoot,
getCurrentTask: vi.fn().mockReturnValue({
cwd: tmpRoot,
handleWebviewAskResponse,
}),
getState: vi.fn().mockResolvedValue({
maxImageFileSize: 5,
maxTotalImageSize: 20,
}),
} as unknown as ClineProvider
await webviewMessageHandler(mockProvider, {
type: "askResponse",
askResponse: "messageResponse",
text: "Please look at @/cat.jpg",
images: [],
} as any)
expect(handleWebviewAskResponse).toHaveBeenCalledWith("messageResponse", "Please look at @/cat.jpg", [
`data:image/jpeg;base64,${imgBytes.toString("base64")}`,
])
} finally {
await fs.rm(tmpRoot, { recursive: true, force: true })
}
})
it("resolves gif image mentions (matching read_file behavior)", async () => {
const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), "roo-image-mentions-"))
try {
const imgBytes = Buffer.from("gif-bytes")
await fs.writeFile(path.join(tmpRoot, "animation.gif"), imgBytes)
const mockProvider = {
cwd: tmpRoot,
getCurrentTask: vi.fn().mockReturnValue(undefined),
createTask: vi.fn().mockResolvedValue(undefined),
postMessageToWebview: vi.fn().mockResolvedValue(undefined),
getState: vi.fn().mockResolvedValue({
maxImageFileSize: 5,
maxTotalImageSize: 20,
}),
} as unknown as ClineProvider
await webviewMessageHandler(mockProvider, {
type: "newTask",
text: "See @/animation.gif",
images: [],
} as any)
expect(mockProvider.createTask).toHaveBeenCalledWith("See @/animation.gif", [
`data:image/gif;base64,${imgBytes.toString("base64")}`,
])
} finally {
await fs.rm(tmpRoot, { recursive: true, force: true })
}
})
})