@@ -68,11 +68,17 @@ describe("ProviderSettingsManager", () => {
6868 JSON . stringify ( {
6969 currentApiConfigName : "default" ,
7070 apiConfigs : {
71+ // Provide a minimal valid structure (missing ID)
7172 default : {
72- config : { } ,
73+ apiProvider : "openai" , // Example provider
74+ openAiModelId : "gpt-4" , // Corresponding model field
75+ rateLimitSeconds : 0 ,
7376 } ,
77+ // Provide a minimal valid structure (missing ID)
7478 test : {
7579 apiProvider : "anthropic" ,
80+ apiModelId : "claude-instant-1" , // Corresponding model field
81+ rateLimitSeconds : 0 ,
7682 } ,
7783 } ,
7884 } ) ,
@@ -94,19 +100,24 @@ describe("ProviderSettingsManager", () => {
94100 JSON . stringify ( {
95101 currentApiConfigName : "default" ,
96102 apiConfigs : {
103+ // Valid structure, missing rateLimitSeconds
97104 default : {
98- config : { } ,
99- id : "default" ,
105+ apiProvider : "openai" ,
106+ openAiModelId : "gpt-4" ,
107+ id : "default-id" , // Needs an ID for migration test structure
100108 rateLimitSeconds : undefined ,
101109 } ,
110+ // Valid structure, missing rateLimitSeconds and ID (ID will be generated)
102111 test : {
103112 apiProvider : "anthropic" ,
113+ apiModelId : "claude-instant-1" ,
104114 rateLimitSeconds : undefined ,
105115 } ,
116+ // Valid structure, existing rateLimitSeconds
106117 existing : {
107118 apiProvider : "anthropic" ,
108- // this should not really be possible, unless someone has loaded a hand edited config ,
109- // but we don't overwrite so we'll check that
119+ apiModelId : "claude-instant-1" ,
120+ id : "existing-id" , // Needs an ID
110121 rateLimitSeconds : 43 ,
111122 } ,
112123 } ,
@@ -422,11 +433,13 @@ describe("ProviderSettingsManager", () => {
422433 JSON . stringify ( {
423434 currentApiConfigName : "default" ,
424435 apiConfigs : {
436+ // Provide a valid structure for 'test'
425437 test : {
426- config : {
427- apiProvider : "anthropic" ,
428- } ,
429- id : "test-id" ,
438+ apiProvider : "anthropic" ,
439+ apiModelId : "claude-instant-1" ,
440+ apiKey : "test-key" ,
441+ rateLimitSeconds : 0 ,
442+ id : "test-id" , // Keep ID as loadConfig uses it
430443 } ,
431444 } ,
432445 } ) ,
@@ -437,6 +450,54 @@ describe("ProviderSettingsManager", () => {
437450 "Failed to load config: Error: Failed to write provider profiles to secrets: Error: Storage failed" ,
438451 )
439452 } )
453+
454+ it ( "should remove invalid profiles during load" , async ( ) => {
455+ const invalidConfig = {
456+ currentApiConfigName : "valid" ,
457+ apiConfigs : {
458+ valid : {
459+ apiProvider : "anthropic" ,
460+ apiKey : "valid-key" ,
461+ // id: "valid-id", // ID is added by the manager, not part of the schema input
462+ apiModelId : "claude-3-opus-20240229" , // Correct field name for Anthropic model
463+ rateLimitSeconds : 0 , // Generic field, should be fine
464+ } ,
465+ invalid : {
466+ // Missing required fields like apiProvider or apiKey
467+ id : "invalid-id" ,
468+ someOtherField : "value" ,
469+ } ,
470+ anotherInvalid : "not an object" , // Incorrect type
471+ } ,
472+ migrations : {
473+ rateLimitSecondsMigrated : true ,
474+ } ,
475+ }
476+
477+ mockSecrets . get . mockResolvedValue ( JSON . stringify ( invalidConfig ) )
478+
479+ // Load a valid config - this should trigger the cleanup
480+ // Note: loadConfig itself doesn't clean, initialization does.
481+ // We need to call initialize to trigger the load and cleanup.
482+ await providerSettingsManager . initialize ( )
483+
484+ // Check that the stored config was updated and invalid profiles removed
485+ // Initialize calls store multiple times potentially (migration, id generation, cleanup)
486+ // We need to find the call that reflects the final cleaned state.
487+ // The last call to store should contain the cleaned config.
488+ const storeCalls = mockSecrets . store . mock . calls
489+ expect ( storeCalls . length ) . toBeGreaterThan ( 0 ) // Ensure store was called at least once
490+ const finalStoredConfigJson = storeCalls [ storeCalls . length - 1 ] [ 1 ]
491+ const storedConfig = JSON . parse ( finalStoredConfigJson )
492+
493+ expect ( storedConfig . apiConfigs . valid ) . toBeDefined ( )
494+ expect ( storedConfig . apiConfigs . invalid ) . toBeUndefined ( )
495+ expect ( storedConfig . apiConfigs . anotherInvalid ) . toBeUndefined ( )
496+ expect ( Object . keys ( storedConfig . apiConfigs ) ) . toEqual ( [ "valid" ] )
497+ // Initialize might reset currentApiConfigName if the original was invalid,
498+ // or keep it if it was valid. Let's check it's still 'valid'.
499+ expect ( storedConfig . currentApiConfigName ) . toBe ( "valid" )
500+ } )
440501 } )
441502
442503 describe ( "ResetAllConfigs" , ( ) => {
0 commit comments