releasesSelectControl.spec.tsx 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import {ReleaseFixture} from 'sentry-fixture/release';
  2. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  3. import {ReleasesContext} from 'sentry/utils/releases/releasesProvider';
  4. import ReleasesSelectControl from 'sentry/views/dashboards/releasesSelectControl';
  5. import type {DashboardFilters} from 'sentry/views/dashboards/types';
  6. function renderReleasesSelect({
  7. onSearch,
  8. handleChangeFilter,
  9. }: {
  10. handleChangeFilter?: (activeFilters: DashboardFilters) => void;
  11. onSearch?: (searchTerm: string) => void;
  12. }) {
  13. render(
  14. <ReleasesContext.Provider
  15. value={{
  16. releases: [
  17. ReleaseFixture({
  18. id: '1',
  19. shortVersion: 'sentry-android-shop@1.2.0',
  20. version: 'sentry-android-shop@1.2.0',
  21. }),
  22. ReleaseFixture({
  23. id: '2',
  24. shortVersion: 'sentry-android-shop@1.3.0',
  25. version: 'sentry-android-shop@1.3.0',
  26. }),
  27. ReleaseFixture({
  28. id: '3',
  29. shortVersion: 'sentry-android-shop@1.4.0',
  30. version: 'sentry-android-shop@1.4.0',
  31. }),
  32. ],
  33. loading: false,
  34. onSearch: onSearch ?? jest.fn(),
  35. }}
  36. >
  37. <ReleasesSelectControl
  38. selectedReleases={[]}
  39. handleChangeFilter={handleChangeFilter}
  40. />
  41. </ReleasesContext.Provider>
  42. );
  43. }
  44. describe('Dashboards > ReleasesSelectControl', function () {
  45. it('updates menu title with selection', async function () {
  46. renderReleasesSelect({});
  47. expect(screen.getByText('All Releases')).toBeInTheDocument();
  48. await userEvent.click(screen.getByText('All Releases'));
  49. expect(screen.getByText('Latest Release(s)')).toBeInTheDocument();
  50. await userEvent.click(screen.getByText('sentry-android-shop@1.2.0'));
  51. await userEvent.click(document.body);
  52. expect(screen.getByText('sentry-android-shop@1.2.0')).toBeInTheDocument();
  53. expect(screen.queryByText('+1')).not.toBeInTheDocument();
  54. });
  55. it('updates menu title with multiple selections', async function () {
  56. renderReleasesSelect({});
  57. expect(screen.getByText('All Releases')).toBeInTheDocument();
  58. await userEvent.click(screen.getByText('All Releases'));
  59. await userEvent.click(screen.getByText('sentry-android-shop@1.2.0'));
  60. await userEvent.click(screen.getByText('sentry-android-shop@1.4.0'));
  61. await userEvent.click(document.body);
  62. expect(screen.getByText('sentry-android-shop@1.2.0')).toBeInTheDocument();
  63. expect(screen.getByText('+1')).toBeInTheDocument();
  64. });
  65. it('calls onSearch when filtering by releases', async function () {
  66. const mockOnSearch = jest.fn();
  67. renderReleasesSelect({onSearch: mockOnSearch});
  68. expect(screen.getByText('All Releases')).toBeInTheDocument();
  69. await userEvent.click(screen.getByText('All Releases'));
  70. await userEvent.type(screen.getByPlaceholderText('Search\u2026'), 'se');
  71. await waitFor(() => expect(mockOnSearch).toHaveBeenCalledWith('se'));
  72. });
  73. it('resets search on close', async function () {
  74. const mockOnSearch = jest.fn();
  75. renderReleasesSelect({onSearch: mockOnSearch});
  76. expect(screen.getByText('All Releases')).toBeInTheDocument();
  77. await userEvent.click(screen.getByText('All Releases'));
  78. await userEvent.type(screen.getByPlaceholderText('Search\u2026'), 'se');
  79. await waitFor(() => expect(mockOnSearch).toHaveBeenCalledWith('se'));
  80. await userEvent.click(document.body);
  81. await waitFor(() => expect(mockOnSearch).toHaveBeenCalledWith(''));
  82. });
  83. it('triggers handleChangeFilter with the release versions', async function () {
  84. const mockHandleChangeFilter = jest.fn();
  85. renderReleasesSelect({handleChangeFilter: mockHandleChangeFilter});
  86. expect(screen.getByText('All Releases')).toBeInTheDocument();
  87. await userEvent.click(screen.getByText('All Releases'));
  88. await userEvent.click(screen.getByText('Latest Release(s)'));
  89. await userEvent.click(screen.getByText('sentry-android-shop@1.2.0'));
  90. await userEvent.click(screen.getByText('sentry-android-shop@1.4.0'));
  91. await userEvent.click(document.body);
  92. expect(mockHandleChangeFilter).toHaveBeenCalledWith({
  93. release: ['latest', 'sentry-android-shop@1.2.0', 'sentry-android-shop@1.4.0'],
  94. });
  95. });
  96. it('includes Latest Release(s) even if no matching releases', async function () {
  97. render(
  98. <ReleasesContext.Provider
  99. value={{
  100. releases: [],
  101. loading: false,
  102. onSearch: jest.fn(),
  103. }}
  104. >
  105. <ReleasesSelectControl selectedReleases={[]} handleChangeFilter={jest.fn()} />
  106. </ReleasesContext.Provider>
  107. );
  108. expect(screen.getByText('All Releases')).toBeInTheDocument();
  109. await userEvent.click(screen.getByText('All Releases'));
  110. await userEvent.type(screen.getByPlaceholderText('Search\u2026'), 'latest');
  111. screen.getByText('Latest Release(s)');
  112. });
  113. });