Issue  作成時にタスクを積むかを確認

This commit is contained in:
nrslib 2026-02-10 23:52:52 +09:00
parent 11045d1c57
commit dbc296e97a
2 changed files with 26 additions and 2 deletions

View File

@ -14,6 +14,10 @@ vi.mock('../shared/ui/index.js', () => ({
withProgress: vi.fn(async (_start, _done, operation) => operation()), withProgress: vi.fn(async (_start, _done, operation) => operation()),
})); }));
vi.mock('../shared/prompt/index.js', () => ({
confirm: vi.fn(() => true),
}));
vi.mock('../shared/utils/index.js', async (importOriginal) => ({ vi.mock('../shared/utils/index.js', async (importOriginal) => ({
...(await importOriginal<Record<string, unknown>>()), ...(await importOriginal<Record<string, unknown>>()),
createLogger: () => ({ createLogger: () => ({
@ -88,6 +92,7 @@ import { checkGhCli, fetchIssue, formatIssueAsTask, parseIssueNumbers } from '..
import { selectAndExecuteTask, determinePiece, createIssueAndSaveTask } from '../features/tasks/index.js'; import { selectAndExecuteTask, determinePiece, createIssueAndSaveTask } from '../features/tasks/index.js';
import { interactiveMode, selectRecentSession } from '../features/interactive/index.js'; import { interactiveMode, selectRecentSession } from '../features/interactive/index.js';
import { loadGlobalConfig } from '../infra/config/index.js'; import { loadGlobalConfig } from '../infra/config/index.js';
import { confirm } from '../shared/prompt/index.js';
import { isDirectTask } from '../app/cli/helpers.js'; import { isDirectTask } from '../app/cli/helpers.js';
import { executeDefaultAction } from '../app/cli/routing.js'; import { executeDefaultAction } from '../app/cli/routing.js';
import type { GitHubIssue } from '../infra/github/types.js'; import type { GitHubIssue } from '../infra/github/types.js';
@ -102,6 +107,7 @@ const mockCreateIssueAndSaveTask = vi.mocked(createIssueAndSaveTask);
const mockInteractiveMode = vi.mocked(interactiveMode); const mockInteractiveMode = vi.mocked(interactiveMode);
const mockSelectRecentSession = vi.mocked(selectRecentSession); const mockSelectRecentSession = vi.mocked(selectRecentSession);
const mockLoadGlobalConfig = vi.mocked(loadGlobalConfig); const mockLoadGlobalConfig = vi.mocked(loadGlobalConfig);
const mockConfirm = vi.mocked(confirm);
const mockIsDirectTask = vi.mocked(isDirectTask); const mockIsDirectTask = vi.mocked(isDirectTask);
function createMockIssue(number: number): GitHubIssue { function createMockIssue(number: number): GitHubIssue {
@ -123,6 +129,7 @@ beforeEach(() => {
// Default setup // Default setup
mockDeterminePiece.mockResolvedValue('default'); mockDeterminePiece.mockResolvedValue('default');
mockInteractiveMode.mockResolvedValue({ action: 'execute', task: 'summarized task' }); mockInteractiveMode.mockResolvedValue({ action: 'execute', task: 'summarized task' });
mockConfirm.mockResolvedValue(true);
mockIsDirectTask.mockReturnValue(false); mockIsDirectTask.mockReturnValue(false);
mockParseIssueNumbers.mockReturnValue([]); mockParseIssueNumbers.mockReturnValue([]);
}); });
@ -273,9 +280,10 @@ describe('Issue resolution in routing', () => {
}); });
describe('create_issue action', () => { describe('create_issue action', () => {
it('should delegate to createIssueAndSaveTask with cwd, task, and pieceId', async () => { it('should delegate to createIssueAndSaveTask with cwd, task, and pieceId when confirmed', async () => {
// Given // Given
mockInteractiveMode.mockResolvedValue({ action: 'create_issue', task: 'New feature request' }); mockInteractiveMode.mockResolvedValue({ action: 'create_issue', task: 'New feature request' });
mockConfirm.mockResolvedValue(true);
// When // When
await executeDefaultAction(); await executeDefaultAction();
@ -288,9 +296,22 @@ describe('Issue resolution in routing', () => {
); );
}); });
it('should skip createIssueAndSaveTask when not confirmed', async () => {
// Given
mockInteractiveMode.mockResolvedValue({ action: 'create_issue', task: 'New feature request' });
mockConfirm.mockResolvedValue(false);
// When
await executeDefaultAction();
// Then: task should not be added when user declines
expect(mockCreateIssueAndSaveTask).not.toHaveBeenCalled();
});
it('should not call selectAndExecuteTask when create_issue action is chosen', async () => { it('should not call selectAndExecuteTask when create_issue action is chosen', async () => {
// Given // Given
mockInteractiveMode.mockResolvedValue({ action: 'create_issue', task: 'New feature request' }); mockInteractiveMode.mockResolvedValue({ action: 'create_issue', task: 'New feature request' });
mockConfirm.mockResolvedValue(true);
// When // When
await executeDefaultAction(); await executeDefaultAction();

View File

@ -6,6 +6,7 @@
*/ */
import { info, error, withProgress } from '../../shared/ui/index.js'; import { info, error, withProgress } from '../../shared/ui/index.js';
import { confirm } from '../../shared/prompt/index.js';
import { getErrorMessage } from '../../shared/utils/index.js'; import { getErrorMessage } from '../../shared/utils/index.js';
import { getLabel } from '../../shared/i18n/index.js'; import { getLabel } from '../../shared/i18n/index.js';
import { fetchIssue, formatIssueAsTask, checkGhCli, parseIssueNumbers, type GitHubIssue } from '../../infra/github/index.js'; import { fetchIssue, formatIssueAsTask, checkGhCli, parseIssueNumbers, type GitHubIssue } from '../../infra/github/index.js';
@ -204,7 +205,9 @@ export async function executeDefaultAction(task?: string): Promise<void> {
break; break;
case 'create_issue': case 'create_issue':
await createIssueAndSaveTask(resolvedCwd, result.task, pieceId); if (await confirm('Add this issue to tasks?', true)) {
await createIssueAndSaveTask(resolvedCwd, result.task, pieceId);
}
break; break;
case 'save_task': case 'save_task':