provider-form-batch-context.test.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import { describe, expect, it } from "vitest";
  2. import {
  3. createInitialState,
  4. providerFormReducer,
  5. } from "@/app/[locale]/settings/providers/_components/forms/provider-form/provider-form-context";
  6. // ---------------------------------------------------------------------------
  7. // createInitialState("batch")
  8. // ---------------------------------------------------------------------------
  9. describe("createInitialState - batch mode", () => {
  10. it("returns batch state with isEnabled set to no_change", () => {
  11. const state = createInitialState("batch");
  12. expect(state.batch.isEnabled).toBe("no_change");
  13. });
  14. it("returns neutral routing defaults (no provider source)", () => {
  15. const state = createInitialState("batch");
  16. expect(state.routing.priority).toBe(0);
  17. expect(state.routing.weight).toBe(1);
  18. expect(state.routing.costMultiplier).toBe(1.0);
  19. expect(state.routing.groupTag).toEqual([]);
  20. expect(state.routing.preserveClientIp).toBe(false);
  21. expect(state.routing.modelRedirects).toEqual({});
  22. expect(state.routing.allowedModels).toEqual([]);
  23. expect(state.routing.cacheTtlPreference).toBe("inherit");
  24. expect(state.routing.swapCacheTtlBilling).toBe(false);
  25. expect(state.routing.anthropicAdaptiveThinking).toBeNull();
  26. });
  27. it("returns neutral rate limit defaults", () => {
  28. const state = createInitialState("batch");
  29. expect(state.rateLimit.limit5hUsd).toBeNull();
  30. expect(state.rateLimit.limitDailyUsd).toBeNull();
  31. expect(state.rateLimit.dailyResetMode).toBe("fixed");
  32. expect(state.rateLimit.dailyResetTime).toBe("00:00");
  33. expect(state.rateLimit.limitWeeklyUsd).toBeNull();
  34. expect(state.rateLimit.limitMonthlyUsd).toBeNull();
  35. expect(state.rateLimit.limitTotalUsd).toBeNull();
  36. expect(state.rateLimit.limitConcurrentSessions).toBeNull();
  37. });
  38. it("returns neutral circuit breaker defaults", () => {
  39. const state = createInitialState("batch");
  40. expect(state.circuitBreaker.failureThreshold).toBeUndefined();
  41. expect(state.circuitBreaker.openDurationMinutes).toBeUndefined();
  42. expect(state.circuitBreaker.halfOpenSuccessThreshold).toBeUndefined();
  43. expect(state.circuitBreaker.maxRetryAttempts).toBeNull();
  44. });
  45. it("returns neutral network defaults", () => {
  46. const state = createInitialState("batch");
  47. expect(state.network.proxyUrl).toBe("");
  48. expect(state.network.proxyFallbackToDirect).toBe(false);
  49. expect(state.network.firstByteTimeoutStreamingSeconds).toBeUndefined();
  50. expect(state.network.streamingIdleTimeoutSeconds).toBeUndefined();
  51. expect(state.network.requestTimeoutNonStreamingSeconds).toBeUndefined();
  52. });
  53. it("returns neutral MCP defaults", () => {
  54. const state = createInitialState("batch");
  55. expect(state.mcp.mcpPassthroughType).toBe("none");
  56. expect(state.mcp.mcpPassthroughUrl).toBe("");
  57. });
  58. it("ignores provider and cloneProvider arguments in batch mode", () => {
  59. const fakeProvider = {
  60. id: 99,
  61. name: "Ignored",
  62. url: "https://ignored.example.com",
  63. maskedKey: "xxxx****xxxx",
  64. isEnabled: false,
  65. weight: 50,
  66. priority: 99,
  67. groupPriorities: null,
  68. costMultiplier: 3.0,
  69. groupTag: "prod",
  70. providerType: "claude" as const,
  71. providerVendorId: null,
  72. preserveClientIp: true,
  73. modelRedirects: null,
  74. allowedModels: null,
  75. mcpPassthroughType: "none" as const,
  76. mcpPassthroughUrl: null,
  77. limit5hUsd: null,
  78. limitDailyUsd: null,
  79. dailyResetMode: "fixed" as const,
  80. dailyResetTime: "00:00",
  81. limitWeeklyUsd: null,
  82. limitMonthlyUsd: null,
  83. limitTotalUsd: null,
  84. limitConcurrentSessions: 10,
  85. maxRetryAttempts: null,
  86. circuitBreakerFailureThreshold: 5,
  87. circuitBreakerOpenDuration: 30000,
  88. circuitBreakerHalfOpenSuccessThreshold: 2,
  89. proxyUrl: null,
  90. proxyFallbackToDirect: false,
  91. firstByteTimeoutStreamingMs: 30000,
  92. streamingIdleTimeoutMs: 120000,
  93. requestTimeoutNonStreamingMs: 120000,
  94. websiteUrl: null,
  95. faviconUrl: null,
  96. cacheTtlPreference: null,
  97. swapCacheTtlBilling: false,
  98. context1mPreference: null,
  99. codexReasoningEffortPreference: null,
  100. codexReasoningSummaryPreference: null,
  101. codexTextVerbosityPreference: null,
  102. codexParallelToolCallsPreference: null,
  103. anthropicMaxTokensPreference: null,
  104. anthropicThinkingBudgetPreference: null,
  105. anthropicAdaptiveThinking: null,
  106. geminiGoogleSearchPreference: null,
  107. tpm: null,
  108. rpm: null,
  109. rpd: null,
  110. cc: null,
  111. createdAt: "2024-01-01T00:00:00Z",
  112. updatedAt: "2024-01-01T00:00:00Z",
  113. };
  114. const state = createInitialState("batch", fakeProvider, fakeProvider);
  115. // Should still be batch defaults, not the provider values
  116. expect(state.routing.priority).toBe(0);
  117. expect(state.routing.weight).toBe(1);
  118. expect(state.routing.costMultiplier).toBe(1.0);
  119. expect(state.batch.isEnabled).toBe("no_change");
  120. });
  121. });
  122. // ---------------------------------------------------------------------------
  123. // providerFormReducer - SET_BATCH_IS_ENABLED
  124. // ---------------------------------------------------------------------------
  125. describe("providerFormReducer - SET_BATCH_IS_ENABLED", () => {
  126. const baseState = createInitialState("batch");
  127. it("sets isEnabled to true", () => {
  128. const next = providerFormReducer(baseState, {
  129. type: "SET_BATCH_IS_ENABLED",
  130. payload: "true",
  131. });
  132. expect(next.batch.isEnabled).toBe("true");
  133. });
  134. it("sets isEnabled to false", () => {
  135. const next = providerFormReducer(baseState, {
  136. type: "SET_BATCH_IS_ENABLED",
  137. payload: "false",
  138. });
  139. expect(next.batch.isEnabled).toBe("false");
  140. });
  141. it("sets isEnabled back to no_change", () => {
  142. const modified = providerFormReducer(baseState, {
  143. type: "SET_BATCH_IS_ENABLED",
  144. payload: "true",
  145. });
  146. const reverted = providerFormReducer(modified, {
  147. type: "SET_BATCH_IS_ENABLED",
  148. payload: "no_change",
  149. });
  150. expect(reverted.batch.isEnabled).toBe("no_change");
  151. });
  152. it("does not mutate other state sections", () => {
  153. const next = providerFormReducer(baseState, {
  154. type: "SET_BATCH_IS_ENABLED",
  155. payload: "true",
  156. });
  157. expect(next.routing).toEqual(baseState.routing);
  158. expect(next.rateLimit).toEqual(baseState.rateLimit);
  159. expect(next.circuitBreaker).toEqual(baseState.circuitBreaker);
  160. expect(next.network).toEqual(baseState.network);
  161. expect(next.mcp).toEqual(baseState.mcp);
  162. expect(next.ui).toEqual(baseState.ui);
  163. });
  164. });