index.spec.tsx 6.7 KB

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