// Licensed to Cloudera, Inc. under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import PartitionsTab from './PartitionsTab';
import { Partition } from '../types';
describe('PartitionsTab', () => {
const mockOnPartitionsChange = jest.fn();
const defaultPartitions: Partition[] = [];
const partitionsWithData: Partition[] = [
{
id: 'partition_1',
name: 'year',
type: 'int',
value: '2023'
},
{
id: 'partition_2',
name: 'month',
type: 'string',
value: 'january'
}
];
const defaultProps = {
partitions: defaultPartitions,
onPartitionsChange: mockOnPartitionsChange
};
beforeEach(() => {
mockOnPartitionsChange.mockClear();
});
describe('Component Rendering', () => {
it('should render add button when no partitions exist', () => {
render();
expect(screen.getByRole('button', { name: /add partitions/i })).toBeInTheDocument();
expect(screen.queryByText('Partition 1')).not.toBeInTheDocument();
});
it('should render partitions when they exist', async () => {
render();
await waitFor(() => {
expect(screen.getByDisplayValue('year')).toBeInTheDocument();
expect(screen.getByDisplayValue('month')).toBeInTheDocument();
expect(screen.getByDisplayValue('2023')).toBeInTheDocument();
expect(screen.getByDisplayValue('january')).toBeInTheDocument();
});
});
it('should render delete buttons for each partition', async () => {
render();
const deleteButtons = screen.getAllByRole('button', { name: 'minus-circle' });
await waitFor(() => {
expect(deleteButtons).toHaveLength(2);
});
});
});
describe('Adding Partitions', () => {
it('should call onPartitionsChange when adding a partition', async () => {
const user = userEvent.setup();
render();
const addButton = screen.getByRole('button', { name: /add partitions/i });
await user.click(addButton);
await waitFor(() => {
expect(mockOnPartitionsChange).toHaveBeenCalledWith([
expect.objectContaining({
id: expect.stringMatching(/^partition_\d+$/),
name: '',
type: 'string',
value: ''
})
]);
});
});
it('should add new partition to existing ones', async () => {
const user = userEvent.setup();
render();
const addButton = screen.getByRole('button', { name: /add partitions/i });
await user.click(addButton);
await waitFor(() => {
expect(mockOnPartitionsChange).toHaveBeenCalledWith([
...partitionsWithData,
expect.objectContaining({
id: expect.stringMatching(/^partition_\d+$/),
name: '',
type: 'string',
value: ''
})
]);
});
});
});
describe('Removing Partitions', () => {
it('should call onPartitionsChange when removing a partition', async () => {
const user = userEvent.setup();
render();
const deleteButtons = screen.getAllByRole('button', { name: 'minus-circle' });
await user.click(deleteButtons[0]);
await waitFor(() => {
expect(mockOnPartitionsChange).toHaveBeenCalledWith([partitionsWithData[1]]);
});
});
it('should remove correct partition when multiple exist', async () => {
const user = userEvent.setup();
render();
const deleteButtons = screen.getAllByRole('button', { name: 'minus-circle' });
await user.click(deleteButtons[1]);
await waitFor(() => {
expect(mockOnPartitionsChange).toHaveBeenCalledWith([partitionsWithData[0]]);
});
});
});
describe('Editing Partition Fields', () => {
it('should call onPartitionsChange when partition name changes', async () => {
const user = userEvent.setup();
render();
const nameInput = screen.getByDisplayValue('year');
await user.clear(nameInput);
await user.type(nameInput, 'x');
await waitFor(() => {
expect(mockOnPartitionsChange).toHaveBeenCalled();
});
const lastCall =
mockOnPartitionsChange.mock.calls[mockOnPartitionsChange.mock.calls.length - 1];
expect(Array.isArray(lastCall[0])).toBe(true);
});
it('should call onPartitionsChange when partition value changes', async () => {
const user = userEvent.setup();
render();
const valueInput = screen.getByDisplayValue('2023');
await user.clear(valueInput);
await user.type(valueInput, '1');
await waitFor(() => {
expect(mockOnPartitionsChange).toHaveBeenCalled();
});
const lastCall =
mockOnPartitionsChange.mock.calls[mockOnPartitionsChange.mock.calls.length - 1];
expect(Array.isArray(lastCall[0])).toBe(true);
});
it('should call onPartitionsChange when partition type changes', async () => {
const user = userEvent.setup();
render();
const typeSelects = screen.getAllByRole('combobox');
const firstTypeSelect = typeSelects[0];
await user.click(firstTypeSelect);
const bigintOption = screen.getByText('Big Integer');
await user.click(bigintOption);
await waitFor(() => {
expect(mockOnPartitionsChange).toHaveBeenCalledWith([
{
...partitionsWithData[0],
type: 'bigint'
},
partitionsWithData[1]
]);
});
});
});
});