Skip to content

Commit

Permalink
Merge pull request #3498 from continuedev/nate/quick-edit-f4d8
Browse files Browse the repository at this point in the history
prompt files e2e tests
  • Loading branch information
sestinj authored Jan 11, 2025
2 parents 95a2329 + d389bb7 commit e9f16ad
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 8 deletions.
34 changes: 33 additions & 1 deletion core/llm/llms/Mock.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { ChatMessage, CompletionOptions } from "../../index.js";
import { ChatMessage, CompletionOptions, LLMOptions } from "../../index.js";
import { BaseLLM } from "../index.js";

type MockMessage = ChatMessage | "REPEAT_LAST_MSG";

class MockLLM extends BaseLLM {
public completion: string = "Test Completion";
public chatStreams: MockMessage[][] | undefined;
static providerName = "mock";

constructor(options: LLMOptions) {
super(options);
this.templateMessages = undefined;
this.chatStreams = options.requestOptions?.extraBodyProperties?.chatStream;
}

protected async *_streamComplete(
prompt: string,
signal: AbortSignal,
Expand All @@ -18,6 +27,29 @@ class MockLLM extends BaseLLM {
signal: AbortSignal,
options: CompletionOptions,
): AsyncGenerator<ChatMessage> {
if (this.chatStreams) {
const chatStream =
this.chatStreams?.[
messages.filter((m) => m.role === "user" || m.role === "tool")
.length - 1
];
if (chatStream) {
for (const message of chatStream) {
switch (message) {
case "REPEAT_LAST_MSG":
yield {
role: "assistant",
content: messages[messages.length - 1].content,
};
break;
default:
yield message;
}
}
}
return;
}

for (const char of this.completion) {
yield {
role: "assistant",
Expand Down
23 changes: 23 additions & 0 deletions extensions/vscode/e2e/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
### Setup

When running e2e tests for the first time, or after changing non-test source code:

```bash
npm run e2e:all
```

### Run

Afterward, you can run the tests with as long as you've only changed the e2e test code:

```bash
npm run e2e:quick
```

### Writing tests

All e2e tests are separated (by folder) into

- `selectors` - functions that return elements
- `actions` - functions that perform actions on the editor
- `tests` - the actual tests, which are typically longer paths of functionality rather than individual actions
8 changes: 7 additions & 1 deletion extensions/vscode/e2e/selectors/GUI.selectors.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { By, WebDriver, WebView } from "vscode-extension-tester";

import { SelectorUtils } from "./SelectorUtils";

export class GUISelectors {
Expand Down Expand Up @@ -31,6 +30,13 @@ export class GUISelectors {
return SelectorUtils.getElementByDataTestId(view, "submit-input-button");
}

public static getAcceptToolCallButton(view: WebView) {
return SelectorUtils.getElementByDataTestId(
view,
"accept-tool-call-button",
);
}

public static getModelDropdownButton(view: WebView) {
return SelectorUtils.getElementByDataTestId(view, "model-select-button");
}
Expand Down
32 changes: 32 additions & 0 deletions extensions/vscode/e2e/test-continue/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,38 @@
"title": "Mock",
"provider": "mock",
"model": "this field is not used"
},
{
"provider": "mock",
"title": "TOOL MOCK LLM",
"model": "claude-3-5-sonnet-latest",
"requestOptions": {
"extraBodyProperties": {
"chatStream": [
[
{
"role": "assistant",
"content": "I'm going to call a tool:"
},
{
"role": "assistant",
"content": "",
"toolCalls": [
{
"id": "test_id",
"type": "function",
"function": {
"name": "builtin_exact_search",
"arguments": "{\"query\": \"\\\" won't be matched because of escaped quotes \\\"\"}"
}
}
]
}
],
["REPEAT_LAST_MSG"]
]
}
}
}
],
"analytics": {
Expand Down
7 changes: 6 additions & 1 deletion extensions/vscode/e2e/tests/Autocomplete.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { EditorView, TextEditor } from "vscode-extension-tester";
import {
EditorView,
InputBox,
TextEditor,
Workbench,
} from "vscode-extension-tester";

import { AutocompleteActions } from "../actions/Autocomplete.actions";
import { GlobalActions } from "../actions/Global.actions";
Expand Down
20 changes: 17 additions & 3 deletions extensions/vscode/e2e/tests/GUI.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { expect } from "chai";
import {
EditorView,
WebView,
WebDriver,
Key,
WebElement,
VSBrowser,
WebDriver,
WebElement,
WebView,
until,
} from "vscode-extension-tester";

Expand Down Expand Up @@ -193,6 +193,20 @@ describe("GUI Test", () => {
}).timeout(DEFAULT_TIMEOUT.XL);
});

describe.skip("Chat with tools", () => {
it("should render tool call", async () => {
await GUIActions.selectModelFromDropdown(view, "TOOL MOCK LLM");

const [messageInput] = await GUISelectors.getMessageInputFields(view);
await messageInput.sendKeys("Hello");
await messageInput.sendKeys(Key.ENTER);

await TestUtils.waitForSuccess(
() => GUISelectors.getThreadMessageByText(view, "No matches found"), // Defined in extensions/vscode/e2e/test-continue/config.json's TOOL MOCK LLM that we are calling the exact search tool
);
});
});

describe("Chat Paths", () => {
it("Send many messages → chat auto scrolls → go to history → open previous chat → it is scrolled to the bottom", async () => {
for (let i = 0; i <= 20; i++) {
Expand Down
65 changes: 65 additions & 0 deletions extensions/vscode/e2e/tests/PromptFile.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { expect } from "chai";
import {
EditorView,
InputBox,
Key,
TextEditor,
Workbench,
} from "vscode-extension-tester";

import { GlobalActions } from "../actions/Global.actions";
import { DEFAULT_TIMEOUT } from "../constants";

describe("Prompt file", () => {
let editor: TextEditor;

beforeEach(async function () {
this.timeout(DEFAULT_TIMEOUT.XL);

await GlobalActions.openTestWorkspace();
await new Workbench().executeCommand("File: New Untitled Text File");
await new Workbench().executeCommand("Change Language Mode");
const inputBox = await new InputBox();
await inputBox.setText("Prompt Language");
await inputBox.confirm();
editor = (await new EditorView().openEditor("Untitled-1")) as TextEditor;
});

afterEach(async function () {
this.timeout(DEFAULT_TIMEOUT.XL);
await editor.clearText();
await new EditorView().closeAllEditors();
});

it("Should display intellisense for default context providers and preamble", async () => {
// Check that "@" dropdown in body works
const providers = [
"currentFile",
"open",
"os",
"problems",
"repo-map",
"terminal",
"tree",
];
for (const provider of providers) {
await editor.typeText("@" + provider.slice(0, 2));
await editor.typeText(Key.ENTER);
const text = await editor.getText();
expect(text).equals("@" + provider);
await editor.clearText();
}

// Check that dropdown for properties in preamble works
// await editor.typeText(Key.ENTER);
// await editor.typeText(Key.ENTER);
// await editor.typeText("---");
// await editor.typeText(Key.UP);
// await editor.typeText(Key.UP);
// await editor.typeText(Key.SPACE);
// await editor.typeText(Key.BACK_SPACE);
// await editor.typeText(Key.ENTER);
// const text = await editor.getText();
// expect(text).equals("description: \n\n---");
}).timeout(DEFAULT_TIMEOUT.XL);
});
7 changes: 5 additions & 2 deletions gui/src/pages/gui/ToolCallDiv/ToolCallButtonsDiv.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import {
vscButtonForeground,
} from "../../../components";
import Spinner from "../../../components/gui/Spinner";
import { useAppDispatch } from "../../../redux/hooks";
import { selectCurrentToolCall } from "../../../redux/selectors/selectCurrentToolCall";
import { callTool } from "../../../redux/thunks/callTool";
import { cancelTool } from "../../../redux/thunks/cancelTool";
import { useAppDispatch } from "../../../redux/hooks";

const ButtonContainer = styled.div`
display: flex;
Expand Down Expand Up @@ -75,7 +75,10 @@ export function ToolCallButtons(props: ToolCallButtonsProps) {
<RejectButton onClick={() => dispatch(cancelTool())}>
Cancel
</RejectButton>
<AcceptButton onClick={() => dispatch(callTool())}>
<AcceptButton
onClick={() => dispatch(callTool())}
data-testid="accept-tool-call-button"
>
Continue
</AcceptButton>
</>
Expand Down

0 comments on commit e9f16ad

Please sign in to comment.