metricsExtractionRuleForm.spec.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import {initializeOrg} from 'sentry-test/initializeOrg';
  2. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  3. import selectEvent from 'sentry-test/selectEvent';
  4. import {textWithMarkupMatcher} from 'sentry-test/utils';
  5. import {INITIAL_DATA} from 'sentry/views/settings/projectMetrics/metricsExtractionRuleCreateModal';
  6. import {MetricsExtractionRuleForm} from 'sentry/views/settings/projectMetrics/metricsExtractionRuleForm';
  7. function renderMockRequests({orgSlug, projectId}: {orgSlug: string; projectId: string}) {
  8. MockApiClient.addMockResponse({
  9. url: `/organizations/${orgSlug}/spans/fields/`,
  10. body: [],
  11. });
  12. MockApiClient.addMockResponse({
  13. url: `/projects/${orgSlug}/${projectId}/metrics/extraction-rules/`,
  14. method: 'GET',
  15. body: [
  16. {
  17. aggregates: ['count'],
  18. conditions: [{id: 102, value: '', mris: ['c:custom/span_attribute_102@none']}],
  19. createdById: 3142223,
  20. dateAdded: '2024-07-29T12:04:23.196785Z',
  21. dateUpdated: '2024-07-29T12:04:23.197008Z',
  22. projectId,
  23. spanAttribute: 'A',
  24. tags: ['release', 'environment'],
  25. unit: 'none',
  26. },
  27. ],
  28. });
  29. MockApiClient.addMockResponse({
  30. url: `/organizations/${orgSlug}/spans/fields/environment/values/`,
  31. body: [
  32. {
  33. key: 'prod',
  34. name: 'prod',
  35. },
  36. {
  37. key: 'dev',
  38. name: 'dev',
  39. },
  40. ],
  41. });
  42. MockApiClient.addMockResponse({
  43. url: '/organizations/org-slug/recent-searches/',
  44. method: 'POST',
  45. body: [],
  46. });
  47. }
  48. describe('Metrics Extraction Rule Form', function () {
  49. it('by focusing on the "select span attribute" field, the UI shall display a hint about custom attribute', async function () {
  50. const {project, organization} = initializeOrg();
  51. renderMockRequests({orgSlug: organization.slug, projectId: project.id});
  52. render(
  53. <MetricsExtractionRuleForm initialData={INITIAL_DATA} projectId={project.id} />
  54. );
  55. await userEvent.click(screen.getByText('Select span attribute'));
  56. expect(screen.getByText(/See how to instrument a custom attribute/)).toHaveAttribute(
  57. 'href',
  58. 'https://docs.sentry.io/product/explore/metrics/metrics-set-up/'
  59. );
  60. });
  61. it('by focusing on the "group and filter by" field, the UI shall display a hint about custom attribute', async function () {
  62. const {project, organization} = initializeOrg();
  63. renderMockRequests({orgSlug: organization.slug, projectId: project.id});
  64. render(
  65. <MetricsExtractionRuleForm initialData={INITIAL_DATA} projectId={project.id} />
  66. );
  67. await userEvent.click(screen.getByLabelText('Select tags'));
  68. expect(screen.getByText(/See how to instrument a custom tag/)).toHaveAttribute(
  69. 'href',
  70. 'https://docs.sentry.io/product/explore/metrics/metrics-set-up/'
  71. );
  72. });
  73. it('When creating a new metric and selecting a custom attribute, an alert should prompt to remember to instrument it', async function () {
  74. const {project, organization} = initializeOrg();
  75. renderMockRequests({orgSlug: organization.slug, projectId: project.id});
  76. render(
  77. <MetricsExtractionRuleForm initialData={INITIAL_DATA} projectId={project.id} />
  78. );
  79. await userEvent.type(screen.getByText('Select span attribute'), 'new-metric');
  80. await userEvent.click(
  81. // the dom renders 2x of this text because of aria
  82. screen.getAllByText(textWithMarkupMatcher('Create "new-metric"'))[1]
  83. );
  84. expect(screen.getByText(/You want to track a custom attribute/)).toBeInTheDocument();
  85. await selectEvent.select(screen.getByText('new-metric'), 'browser.name');
  86. expect(
  87. screen.queryByText(/You want to track a custom attribute/)
  88. ).not.toBeInTheDocument();
  89. });
  90. it('When editing a metric and updating the form, an alert should prompt to remember it applies only for future data.', async function () {
  91. const {project, organization} = initializeOrg();
  92. renderMockRequests({orgSlug: organization.slug, projectId: project.id});
  93. render(
  94. <MetricsExtractionRuleForm
  95. initialData={INITIAL_DATA}
  96. projectId={project.id}
  97. isEdit
  98. />
  99. );
  100. await selectEvent.select(screen.getByText('none'), 'days');
  101. expect(screen.getByText(/only be reflected on future data/)).toBeInTheDocument();
  102. });
  103. it('Do not allow duplicated filters', async function () {
  104. const {project, organization} = initializeOrg();
  105. renderMockRequests({orgSlug: organization.slug, projectId: project.id});
  106. render(
  107. <MetricsExtractionRuleForm
  108. initialData={INITIAL_DATA}
  109. projectId={project.id}
  110. onSubmit={jest.fn()}
  111. />
  112. );
  113. await selectEvent.select(screen.getByText('Select span attribute'), 'user.id');
  114. await userEvent.click(screen.getByText('Add Filter'));
  115. await userEvent.click(screen.getByText('Save Changes'));
  116. expect(screen.getByText(/duplicates are not allowed/)).toBeInTheDocument();
  117. await userEvent.type(
  118. screen.getAllByPlaceholderText('Add span attributes')[0],
  119. 'environment:prod{enter}'
  120. );
  121. await userEvent.type(
  122. screen.getAllByPlaceholderText('Add span attributes')[1],
  123. 'environment:prod{enter}'
  124. );
  125. await userEvent.click(screen.getByText('Save Changes'));
  126. expect(screen.getByText(/duplicates are not allowed/)).toBeInTheDocument();
  127. await userEvent.type(
  128. screen.getAllByPlaceholderText('Add span attributes')[1],
  129. 'environment:dev{enter}'
  130. );
  131. expect(screen.queryByText(/duplicates are not allowed/)).not.toBeInTheDocument();
  132. });
  133. });