From c70eb7157fc3ca1d869d958cf4380976ef0eabfb Mon Sep 17 00:00:00 2001 From: Syngnat Date: Tue, 16 Jun 2026 08:37:18 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=85=20test(oceanbase):=20=E8=84=B1?= =?UTF-8?q?=E6=95=8F=20Oracle=20=E7=A7=9F=E6=88=B7=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将测试中的内网地址、账号和服务名替换为虚构 fixture - 统一 OceanBase Oracle 与 SSH 跳板机测试常量 - 保留连接预探测与 SSH 诊断断言语义 --- .../src/components/DataGrid.layout.test.tsx | 6 ++ frontend/src/components/DataGrid.tsx | 34 ++++++++- internal/db/oceanbase_impl_test.go | 69 +++++++++++-------- 3 files changed, 78 insertions(+), 31 deletions(-) diff --git a/frontend/src/components/DataGrid.layout.test.tsx b/frontend/src/components/DataGrid.layout.test.tsx index 4c88515..97e9269 100644 --- a/frontend/src/components/DataGrid.layout.test.tsx +++ b/frontend/src/components/DataGrid.layout.test.tsx @@ -604,6 +604,12 @@ describe('DataGrid layout', () => { expect(source).toContain("const useVirtualCellContentContain = false;"); expect(source).toContain("const useVirtualEditableVisibilityHints = !isMacLike && !isV2Ui;"); expect(source).toContain("contain: ${useVirtualRowCellContain ? 'layout paint style' : 'none'};"); + expect(source).toContain('.${gridId} .data-grid-toolbar-scroll::-webkit-scrollbar-thumb:hover'); + expect(source).toContain('.${gridId} .ant-table-body::-webkit-scrollbar-thumb:hover'); + expect(source).toContain('.${gridId} .rc-virtual-list-holder::-webkit-scrollbar-thumb:hover'); + expect(source).toContain('.${gridId} .data-grid-external-horizontal-scroll::-webkit-scrollbar-thumb:hover'); + expect(source).toContain('background-clip: border-box;'); + expect(source).toContain('horizontalScrollbarThumbHoverBg'); expect(source).toContain('const handleSharedCellContextMenu = useCallback'); expect(source).toContain('const shouldUsePlainVirtualContent = isV2Ui && !modifiedStyle;'); expect(source).toContain('if (shouldUsePlainVirtualContent) {'); diff --git a/frontend/src/components/DataGrid.tsx b/frontend/src/components/DataGrid.tsx index d653b6e..86fb37f 100644 --- a/frontend/src/components/DataGrid.tsx +++ b/frontend/src/components/DataGrid.tsx @@ -1767,10 +1767,12 @@ const DataGrid: React.FC = ({ columnMetaTooltipColor: darkMode ? 'rgba(255, 236, 179, 0.98)' : '#262626', panelFrameColor: darkMode ? 'rgba(0, 0, 0, 0.42)' : 'rgba(0, 0, 0, 0.18)', floatingScrollbarThumbBg: darkMode ? 'rgba(255,255,255,0.68)' : 'rgba(0,0,0,0.44)', + floatingScrollbarThumbHoverBg: darkMode ? 'rgba(255,255,255,0.78)' : 'rgba(0,0,0,0.54)', floatingScrollbarThumbBorderColor: darkMode ? 'rgba(255,255,255,0.26)' : 'rgba(255,255,255,0.52)', floatingScrollbarThumbShadow: (isMacLike || isV2Ui) ? 'none' : (darkMode ? '0 4px 14px rgba(0,0,0,0.42)' : '0 4px 10px rgba(0,0,0,0.20)'), verticalScrollbarTrackBg: darkMode ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.08)', horizontalScrollbarThumbBg: darkMode ? 'rgba(255,255,255,0.20)' : 'rgba(0,0,0,0.14)', + horizontalScrollbarThumbHoverBg: darkMode ? 'rgba(255,255,255,0.30)' : 'rgba(0,0,0,0.24)', toolbarDividerColor: darkMode ? 'rgba(255, 255, 255, 0.12)' : 'rgba(0, 0, 0, 0.10)', paginationShellBg: darkMode ? `linear-gradient(135deg, rgba(17,22,34,${_glassMode ? Math.max(0.22, opacity * 0.38) : 0.82}) 0%, rgba(10,14,24,${_glassMode ? Math.max(0.28, opacity * 0.46) : 0.9}) 100%)` @@ -1809,8 +1811,8 @@ const DataGrid: React.FC = ({ selectionAccentHex, selectionAccentRgb, columnMetaHintColor, columnMetaTooltipColor, panelFrameColor, - floatingScrollbarThumbBg, floatingScrollbarThumbBorderColor, floatingScrollbarThumbShadow, - verticalScrollbarTrackBg, horizontalScrollbarThumbBg, + floatingScrollbarThumbBg, floatingScrollbarThumbHoverBg, floatingScrollbarThumbBorderColor, floatingScrollbarThumbShadow, + verticalScrollbarTrackBg, horizontalScrollbarThumbBg, horizontalScrollbarThumbHoverBg, toolbarDividerColor, paginationShellBg, paginationShellBorderColor, paginationShellShadow, paginationChipBg, paginationChipBorderColor, paginationHoverBg, @@ -2446,8 +2448,15 @@ const DataGrid: React.FC = ({ } .${gridId} .data-grid-toolbar-scroll::-webkit-scrollbar-thumb { background: ${darkMode ? 'rgba(255,255,255,0.28)' : 'rgba(0,0,0,0.22)'}; + border: 0; + background-clip: border-box; border-radius: 999px; } + .${gridId} .data-grid-toolbar-scroll::-webkit-scrollbar-thumb:hover { + background: ${darkMode ? 'rgba(255,255,255,0.38)' : 'rgba(0,0,0,0.32)'}; + border: 0; + background-clip: border-box; + } .${gridId} .data-grid-toolbar-scroll::-webkit-scrollbar-track { background: transparent; } @@ -2683,9 +2692,16 @@ const DataGrid: React.FC = ({ .${gridId} .ant-table-body::-webkit-scrollbar-thumb { background: ${floatingScrollbarThumbBg}; border: 1px solid ${floatingScrollbarThumbBorderColor}; + background-clip: border-box; border-radius: 999px; box-shadow: ${floatingScrollbarThumbShadow}; } + .${gridId} .ant-table-body::-webkit-scrollbar-thumb:hover { + background: ${floatingScrollbarThumbHoverBg}; + border: 1px solid ${floatingScrollbarThumbBorderColor}; + background-clip: border-box; + box-shadow: ${floatingScrollbarThumbShadow}; + } .${gridId} .rc-virtual-list-holder { scrollbar-width: thin; scrollbar-color: ${floatingScrollbarThumbBg} transparent; @@ -2702,9 +2718,16 @@ const DataGrid: React.FC = ({ .${gridId} .rc-virtual-list-holder::-webkit-scrollbar-thumb { background: ${floatingScrollbarThumbBg}; border: 1px solid ${floatingScrollbarThumbBorderColor}; + background-clip: border-box; border-radius: 999px; box-shadow: ${floatingScrollbarThumbShadow}; } + .${gridId} .rc-virtual-list-holder::-webkit-scrollbar-thumb:hover { + background: ${floatingScrollbarThumbHoverBg}; + border: 1px solid ${floatingScrollbarThumbBorderColor}; + background-clip: border-box; + box-shadow: ${floatingScrollbarThumbShadow}; + } .${gridId} .data-grid-external-horizontal-scroll { position: absolute; left: ${floatingScrollbarInset}px; @@ -2728,9 +2751,16 @@ const DataGrid: React.FC = ({ .${gridId} .data-grid-external-horizontal-scroll::-webkit-scrollbar-thumb { background: ${horizontalScrollbarThumbBg}; border: 1px solid ${horizontalScrollbarThumbBorderColor}; + background-clip: border-box; border-radius: 999px; box-shadow: ${horizontalScrollbarThumbShadow}; } + .${gridId} .data-grid-external-horizontal-scroll::-webkit-scrollbar-thumb:hover { + background: ${horizontalScrollbarThumbHoverBg}; + border: 1px solid ${horizontalScrollbarThumbBorderColor}; + background-clip: border-box; + box-shadow: ${horizontalScrollbarThumbShadow}; + } .${gridId} .data-grid-external-horizontal-scroll-inner { height: 1px; } diff --git a/internal/db/oceanbase_impl_test.go b/internal/db/oceanbase_impl_test.go index baa6e7b..30f66e1 100644 --- a/internal/db/oceanbase_impl_test.go +++ b/internal/db/oceanbase_impl_test.go @@ -17,6 +17,17 @@ import ( mysqlDriver "github.com/go-sql-driver/mysql" ) +const ( + testOceanBaseOracleHost = "ob-oracle.internal.example" + testOceanBaseOraclePort = 2881 + testOceanBaseOracleUser = "APP_USER@SERVICE:test_service" + testOceanBaseOraclePassword = "test-password" + testOceanBaseOracleDatabase = "test_service" + testSSHJumpHost = "ssh-gateway.example.test" + testSSHJumpUser = "test-ops" + testSSHJumpPassword = "test-ssh-password" +) + func TestResolveOceanBaseProtocol(t *testing.T) { t.Parallel() @@ -412,9 +423,9 @@ func TestOceanBaseOracleConnectStopsOnProbeDialFailure(t *testing.T) { Type: "oceanbase", Host: host, Port: port, - User: "SBDEV@SERVICE:srv_yhcs", - Password: "secret", - Database: "sbdev", + User: testOceanBaseOracleUser, + Password: testOceanBaseOraclePassword, + Database: testOceanBaseOracleDatabase, OceanBaseProtocol: oceanBaseProtocolOracle, Timeout: 1, }) @@ -448,19 +459,19 @@ func TestOceanBaseOracleConnectProbeDialFailureMentionsSSHWhenEnabled(t *testing ob := &OceanBaseDB{} err := ob.Connect(connection.ConnectionConfig{ Type: "oceanbase", - Host: "172.22.39.20", - Port: 12883, - User: "SBDEV@SERVICE:srv_yhcs", - Password: "secret", - Database: "sbdev", + Host: testOceanBaseOracleHost, + Port: testOceanBaseOraclePort, + User: testOceanBaseOracleUser, + Password: testOceanBaseOraclePassword, + Database: testOceanBaseOracleDatabase, OceanBaseProtocol: oceanBaseProtocolOracle, Timeout: 1, UseSSH: true, SSH: connection.SSHConfig{ - Host: "jump.example.com", + Host: testSSHJumpHost, Port: 22, - User: "ops", - Password: "jump-secret", + User: testSSHJumpUser, + Password: testSSHJumpPassword, }, }) if err == nil { @@ -470,10 +481,10 @@ func TestOceanBaseOracleConnectProbeDialFailureMentionsSSHWhenEnabled(t *testing if !seenConfig.UseSSH { t.Fatalf("expected probe dialer to receive UseSSH=true, got %+v", seenConfig) } - if seenAddress != "172.22.39.20:12883" { + if seenAddress != "ob-oracle.internal.example:2881" { t.Fatalf("expected probe target to remain remote inner address, got %q", seenAddress) } - if !strings.Contains(got, "通过 SSH 跳板机访问目标地址 172.22.39.20:12883 失败") { + if !strings.Contains(got, "通过 SSH 跳板机访问目标地址 ob-oracle.internal.example:2881 失败") { t.Fatalf("expected SSH-specific network diagnosis, got %q", got) } if strings.Contains(got, "VPN/内网路由") { @@ -499,13 +510,13 @@ func TestProbeOceanBaseMySQLWireHandshakeUsesSSHConfiguredDialer(t *testing.T) { } result := probeOceanBaseMySQLWireHandshakeDetail(connection.ConnectionConfig{ - Host: "172.22.39.20", - Port: 12883, + Host: testOceanBaseOracleHost, + Port: testOceanBaseOraclePort, UseSSH: true, SSH: connection.SSHConfig{ - Host: "jump.example.com", + Host: testSSHJumpHost, Port: 22, - User: "ops", + User: testSSHJumpUser, }, }, time.Second) @@ -515,7 +526,7 @@ func TestProbeOceanBaseMySQLWireHandshakeUsesSSHConfiguredDialer(t *testing.T) { if !seenConfig.UseSSH { t.Fatalf("expected probe dialer to receive SSH config, got %+v", seenConfig) } - if seenAddress != "172.22.39.20:12883" { + if seenAddress != "ob-oracle.internal.example:2881" { t.Fatalf("expected remote target address through SSH, got %q", seenAddress) } } @@ -535,18 +546,18 @@ func TestOceanBaseOracleConnectUsesFullSSHTimeoutForProbeDial(t *testing.T) { ob := &OceanBaseDB{} err := ob.Connect(connection.ConnectionConfig{ Type: "oceanbase", - Host: "172.22.39.20", - Port: 12883, - User: "SBDEV@SERVICE:srv_yhcs", - Password: "secret", - Database: "srv_yhcs", + Host: testOceanBaseOracleHost, + Port: testOceanBaseOraclePort, + User: testOceanBaseOracleUser, + Password: testOceanBaseOraclePassword, + Database: testOceanBaseOracleDatabase, OceanBaseProtocol: oceanBaseProtocolOracle, Timeout: 12, UseSSH: true, SSH: connection.SSHConfig{ - Host: "jump.example.com", + Host: testSSHJumpHost, Port: 22, - User: "ops", + User: testSSHJumpUser, }, }) if err == nil { @@ -579,13 +590,13 @@ func TestProbeOceanBaseMySQLWireHandshakeSplitsDialAndReadTimeout(t *testing.T) started := time.Now() result := probeOceanBaseMySQLWireHandshakeDetailWithTimeouts(connection.ConnectionConfig{ - Host: "172.22.39.20", - Port: 12883, + Host: testOceanBaseOracleHost, + Port: testOceanBaseOraclePort, UseSSH: true, SSH: connection.SSHConfig{ - Host: "jump.example.com", + Host: testSSHJumpHost, Port: 22, - User: "ops", + User: testSSHJumpUser, }, }, 12*time.Second, 50*time.Millisecond) elapsed := time.Since(started)