Path: blob/main/extensions/copilot/src/extension/chronicle/common/test/standupPrompt.spec.ts
13405 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { describe, expect, it } from 'vitest';6import { extractFilePath, extractRefsFromMcpTool, extractRefsFromTerminal, extractRepoFromMcpTool, isGitHubMcpTool } from '../sessionStoreTracking';7import { type AnnotatedRef, type AnnotatedSession, buildRefsQuery, buildStandupPrompt } from '../standupPrompt';89describe('buildStandupPrompt', () => {10it('returns no-activity message when no sessions', () => {11const result = buildStandupPrompt([], [], [], []);12expect(result).toContain('no sessions were found');13});1415it('includes session data in prompt', () => {16const sessions: AnnotatedSession[] = [17{ id: 'sess-1', branch: 'feature/auth', repository: 'owner/repo', summary: 'Added OAuth', updated_at: '2026-04-06T10:00:00Z', source: 'cloud' },18];19const result = buildStandupPrompt(sessions, [], [], []);20expect(result).toContain('sess-1');21expect(result).toContain('feature/auth');22expect(result).toContain('owner/repo');23expect(result).toContain('Added OAuth');24});2526it('includes refs in prompt', () => {27const sessions: AnnotatedSession[] = [28{ id: 'sess-1', branch: 'main', summary: 'Fix', source: 'cloud' },29];30const refs: AnnotatedRef[] = [31{ session_id: 'sess-1', ref_type: 'pr', ref_value: '42', source: 'cloud' },32{ session_id: 'sess-1', ref_type: 'commit', ref_value: 'abc123', source: 'cloud' },33];34const result = buildStandupPrompt(sessions, refs, [], []);35expect(result).toContain('commit: abc123');36});3738it('shows "No references found" when refs empty', () => {39const sessions: AnnotatedSession[] = [{ id: 'sess-1', branch: 'main', summary: 'Fix', source: 'cloud' }];40const result = buildStandupPrompt(sessions, [], [], []);41expect(result).toContain('No references found.');42});4344it('includes extra context when provided', () => {45const sessions: AnnotatedSession[] = [{ id: 'sess-1', summary: 'Work', source: 'cloud' }];46const result = buildStandupPrompt(sessions, [], [], [], 'Focus on backend changes');47expect(result).toContain('Additional context: Focus on backend changes');48});4950it('shows "unknown" for missing branch and repo', () => {51const sessions: AnnotatedSession[] = [{ id: 'sess-1', summary: 'Work', source: 'cloud' }];52const result = buildStandupPrompt(sessions, [], [], []);53expect(result).toContain('unknown (unknown)');54});5556it('handles multiple sessions from different branches', () => {57const sessions: AnnotatedSession[] = [58{ id: 'sess-1', branch: 'feature/a', repository: 'org/repo', summary: 'Feature A', source: 'cloud' },59{ id: 'sess-2', branch: 'feature/b', repository: 'org/repo', summary: 'Feature B', source: 'cloud' },60];61const result = buildStandupPrompt(sessions, [], [], []);62expect(result).toContain('feature/a');63expect(result).toContain('feature/b');64});6566it('shows source tags for cloud sessions', () => {67const sessions: AnnotatedSession[] = [68{ id: 'cloud-1', branch: 'main', summary: 'Cloud work 1', source: 'cloud' },69{ id: 'cloud-2', branch: 'feature/x', summary: 'Cloud work 2', source: 'cloud' },70];71const refs: AnnotatedRef[] = [72{ session_id: 'cloud-2', ref_type: 'pr', ref_value: '99', source: 'cloud' },73];74const result = buildStandupPrompt(sessions, refs, [], []);75expect(result).toContain('cloud-2 | pr: 99');76});77});7879describe('buildRefsQuery', () => {80it('builds IN clause with escaped IDs', () => {81const query = buildRefsQuery(['sess-1', 'sess-2']);82expect(query).toContain('\'sess-1\'');83expect(query).toContain('\'sess-2\'');84expect(query).toContain('session_refs');85});8687it('escapes single quotes in session IDs', () => {88const query = buildRefsQuery(['it\'s']);89expect(query).toContain('\'it\'\'s\'');90});91});9293describe('extractFilePath', () => {94it('extracts filePath from apply_patch args', () => {95expect(extractFilePath('apply_patch', { filePath: '/src/index.ts' })).toBe('/src/index.ts');96});9798it('extracts path from create tool args', () => {99expect(extractFilePath('create', { path: '/src/new.ts' })).toBe('/src/new.ts');100});101102it('extracts filePath from read_file args', () => {103expect(extractFilePath('read_file', { filePath: '/src/index.ts' })).toBe('/src/index.ts');104});105106it('returns undefined for null args', () => {107expect(extractFilePath('apply_patch', null)).toBeUndefined();108});109110it('returns undefined when no path field exists', () => {111expect(extractFilePath('apply_patch', { content: 'hello' })).toBeUndefined();112});113});114115describe('extractRefsFromMcpTool', () => {116it('extracts PR number from pull_request tool', () => {117const refs = extractRefsFromMcpTool('github-mcp-server-pull_request_read', { pullNumber: 42 });118expect(refs).toEqual([{ ref_type: 'pr', ref_value: '42' }]);119});120121it('extracts issue number from issue tool', () => {122const refs = extractRefsFromMcpTool('github-mcp-server-issue_read', { issue_number: 99 });123expect(refs).toEqual([{ ref_type: 'issue', ref_value: '99' }]);124});125126it('extracts commit SHA from commit tool', () => {127const refs = extractRefsFromMcpTool('github-mcp-server-get_commit', { sha: 'abc123' });128expect(refs).toEqual([{ ref_type: 'commit', ref_value: 'abc123' }]);129});130131it('returns empty for unrecognized tool', () => {132expect(extractRefsFromMcpTool('github-mcp-server-list_repos', {})).toEqual([]);133});134});135136describe('extractRefsFromTerminal', () => {137it('extracts PR URL from gh pr create output', () => {138const refs = extractRefsFromTerminal(139{ command: 'gh pr create --title "feat"' },140'https://github.com/owner/repo/pull/123'141);142expect(refs).toEqual([{ ref_type: 'pr', ref_value: '123' }]);143});144145it('extracts issue URL from gh issue create output', () => {146const refs = extractRefsFromTerminal(147{ command: 'gh issue create --title "bug"' },148'https://github.com/owner/repo/issues/456'149);150expect(refs).toEqual([{ ref_type: 'issue', ref_value: '456' }]);151});152153it('extracts commit SHA from git commit output', () => {154const refs = extractRefsFromTerminal(155{ command: 'git commit -m "fix"' },156'[main abc1234] fix'157);158expect(refs).toEqual([{ ref_type: 'commit', ref_value: 'abc1234' }]);159});160161it('returns empty for missing command', () => {162expect(extractRefsFromTerminal({}, undefined)).toEqual([]);163});164165it('returns empty for unrecognized command', () => {166expect(extractRefsFromTerminal({ command: 'npm install' }, 'done')).toEqual([]);167});168});169170describe('extractRepoFromMcpTool', () => {171it('extracts owner/repo', () => {172expect(extractRepoFromMcpTool({ owner: 'microsoft', repo: 'vscode' })).toBe('microsoft/vscode');173});174175it('returns undefined when owner missing', () => {176expect(extractRepoFromMcpTool({ repo: 'vscode' })).toBeUndefined();177});178179it('returns undefined when repo missing', () => {180expect(extractRepoFromMcpTool({ owner: 'microsoft' })).toBeUndefined();181});182});183184describe('isGitHubMcpTool', () => {185it('returns true for github-mcp-server-* tools', () => {186expect(isGitHubMcpTool('github-mcp-server-pull_request_read')).toBe(true);187});188189it('returns false for other tools', () => {190expect(isGitHubMcpTool('apply_patch')).toBe(false);191});192});193194195