mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-16 01:26:07 +00:00
8662c31296
The desktop node table used rowKey="id", but transitive sub-nodes (the
read-only rows surfaced from downstream nodes) all carry id 0, so a topology
with two or more transitive rows gave React duplicate keys. antd's rowKey
prop overrides the row object's own computed `key` (`t-${guid}` for
transitive rows, the numeric id otherwise), so the unique key the code
already builds was ignored — causing row-state/DOM mis-association on any
re-render (heartbeat refetch, address-eye toggle). The mobile card path
already keyed by record.key.
Key the table by "key" so transitive rows get their distinct t-${guid}
identity; direct nodes keep key === id, so row selection (filtered to numeric
keys) is unchanged.
47 lines
1.4 KiB
TypeScript
47 lines
1.4 KiB
TypeScript
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
|
|
import NodeList from '@/pages/nodes/NodeList';
|
|
import type { NodeRecord } from '@/schemas/node';
|
|
|
|
import { renderWithProviders } from './test-utils';
|
|
|
|
const noop = () => {};
|
|
|
|
function sampleNodes(): NodeRecord[] {
|
|
return [
|
|
{ id: 1, name: 'parent', guid: 'p1', transitive: false, enable: true, status: 'online' },
|
|
{ id: 0, name: 'child-a', guid: 'ca', parentGuid: 'p1', transitive: true },
|
|
{ id: 0, name: 'child-b', guid: 'cb', parentGuid: 'p1', transitive: true },
|
|
];
|
|
}
|
|
|
|
describe('NodeList desktop table row keys', () => {
|
|
afterEach(() => vi.restoreAllMocks());
|
|
|
|
it('gives transitive sub-node rows distinct keys instead of colliding on id 0', () => {
|
|
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
|
|
|
renderWithProviders(
|
|
<NodeList
|
|
nodes={sampleNodes()}
|
|
isMobile={false}
|
|
selectedIds={[]}
|
|
onSelectionChange={noop}
|
|
onAdd={noop}
|
|
onMtls={noop}
|
|
onEdit={noop}
|
|
onDelete={noop}
|
|
onProbe={noop}
|
|
onToggleEnable={noop}
|
|
onUpdateNode={noop}
|
|
onUpdateSelected={noop}
|
|
/>,
|
|
);
|
|
|
|
const duplicateKeyWarning = errorSpy.mock.calls.some((call) =>
|
|
call.some((arg) => typeof arg === 'string' && arg.includes('same key')),
|
|
);
|
|
expect(duplicateKeyWarning).toBe(false);
|
|
});
|
|
});
|