index.spec.tsx 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. import {screen, userEvent, within} from 'sentry-test/reactTestingLibrary';
  2. import {textWithMarkupMatcher} from 'sentry-test/utils';
  3. import {SamplingRuleType} from 'sentry/types/sampling';
  4. import {SAMPLING_DOC_LINK} from 'sentry/views/settings/project/sampling/utils';
  5. import {renderComponent} from './utils';
  6. describe('Sampling', function () {
  7. const EMPTY_MESSAGE = 'There are no transaction rules to display';
  8. it('renders empty', function () {
  9. MockApiClient.addMockResponse({
  10. url: '/projects/org-slug/project-slug/',
  11. method: 'GET',
  12. body: TestStubs.Project(),
  13. });
  14. renderComponent({withModal: false});
  15. // Subitle has the right link to the docs
  16. expect(
  17. screen.getByRole('link', {
  18. name: 'SDK sampling configuration',
  19. })
  20. ).toHaveAttribute('href', SAMPLING_DOC_LINK);
  21. // Rules tabs
  22. expect(screen.getAllByRole('tab')).toHaveLength(2);
  23. expect(screen.getByRole('tab', {name: /Distributed Traces/})).toHaveAttribute(
  24. 'aria-selected',
  25. 'true'
  26. );
  27. expect(screen.getByRole('tab', {name: /Individual Transactions/})).toHaveAttribute(
  28. 'aria-selected',
  29. 'false'
  30. );
  31. // Tab content
  32. expect(screen.getByText('Operator')).toBeInTheDocument();
  33. expect(screen.getByText('Condition')).toBeInTheDocument();
  34. expect(screen.getByText('Rate')).toBeInTheDocument();
  35. // Empty message is displayed
  36. expect(screen.getByText(EMPTY_MESSAGE)).toBeInTheDocument();
  37. // Actions
  38. expect(screen.getByRole('button', {name: 'Read Docs'})).toHaveAttribute(
  39. 'href',
  40. SAMPLING_DOC_LINK
  41. );
  42. expect(screen.getByRole('button', {name: 'Add Rule'})).toBeInTheDocument();
  43. });
  44. it('renders distributed traces tab', function () {
  45. MockApiClient.addMockResponse({
  46. url: '/projects/org-slug/project-slug/',
  47. method: 'GET',
  48. body: TestStubs.Project({
  49. dynamicSampling: {
  50. rules: [
  51. {
  52. sampleRate: 0.2,
  53. type: 'trace',
  54. condition: {
  55. op: 'and',
  56. inner: [
  57. {
  58. op: 'glob',
  59. name: 'trace.release',
  60. value: ['1.2.3'],
  61. },
  62. ],
  63. },
  64. id: 40,
  65. },
  66. ],
  67. next_id: 41,
  68. },
  69. }),
  70. });
  71. const {router} = renderComponent({
  72. withModal: false,
  73. ruleType: SamplingRuleType.TRACE,
  74. });
  75. const tracesTab = screen.getByRole('tab', {name: /Distributed Traces/});
  76. // Tab is active
  77. expect(tracesTab).toHaveAttribute('aria-selected', 'true');
  78. // Tab has the correct number of rules badge
  79. expect(within(tracesTab).getByText('1')).toBeInTheDocument();
  80. // Tab description
  81. expect(
  82. screen.getByText(
  83. 'Using a Trace ID, select all Transactions distributed across multiple projects/services which match your conditions.'
  84. )
  85. ).toBeInTheDocument();
  86. // Tab content
  87. expect(screen.getAllByTestId('sampling-rule').length).toBe(1);
  88. expect(screen.getByTestId('sampling-rule')).toHaveTextContent('If');
  89. expect(screen.getByText('Release')).toBeInTheDocument();
  90. expect(screen.getByText('1.2.3')).toBeInTheDocument();
  91. expect(screen.getByText('20%')).toBeInTheDocument();
  92. // Empty message is not displayed
  93. expect(screen.queryByText(EMPTY_MESSAGE)).not.toBeInTheDocument();
  94. // Switch tabs
  95. userEvent.click(screen.getByRole('tab', {name: /Individual Transactions/}));
  96. // Transaction tab is pushed to the router
  97. expect(router.push).toHaveBeenCalledWith(`${SamplingRuleType.TRANSACTION}/`);
  98. });
  99. it('renders single rule without conditions', function () {
  100. MockApiClient.addMockResponse({
  101. url: '/projects/org-slug/project-slug/',
  102. method: 'GET',
  103. body: TestStubs.Project({
  104. dynamicSampling: {
  105. rules: [
  106. {
  107. sampleRate: 0.2,
  108. type: 'trace',
  109. condition: {
  110. op: 'and',
  111. inner: [],
  112. },
  113. id: 40,
  114. },
  115. ],
  116. next_id: 41,
  117. },
  118. }),
  119. });
  120. renderComponent({
  121. withModal: false,
  122. ruleType: SamplingRuleType.TRACE,
  123. });
  124. // Tab content
  125. expect(screen.getAllByTestId('sampling-rule').length).toBe(1);
  126. expect(screen.getByTestId('sampling-rule')).toHaveTextContent('All');
  127. });
  128. it('renders individual transactions tab', function () {
  129. MockApiClient.addMockResponse({
  130. url: '/projects/org-slug/project-slug/',
  131. method: 'GET',
  132. body: TestStubs.Project({
  133. dynamicSampling: {
  134. rules: [
  135. {
  136. sampleRate: 0.2,
  137. type: 'transaction',
  138. condition: {
  139. op: 'and',
  140. inner: [
  141. {
  142. op: 'eq',
  143. name: 'event.environment',
  144. value: ['prod'],
  145. },
  146. ],
  147. },
  148. id: 41,
  149. },
  150. {
  151. sampleRate: 0.5,
  152. type: 'transaction',
  153. condition: {
  154. op: 'and',
  155. inner: [],
  156. },
  157. id: 42,
  158. },
  159. {
  160. sampleRate: 0.2,
  161. type: 'trace',
  162. condition: {
  163. op: 'and',
  164. inner: [
  165. {
  166. op: 'glob',
  167. name: 'trace.release',
  168. value: ['1.2.3'],
  169. },
  170. ],
  171. },
  172. id: 43,
  173. },
  174. ],
  175. next_id: 44,
  176. },
  177. }),
  178. });
  179. const {router} = renderComponent({
  180. withModal: false,
  181. ruleType: SamplingRuleType.TRANSACTION,
  182. });
  183. const transactionsTab = screen.getByRole('tab', {name: /Individual Transactions/});
  184. // Tab is active
  185. expect(transactionsTab).toHaveAttribute('aria-selected', 'true');
  186. // Tab has the correct number of rules badge
  187. expect(within(transactionsTab).getByText('2')).toBeInTheDocument();
  188. // Tab description
  189. screen.getByText(
  190. 'Select Transactions only within this project which match your conditions.'
  191. );
  192. // Tab content
  193. const rules = screen.getAllByTestId('sampling-rule');
  194. expect(rules.length).toBe(2);
  195. expect(rules[0]).toHaveTextContent('IfEnvironment=prod20%');
  196. expect(rules[1]).toHaveTextContent('Else50%');
  197. // Info Alert
  198. screen.getByText(
  199. textWithMarkupMatcher('1 Distributed Trace rule will initiate before these rules')
  200. );
  201. expect(screen.getByRole('link', {name: '1 Distributed Trace rule'})).toHaveAttribute(
  202. 'href',
  203. `${SamplingRuleType.TRACE}/`
  204. );
  205. // Empty message is not displayed
  206. expect(screen.queryByText(EMPTY_MESSAGE)).not.toBeInTheDocument();
  207. // Switch tabs
  208. userEvent.click(screen.getByRole('tab', {name: /Distributed Traces/}));
  209. // Distributed Traces tab is pushed to the router
  210. expect(router.push).toHaveBeenCalledWith(`${SamplingRuleType.TRACE}/`);
  211. });
  212. });