@@ -14,7 +14,9 @@ import {
1414 coreEvents ,
1515 processSingleFileContent ,
1616 type ProcessedFileReadResult ,
17+ readFileWithEncoding ,
1718} from '@google/gemini-cli-core' ;
19+ import { copyToClipboard } from '../utils/commandUtils.js' ;
1820
1921vi . mock ( '@google/gemini-cli-core' , async ( importOriginal ) => {
2022 const actual =
@@ -25,6 +27,7 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
2527 emitFeedback : vi . fn ( ) ,
2628 } ,
2729 processSingleFileContent : vi . fn ( ) ,
30+ readFileWithEncoding : vi . fn ( ) ,
2831 partToString : vi . fn ( ( val ) => val ) ,
2932 } ;
3033} ) ;
@@ -35,9 +38,14 @@ vi.mock('node:path', async (importOriginal) => {
3538 ...actual ,
3639 default : { ...actual } ,
3740 join : vi . fn ( ( ...args ) => args . join ( '/' ) ) ,
41+ basename : vi . fn ( ( p ) => p . split ( '/' ) . pop ( ) ) ,
3842 } ;
3943} ) ;
4044
45+ vi . mock ( '../utils/commandUtils.js' , ( ) => ( {
46+ copyToClipboard : vi . fn ( ) ,
47+ } ) ) ;
48+
4149describe ( 'planCommand' , ( ) => {
4250 let mockContext : CommandContext ;
4351
@@ -115,4 +123,46 @@ describe('planCommand', () => {
115123 text : '# Approved Plan Content' ,
116124 } ) ;
117125 } ) ;
126+
127+ describe ( 'copy subcommand' , ( ) => {
128+ it ( 'should copy the approved plan to clipboard' , async ( ) => {
129+ const mockPlanPath = '/mock/plans/dir/approved-plan.md' ;
130+ vi . mocked (
131+ mockContext . services . config ! . getApprovedPlanPath ,
132+ ) . mockReturnValue ( mockPlanPath ) ;
133+ vi . mocked ( readFileWithEncoding ) . mockResolvedValue ( '# Plan Content' ) ;
134+
135+ const copySubCommand = planCommand . subCommands ?. find (
136+ ( sc ) => sc . name === 'copy' ,
137+ ) ;
138+ if ( ! copySubCommand ?. action ) throw new Error ( 'Copy action missing' ) ;
139+
140+ await copySubCommand . action ( mockContext , '' ) ;
141+
142+ expect ( readFileWithEncoding ) . toHaveBeenCalledWith ( mockPlanPath ) ;
143+ expect ( copyToClipboard ) . toHaveBeenCalledWith ( '# Plan Content' ) ;
144+ expect ( coreEvents . emitFeedback ) . toHaveBeenCalledWith (
145+ 'info' ,
146+ 'Plan copied to clipboard (approved-plan.md).' ,
147+ ) ;
148+ } ) ;
149+
150+ it ( 'should warn if no approved plan is found' , async ( ) => {
151+ vi . mocked (
152+ mockContext . services . config ! . getApprovedPlanPath ,
153+ ) . mockReturnValue ( undefined ) ;
154+
155+ const copySubCommand = planCommand . subCommands ?. find (
156+ ( sc ) => sc . name === 'copy' ,
157+ ) ;
158+ if ( ! copySubCommand ?. action ) throw new Error ( 'Copy action missing' ) ;
159+
160+ await copySubCommand . action ( mockContext , '' ) ;
161+
162+ expect ( coreEvents . emitFeedback ) . toHaveBeenCalledWith (
163+ 'warning' ,
164+ 'No approved plan found to copy.' ,
165+ ) ;
166+ } ) ;
167+ } ) ;
118168} ) ;
0 commit comments