import {ReleaseFixture} from 'sentry-fixture/release';
import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
import {ReleasesContext} from 'sentry/utils/releases/releasesProvider';
import ReleasesSelectControl from 'sentry/views/dashboards/releasesSelectControl';
import type {DashboardFilters} from 'sentry/views/dashboards/types';
function renderReleasesSelect({
onSearch,
handleChangeFilter,
}: {
handleChangeFilter?: (activeFilters: DashboardFilters) => void;
onSearch?: (searchTerm: string) => void;
}) {
render(
);
}
describe('Dashboards > ReleasesSelectControl', function () {
it('updates menu title with selection', async function () {
renderReleasesSelect({});
expect(screen.getByText('All Releases')).toBeInTheDocument();
await userEvent.click(screen.getByText('All Releases'));
expect(screen.getByText('Latest Release(s)')).toBeInTheDocument();
await userEvent.click(screen.getByText('sentry-android-shop@1.2.0'));
await userEvent.click(document.body);
expect(screen.getByText('sentry-android-shop@1.2.0')).toBeInTheDocument();
expect(screen.queryByText('+1')).not.toBeInTheDocument();
});
it('updates menu title with multiple selections', async function () {
renderReleasesSelect({});
expect(screen.getByText('All Releases')).toBeInTheDocument();
await userEvent.click(screen.getByText('All Releases'));
await userEvent.click(screen.getByText('sentry-android-shop@1.2.0'));
await userEvent.click(screen.getByText('sentry-android-shop@1.4.0'));
await userEvent.click(document.body);
expect(screen.getByText('sentry-android-shop@1.2.0')).toBeInTheDocument();
expect(screen.getByText('+1')).toBeInTheDocument();
});
it('calls onSearch when filtering by releases', async function () {
const mockOnSearch = jest.fn();
renderReleasesSelect({onSearch: mockOnSearch});
expect(screen.getByText('All Releases')).toBeInTheDocument();
await userEvent.click(screen.getByText('All Releases'));
await userEvent.type(screen.getByPlaceholderText('Search\u2026'), 'se');
await waitFor(() => expect(mockOnSearch).toHaveBeenCalledWith('se'));
});
it('resets search on close', async function () {
const mockOnSearch = jest.fn();
renderReleasesSelect({onSearch: mockOnSearch});
expect(screen.getByText('All Releases')).toBeInTheDocument();
await userEvent.click(screen.getByText('All Releases'));
await userEvent.type(screen.getByPlaceholderText('Search\u2026'), 'se');
await waitFor(() => expect(mockOnSearch).toHaveBeenCalledWith('se'));
await userEvent.click(document.body);
await waitFor(() => expect(mockOnSearch).toHaveBeenCalledWith(''));
});
it('triggers handleChangeFilter with the release versions', async function () {
const mockHandleChangeFilter = jest.fn();
renderReleasesSelect({handleChangeFilter: mockHandleChangeFilter});
expect(screen.getByText('All Releases')).toBeInTheDocument();
await userEvent.click(screen.getByText('All Releases'));
await userEvent.click(screen.getByText('Latest Release(s)'));
await userEvent.click(screen.getByText('sentry-android-shop@1.2.0'));
await userEvent.click(screen.getByText('sentry-android-shop@1.4.0'));
await userEvent.click(document.body);
expect(mockHandleChangeFilter).toHaveBeenCalledWith({
release: ['latest', 'sentry-android-shop@1.2.0', 'sentry-android-shop@1.4.0'],
});
});
it('includes Latest Release(s) even if no matching releases', async function () {
render(
);
expect(screen.getByText('All Releases')).toBeInTheDocument();
await userEvent.click(screen.getByText('All Releases'));
await userEvent.type(screen.getByPlaceholderText('Search\u2026'), 'latest');
screen.getByText('Latest Release(s)');
});
});