|
|
@@ -705,7 +705,55 @@ describe("ProviderSettingsManager", () => {
|
|
|
)
|
|
|
})
|
|
|
|
|
|
- it("should remove invalid profiles during load", async () => {
|
|
|
+ it("should sanitize invalid/removed providers by resetting apiProvider to undefined", async () => {
|
|
|
+ // This tests the fix for the infinite loop issue when a provider is removed
|
|
|
+ const configWithRemovedProvider = {
|
|
|
+ currentApiConfigName: "valid",
|
|
|
+ apiConfigs: {
|
|
|
+ valid: {
|
|
|
+ apiProvider: "anthropic",
|
|
|
+ apiKey: "valid-key",
|
|
|
+ apiModelId: "claude-3-opus-20240229",
|
|
|
+ id: "valid-id",
|
|
|
+ },
|
|
|
+ removedProvider: {
|
|
|
+ // Provider that was removed from the extension (e.g., "invalid-removed-provider")
|
|
|
+ id: "removed-id",
|
|
|
+ apiProvider: "invalid-removed-provider",
|
|
|
+ apiKey: "some-key",
|
|
|
+ apiModelId: "some-model",
|
|
|
+ },
|
|
|
+ },
|
|
|
+ migrations: {
|
|
|
+ rateLimitSecondsMigrated: true,
|
|
|
+ diffSettingsMigrated: true,
|
|
|
+ openAiHeadersMigrated: true,
|
|
|
+ consecutiveMistakeLimitMigrated: true,
|
|
|
+ todoListEnabledMigrated: true,
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ mockSecrets.get.mockResolvedValue(JSON.stringify(configWithRemovedProvider))
|
|
|
+
|
|
|
+ await providerSettingsManager.initialize()
|
|
|
+
|
|
|
+ const storeCalls = mockSecrets.store.mock.calls
|
|
|
+ expect(storeCalls.length).toBeGreaterThan(0)
|
|
|
+ const finalStoredConfigJson = storeCalls[storeCalls.length - 1][1]
|
|
|
+
|
|
|
+ const storedConfig = JSON.parse(finalStoredConfigJson)
|
|
|
+ // The valid provider should be untouched
|
|
|
+ expect(storedConfig.apiConfigs.valid).toBeDefined()
|
|
|
+ expect(storedConfig.apiConfigs.valid.apiProvider).toBe("anthropic")
|
|
|
+
|
|
|
+ // The config with the removed provider should have its apiProvider reset to undefined
|
|
|
+ // but still be present (not filtered out entirely)
|
|
|
+ expect(storedConfig.apiConfigs.removedProvider).toBeDefined()
|
|
|
+ expect(storedConfig.apiConfigs.removedProvider.apiProvider).toBeUndefined()
|
|
|
+ expect(storedConfig.apiConfigs.removedProvider.id).toBe("removed-id")
|
|
|
+ })
|
|
|
+
|
|
|
+ it("should sanitize invalid providers and remove non-object profiles during load", async () => {
|
|
|
const invalidConfig = {
|
|
|
currentApiConfigName: "valid",
|
|
|
apiConfigs: {
|
|
|
@@ -715,12 +763,12 @@ describe("ProviderSettingsManager", () => {
|
|
|
apiModelId: "claude-3-opus-20240229",
|
|
|
rateLimitSeconds: 0,
|
|
|
},
|
|
|
- invalid: {
|
|
|
- // Invalid API provider.
|
|
|
+ invalidProvider: {
|
|
|
+ // Invalid API provider - should be sanitized (kept but apiProvider reset to undefined)
|
|
|
id: "x.ai",
|
|
|
apiProvider: "x.ai",
|
|
|
},
|
|
|
- // Incorrect type.
|
|
|
+ // Incorrect type - should be completely removed
|
|
|
anotherInvalid: "not an object",
|
|
|
},
|
|
|
migrations: {
|
|
|
@@ -737,10 +785,19 @@ describe("ProviderSettingsManager", () => {
|
|
|
const finalStoredConfigJson = storeCalls[storeCalls.length - 1][1]
|
|
|
|
|
|
const storedConfig = JSON.parse(finalStoredConfigJson)
|
|
|
+ // Valid config should be untouched
|
|
|
expect(storedConfig.apiConfigs.valid).toBeDefined()
|
|
|
- expect(storedConfig.apiConfigs.invalid).toBeUndefined()
|
|
|
+ expect(storedConfig.apiConfigs.valid.apiProvider).toBe("anthropic")
|
|
|
+
|
|
|
+ // Invalid provider config should be sanitized - kept but apiProvider reset to undefined
|
|
|
+ expect(storedConfig.apiConfigs.invalidProvider).toBeDefined()
|
|
|
+ expect(storedConfig.apiConfigs.invalidProvider.apiProvider).toBeUndefined()
|
|
|
+ expect(storedConfig.apiConfigs.invalidProvider.id).toBe("x.ai")
|
|
|
+
|
|
|
+ // Non-object config should be completely removed
|
|
|
expect(storedConfig.apiConfigs.anotherInvalid).toBeUndefined()
|
|
|
- expect(Object.keys(storedConfig.apiConfigs)).toEqual(["valid"])
|
|
|
+
|
|
|
+ expect(Object.keys(storedConfig.apiConfigs)).toEqual(["valid", "invalidProvider"])
|
|
|
expect(storedConfig.currentApiConfigName).toBe("valid")
|
|
|
})
|
|
|
})
|