@@ -7,10 +7,13 @@ import {
77 runFailure ,
88 runSuccess ,
99} from '../src/test-utils/index.js' ;
10+ import { createTelemetryHelper } from '../src/test-utils/telemetry-helper.js' ;
1011import { writeFile } from 'node:fs/promises' ;
1112import { join } from 'node:path' ;
1213import { afterAll , beforeAll , describe , expect , it } from 'vitest' ;
1314
15+ const telemetry = createTelemetryHelper ( ) ;
16+
1417describe ( 'integration: add and remove config-bundle' , ( ) => {
1518 let project : TestProject ;
1619
@@ -20,6 +23,7 @@ describe('integration: add and remove config-bundle', () => {
2023
2124 afterAll ( async ( ) => {
2225 await project . cleanup ( ) ;
26+ telemetry . destroy ( ) ;
2327 } ) ;
2428
2529 // ── Add lifecycle ─────────────────────────────────────────────────────
@@ -40,7 +44,7 @@ describe('integration: add and remove config-bundle', () => {
4044 expect ( json . bundleName ) . toBe ( 'InlineBundle' ) ;
4145
4246 const config = await readProjectConfig ( project . projectPath ) ;
43- const bundle = config . configBundles ! . find ( b => b . name === 'InlineBundle' ) ;
47+ const bundle = config . configBundles . find ( b => b . name === 'InlineBundle' ) ;
4448 expect ( bundle ) . toBeDefined ( ) ;
4549 expect ( bundle ! . type ) . toBe ( 'ConfigurationBundle' ) ;
4650 expect ( bundle ! . branchName ) . toBe ( 'mainline' ) ;
@@ -68,7 +72,7 @@ describe('integration: add and remove config-bundle', () => {
6872 expect ( json . bundleName ) . toBe ( 'FileBundle' ) ;
6973
7074 const config = await readProjectConfig ( project . projectPath ) ;
71- const bundle = config . configBundles ! . find ( b => b . name === 'FileBundle' ) ;
75+ const bundle = config . configBundles . find ( b => b . name === 'FileBundle' ) ;
7276 expect ( bundle ) . toBeDefined ( ) ;
7377 expect ( Object . keys ( bundle ! . components ) ) . toHaveLength ( 2 ) ;
7478 } ) ;
@@ -102,7 +106,7 @@ describe('integration: add and remove config-bundle', () => {
102106 expect ( json . bundleName ) . toBe ( 'FullOptsBundle' ) ;
103107
104108 const config = await readProjectConfig ( project . projectPath ) ;
105- const bundle = config . configBundles ! . find ( b => b . name === 'FullOptsBundle' ) ;
109+ const bundle = config . configBundles . find ( b => b . name === 'FullOptsBundle' ) ;
106110 expect ( bundle ) . toBeDefined ( ) ;
107111 expect ( bundle ! . description ) . toBe ( 'A bundle with all optional fields' ) ;
108112 expect ( bundle ! . branchName ) . toBe ( 'feature-branch' ) ;
@@ -127,7 +131,7 @@ describe('integration: add and remove config-bundle', () => {
127131 expect ( json . bundleName ) . toBe ( 'PlaceholderBundle' ) ;
128132
129133 const config = await readProjectConfig ( project . projectPath ) ;
130- const bundle = config . configBundles ! . find ( b => b . name === 'PlaceholderBundle' ) ;
134+ const bundle = config . configBundles . find ( b => b . name === 'PlaceholderBundle' ) ;
131135 expect ( bundle ) . toBeDefined ( ) ;
132136 const keys = Object . keys ( bundle ! . components ) ;
133137 expect ( keys ) . toContain ( '{{runtime:AgentA}}' ) ;
@@ -228,37 +232,45 @@ describe('integration: add and remove config-bundle', () => {
228232
229233 describe ( 'remove config-bundle' , ( ) => {
230234 it ( 'removes an existing config bundle' , async ( ) => {
231- const json = await runSuccess (
235+ const result = await runCLI (
232236 [ 'remove' , 'config-bundle' , '--name' , 'InlineBundle' , '--json' ] ,
233- project . projectPath
237+ project . projectPath ,
238+ { env : telemetry . env }
234239 ) ;
235240
241+ expect ( result . exitCode ) . toBe ( 0 ) ;
242+ const json = JSON . parse ( result . stdout ) ;
236243 expect ( json . success ) . toBe ( true ) ;
237244
238245 const config = await readProjectConfig ( project . projectPath ) ;
239- const bundle = config . configBundles ! . find ( b => b . name === 'InlineBundle' ) ;
246+ const bundle = config . configBundles . find ( b => b . name === 'InlineBundle' ) ;
240247 expect ( bundle ) . toBeUndefined ( ) ;
248+ telemetry . assertMetricEmitted ( { command : 'remove.config-bundle' , exit_reason : 'success' } ) ;
241249 } ) ;
242250
243251 it ( 'returns error for non-existent bundle' , async ( ) => {
244- const json = await runFailure (
252+ const result = await runCLI (
245253 [ 'remove' , 'config-bundle' , '--name' , 'DoesNotExist' , '--json' ] ,
246- project . projectPath
254+ project . projectPath ,
255+ { env : telemetry . env }
247256 ) ;
248257
258+ expect ( result . exitCode ) . toBe ( 1 ) ;
259+ const json = JSON . parse ( result . stdout ) ;
249260 expect ( json . error ) . toContain ( 'not found' ) ;
261+ telemetry . assertMetricEmitted ( { command : 'remove.config-bundle' , exit_reason : 'failure' } ) ;
250262 } ) ;
251263
252264 it ( 'removes all remaining config bundles one by one' , async ( ) => {
253265 const configBefore = await readProjectConfig ( project . projectPath ) ;
254- const remaining = configBefore . configBundles ! . map ( b => b . name ) ;
266+ const remaining = configBefore . configBundles . map ( b => b . name ) ;
255267
256268 for ( const name of remaining ) {
257269 await runSuccess ( [ 'remove' , 'config-bundle' , '--name' , name , '--json' ] , project . projectPath ) ;
258270 }
259271
260272 const configAfter = await readProjectConfig ( project . projectPath ) ;
261- expect ( configAfter . configBundles ! ) . toHaveLength ( 0 ) ;
273+ expect ( configAfter . configBundles ) . toHaveLength ( 0 ) ;
262274 } ) ;
263275 } ) ;
264276
@@ -282,21 +294,21 @@ describe('integration: add and remove config-bundle', () => {
282294 }
283295
284296 const config = await readProjectConfig ( project . projectPath ) ;
285- expect ( config . configBundles ! ) . toHaveLength ( bundleNames . length ) ;
297+ expect ( config . configBundles ) . toHaveLength ( bundleNames . length ) ;
286298
287299 for ( const name of bundleNames ) {
288- expect ( config . configBundles ! . find ( b => b . name === name ) ) . toBeDefined ( ) ;
300+ expect ( config . configBundles . find ( b => b . name === name ) ) . toBeDefined ( ) ;
289301 }
290302 } ) ;
291303
292304 it ( 'removing one bundle does not affect others' , async ( ) => {
293305 await runSuccess ( [ 'remove' , 'config-bundle' , '--name' , 'BundleBeta' , '--json' ] , project . projectPath ) ;
294306
295307 const config = await readProjectConfig ( project . projectPath ) ;
296- expect ( config . configBundles ! ) . toHaveLength ( 2 ) ;
297- expect ( config . configBundles ! . find ( b => b . name === 'BundleAlpha' ) ) . toBeDefined ( ) ;
298- expect ( config . configBundles ! . find ( b => b . name === 'BundleGamma' ) ) . toBeDefined ( ) ;
299- expect ( config . configBundles ! . find ( b => b . name === 'BundleBeta' ) ) . toBeUndefined ( ) ;
308+ expect ( config . configBundles ) . toHaveLength ( 2 ) ;
309+ expect ( config . configBundles . find ( b => b . name === 'BundleAlpha' ) ) . toBeDefined ( ) ;
310+ expect ( config . configBundles . find ( b => b . name === 'BundleGamma' ) ) . toBeDefined ( ) ;
311+ expect ( config . configBundles . find ( b => b . name === 'BundleBeta' ) ) . toBeUndefined ( ) ;
300312 } ) ;
301313
302314 afterAll ( async ( ) => {
0 commit comments