fix: Add ALL COLUMNS in the profiling Settings #18507 (#20271)

This commit is contained in:
Shailesh Parmar 2025-03-17 13:04:39 +05:30 committed by GitHub
parent 992a4547af
commit 5756b4c9d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 134 additions and 135 deletions

View File

@ -14,40 +14,75 @@
import { import {
act, act,
cleanup, cleanup,
findByText,
fireEvent, fireEvent,
render, render,
screen, screen,
waitFor,
} from '@testing-library/react'; } from '@testing-library/react';
import React from 'react'; import React from 'react';
import { Column } from '../../../../../generated/entity/data/dashboardDataModel';
import { MOCK_TABLE } from '../../../../../mocks/TableData.mock'; import { MOCK_TABLE } from '../../../../../mocks/TableData.mock';
import { getTableProfilerConfig } from '../../../../../rest/tableAPI'; import { getTableProfilerConfig } from '../../../../../rest/tableAPI';
import { ProfilerSettingsModalProps } from '../TableProfiler.interface'; import { ProfilerSettingsModalProps } from '../TableProfiler.interface';
import ProfilerSettingsModal from './ProfilerSettingsModal'; import ProfilerSettingsModal from './ProfilerSettingsModal';
const mockShowSuccessToast = jest.fn();
const mockShowErrorToast = jest.fn();
const mockOnVisibilityChange = jest.fn();
jest.mock('../../../../../rest/tableAPI', () => ({ jest.mock('../../../../../rest/tableAPI', () => ({
getTableProfilerConfig: jest getTableProfilerConfig: jest
.fn() .fn()
.mockImplementation(() => Promise.resolve(MOCK_TABLE)), .mockImplementation(() => Promise.resolve(MOCK_TABLE)),
putTableProfileConfig: jest.fn(), putTableProfileConfig: jest.fn().mockResolvedValue({}),
})); }));
const mockProps: ProfilerSettingsModalProps = { const mockProps: ProfilerSettingsModalProps = {
tableId: MOCK_TABLE.id, tableId: MOCK_TABLE.id,
columns: MOCK_TABLE.columns || [], columns: [
{ name: 'column1', dataType: 'string' },
{ name: 'column2', dataType: 'timestamp' },
] as unknown as Column[],
visible: true, visible: true,
onVisibilityChange: jest.fn(), onVisibilityChange: mockOnVisibilityChange,
};
const mockTableProfilerConfig = {
profileSample: 60.0,
profileSampleType: 'PERCENTAGE',
sampleDataCount: 500,
profileQuery: 'select * from table',
excludeColumns: ['column1'],
includeColumns: [{ columnName: 'column2', metrics: ['column_count'] }],
partitioning: {
enablePartitioning: true,
partitionColumnName: 'column2',
partitionIntervalType: 'COLUMN-VALUE',
partitionValues: ['test'],
},
}; };
jest.mock('../../../../../constants/profiler.constant', () => ({ jest.mock('../../../../../constants/profiler.constant', () => ({
DEFAULT_INCLUDE_PROFILE: [], DEFAULT_INCLUDE_PROFILE: [],
INTERVAL_TYPE_OPTIONS: [], INTERVAL_TYPE_OPTIONS: [
INTERVAL_UNIT_OPTIONS: [], { label: 'Column Value', value: 'COLUMN-VALUE' },
PROFILER_METRIC: [], { label: 'Time Unit', value: 'TIME-UNIT' },
],
INTERVAL_UNIT_OPTIONS: [
{ label: 'Day', value: 'DAY' },
{ label: 'Hour', value: 'HOUR' },
],
PROFILER_METRIC: ['column_count', 'distinct_count'],
PROFILER_MODAL_LABEL_STYLE: {}, PROFILER_MODAL_LABEL_STYLE: {},
PROFILE_SAMPLE_OPTIONS: [], PROFILE_SAMPLE_OPTIONS: [
SUPPORTED_COLUMN_DATA_TYPE_FOR_INTERVAL: {}, { label: 'Percentage', value: 'PERCENTAGE' },
TIME_BASED_PARTITION: [], { label: 'Row Count', value: 'ROW_COUNT' },
],
SUPPORTED_COLUMN_DATA_TYPE_FOR_INTERVAL: {
'COLUMN-VALUE': ['string'],
'TIME-UNIT': ['timestamp'],
},
TIME_BASED_PARTITION: ['TIME-UNIT'],
})); }));
jest.mock('../../../../../utils/CommonUtils', () => ({ jest.mock('../../../../../utils/CommonUtils', () => ({
@ -55,8 +90,12 @@ jest.mock('../../../../../utils/CommonUtils', () => ({
})); }));
jest.mock('../../../../../utils/ToastUtils', () => ({ jest.mock('../../../../../utils/ToastUtils', () => ({
showErrorToast: jest.fn(), showErrorToast: jest
showSuccessToast: jest.fn(), .fn()
.mockImplementation((error) => mockShowErrorToast(error)),
showSuccessToast: jest
.fn()
.mockImplementation((msg) => mockShowSuccessToast(msg)),
})); }));
jest.mock('../../../SchemaEditor/SchemaEditor', () => { jest.mock('../../../SchemaEditor/SchemaEditor', () => {
@ -70,133 +109,84 @@ jest.mock('../../../../common/SliderWithInput/SliderWithInput', () => {
describe('Test ProfilerSettingsModal component', () => { describe('Test ProfilerSettingsModal component', () => {
beforeEach(() => { beforeEach(() => {
cleanup(); cleanup();
jest.clearAllMocks();
});
afterEach(() => {
jest.clearAllMocks();
}); });
it('should render without crashing', async () => { it('should render without crashing', async () => {
render(<ProfilerSettingsModal {...mockProps} />);
const modal = await screen.findByTestId('profiler-settings-modal');
const sampleContainer = await screen.findByTestId(
'profile-sample-container'
);
const sqlEditor = await screen.findByTestId('sql-editor-container');
const includeSelect = await screen.findByTestId('include-column-container');
const excludeSelect = await screen.findByTestId('exclude-column-container');
const partitionSwitch = await screen.findByTestId(
'enable-partition-switch'
);
const intervalType = await screen.findByTestId('interval-type');
const columnName = await screen.findByTestId('column-name');
const sampleDataCount = await screen.findByTestId(
'sample-data-count-input'
);
expect(modal).toBeInTheDocument();
expect(sampleContainer).toBeInTheDocument();
expect(sqlEditor).toBeInTheDocument();
expect(includeSelect).toBeInTheDocument();
expect(excludeSelect).toBeInTheDocument();
expect(partitionSwitch).toBeInTheDocument();
expect(intervalType).toBeInTheDocument();
expect(columnName).toBeInTheDocument();
expect(sampleDataCount).toBeInTheDocument();
});
it('Interval Type and Column Name field should be disabled, when partition switch is off', async () => {
render(<ProfilerSettingsModal {...mockProps} />);
const partitionSwitch = await screen.findByTestId(
'enable-partition-switch'
);
const intervalType = await screen.findByTestId('interval-type');
const columnName = await screen.findByTestId('column-name');
expect(partitionSwitch).toHaveAttribute('aria-checked', 'false');
expect(intervalType).toHaveClass('ant-select-disabled');
expect(columnName).toHaveClass('ant-select-disabled');
});
it.skip('Interval Type and Column Name field should be enabled, when partition switch is on', async () => {
render(<ProfilerSettingsModal {...mockProps} />);
const partitionSwitch = await screen.findByTestId(
'enable-partition-switch'
);
expect(partitionSwitch).toHaveAttribute('aria-checked', 'false');
await act(async () => { await act(async () => {
fireEvent.click(partitionSwitch); render(<ProfilerSettingsModal {...mockProps} />);
}); });
expect(await screen.findByTestId('interval-type')).not.toHaveClass( await waitFor(() => {
'ant-select-disabled' expect(screen.getByTestId('profiler-settings-modal')).toBeInTheDocument();
); expect(
expect(await screen.findByTestId('column-name')).not.toHaveClass( screen.getByTestId('profile-sample-container')
'ant-select-disabled' ).toBeInTheDocument();
); expect(screen.getByTestId('sql-editor-container')).toBeInTheDocument();
expect(
screen.getByTestId('include-column-container')
).toBeInTheDocument();
expect(
screen.getByTestId('exclude-column-container')
).toBeInTheDocument();
expect(screen.getByTestId('enable-partition-switch')).toBeInTheDocument();
expect(screen.getByTestId('interval-type')).toBeInTheDocument();
expect(screen.getByTestId('column-name')).toBeInTheDocument();
expect(screen.getByTestId('sample-data-count-input')).toBeInTheDocument();
});
}); });
it.skip('initial values should be visible in the form', async () => { it('should handle modal visibility', async () => {
const tableProfilerConfig = { await act(async () => {
profileSample: 60.0, render(<ProfilerSettingsModal {...mockProps} />);
profileSampleType: 'PERCENTAGE', });
sampleDataCount: 500,
profileQuery: 'select * from table',
excludeColumns: ['address_id'],
includeColumns: [
{
columnName: 'first_name',
},
],
partitioning: {
enablePartitioning: true,
partitionColumnName: 'last_name',
partitionIntervalType: 'COLUMN-VALUE',
partitionValues: ['test'],
},
};
(getTableProfilerConfig as jest.Mock).mockImplementationOnce(() =>
Promise.resolve({ ...MOCK_TABLE, tableProfilerConfig })
);
render(<ProfilerSettingsModal {...mockProps} />);
const excludeSelect = await screen.findByTestId('exclude-column-select'); await waitFor(() => {
const includeSelect = await screen.findByTestId('include-column-select'); expect(screen.getByTestId('profiler-settings-modal')).toBeInTheDocument();
const partitionSwitch = await screen.findByTestId( });
'enable-partition-switch'
);
const intervalType = await screen.findByTestId('interval-type');
const columnName = await screen.findByTestId('column-name');
expect(await screen.findByTestId('sample-data-count-input')).toHaveValue( const cancelButton = screen.getByRole('button', { name: /cancel/i });
tableProfilerConfig.sampleDataCount.toString() await act(async () => {
); fireEvent.click(cancelButton);
expect(await screen.findByTestId('slider-input')).toHaveValue( });
`${tableProfilerConfig.profileSample}%`
); expect(mockOnVisibilityChange).toHaveBeenCalledWith(false);
expect(await screen.findByTestId('partition-value')).toHaveValue( });
tableProfilerConfig.partitioning.partitionValues[0]
); it('should load initial profiler config', async () => {
expect( (getTableProfilerConfig as jest.Mock).mockResolvedValueOnce({
await findByText(excludeSelect, tableProfilerConfig.excludeColumns[0]) ...MOCK_TABLE,
).toBeInTheDocument(); tableProfilerConfig: mockTableProfilerConfig,
expect( });
await findByText(
includeSelect, await act(async () => {
tableProfilerConfig.includeColumns[0].columnName render(<ProfilerSettingsModal {...mockProps} />);
) });
).toBeInTheDocument();
expect( await waitFor(() => {
await findByText( const sampleDataCount = screen.getByTestId('sample-data-count-input');
intervalType,
tableProfilerConfig.partitioning.partitionIntervalType expect(sampleDataCount).toHaveAttribute('value', '500');
) });
).toBeInTheDocument(); });
expect(
await findByText( it('should handle sample data count change', async () => {
columnName, await act(async () => {
tableProfilerConfig.partitioning.partitionColumnName render(<ProfilerSettingsModal {...mockProps} />);
) });
).toBeInTheDocument();
expect(partitionSwitch).toHaveAttribute('aria-checked', 'true'); const sampleDataCount = screen.getByTestId('sample-data-count-input');
await act(async () => {
fireEvent.change(sampleDataCount, { target: { value: '100' } });
});
await waitFor(() => {
expect(sampleDataCount).toHaveAttribute('value', '100');
});
}); });
}); });

View File

@ -113,11 +113,20 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
[] []
); );
const selectOptions = useMemo(() => { const { columnOptions, columnWithAllOption } = useMemo(() => {
return columns.map(({ name }) => ({ const columnOptions = columns.map(({ name }) => ({
label: name, label: name,
value: name, value: name,
})); }));
const columnWithAllOption = [
{
label: t('label.all'),
value: 'all',
},
...columnOptions,
];
return { columnOptions, columnWithAllOption };
}, [columns]); }, [columns]);
const metricsOptions = useMemo(() => { const metricsOptions = useMemo(() => {
const metricsOptions = [ const metricsOptions = [
@ -547,9 +556,9 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
allowClear allowClear
className="w-full" className="w-full"
data-testid="exclude-column-select" data-testid="exclude-column-select"
dropdownStyle={{ maxHeight: 200 }} dropdownStyle={{ maxHeight: 200, overflowY: 'auto' }}
mode="multiple" mode="multiple"
options={selectOptions} options={columnOptions}
placeholder={t('label.select-column-plural-to-exclude')} placeholder={t('label.select-column-plural-to-exclude')}
size="middle" size="middle"
value={state?.excludeCol} value={state?.excludeCol}
@ -604,7 +613,7 @@ const ProfilerSettingsModal: React.FC<ProfilerSettingsModalProps> = ({
showSearch showSearch
className="w-full" className="w-full"
data-testid="include-column-select" data-testid="include-column-select"
options={selectOptions} options={columnWithAllOption}
placeholder={t( placeholder={t(
'label.select-column-plural-to-include' 'label.select-column-plural-to-include'
)} )}