index.spec.tsx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import {render, screen, within} from 'sentry-test/reactTestingLibrary';
  2. import SentryApplicationDashboard from './index';
  3. jest.mock('sentry/components/charts/baseChart', () => {
  4. return jest.fn().mockImplementation(() => <div data-test-id="chart" />);
  5. });
  6. describe('Sentry Application Dashboard', function () {
  7. const NUM_INSTALLS = 5;
  8. const NUM_UNINSTALLS = 2;
  9. let sentryApp;
  10. let webhookRequest;
  11. afterEach(() => {
  12. MockApiClient.clearMockResponses();
  13. });
  14. describe('Viewing the Sentry App Dashboard for a published integration', () => {
  15. beforeEach(() => {
  16. sentryApp = TestStubs.SentryApp({
  17. status: 'published',
  18. schema: {
  19. elements: [
  20. {type: 'stacktrace-link', uri: '/test'},
  21. {
  22. type: 'issue-link',
  23. create: {uri: '/test', required_fields: []},
  24. link: {uri: '/test', required_fields: []},
  25. },
  26. ],
  27. },
  28. });
  29. webhookRequest = TestStubs.SentryAppWebhookRequest();
  30. MockApiClient.addMockResponse({
  31. url: `/sentry-apps/${sentryApp.slug}/stats/`,
  32. body: {
  33. totalInstalls: NUM_INSTALLS,
  34. totalUninstalls: NUM_UNINSTALLS,
  35. installStats: [[1569783600, NUM_INSTALLS]],
  36. uninstallStats: [[1569783600, NUM_UNINSTALLS]],
  37. },
  38. });
  39. MockApiClient.addMockResponse({
  40. url: `/sentry-apps/${sentryApp.slug}/requests/`,
  41. body: [webhookRequest],
  42. });
  43. MockApiClient.addMockResponse({
  44. url: `/sentry-apps/${sentryApp.slug}/interaction/`,
  45. body: {
  46. componentInteractions: {
  47. 'stacktrace-link': [[1569783600, 1]],
  48. 'issue-link': [[1569783600, 1]],
  49. },
  50. views: [[1569783600, 1]],
  51. },
  52. });
  53. MockApiClient.addMockResponse({
  54. url: `/sentry-apps/${sentryApp.slug}/`,
  55. body: sentryApp,
  56. });
  57. });
  58. it('shows the total install/uninstall stats', () => {
  59. render(
  60. <SentryApplicationDashboard
  61. {...TestStubs.routeComponentProps()}
  62. params={{appSlug: sentryApp.slug}}
  63. />
  64. );
  65. expect(screen.getByTestId('installs')).toHaveTextContent('Total installs5');
  66. expect(screen.getByTestId('uninstalls')).toHaveTextContent('Total uninstalls2');
  67. });
  68. it('shows the request log', () => {
  69. render(
  70. <SentryApplicationDashboard
  71. {...TestStubs.routeComponentProps()}
  72. params={{appSlug: sentryApp.slug}}
  73. />
  74. );
  75. // The mock response has 1 request
  76. expect(screen.getByTestId('request-item')).toBeInTheDocument();
  77. const requestLog = within(screen.getByTestId('request-item'));
  78. // Make sure that all the info is displayed
  79. expect(requestLog.getByText('https://example.com/webhook')).toBeInTheDocument();
  80. expect(requestLog.getByText('400')).toBeInTheDocument();
  81. expect(requestLog.getByText('issue.assigned')).toBeInTheDocument();
  82. expect(requestLog.getByText('Test Org')).toBeInTheDocument();
  83. });
  84. it('shows an empty message if there are no requests', () => {
  85. MockApiClient.addMockResponse({
  86. url: `/sentry-apps/${sentryApp.slug}/requests/`,
  87. body: [],
  88. });
  89. render(
  90. <SentryApplicationDashboard
  91. {...TestStubs.routeComponentProps()}
  92. params={{appSlug: sentryApp.slug}}
  93. />
  94. );
  95. expect(
  96. screen.getByText('No requests found in the last 30 days.')
  97. ).toBeInTheDocument();
  98. });
  99. it('shows integration and interactions chart', () => {
  100. render(
  101. <SentryApplicationDashboard
  102. {...TestStubs.routeComponentProps()}
  103. params={{appSlug: sentryApp.slug}}
  104. />
  105. );
  106. expect(screen.getAllByTestId('chart')).toHaveLength(3);
  107. });
  108. });
  109. describe('Viewing the Sentry App Dashboard for an internal integration', () => {
  110. beforeEach(() => {
  111. sentryApp = TestStubs.SentryApp({
  112. status: 'internal',
  113. schema: {
  114. elements: [{type: 'stacktrace-link', uri: '/test'}],
  115. },
  116. });
  117. webhookRequest = TestStubs.SentryAppWebhookRequest();
  118. MockApiClient.addMockResponse({
  119. url: `/sentry-apps/${sentryApp.slug}/stats/`,
  120. body: {
  121. totalInstalls: 1,
  122. totalUninstalls: 0,
  123. installStats: [[1569783600, 1]],
  124. uninstallStats: [[1569783600, 0]],
  125. },
  126. });
  127. MockApiClient.addMockResponse({
  128. url: `/sentry-apps/${sentryApp.slug}/requests/`,
  129. body: [webhookRequest],
  130. });
  131. MockApiClient.addMockResponse({
  132. url: `/sentry-apps/${sentryApp.slug}/interaction/`,
  133. body: {
  134. componentInteractions: {
  135. 'stacktrace-link': [[1569783600, 1]],
  136. },
  137. views: [[1569783600, 1]],
  138. },
  139. });
  140. MockApiClient.addMockResponse({
  141. url: `/sentry-apps/${sentryApp.slug}/`,
  142. body: sentryApp,
  143. });
  144. });
  145. it('shows the request log', () => {
  146. render(
  147. <SentryApplicationDashboard
  148. {...TestStubs.routeComponentProps()}
  149. params={{appSlug: sentryApp.slug}}
  150. />
  151. );
  152. // The mock response has 1 request
  153. expect(screen.getByTestId('request-item')).toBeInTheDocument();
  154. const requestLog = within(screen.getByTestId('request-item'));
  155. // Make sure that all the info is displayed
  156. expect(requestLog.getByText('https://example.com/webhook')).toBeInTheDocument();
  157. expect(requestLog.getByText('400')).toBeInTheDocument();
  158. expect(requestLog.getByText('issue.assigned')).toBeInTheDocument();
  159. // Does not show the integration views
  160. expect(screen.queryByText('Integration Views')).not.toBeInTheDocument();
  161. });
  162. it('shows an empty message if there are no requests', () => {
  163. MockApiClient.addMockResponse({
  164. url: `/sentry-apps/${sentryApp.slug}/requests/`,
  165. body: [],
  166. });
  167. render(
  168. <SentryApplicationDashboard
  169. {...TestStubs.routeComponentProps()}
  170. params={{appSlug: sentryApp.slug}}
  171. />
  172. );
  173. expect(
  174. screen.getByText('No requests found in the last 30 days.')
  175. ).toBeInTheDocument();
  176. });
  177. it('shows the component interactions in a line chart', () => {
  178. render(
  179. <SentryApplicationDashboard
  180. {...TestStubs.routeComponentProps()}
  181. params={{appSlug: sentryApp.slug}}
  182. />
  183. );
  184. expect(screen.getByTestId('chart')).toBeInTheDocument();
  185. });
  186. });
  187. });