Loading src/common/chat/gitlab_chat_slash_commands.test.ts 0 → 100644 +13 −0 Original line number Diff line number Diff line import { defaultSlashCommands } from './gitlab_chat_slash_commands'; describe('GitLab Chat Slash Commands', () => { it('returns pre-defined set of slash commands', () => { expect(defaultSlashCommands).toEqual([ expect.objectContaining({ name: '/reset' }), expect.objectContaining({ name: '/clean' }), expect.objectContaining({ name: '/tests' }), expect.objectContaining({ name: '/refactor' }), expect.objectContaining({ name: '/explain' }), ]); }); }); src/common/chat/gitlab_chat_slash_commands.ts 0 → 100644 +39 −0 Original line number Diff line number Diff line export interface GitlabChatSlashCommand { name: string; description: string; shouldSubmit?: boolean; } const ResetCommand: GitlabChatSlashCommand = { name: '/reset', description: 'Reset conversation, ignore the previous messages.', shouldSubmit: true, }; const CleanCommand: GitlabChatSlashCommand = { name: '/clean', description: 'Delet all messages in this conversation.', }; const TestsCommand: GitlabChatSlashCommand = { name: '/tests', description: 'Write tests for the selected snippet.', }; const RefactorCommand: GitlabChatSlashCommand = { name: '/refactor', description: 'Refactor the selected snippet.', }; const ExplainCommand: GitlabChatSlashCommand = { name: '/explain', description: 'Explain the selected snippet.', }; export const defaultSlashCommands: GitlabChatSlashCommand[] = [ ResetCommand, CleanCommand, TestsCommand, RefactorCommand, ExplainCommand, ]; src/common/chat/gitlab_chat_view.test.ts +4 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ import * as vscode from 'vscode'; import { GitLabChatView } from './gitlab_chat_view'; import { GitLabChatRecord } from './gitlab_chat_record'; import { prepareWebviewSource } from '../utils/webviews/prepare_webview_source'; import { defaultSlashCommands } from './gitlab_chat_slash_commands'; jest.mock('../utils/webviews/wait_for_webview'); jest.mock('../utils/webviews/prepare_webview_source', () => ({ Loading Loading @@ -56,6 +57,9 @@ describe('GitLabChatView', () => { webview.webview, context, 'gitlab_duo_chat', { slashCommands: defaultSlashCommands, }, ); }); }); Loading src/common/chat/gitlab_chat_view.ts +11 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,8 @@ import { GitLabChatRecord } from './gitlab_chat_record'; import { waitForWebview } from '../utils/webviews/wait_for_webview'; import { log } from '../log'; import { prepareWebviewSource } from '../utils/webviews/prepare_webview_source'; import { defaultSlashCommands } from './gitlab_chat_slash_commands'; import type { GitlabChatSlashCommand } from './gitlab_chat_slash_commands'; export const CHAT_SIDEBAR_VIEW_ID = 'gl.chatView'; Loading Loading @@ -40,6 +42,10 @@ interface FeedbackMessage { }; } interface WebViewInitialStateInterface { slashCommands: GitlabChatSlashCommand[]; } export type ViewEmittedMessage = NewPromptMessage | FeedbackMessage | CleanChatMessage; export class GitLabChatView { Loading @@ -66,10 +72,15 @@ export class GitLabChatView { enableScripts: true, }; const initialState: WebViewInitialStateInterface = { slashCommands: defaultSlashCommands, }; this.#chatView.webview.html = await prepareWebviewSource( this.#chatView.webview, this.#context, 'gitlab_duo_chat', initialState, ); await waitForWebview(this.#chatView.webview); Loading src/common/utils/webviews/prepare_webview_source.test.ts +18 −3 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ describe('prepareWebViewSource', () => { <link rel="stylesheet" href="/gitlab_duo_chat/assets/index.css"> </head> <body> <div id="app"></div> <div id="app" data-initial-state='{{initialState}}'></div> </body> </html> `; Loading @@ -35,13 +35,17 @@ describe('prepareWebViewSource', () => { <link rel="stylesheet" href="file:///foo/bar/webviews/gitlab_duo_chat/assets/index.css"> </head> <body> <div id="app"></div> <div id="app" data-initial-state=''></div> </body> </html> `; let context: vscode.ExtensionContext; let webview: vscode.Webview; const setHTMLFixture = (htmlContent: string) => { document.body.innerHTML = htmlContent; }; beforeEach(() => { context = { extensionUri: vscode.Uri.file('/foo/bar'), Loading @@ -59,7 +63,18 @@ describe('prepareWebViewSource', () => { it('returns WebView source with inserted nonce and assets', async () => { const result = await prepareWebviewSource(webview, context, 'gitlab_duo_chat'); expect(result).toStrictEqual(expectedHTML); }); it('returns WebView source with initial app state set', async () => { const initState = { foo: 'bar', }; const result = await prepareWebviewSource(webview, context, 'gitlab_duo_chat', initState); const expectedHtmlString = expectedHTML.replace( "data-initial-state=''", `data-initial-state='${JSON.stringify(initState)}'`, ); expect(result).toStrictEqual(expectedHtmlString); }); }); Loading
src/common/chat/gitlab_chat_slash_commands.test.ts 0 → 100644 +13 −0 Original line number Diff line number Diff line import { defaultSlashCommands } from './gitlab_chat_slash_commands'; describe('GitLab Chat Slash Commands', () => { it('returns pre-defined set of slash commands', () => { expect(defaultSlashCommands).toEqual([ expect.objectContaining({ name: '/reset' }), expect.objectContaining({ name: '/clean' }), expect.objectContaining({ name: '/tests' }), expect.objectContaining({ name: '/refactor' }), expect.objectContaining({ name: '/explain' }), ]); }); });
src/common/chat/gitlab_chat_slash_commands.ts 0 → 100644 +39 −0 Original line number Diff line number Diff line export interface GitlabChatSlashCommand { name: string; description: string; shouldSubmit?: boolean; } const ResetCommand: GitlabChatSlashCommand = { name: '/reset', description: 'Reset conversation, ignore the previous messages.', shouldSubmit: true, }; const CleanCommand: GitlabChatSlashCommand = { name: '/clean', description: 'Delet all messages in this conversation.', }; const TestsCommand: GitlabChatSlashCommand = { name: '/tests', description: 'Write tests for the selected snippet.', }; const RefactorCommand: GitlabChatSlashCommand = { name: '/refactor', description: 'Refactor the selected snippet.', }; const ExplainCommand: GitlabChatSlashCommand = { name: '/explain', description: 'Explain the selected snippet.', }; export const defaultSlashCommands: GitlabChatSlashCommand[] = [ ResetCommand, CleanCommand, TestsCommand, RefactorCommand, ExplainCommand, ];
src/common/chat/gitlab_chat_view.test.ts +4 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ import * as vscode from 'vscode'; import { GitLabChatView } from './gitlab_chat_view'; import { GitLabChatRecord } from './gitlab_chat_record'; import { prepareWebviewSource } from '../utils/webviews/prepare_webview_source'; import { defaultSlashCommands } from './gitlab_chat_slash_commands'; jest.mock('../utils/webviews/wait_for_webview'); jest.mock('../utils/webviews/prepare_webview_source', () => ({ Loading Loading @@ -56,6 +57,9 @@ describe('GitLabChatView', () => { webview.webview, context, 'gitlab_duo_chat', { slashCommands: defaultSlashCommands, }, ); }); }); Loading
src/common/chat/gitlab_chat_view.ts +11 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,8 @@ import { GitLabChatRecord } from './gitlab_chat_record'; import { waitForWebview } from '../utils/webviews/wait_for_webview'; import { log } from '../log'; import { prepareWebviewSource } from '../utils/webviews/prepare_webview_source'; import { defaultSlashCommands } from './gitlab_chat_slash_commands'; import type { GitlabChatSlashCommand } from './gitlab_chat_slash_commands'; export const CHAT_SIDEBAR_VIEW_ID = 'gl.chatView'; Loading Loading @@ -40,6 +42,10 @@ interface FeedbackMessage { }; } interface WebViewInitialStateInterface { slashCommands: GitlabChatSlashCommand[]; } export type ViewEmittedMessage = NewPromptMessage | FeedbackMessage | CleanChatMessage; export class GitLabChatView { Loading @@ -66,10 +72,15 @@ export class GitLabChatView { enableScripts: true, }; const initialState: WebViewInitialStateInterface = { slashCommands: defaultSlashCommands, }; this.#chatView.webview.html = await prepareWebviewSource( this.#chatView.webview, this.#context, 'gitlab_duo_chat', initialState, ); await waitForWebview(this.#chatView.webview); Loading
src/common/utils/webviews/prepare_webview_source.test.ts +18 −3 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ describe('prepareWebViewSource', () => { <link rel="stylesheet" href="/gitlab_duo_chat/assets/index.css"> </head> <body> <div id="app"></div> <div id="app" data-initial-state='{{initialState}}'></div> </body> </html> `; Loading @@ -35,13 +35,17 @@ describe('prepareWebViewSource', () => { <link rel="stylesheet" href="file:///foo/bar/webviews/gitlab_duo_chat/assets/index.css"> </head> <body> <div id="app"></div> <div id="app" data-initial-state=''></div> </body> </html> `; let context: vscode.ExtensionContext; let webview: vscode.Webview; const setHTMLFixture = (htmlContent: string) => { document.body.innerHTML = htmlContent; }; beforeEach(() => { context = { extensionUri: vscode.Uri.file('/foo/bar'), Loading @@ -59,7 +63,18 @@ describe('prepareWebViewSource', () => { it('returns WebView source with inserted nonce and assets', async () => { const result = await prepareWebviewSource(webview, context, 'gitlab_duo_chat'); expect(result).toStrictEqual(expectedHTML); }); it('returns WebView source with initial app state set', async () => { const initState = { foo: 'bar', }; const result = await prepareWebviewSource(webview, context, 'gitlab_duo_chat', initState); const expectedHtmlString = expectedHTML.replace( "data-initial-state=''", `data-initial-state='${JSON.stringify(initState)}'`, ); expect(result).toStrictEqual(expectedHtmlString); }); });