1
0
forked from boos/BoosAPI

Restore the full payload-rule protocol list in Settings

One last review thread caught a real UI regression: the visual payload-rule
editor had drifted away from the shared protocol option source and no longer
exposed several active platform targets. Rebinding the dropdown to the shared
option list fixes the regression without inventing another source of truth.

Constraint: The fix should reuse the existing shared option list instead of creating another hardcoded protocol subset
Rejected: Expand the inline array manually | would repeat the same drift problem that caused the regression
Confidence: high
Scope-risk: narrow
Directive: Payload-rule protocol selectors should always read from the shared option source so Settings and the payload-rule parser stay aligned
Tested: settings.payload-rules vitest; typecheck; git diff --check
Not-tested: Full npm test
This commit is contained in:
cita-777
2026-04-18 14:01:26 +08:00
parent 1f464dc03d
commit 544324ed0a
2 changed files with 64 additions and 9 deletions
+1 -9
View File
@@ -18,6 +18,7 @@ import {
type VisualPayloadRuleValueMode, type VisualPayloadRuleValueMode,
visualRulesToPayloadRules, visualRulesToPayloadRules,
} from './settings/payloadRulesVisual.js'; } from './settings/payloadRulesVisual.js';
import { PAYLOAD_RULE_PROTOCOL_OPTIONS } from './settings/payloadRuleProtocolOptions.js';
import UpdateCenterSection from './settings/UpdateCenterSection.js'; import UpdateCenterSection from './settings/UpdateCenterSection.js';
import { import {
applyRoutingProfilePreset, applyRoutingProfilePreset,
@@ -209,15 +210,6 @@ const PAYLOAD_RULE_ACTION_OPTIONS: Array<{ value: PayloadRuleAction; label: stri
{ value: 'filter', label: '删除字段' }, { value: 'filter', label: '删除字段' },
]; ];
const PAYLOAD_RULE_PROTOCOL_OPTIONS = [
{ value: '', label: '全部协议' },
{ value: 'codex', label: 'Codex' },
{ value: 'openai', label: 'OpenAI' },
{ value: 'claude', label: 'Claude' },
{ value: 'gemini', label: 'Gemini' },
{ value: 'antigravity', label: 'Antigravity' },
];
const PAYLOAD_RULE_VALUE_MODE_OPTIONS: Array<{ value: VisualPayloadRuleValueMode; label: string }> = [ const PAYLOAD_RULE_VALUE_MODE_OPTIONS: Array<{ value: VisualPayloadRuleValueMode; label: string }> = [
{ value: 'text', label: '文本' }, { value: 'text', label: '文本' },
{ value: 'json', label: 'JSON' }, { value: 'json', label: 'JSON' },
@@ -327,6 +327,69 @@ describe('Settings payload rules', () => {
} }
}); });
it('keeps the full payload-rule protocol option set in the visual editor', async () => {
apiMock.getRuntimeSettings.mockResolvedValueOnce({
checkinCron: '0 8 * * *',
checkinScheduleMode: 'interval',
checkinIntervalHours: 6,
balanceRefreshCron: '0 * * * *',
logCleanupCron: '15 4 * * *',
logCleanupUsageLogsEnabled: true,
logCleanupProgramLogsEnabled: true,
logCleanupRetentionDays: 14,
routingFallbackUnitCost: 1,
proxyFirstByteTimeoutSec: 0,
routingWeights: {},
tokenRouterFailureCooldownMaxSec: 30 * 24 * 60 * 60,
adminIpAllowlist: [],
systemProxyUrl: '',
payloadRules: {},
});
let root!: ReactTestRenderer;
try {
await act(async () => {
root = create(
<MemoryRouter>
<ToastProvider>
<Settings />
</ToastProvider>
</MemoryRouter>,
);
});
await flushMicrotasks();
const addButton = root.root.find((node) => (
node.type === 'button'
&& typeof node.props.onClick === 'function'
&& collectText(node).trim() === '新增规则'
));
await act(async () => {
addButton.props.onClick();
});
const protocolSelect = root.root.find((node) => (
node.props['data-testid'] === 'payload-rule-protocol-1'
));
const options = Array.isArray(protocolSelect.props.options)
? protocolSelect.props.options
: [];
const values = options.map((option: { value: string }) => option.value);
expect(values).toEqual(expect.arrayContaining([
'',
'sub2api',
'new-api',
'one-api',
'gemini-cli',
'anyrouter',
]));
} finally {
root?.unmount();
}
});
it('blocks save when a payload-rule section contains invalid JSON', async () => { it('blocks save when a payload-rule section contains invalid JSON', async () => {
let root!: ReactTestRenderer; let root!: ReactTestRenderer;
try { try {