Files
cc-switch/tests/utils/providerMetaUtils.test.ts
Jason 7d56aed543 fix(providers): preserve custom endpoints in meta during add/edit operations
Fixed two critical data loss bugs where user-added custom endpoints were discarded:

1. **AddProviderDialog**: Form submission ignored values.meta from ProviderForm and
   re-inferred URLs only from presets/config, causing loss of endpoints added via
   speed test modal. Now prioritizes form-collected meta and uses fallback inference
   only when custom_endpoints is missing.

2. **ProviderForm**: Edit mode always returned initialData.meta, discarding any
   changes made in the speed test modal. Now uses mergeProviderMeta to properly
   merge customEndpointsMap with existing meta fields.

Changes:
- Extract mergeProviderMeta utility to handle meta field merging logic
- Preserve other meta fields (e.g., usage_script) during endpoint updates
- Unify new/edit code paths to use consistent meta handling
- Add comprehensive unit tests for meta merging scenarios
- Add integration tests for AddProviderDialog submission flow

Impact:
- Third-party and custom providers can now reliably manage multiple endpoints
- Edit operations correctly reflect user modifications
- No data loss for existing meta fields like usage_script
2025-10-28 20:28:11 +08:00

81 lines
2.2 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { ProviderMeta } from "@/types";
import { mergeProviderMeta } from "@/utils/providerMetaUtils";
const buildEndpoint = (url: string) => ({
url,
addedAt: 1,
});
describe("mergeProviderMeta", () => {
it("returns undefined when no initial meta and no endpoints", () => {
expect(mergeProviderMeta(undefined, null)).toBeUndefined();
expect(mergeProviderMeta(undefined, undefined)).toBeUndefined();
});
it("creates meta when endpoints are provided for new provider", () => {
const result = mergeProviderMeta(undefined, {
"https://example.com": buildEndpoint("https://example.com"),
});
expect(result).toEqual({
custom_endpoints: {
"https://example.com": buildEndpoint("https://example.com"),
},
});
});
it("overrides custom endpoints but preserves other fields", () => {
const initial: ProviderMeta = {
usage_script: {
enabled: true,
language: "javascript",
code: "console.log(1);",
},
custom_endpoints: {
"https://old.com": buildEndpoint("https://old.com"),
},
};
const result = mergeProviderMeta(initial, {
"https://new.com": buildEndpoint("https://new.com"),
});
expect(result).toEqual({
usage_script: initial.usage_script,
custom_endpoints: {
"https://new.com": buildEndpoint("https://new.com"),
},
});
});
it("removes custom endpoints when result is empty but keeps other meta", () => {
const initial: ProviderMeta = {
usage_script: {
enabled: true,
language: "javascript",
code: "console.log(1);",
},
custom_endpoints: {
"https://example.com": buildEndpoint("https://example.com"),
},
};
const result = mergeProviderMeta(initial, null);
expect(result).toEqual({
usage_script: initial.usage_script,
});
});
it("returns undefined when removing last field", () => {
const initial: ProviderMeta = {
custom_endpoints: {
"https://example.com": buildEndpoint("https://example.com"),
},
};
expect(mergeProviderMeta(initial, null)).toBeUndefined();
});
});