utils.spec.tsx 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import {MetricRule} from 'sentry-fixture/metricRule';
  2. import {initializeOrg} from 'sentry-test/initializeOrg';
  3. import {
  4. Dataset,
  5. Datasource,
  6. SessionsAggregate,
  7. } from 'sentry/views/alerts/rules/metric/types';
  8. import {Incident, IncidentStats} from 'sentry/views/alerts/types';
  9. import {
  10. alertAxisFormatter,
  11. alertTooltipValueFormatter,
  12. getQueryDatasource,
  13. getTeamParams,
  14. isSessionAggregate,
  15. } from 'sentry/views/alerts/utils';
  16. import {getIncidentDiscoverUrl} from 'sentry/views/alerts/utils/getIncidentDiscoverUrl';
  17. describe('Alert utils', function () {
  18. const {organization, projects} = initializeOrg();
  19. const mockStats: IncidentStats = {
  20. eventStats: {
  21. data: [
  22. [0, [{count: 10}]],
  23. [120, [{count: 10}]],
  24. ],
  25. },
  26. totalEvents: 0,
  27. uniqueUsers: 0,
  28. };
  29. describe('getIncidentDiscoverUrl', function () {
  30. it('creates a discover query url for errors', function () {
  31. // TODO(ts): Add a TestStub for Incident
  32. const incident: Incident = {
  33. title: 'Test error alert',
  34. discoverQuery: 'id:test',
  35. projects,
  36. alertRule: MetricRule({
  37. timeWindow: 1,
  38. dataset: Dataset.ERRORS,
  39. aggregate: 'count()',
  40. }),
  41. } as Incident;
  42. const to = getIncidentDiscoverUrl({
  43. orgSlug: organization.slug,
  44. projects,
  45. incident,
  46. stats: mockStats,
  47. });
  48. expect(to).toEqual({
  49. query: expect.objectContaining({
  50. name: 'Test error alert',
  51. field: ['issue', 'count()', 'count_unique(user)'],
  52. sort: ['-count'],
  53. query: 'id:test',
  54. yAxis: 'count()',
  55. start: '1970-01-01T00:00:00.000',
  56. end: '1970-01-01T00:02:00.000',
  57. interval: '1m',
  58. }),
  59. pathname: '/organizations/org-slug/discover/results/',
  60. });
  61. });
  62. it('creates a discover query url for transactions', function () {
  63. // TODO(ts): Add a TestStub for Incident
  64. const incident = {
  65. title: 'Test transaction alert',
  66. discoverQuery: 'id:test',
  67. projects,
  68. alertRule: MetricRule({
  69. timeWindow: 1,
  70. dataset: Dataset.TRANSACTIONS,
  71. aggregate: 'p90()',
  72. }),
  73. } as Incident;
  74. const to = getIncidentDiscoverUrl({
  75. orgSlug: organization.slug,
  76. projects,
  77. incident,
  78. stats: mockStats,
  79. });
  80. expect(to).toEqual({
  81. query: expect.objectContaining({
  82. name: 'Test transaction alert',
  83. field: ['transaction', 'p90()'],
  84. sort: ['-p90'],
  85. query: 'id:test',
  86. yAxis: 'p90()',
  87. }),
  88. pathname: '/organizations/org-slug/discover/results/',
  89. });
  90. });
  91. });
  92. describe('getQuerySource', () => {
  93. it('should parse event type error or default', () => {
  94. expect(getQueryDatasource('event.type:default OR event.type:error')).toEqual({
  95. source: Datasource.ERROR_DEFAULT,
  96. query: '',
  97. });
  98. expect(
  99. getQueryDatasource(
  100. 'event.type:error OR event.type:default transaction.duration:<30s'
  101. )
  102. ).toEqual({
  103. source: Datasource.ERROR_DEFAULT,
  104. query: 'transaction.duration:<30s',
  105. });
  106. expect(
  107. getQueryDatasource('event.type:error OR (event.type:default event.level:fatal)')
  108. ).toEqual({
  109. source: Datasource.ERROR_DEFAULT,
  110. query: 'event.level:fatal)',
  111. });
  112. expect(
  113. getQueryDatasource('(event.type:error OR event.type:default) event.level:fatal')
  114. ).toEqual({
  115. source: Datasource.ERROR_DEFAULT,
  116. query: 'event.level:fatal',
  117. });
  118. });
  119. it('should not allow event type transaction with anything else', () => {
  120. expect(getQueryDatasource('event.type:error OR event.type:transaction')).toBeNull();
  121. expect(
  122. getQueryDatasource('event.type:transaction OR event.type:default')
  123. ).toBeNull();
  124. });
  125. it('should not allow boolean event types', () => {
  126. expect(getQueryDatasource('!event.type:error')).toBeNull();
  127. expect(getQueryDatasource('!event.type:transaction something')).toBeNull();
  128. expect(getQueryDatasource('!event.type:default')).toBeNull();
  129. });
  130. it('should allow error, transaction, default alone', () => {
  131. expect(getQueryDatasource('event.type:error test')).toEqual({
  132. source: Datasource.ERROR,
  133. query: 'test',
  134. });
  135. expect(getQueryDatasource('event.type:default test')).toEqual({
  136. source: Datasource.DEFAULT,
  137. query: 'test',
  138. });
  139. expect(getQueryDatasource('event.type:transaction test')).toEqual({
  140. source: Datasource.TRANSACTION,
  141. query: 'test',
  142. });
  143. expect(
  144. getQueryDatasource(
  145. 'event.type:error explode OR (event.type:default event.level:fatal)'
  146. )
  147. ).toEqual({
  148. source: Datasource.ERROR,
  149. query: 'explode OR (event.type:default event.level:fatal)',
  150. });
  151. });
  152. });
  153. describe('isSessionAggregate', () => {
  154. it('accepts session aggregate', () => {
  155. Object.values(SessionsAggregate).forEach(aggregate => {
  156. expect(isSessionAggregate(aggregate)).toBeTruthy();
  157. });
  158. });
  159. it('rejects other aggregates', () => {
  160. expect(isSessionAggregate('p95(transaction.duration)')).toBeFalsy();
  161. });
  162. });
  163. describe('alertAxisFormatter', () => {
  164. it('formatts', () => {
  165. expect(
  166. alertAxisFormatter(
  167. 98.312,
  168. 'Crash Free Rate',
  169. SessionsAggregate.CRASH_FREE_SESSIONS
  170. )
  171. ).toBe('98.31%');
  172. expect(alertAxisFormatter(0.1234, 'failure_rate()', 'failure_rate()')).toBe('12%');
  173. });
  174. });
  175. describe('alertTooltipValueFormatter', () => {
  176. it('formatts', () => {
  177. expect(
  178. alertTooltipValueFormatter(
  179. 98.312,
  180. 'Crash Free Rate',
  181. SessionsAggregate.CRASH_FREE_SESSIONS
  182. )
  183. ).toBe('98.312%');
  184. expect(alertTooltipValueFormatter(0.1234, 'failure_rate()', 'failure_rate()')).toBe(
  185. '12.34%'
  186. );
  187. });
  188. });
  189. describe('getTeamParams', () => {
  190. it('should use default teams', () => {
  191. expect(getTeamParams()).toEqual(['myteams', 'unassigned']);
  192. });
  193. it('should allow no teams with an empty string param', () => {
  194. expect(getTeamParams('')).toEqual([]);
  195. });
  196. it('should allow one or more teams', () => {
  197. expect(getTeamParams('team-sentry')).toEqual(['team-sentry']);
  198. expect(getTeamParams(['team-sentry', 'team-two'])).toEqual([
  199. 'team-sentry',
  200. 'team-two',
  201. ]);
  202. });
  203. });
  204. });