@@ -391,6 +391,52 @@ describe("preset resolution", () => {
391391 // Should return empty config due to validation failure
392392 expect ( loadPluginConfig ( projectDir ) ) . toEqual ( { } )
393393 } )
394+
395+ test ( "nonexistent preset from config warns and falls back to root agents" , ( ) => {
396+ const projectDir = path . join ( tempDir , "project" )
397+ const projectConfigDir = path . join ( projectDir , ".opencode" )
398+ fs . mkdirSync ( projectConfigDir , { recursive : true } )
399+ fs . writeFileSync (
400+ path . join ( projectConfigDir , "oh-my-opencode-slim.json" ) ,
401+ JSON . stringify ( {
402+ preset : "nonexistent" ,
403+ presets : {
404+ other : { oracle : { model : "other" } }
405+ } ,
406+ agents : { oracle : { model : "root" } }
407+ } )
408+ )
409+
410+ const consoleWarnSpy = spyOn ( console , "warn" )
411+ const config = loadPluginConfig ( projectDir )
412+ expect ( config . agents ?. oracle ?. model ) . toBe ( "root" )
413+ expect ( consoleWarnSpy ) . toHaveBeenCalled ( )
414+ const warningMessage = consoleWarnSpy . mock . calls [ 0 ] [ 0 ] as string
415+ expect ( warningMessage ) . toContain ( 'Preset "nonexistent" not found' )
416+ expect ( warningMessage ) . toContain ( 'Available presets: other' )
417+ } )
418+
419+ test ( "nonexistent preset with no root agents returns empty agents" , ( ) => {
420+ const projectDir = path . join ( tempDir , "project" )
421+ const projectConfigDir = path . join ( projectDir , ".opencode" )
422+ fs . mkdirSync ( projectConfigDir , { recursive : true } )
423+ fs . writeFileSync (
424+ path . join ( projectConfigDir , "oh-my-opencode-slim.json" ) ,
425+ JSON . stringify ( {
426+ preset : "nonexistent" ,
427+ presets : {
428+ other : { oracle : { model : "other" } }
429+ }
430+ } )
431+ )
432+
433+ const consoleWarnSpy = spyOn ( console , "warn" )
434+ const config = loadPluginConfig ( projectDir )
435+ expect ( config . agents ) . toBeUndefined ( )
436+ expect ( consoleWarnSpy ) . toHaveBeenCalled ( )
437+ const warningMessage = consoleWarnSpy . mock . calls [ 0 ] [ 0 ] as string
438+ expect ( warningMessage ) . toContain ( 'Preset "nonexistent" not found' )
439+ } )
394440} )
395441
396442describe ( "environment variable preset override" , ( ) => {
@@ -487,4 +533,34 @@ describe("environment variable preset override", () => {
487533 expect ( config . preset ) . toBe ( "config-preset" )
488534 expect ( config . agents ?. oracle ?. model ) . toBe ( "config-model" )
489535 } )
536+
537+ test ( "Env var with nonexistent preset warns and falls back" , ( ) => {
538+ const projectDir = path . join ( tempDir , "project" )
539+ const projectConfigDir = path . join ( projectDir , ".opencode" )
540+ fs . mkdirSync ( projectConfigDir , { recursive : true } )
541+ fs . writeFileSync (
542+ path . join ( projectConfigDir , "oh-my-opencode-slim.json" ) ,
543+ JSON . stringify ( {
544+ preset : "config-preset" ,
545+ presets : {
546+ "config-preset" : { oracle : { model : "config-model" } }
547+ } ,
548+ agents : { oracle : { model : "fallback" } }
549+ } )
550+ )
551+
552+ process . env . OH_MY_OPENCODE_SLIM_PRESET = "typo-preset"
553+ const consoleWarnSpy = spyOn ( console , "warn" )
554+ const config = loadPluginConfig ( projectDir )
555+ expect ( config . preset ) . toBe ( "typo-preset" )
556+ expect ( config . agents ?. oracle ?. model ) . toBe ( "fallback" )
557+ expect ( consoleWarnSpy ) . toHaveBeenCalled ( )
558+ const calls = consoleWarnSpy . mock . calls as string [ ] [ ]
559+ const warningMessage = calls . find ( call =>
560+ call [ 0 ] ?. includes ( "typo-preset" )
561+ ) ?. [ 0 ] || ""
562+ expect ( warningMessage ) . toContain ( 'Preset "typo-preset" not found' )
563+ expect ( warningMessage ) . toContain ( 'environment variable' )
564+ expect ( warningMessage ) . toContain ( 'config-preset' )
565+ } )
490566} )
0 commit comments