mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-15 17:16:07 +00:00
fix(frontend): map outbound mobile-card actions through the real index too
The desktop outbounds table was keyed by the outbound's real index, but the mobile card list was left keying the probe trigger and every test-state lookup by the positional row index. With a hidden balancer-loopback outbound present, tapping Check on a mobile card probed the wrong outbound and the Test-All results landed on the wrong card. Key onTest and the testResult/isTesting reads by record.key, matching the desktop columns.
This commit is contained in:
@@ -63,8 +63,8 @@ export default function OutboundCardList({
|
||||
setShowEgressIp((prev) => ({ ...prev, [key]: visible }));
|
||||
};
|
||||
|
||||
const renderEgress = (index: number, rowKey: string) => {
|
||||
const result = testResult(outboundTestStates, index);
|
||||
const renderEgress = (testKey: number, rowKey: string) => {
|
||||
const result = testResult(outboundTestStates, testKey);
|
||||
const egress = result?.egress;
|
||||
const isEgressVisible = !!showEgressIp[rowKey];
|
||||
const flag = countryFlag(egress?.country);
|
||||
@@ -156,26 +156,26 @@ export default function OutboundCardList({
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{renderEgress(index, String(record.key))}
|
||||
{renderEgress(record.key, String(record.key))}
|
||||
<div className="card-foot">
|
||||
<span className="traffic-up">↑ {SizeFormatter.sizeFormat(trafficFor(outboundsTraffic, record).up)}</span>
|
||||
<span className="traffic-sep" />
|
||||
<span className="traffic-down">↓ {SizeFormatter.sizeFormat(trafficFor(outboundsTraffic, record).down)}</span>
|
||||
<span className="card-test">
|
||||
{testResult(outboundTestStates, index) ? (
|
||||
<TestResultPopover result={testResult(outboundTestStates, index)!} />
|
||||
) : isTesting(outboundTestStates, index) ? (
|
||||
{testResult(outboundTestStates, record.key) ? (
|
||||
<TestResultPopover result={testResult(outboundTestStates, record.key)!} />
|
||||
) : isTesting(outboundTestStates, record.key) ? (
|
||||
<LoadingOutlined />
|
||||
) : null}
|
||||
<Button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
size="small"
|
||||
loading={isTesting(outboundTestStates, index)}
|
||||
disabled={isUntestable(record) || isTesting(outboundTestStates, index)}
|
||||
loading={isTesting(outboundTestStates, record.key)}
|
||||
disabled={isUntestable(record) || isTesting(outboundTestStates, record.key)}
|
||||
icon={<ThunderboltOutlined />}
|
||||
aria-label={t('check')}
|
||||
onClick={() => onTest(index, testMode)}
|
||||
onClick={() => onTest(record.key, testMode)}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -53,4 +53,39 @@ describe('OutboundsTab hidden-loopback index mapping', () => {
|
||||
expect(onTest).toHaveBeenCalledTimes(1);
|
||||
expect(onTest.mock.calls[0][0]).toBe(2);
|
||||
});
|
||||
|
||||
it('probes the real array index from the mobile card list as well', () => {
|
||||
const onTest = vi.fn();
|
||||
const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
|
||||
|
||||
renderWithProviders(
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<OutboundsTab
|
||||
templateSettings={settingsWithHiddenLoopback()}
|
||||
setTemplateSettings={vi.fn()}
|
||||
outboundsTraffic={[]}
|
||||
outboundTestStates={{}}
|
||||
subscriptionTestStates={{}}
|
||||
testingAll={false}
|
||||
inboundTags={[]}
|
||||
isMobile
|
||||
onResetTraffic={vi.fn()}
|
||||
onTest={onTest}
|
||||
onTestSubscription={vi.fn()}
|
||||
onTestAll={vi.fn()}
|
||||
onShowWarp={vi.fn()}
|
||||
onShowNord={vi.fn()}
|
||||
/>
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
|
||||
const cards = document.querySelectorAll('.outbound-card');
|
||||
expect(cards.length).toBe(2);
|
||||
|
||||
const checkButton = cards[1].querySelector('button[aria-label="Check"]') as HTMLButtonElement;
|
||||
fireEvent.click(checkButton);
|
||||
|
||||
expect(onTest).toHaveBeenCalledTimes(1);
|
||||
expect(onTest.mock.calls[0][0]).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user