diff --git a/frontend/src/components/QueryEditor.external-sql-save.test.tsx b/frontend/src/components/QueryEditor.external-sql-save.test.tsx index 199271b..2570da8 100644 --- a/frontend/src/components/QueryEditor.external-sql-save.test.tsx +++ b/frontend/src/components/QueryEditor.external-sql-save.test.tsx @@ -7227,8 +7227,9 @@ describe('QueryEditor external SQL save', () => { expect(transactionSettingsSource).toContain('query_editor.transaction.mode.auto'); expect(transactionSettingsSource).not.toContain("label: '手动提交'"); expect(transactionSettingsSource).not.toContain("label: '自动提交'"); - expect(transactionSettingsSource).toContain('query_editor.transaction.delay.immediate'); - expect(transactionSettingsSource).toContain("label: '3s'"); + expect(transactionSettingsSource).toContain('query_editor.transaction.delay.immediate_commit'); + expect(transactionSettingsSource).toContain('query_editor.transaction.delay.seconds_commit'); + expect(transactionSettingsSource).not.toContain("label: '3s'"); expect(source).toContain('QueryEditorTransactionToolbar'); expect(transactionToolbarSource).toContain("className={isV2Ui ? 'gn-v2-query-transaction-toolbar' : undefined}"); expect(transactionToolbarSource).toContain(": null;"); @@ -7255,8 +7256,8 @@ describe('QueryEditor external SQL save', () => { expect(css).toContain('body[data-ui-version="v2"] .gn-v2-query-toolbar-selects'); expect(css).toContain('body[data-ui-version="v2"] .gn-v2-query-toolbar-actions'); - expect(css).toContain('width: 74px !important;'); - expect(css).toContain('width: 62px !important;'); + expect(css).toContain('width: 78px !important;'); + expect(css).toContain('width: 104px !important;'); expect(css).toContain('flex: 0 0 auto !important;'); expect(css).toContain('justify-content: flex-start;'); expect(css).toContain('height: 32px !important;'); diff --git a/frontend/src/components/QueryEditor.results-and-drop.test.tsx b/frontend/src/components/QueryEditor.results-and-drop.test.tsx index f83cb4e..6da266a 100644 --- a/frontend/src/components/QueryEditor.results-and-drop.test.tsx +++ b/frontend/src/components/QueryEditor.results-and-drop.test.tsx @@ -2553,8 +2553,9 @@ describe('QueryEditor external SQL save', () => { expect(transactionSettingsSource).toContain('query_editor.transaction.mode.auto'); expect(transactionSettingsSource).not.toContain("label: '手动提交'"); expect(transactionSettingsSource).not.toContain("label: '自动提交'"); - expect(transactionSettingsSource).toContain('query_editor.transaction.delay.immediate'); - expect(transactionSettingsSource).toContain("label: '3s'"); + expect(transactionSettingsSource).toContain('query_editor.transaction.delay.immediate_commit'); + expect(transactionSettingsSource).toContain('query_editor.transaction.delay.seconds_commit'); + expect(transactionSettingsSource).not.toContain("label: '3s'"); expect(source).toContain('QueryEditorTransactionToolbar'); expect(transactionToolbarSource).toContain("className={isV2Ui ? 'gn-v2-query-transaction-toolbar' : undefined}"); expect(transactionToolbarSource).toContain(": null;"); @@ -2581,8 +2582,8 @@ describe('QueryEditor external SQL save', () => { expect(css).toContain('body[data-ui-version="v2"] .gn-v2-query-toolbar-selects'); expect(css).toContain('body[data-ui-version="v2"] .gn-v2-query-toolbar-actions'); - expect(css).toContain('width: 74px !important;'); - expect(css).toContain('width: 62px !important;'); + expect(css).toContain('width: 78px !important;'); + expect(css).toContain('width: 104px !important;'); expect(css).toContain('flex: 0 0 auto !important;'); expect(css).toContain('justify-content: flex-start;'); expect(css).toContain('height: 32px !important;'); diff --git a/frontend/src/components/QueryEditorToolbar.layout.test.tsx b/frontend/src/components/QueryEditorToolbar.layout.test.tsx index 38dcc78..0f33e0d 100644 --- a/frontend/src/components/QueryEditorToolbar.layout.test.tsx +++ b/frontend/src/components/QueryEditorToolbar.layout.test.tsx @@ -62,4 +62,21 @@ describe('QueryEditorToolbar layout', () => { expect(commitHoverCss).toContain('box-shadow:'); expect(commitKbdHoverCss).toContain('background:'); }); + + it('keeps transaction selects wide enough for localized auto-commit labels', () => { + const css = readV2ThemeCss(); + const transactionModeCss = css.slice( + css.indexOf('body[data-ui-version="v2"] .gn-v2-query-toolbar-transaction-mode-select {'), + css.indexOf('body[data-ui-version="v2"] .gn-v2-query-toolbar-transaction-delay-select {'), + ); + const transactionDelayCss = css.slice( + css.indexOf('body[data-ui-version="v2"] .gn-v2-query-toolbar-transaction-delay-select {'), + css.indexOf('body[data-ui-version="v2"] .gn-v2-query-toolbar .ant-select-selector {'), + ); + + expect(transactionModeCss).toContain('width: 78px !important;'); + expect(transactionModeCss).toContain('flex: 0 0 78px !important;'); + expect(transactionDelayCss).toContain('width: 104px !important;'); + expect(transactionDelayCss).toContain('flex: 0 0 104px !important;'); + }); }); diff --git a/frontend/src/components/QueryEditorTransaction.i18n.test.ts b/frontend/src/components/QueryEditorTransaction.i18n.test.ts index e289205..ba600b6 100644 --- a/frontend/src/components/QueryEditorTransaction.i18n.test.ts +++ b/frontend/src/components/QueryEditorTransaction.i18n.test.ts @@ -20,6 +20,8 @@ const toolbarLegacyLiterals = [ const requiredKeys = [ 'query_editor.transaction.delay.immediate', + 'query_editor.transaction.delay.immediate_commit', + 'query_editor.transaction.delay.seconds_commit', 'query_editor.transaction.mode.tooltip', 'query_editor.transaction.mode.manual', 'query_editor.transaction.mode.auto', diff --git a/frontend/src/components/QueryEditorTransactionSettings.test.tsx b/frontend/src/components/QueryEditorTransactionSettings.test.tsx new file mode 100644 index 0000000..d850990 --- /dev/null +++ b/frontend/src/components/QueryEditorTransactionSettings.test.tsx @@ -0,0 +1,74 @@ +import React from 'react'; +import { act, create, type ReactTestRenderer } from 'react-test-renderer'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +import QueryEditorTransactionSettings from './QueryEditorTransactionSettings'; + +const antdState = vi.hoisted(() => ({ + selectProps: [] as any[], + tooltipProps: [] as any[], +})); + +vi.mock('antd', () => ({ + Select: (props: any) => { + antdState.selectProps.push(props); + return ; + }, + Tooltip: (props: any) => { + antdState.tooltipProps.push(props); + return
{props.children}
; + }, +})); + +vi.mock('../i18n/provider', () => ({ + useOptionalI18n: () => ({ + t: (key: string, params?: Record) => params?.seconds ? `${params.seconds}s后提交` : key, + }), +})); + +const latestSelectProps = () => antdState.selectProps[antdState.selectProps.length - 1]; +const latestTooltipProps = () => antdState.tooltipProps[antdState.tooltipProps.length - 1]; + +describe('QueryEditorTransactionSettings', () => { + let renderer: ReactTestRenderer | null = null; + + beforeEach(() => { + antdState.selectProps = []; + antdState.tooltipProps = []; + }); + + afterEach(() => { + renderer?.unmount(); + renderer = null; + }); + + it('hides the DBeaver reference tooltip while the transaction mode select is open', () => { + act(() => { + renderer = create( + , + ); + }); + + act(() => { + latestTooltipProps().onOpenChange(true); + }); + expect(latestTooltipProps().open).toBe(true); + + act(() => { + latestSelectProps().onOpenChange(true); + }); + expect(latestTooltipProps().open).toBe(false); + + act(() => { + latestSelectProps().onOpenChange(false); + latestTooltipProps().onOpenChange(true); + }); + expect(latestTooltipProps().open).toBe(true); + }); +}); diff --git a/frontend/src/components/QueryEditorTransactionSettings.tsx b/frontend/src/components/QueryEditorTransactionSettings.tsx index a52c083..9af9fef 100644 --- a/frontend/src/components/QueryEditorTransactionSettings.tsx +++ b/frontend/src/components/QueryEditorTransactionSettings.tsx @@ -8,18 +8,14 @@ export type SqlEditorCommitMode = 'manual' | 'auto'; type SqlEditorAutoCommitDelayOption = { value: number; - label: string; -} | { - value: number; - labelKey: string; }; export const SQL_EDITOR_AUTO_COMMIT_DELAY_OPTIONS: SqlEditorAutoCommitDelayOption[] = [ - { value: 0, labelKey: 'query_editor.transaction.delay.immediate' }, - { value: 3000, label: '3s' }, - { value: 5000, label: '5s' }, - { value: 10000, label: '10s' }, - { value: 30000, label: '30s' }, + { value: 0 }, + { value: 3000 }, + { value: 5000 }, + { value: 10000 }, + { value: 30000 }, ]; type QueryEditorTransactionSettingsProps = { @@ -39,18 +35,36 @@ const QueryEditorTransactionSettings: React.FC { const i18n = useOptionalI18n(); const t = i18n?.t ?? defaultTranslate; + const [isModeSelectOpen, setIsModeSelectOpen] = React.useState(false); + const [isModeTooltipOpen, setIsModeTooltipOpen] = React.useState(false); const autoCommitDelayOptions = SQL_EDITOR_AUTO_COMMIT_DELAY_OPTIONS.map((option) => ({ value: option.value, - label: 'labelKey' in option ? t(option.labelKey) : option.label, + label: option.value === 0 + ? t('query_editor.transaction.delay.immediate_commit') + : t('query_editor.transaction.delay.seconds_commit', { seconds: Math.round(option.value / 1000) }), })); + const handleModeSelectOpenChange = (open: boolean) => { + setIsModeSelectOpen(open); + if (open) { + setIsModeTooltipOpen(false); + } + }; + const handleModeTooltipOpenChange = (open: boolean) => { + setIsModeTooltipOpen(open); + }; return ( <> - +