groupTagValues.spec.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import {GroupFixture} from 'sentry-fixture/group';
  2. import {TagsFixture} from 'sentry-fixture/tags';
  3. import {TagValuesFixture} from 'sentry-fixture/tagvalues';
  4. import {initializeOrg} from 'sentry-test/initializeOrg';
  5. import {
  6. render,
  7. screen,
  8. userEvent,
  9. waitFor,
  10. waitForElementToBeRemoved,
  11. within,
  12. } from 'sentry-test/reactTestingLibrary';
  13. import {browserHistory} from 'sentry/utils/browserHistory';
  14. import GroupTagValues from 'sentry/views/issueDetails/groupTagValues';
  15. const group = GroupFixture();
  16. const tags = TagsFixture();
  17. function init(tagKey: string) {
  18. return initializeOrg({
  19. router: {
  20. location: {
  21. query: {},
  22. pathname: '/organizations/:orgId/issues/:groupId/tags/:tagKey/',
  23. },
  24. params: {orgId: 'org-slug', groupId: group.id, tagKey},
  25. },
  26. });
  27. }
  28. describe('GroupTagValues', () => {
  29. beforeEach(() => {
  30. MockApiClient.addMockResponse({
  31. url: '/organizations/org-slug/issues/1/tags/user/',
  32. body: tags.find(({key}) => key === 'user'),
  33. });
  34. });
  35. afterEach(() => {
  36. MockApiClient.clearMockResponses();
  37. });
  38. it('renders a list of tag values', async () => {
  39. const {router, routerProps, project} = init('user');
  40. MockApiClient.addMockResponse({
  41. url: '/organizations/org-slug/issues/1/tags/user/values/',
  42. body: TagValuesFixture(),
  43. });
  44. render(
  45. <GroupTagValues
  46. environments={[]}
  47. group={group}
  48. project={project}
  49. baseUrl=""
  50. {...routerProps}
  51. />,
  52. {router}
  53. );
  54. await waitForElementToBeRemoved(() => screen.getByTestId('loading-indicator'));
  55. // Special case for user tag - column title changes to Affected Users
  56. expect(screen.getByText('Affected Users')).toBeInTheDocument();
  57. // Affected user column
  58. expect(screen.getByText('David Cramer')).toBeInTheDocument();
  59. // Percent column
  60. expect(screen.getByText('16.67%')).toBeInTheDocument();
  61. // Count column
  62. expect(screen.getByText('3')).toBeInTheDocument();
  63. });
  64. it('can page through tag values', async () => {
  65. const {router, routerProps, project} = init('user');
  66. MockApiClient.addMockResponse({
  67. url: '/organizations/org-slug/issues/1/tags/user/values/',
  68. body: TagValuesFixture(),
  69. headers: {
  70. Link:
  71. '<https://sentry.io/api/0/organizations/sentry/user-feedback/?statsPeriod=14d&cursor=0:0:1>; rel="previous"; results="false"; cursor="0:0:1", ' +
  72. '<https://sentry.io/api/0/organizations/sentry/user-feedback/?statsPeriod=14d&cursor=0:100:0>; rel="next"; results="true"; cursor="0:100:0"',
  73. },
  74. });
  75. render(
  76. <GroupTagValues
  77. environments={[]}
  78. group={group}
  79. project={project}
  80. baseUrl=""
  81. {...routerProps}
  82. />,
  83. {router}
  84. );
  85. await waitForElementToBeRemoved(() => screen.getByTestId('loading-indicator'));
  86. expect(screen.getByRole('button', {name: 'Previous'})).toBeDisabled();
  87. expect(screen.getByRole('button', {name: 'Next'})).toBeEnabled();
  88. // Clicking next button loads page with query param ?cursor=0:100:0
  89. await userEvent.click(screen.getByRole('button', {name: 'Next'}));
  90. await waitFor(() => {
  91. expect(browserHistory.push).toHaveBeenCalledWith(
  92. expect.objectContaining({query: expect.objectContaining({cursor: '0:100:0'})})
  93. );
  94. });
  95. });
  96. it('navigates to issue details events tab with correct query params', async () => {
  97. const {routerProps, router, project} = init('user');
  98. MockApiClient.addMockResponse({
  99. url: '/organizations/org-slug/issues/1/tags/user/values/',
  100. body: TagValuesFixture(),
  101. });
  102. render(
  103. <GroupTagValues
  104. environments={[]}
  105. group={group}
  106. project={project}
  107. baseUrl=""
  108. {...routerProps}
  109. />,
  110. {
  111. router,
  112. }
  113. );
  114. await userEvent.click(await screen.findByRole('button', {name: 'More'}));
  115. await userEvent.click(
  116. within(
  117. screen.getByRole('menuitemradio', {name: 'Search All Issues with Tag Value'})
  118. ).getByRole('link')
  119. );
  120. expect(router.push).toHaveBeenCalledWith({
  121. pathname: '/organizations/org-slug/issues/',
  122. query: {query: 'user.username:david'},
  123. });
  124. });
  125. it('renders an error message if tag values request fails', async () => {
  126. const {router, routerProps, project} = init('user');
  127. MockApiClient.addMockResponse({
  128. url: '/organizations/org-slug/issues/1/tags/user/values/',
  129. statusCode: 500,
  130. });
  131. render(
  132. <GroupTagValues
  133. environments={['staging']}
  134. group={group}
  135. project={project}
  136. baseUrl=""
  137. {...routerProps}
  138. />,
  139. {router}
  140. );
  141. expect(
  142. await screen.findByText('There was an error loading tag details')
  143. ).toBeInTheDocument();
  144. });
  145. it('renders an error message if no tag values are returned because of environment selection', async () => {
  146. const {router, routerProps, project} = init('user');
  147. MockApiClient.addMockResponse({
  148. url: '/organizations/org-slug/issues/1/tags/user/values/',
  149. body: [],
  150. });
  151. render(
  152. <GroupTagValues
  153. environments={['staging']}
  154. group={group}
  155. project={project}
  156. baseUrl=""
  157. {...routerProps}
  158. />,
  159. {router}
  160. );
  161. expect(
  162. await screen.findByText(
  163. 'No tags were found for the currently selected environments'
  164. )
  165. ).toBeInTheDocument();
  166. });
  167. });