profileEventsTable.spec.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import {initializeOrg} from 'sentry-test/initializeOrg';
  2. import {render, screen} from 'sentry-test/reactTestingLibrary';
  3. import {ProfileEventsTable} from 'sentry/components/profiling/profileEventsTable';
  4. import ProjectsStore from 'sentry/stores/projectsStore';
  5. import {FieldValueType} from 'sentry/utils/fields';
  6. import {EventsResults} from 'sentry/utils/profiling/hooks/useProfileEvents';
  7. function customEncodeURIComponent(str) {
  8. return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
  9. return '%' + c.charCodeAt(0).toString(16);
  10. });
  11. }
  12. const project = TestStubs.Project({
  13. id: '1',
  14. slug: 'foo',
  15. });
  16. describe('ProfileEventsTable', function () {
  17. beforeEach(function () {
  18. ProjectsStore.loadInitialData([project]);
  19. });
  20. it('renders loading', function () {
  21. const {organization, routerContext} = initializeOrg();
  22. const columns = ['count()' as const];
  23. const sort = {
  24. key: 'count()' as const,
  25. order: 'desc' as const,
  26. };
  27. render(
  28. <ProfileEventsTable
  29. columns={columns}
  30. data={null}
  31. error={null}
  32. isLoading
  33. sort={sort}
  34. />,
  35. {context: routerContext, organization}
  36. );
  37. expect(screen.getByTestId('loading-indicator')).toBeInTheDocument();
  38. });
  39. it('renders error', function () {
  40. const {organization, routerContext} = initializeOrg();
  41. const columns = ['count()' as const];
  42. const sort = {
  43. key: 'count()' as const,
  44. order: 'desc' as const,
  45. };
  46. render(
  47. <ProfileEventsTable
  48. columns={columns}
  49. data={null}
  50. error="error"
  51. isLoading={false}
  52. sort={sort}
  53. />,
  54. {context: routerContext, organization}
  55. );
  56. expect(screen.getByTestId('error-indicator')).toBeInTheDocument();
  57. });
  58. it('renders asc sort links on the header', function () {
  59. const {organization, routerContext} = initializeOrg();
  60. const columns = ['count()' as const];
  61. const sort = {
  62. key: 'count()' as const,
  63. order: 'desc' as const,
  64. };
  65. render(
  66. <ProfileEventsTable
  67. columns={columns}
  68. data={null}
  69. error={null}
  70. isLoading
  71. sort={sort}
  72. sortableColumns={new Set(columns)}
  73. />,
  74. {context: routerContext, organization}
  75. );
  76. const link = screen.getByRole('link', {name: 'Count()'});
  77. expect(link).toBeInTheDocument();
  78. expect(link).toHaveAttribute(
  79. 'href',
  80. `/mock-pathname/?sort=${customEncodeURIComponent('count()')}`
  81. );
  82. });
  83. it('renders desc sort links on the header', function () {
  84. const {organization, routerContext} = initializeOrg();
  85. const columns = ['count()' as const];
  86. const sort = {
  87. key: 'count()' as const,
  88. order: 'asc' as const,
  89. };
  90. render(
  91. <ProfileEventsTable
  92. columns={columns}
  93. data={null}
  94. error={null}
  95. isLoading
  96. sort={sort}
  97. sortableColumns={new Set(columns)}
  98. />,
  99. {context: routerContext, organization}
  100. );
  101. const link = screen.getByRole('link', {name: 'Count()'});
  102. expect(link).toBeInTheDocument();
  103. expect(link).toHaveAttribute(
  104. 'href',
  105. `/mock-pathname/?sort=${customEncodeURIComponent('-count()')}`
  106. );
  107. });
  108. it('renders formatted values', function () {
  109. const {organization, routerContext} = initializeOrg();
  110. const columns = [
  111. 'id',
  112. 'project',
  113. 'transaction',
  114. 'release',
  115. 'timestamp',
  116. 'profile.duration',
  117. 'count()',
  118. ] as const;
  119. const data: EventsResults<(typeof columns)[number]> = {
  120. data: [
  121. {
  122. id: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
  123. project: 'foo',
  124. transaction: 'bar',
  125. release: 'baz@1.0.0+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
  126. timestamp: '2022-11-01T00:00:00+00:00',
  127. 'profile.duration': 100000000,
  128. 'count()': 123,
  129. },
  130. ],
  131. meta: {
  132. fields: {
  133. id: FieldValueType.STRING,
  134. project: FieldValueType.STRING,
  135. transaction: FieldValueType.STRING,
  136. release: FieldValueType.STRING,
  137. timestamp: FieldValueType.DATE,
  138. 'profile.duration': FieldValueType.DURATION,
  139. 'count()': FieldValueType.INTEGER,
  140. },
  141. units: {
  142. id: null,
  143. project: null,
  144. transaction: null,
  145. release: null,
  146. timestamp: null,
  147. 'profile.duration': 'nanosecond',
  148. 'count()': null,
  149. },
  150. },
  151. };
  152. const sort = {
  153. key: 'transaction' as const,
  154. order: 'asc' as const,
  155. };
  156. render(
  157. <ProfileEventsTable
  158. columns={columns.slice()}
  159. data={data}
  160. error={null}
  161. isLoading={false}
  162. sort={sort}
  163. sortableColumns={new Set(columns)}
  164. />,
  165. {context: routerContext, organization}
  166. );
  167. // id
  168. expect(screen.getByRole('cell', {name: 'aaaaaaaa'})).toBeInTheDocument();
  169. // project
  170. expect(screen.getByRole('cell', {name: 'foo'})).toBeInTheDocument();
  171. // the transaction is both a cell and a link
  172. expect(screen.getByRole('link', {name: 'bar'})).toBeInTheDocument();
  173. expect(screen.getByRole('cell', {name: 'bar'})).toBeInTheDocument();
  174. // release
  175. expect(screen.getByRole('cell', {name: '1.0.0 (aaaaaaaaaaaa)'})).toBeInTheDocument();
  176. // timestamp
  177. expect(
  178. screen.getByRole('cell', {name: 'Nov 1, 2022 12:00:00 AM UTC'})
  179. ).toBeInTheDocument();
  180. // profile.duration
  181. expect(screen.getByRole('cell', {name: '100.00ms'})).toBeInTheDocument();
  182. // count()
  183. expect(screen.getByRole('cell', {name: '123'})).toBeInTheDocument();
  184. });
  185. });