Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit e1a948f

Browse files
authored
Cody: Add e2e test for inline assist and add cody tests to sg(#52337)
1 parent ff93611 commit e1a948f

File tree

15 files changed

+223
-46
lines changed

15 files changed

+223
-46
lines changed

client/cody/CONTRIBUTING.md

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,40 @@
3232
1. Unit tests:
3333

3434
```shell
35-
$ cd client/cody
36-
$ pnpm test:unit
35+
cd client/cody
36+
pnpm test:unit
3737
```
3838

3939
2. Integration tests:
4040

4141
```shell
42-
$ cd client/cody
43-
$ pnpm test:integration
42+
cd client/cody
43+
pnpm test:integration
44+
```
45+
46+
3. E2E tests:
47+
48+
To run all the tests inside the `client/cody/test/e2e` directory:
49+
50+
```shell
51+
cd client/cody
52+
pnpm test:e2e
53+
```
54+
55+
To run test individually, pass in the name of the test by replacing $TEST_NAME below.
56+
57+
```sh
58+
pnpm test:e2e $TEST_NAME
59+
# Example: Run the inline-assist test only
60+
pnpm test:e2e inline-assist
61+
```
62+
63+
Example: Run the inline-assist test only
64+
65+
```sh
66+
pnpm test:e2e --debug
67+
# Example: Run the inline-assist test in debug mode
68+
pnpm test:e2e inline-assist --debug
4469
```
4570

4671
## Release Process

client/cody/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"lint:js": "eslint --cache '**/*.[tj]s?(x)'",
6060
"test:integration": "tsc -b ./test/integration && pnpm run --silent build:dev && node --inspect -r ts-node/register out/test/integration/main.js",
6161
"test:unit": "jest",
62-
"test:e2e": "npx playwright install && pnpm run --silent build:dev && playwright test test/e2e",
62+
"test:e2e": "npx playwright install && pnpm run --silent build:dev && playwright test",
6363
"vscode:prepublish": "scripts/check-rg.sh",
6464
"vsce:package": "pnpm --silent build && vsce package --no-dependencies -o dist/cody.vsix",
6565
"vsce:prerelease": "pnpm --silent build && vsce package patch --pre-release --no-dependencies -o dist/cody.vsix",

client/cody/playwright.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { defineConfig } from '@playwright/test'
2+
3+
// eslint-disable-next-line import/no-default-export
4+
export default defineConfig({
5+
workers: 1,
6+
testDir: 'test/e2e',
7+
})

client/cody/src/configuration.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { SecretStorage, getAccessToken } from './services/SecretStorageProvider'
1212
* All configuration values, with some sanitization performed.
1313
*/
1414
export function getConfiguration(config: Pick<vscode.WorkspaceConfiguration, 'get'>): Configuration {
15+
const isTesting = process.env.CODY_TESTING === 'true'
16+
1517
let debugRegex: RegExp | null = null
1618
try {
1719
const debugPattern: string | null = config.get<string | null>('cody.debug.filter', null)
@@ -30,15 +32,15 @@ export function getConfiguration(config: Pick<vscode.WorkspaceConfiguration, 'ge
3032
return {
3133
serverEndpoint: sanitizeServerEndpoint(config.get('cody.serverEndpoint', '')),
3234
codebase: sanitizeCodebase(config.get('cody.codebase')),
35+
customHeaders: config.get<object>('cody.customHeaders', {}) as Record<string, string>,
36+
useContext: config.get<ConfigurationUseContext>('cody.useContext') || 'embeddings',
3337
debugEnable: config.get<boolean>('cody.debug.enable', false),
3438
debugVerbose: config.get<boolean>('cody.debug.verbose', false),
3539
debugFilter: debugRegex,
36-
useContext: config.get<ConfigurationUseContext>('cody.useContext') || 'embeddings',
37-
experimentalSuggest: config.get('cody.experimental.suggestions', false),
38-
experimentalChatPredictions: config.get('cody.experimental.chatPredictions', false),
39-
experimentalInline: config.get('cody.experimental.inline', false),
40-
experimentalGuardrails: config.get('cody.experimental.guardrails', false),
41-
customHeaders: config.get<object>('cody.customHeaders', {}) as Record<string, string>,
40+
experimentalSuggest: config.get('cody.experimental.suggestions', isTesting),
41+
experimentalChatPredictions: config.get('cody.experimental.chatPredictions', isTesting),
42+
experimentalInline: config.get('cody.experimental.inline', isTesting),
43+
experimentalGuardrails: config.get('cody.experimental.guardrails', isTesting),
4244
}
4345
}
4446

client/cody/src/services/DecorationProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export class DecorationProvider {
4747
await vscode.window.showTextDocument(this.fileUri)
4848
if (this.status === CodyTaskState.done) {
4949
this.decorationTypePending.dispose()
50-
this.decorations.push({ range, hoverMessage: 'Cody Task#' + this.id })
50+
this.decorations.push({ range, hoverMessage: 'Cody Assist #' + this.id })
5151
this.decorationsForIcon.push({ range: getSingleLineRange(range.start.line) })
5252
vscode.window.activeTextEditor?.setDecorations(this.decorationTypeIcon, this.decorationsForIcon)
5353
vscode.window.activeTextEditor?.setDecorations(this.decorationTypeDiff, this.decorations)

client/cody/test/e2e/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/cody/test/e2e/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Cody E2E Testing
2+
3+
See the [client/cody/CONTRIBUTING.md](../../CONTRIBUTING.md) for more information.
4+
5+
### Commands
6+
7+
#### All Tests
8+
9+
```sh
10+
pnpm test:e2e
11+
```
12+
13+
#### Individual Test
14+
15+
```sh
16+
pnpm test:e2e $TEST_NAME
17+
```
18+
19+
#### Debug Test
20+
21+
```sh
22+
pnpm test:e2e --debug
23+
```

client/cody/test/e2e/common.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Frame, Locator, Page, expect } from '@playwright/test'
2+
3+
import { SERVER_URL, VALID_TOKEN } from '../fixtures/mock-server'
4+
5+
// Sign into Cody with valid auth from the sidebar
6+
export const sidebarSignin = async (sidebar: Frame): Promise<void> => {
7+
await sidebar.getByRole('textbox', { name: 'Sourcegraph Instance URL' }).fill(SERVER_URL)
8+
await sidebar.getByRole('textbox', { name: 'Access Token (docs)' }).fill(VALID_TOKEN)
9+
await sidebar.getByRole('button', { name: 'Sign In' }).click()
10+
11+
await expect(sidebar.getByText("Hello! I'm Cody.")).toBeVisible()
12+
}
13+
14+
// Selector for the Explorer button in the sidebar that would match on Mac and Linux
15+
const sidbarExplorerRole = { name: /Explorer.*/ }
16+
export const sidebarExplorer = (page: Page): Locator => page.getByRole('tab', sidbarExplorerRole)

client/cody/test/e2e/helpers.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { mkdtempSync, rmdirSync } from 'fs'
1+
import { mkdir, mkdtempSync, rmdirSync, writeFile } from 'fs'
22
import { tmpdir } from 'os'
33
import * as path from 'path'
44

@@ -24,6 +24,8 @@ export const test = base
2424

2525
const workspaceDirectory = path.join(codyRoot, 'test', 'fixtures', 'workspace')
2626

27+
await buildWorkSpaceSettings(workspaceDirectory)
28+
2729
// See: https://github.com/microsoft/vscode-test/blob/main/lib/runTest.ts
2830
const app = await electron.launch({
2931
executablePath: vscodeExecutablePath,
@@ -113,7 +115,7 @@ export async function getCodySidebar(page: Page): Promise<Frame> {
113115
return null
114116
}
115117
await waitUntil(async () => (await findCodySidebarFrame()) !== null)
116-
return (await findCodySidebarFrame())!
118+
return (await findCodySidebarFrame()) || page.mainFrame()
117119
}
118120

119121
async function waitUntil(predicate: () => boolean | Promise<boolean>): Promise<void> {
@@ -127,3 +129,23 @@ async function waitUntil(predicate: () => boolean | Promise<boolean>): Promise<v
127129
function escapeToPath(text: string): string {
128130
return text.replace(/\W/g, '_')
129131
}
132+
133+
// Build a workspace settings file that enables the experimental inline mode
134+
export async function buildWorkSpaceSettings(workspaceDirectory: string): Promise<void> {
135+
const settings = {
136+
'cody.experimental.inline': true,
137+
}
138+
// create a temporary directory with settings.json and add to the workspaceDirectory
139+
const workspaceSettingsPath = path.join(workspaceDirectory, '.vscode', 'settings.json')
140+
const workspaceSettingsDirectory = path.join(workspaceDirectory, '.vscode')
141+
mkdir(workspaceSettingsDirectory, { recursive: true }, () => {})
142+
await new Promise<void>((resolve, reject) => {
143+
writeFile(workspaceSettingsPath, JSON.stringify(settings), error => {
144+
if (error) {
145+
reject(error)
146+
} else {
147+
resolve()
148+
}
149+
})
150+
})
151+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { expect } from '@playwright/test'
2+
3+
import { sidebarExplorer, sidebarSignin } from './common'
4+
import { test } from './helpers'
5+
6+
test('start a fixup job from inline assist with valid auth', async ({ page, sidebar }) => {
7+
// Sign into Cody
8+
await sidebarSignin(sidebar)
9+
10+
// Open the Explorer view from the sidebar
11+
await sidebarExplorer(page).click()
12+
13+
// Select the second files from the tree view, which is the index.html file
14+
await page.locator('.monaco-highlighted-label').nth(2).click()
15+
16+
// Click on line number 6 to open the comment thread
17+
await page.locator('.comment-diff-added').nth(5).hover()
18+
await page.locator('.comment-diff-added').nth(5).click()
19+
20+
// After opening the comment thread, we need to wait for the editor to load
21+
await page.waitForSelector('.monaco-editor')
22+
await page.waitForSelector('.monaco-text-button')
23+
24+
// Type in the instruction for fixup
25+
await page.keyboard.type('/fix replace hello with goodbye')
26+
// Click on the submit button with the name Ask Cody
27+
await page.click('.monaco-text-button')
28+
29+
// TODO: Capture processing state. It is currently to quick to capture the processing elements
30+
// Wait for the code lens to show up to ensure that the fixup has been applied
31+
// await expect(page.getByText('Processing by Cody')).toBeVisible()
32+
33+
// Ensures Code Lens is added
34+
await expect(page.getByText('Edited by Cody')).toBeVisible()
35+
await expect(page.getByText('<title>Goodbye Cody</title>')).toBeVisible()
36+
37+
// Ensures Cody's fixup is displayed in comment thread
38+
await expect(page.getByText('Check your document for updates from Cody.')).toBeVisible()
39+
40+
// Ensures Decorations is displayed by checking hover text
41+
await page.getByText('>Goodbye Cody<').hover()
42+
// The decoration text on hover should start with 'Cody Fixup #' and end with random number
43+
await page.getByRole('tooltip', { name: /Cody Assist.*/ }).click()
44+
})

0 commit comments

Comments
 (0)