mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-25 13:56:10 +00:00
ade74eb321
* fix(balancers): keep mixed strategies on one observer Xray resolves Observatory and Burst Observatory through the same global observer feature. When any burst-required strategy is present, keep all observer-backed balancer selectors on burstObservatory and remove the regular observatory so mixed leastPing configs cannot generate two competing observer blocks. * test(balancers): cover observer strategy combinations Exercise the observer sync matrix for random, round-robin, leastPing, and leastLoad balancers. Include mixed and stale-observer cases so the panel keeps only the observer type that Xray should consume. * fix(balancers): clarify observer empty state Update the Observatory tab empty hint to describe the actual auto-managed cases. Least Ping, Least Load, and fallback Random or Round-robin balancers now explain why an observer is added before the balancer can choose a target. * fix(balancers): remove mixed observer switch Show only the observer settings panel that matches the current balancer requirements. Legacy configs that still contain both observatory blocks now display a warning instead of a tab switch, since saving balancers normalizes the config back to one global observer. * test(balancers): cover observer cleanup on deletion Add direct balancer deletion and outbound cascade cases for leastLoad, fallback, and mixed leastPing scenarios. These tests pin that the final unneeded observer is removed, burst switches back to regular observatory when only leastPing remains, and burst remains when a burst-required balancer survives.
48 lines
1.9 KiB
TypeScript
48 lines
1.9 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest';
|
|
import { screen } from '@testing-library/react';
|
|
|
|
import ObservatorySettingsTab from '@/pages/xray/balancers/ObservatorySettingsTab';
|
|
import type { XraySettingsValue } from '@/hooks/useXraySetting';
|
|
import { renderWithProviders } from './test-utils';
|
|
|
|
function renderTab(templateSettings: XraySettingsValue) {
|
|
renderWithProviders(
|
|
<ObservatorySettingsTab
|
|
templateSettings={templateSettings}
|
|
mutate={vi.fn()}
|
|
/>,
|
|
);
|
|
}
|
|
|
|
describe('ObservatorySettingsTab', () => {
|
|
it('shows one burst settings panel and warns for legacy mixed observers', () => {
|
|
renderTab({
|
|
routing: {
|
|
balancers: [{ tag: 'll', selector: ['proxy-a'], strategy: { type: 'leastLoad' } }],
|
|
},
|
|
observatory: { subjectSelector: ['stale-regular'] },
|
|
burstObservatory: { subjectSelector: ['proxy-a'] },
|
|
} as unknown as XraySettingsValue);
|
|
|
|
expect(screen.getByText(/This config contains both Observatory and Burst Observatory/)).toBeTruthy();
|
|
expect(document.querySelector('.ant-segmented')).toBeFalsy();
|
|
expect(screen.getByText('Probe Destination')).toBeTruthy();
|
|
expect(screen.queryByText('Probe URL')).toBeFalsy();
|
|
});
|
|
|
|
it('shows regular observatory settings for mixed legacy configs that normalize back to leastPing only', () => {
|
|
renderTab({
|
|
routing: {
|
|
balancers: [{ tag: 'lp', selector: ['proxy-b'], strategy: { type: 'leastPing' } }],
|
|
},
|
|
observatory: { subjectSelector: ['proxy-b'] },
|
|
burstObservatory: { subjectSelector: ['stale-burst'] },
|
|
} as unknown as XraySettingsValue);
|
|
|
|
expect(screen.getByText(/This config contains both Observatory and Burst Observatory/)).toBeTruthy();
|
|
expect(document.querySelector('.ant-segmented')).toBeFalsy();
|
|
expect(screen.getByText('Probe URL')).toBeTruthy();
|
|
expect(screen.queryByText('Probe Destination')).toBeFalsy();
|
|
});
|
|
});
|