sentryAppExternalIssueActions.spec.jsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. import React from 'react';
  2. import {mountWithTheme} from 'sentry-test/enzyme';
  3. import {selectByValue} from 'sentry-test/select';
  4. import SentryAppExternalIssueActions from 'app/components/group/sentryAppExternalIssueActions';
  5. describe('SentryAppExternalIssueActions', () => {
  6. let group;
  7. let component;
  8. let sentryApp;
  9. let install;
  10. let externalIssue;
  11. let wrapper;
  12. beforeEach(() => {
  13. group = TestStubs.Group();
  14. component = TestStubs.SentryAppComponent();
  15. sentryApp = TestStubs.SentryApp();
  16. install = TestStubs.SentryAppInstallation({sentryApp});
  17. externalIssue = TestStubs.PlatformExternalIssue({
  18. groupId: group.id,
  19. serviceType: component.sentryApp.slug,
  20. });
  21. });
  22. describe('without an external issue linked', () => {
  23. beforeEach(() => {
  24. wrapper = mountWithTheme(
  25. <SentryAppExternalIssueActions
  26. group={group}
  27. sentryAppInstallation={install}
  28. sentryAppComponent={component}
  29. />,
  30. TestStubs.routerContext()
  31. );
  32. });
  33. it('renders a link to open the modal', () => {
  34. expect(wrapper.find('IntegrationLink a').text()).toEqual(
  35. `Link ${component.sentryApp.name} Issue`
  36. );
  37. });
  38. it('renders the add icon', () => {
  39. expect(wrapper.find('AddRemoveIcon').prop('isLinked')).toBe(false);
  40. });
  41. it('opens the modal', () => {
  42. wrapper.find('IntegrationLink a').simulate('click');
  43. expect(
  44. wrapper
  45. .find('Modal')
  46. .first()
  47. .prop('show')
  48. ).toEqual(true);
  49. });
  50. it('renders the Create Issue form fields, based on schema', () => {
  51. wrapper.find('IntegrationLink a').simulate('click');
  52. wrapper
  53. .find('Modal NavTabs li.create a')
  54. .first()
  55. .simulate('click'); // Create
  56. component.schema.create.required_fields.forEach(field => {
  57. expect(wrapper.exists(`SentryAppExternalIssueForm #${field.name}`)).toBe(true);
  58. });
  59. (component.schema.create.optional_fields || []).forEach(field => {
  60. expect(wrapper.exists(`SentryAppExternalIssueForm #${field.name}`)).toBe(true);
  61. });
  62. });
  63. it('renders the Link Issue form fields, based on schema', () => {
  64. wrapper.find('IntegrationLink a').simulate('click');
  65. wrapper
  66. .find('Modal NavTabs li.link a')
  67. .first()
  68. .simulate('click'); // Link
  69. component.schema.link.required_fields.forEach(field => {
  70. expect(wrapper.exists(`SentryAppExternalIssueForm #${field.name}`)).toBe(true);
  71. });
  72. (component.schema.link.optional_fields || []).forEach(field => {
  73. expect(wrapper.exists(`SentryAppExternalIssueForm #${field.name}`)).toBe(true);
  74. });
  75. });
  76. it('links to an existing Issue', () => {
  77. const request = MockApiClient.addMockResponse({
  78. url: `/sentry-app-installations/${install.uuid}/external-issues/`,
  79. method: 'POST',
  80. body: externalIssue,
  81. });
  82. wrapper.find('IntegrationLink a').simulate('click');
  83. wrapper.find('NavTabs li.link a').simulate('click');
  84. wrapper.find('Input#issue').simulate('change', {target: {value: '99'}});
  85. wrapper.find('Form form').simulate('submit');
  86. expect(request).toHaveBeenCalledWith(
  87. `/sentry-app-installations/${install.uuid}/external-issues/`,
  88. expect.objectContaining({
  89. data: expect.objectContaining({
  90. action: 'link',
  91. issue: '99',
  92. groupId: group.id,
  93. }),
  94. })
  95. );
  96. });
  97. it('creates a new Issue', () => {
  98. const request = MockApiClient.addMockResponse({
  99. url: `/sentry-app-installations/${install.uuid}/external-issues/`,
  100. method: 'POST',
  101. body: externalIssue,
  102. });
  103. wrapper.find('IntegrationLink a').simulate('click');
  104. wrapper.find('NavTabs li.create a').simulate('click');
  105. wrapper.find('Input#title').simulate('change', {target: {value: 'foo'}});
  106. wrapper.find('TextArea#description').simulate('change', {target: {value: 'bar'}});
  107. selectByValue(wrapper, 1, {name: 'numbers'});
  108. wrapper.find('Form form').simulate('submit');
  109. expect(request).toHaveBeenCalledWith(
  110. `/sentry-app-installations/${install.uuid}/external-issues/`,
  111. expect.objectContaining({
  112. data: expect.objectContaining({
  113. action: 'create',
  114. title: 'foo',
  115. description: 'bar',
  116. groupId: group.id,
  117. }),
  118. })
  119. );
  120. });
  121. });
  122. describe('with an external issue linked', () => {
  123. beforeEach(() => {
  124. wrapper = mountWithTheme(
  125. <SentryAppExternalIssueActions
  126. group={group}
  127. sentryAppComponent={component}
  128. sentryAppInstallation={install}
  129. externalIssue={externalIssue}
  130. />,
  131. TestStubs.routerContext()
  132. );
  133. });
  134. it('renders a link to the external issue', () => {
  135. expect(wrapper.find('IntegrationLink a').text()).toEqual(externalIssue.displayName);
  136. });
  137. it('links to the issue', () => {
  138. expect(
  139. wrapper
  140. .find('IntegrationLink')
  141. .first()
  142. .prop('href')
  143. ).toEqual(externalIssue.webUrl);
  144. });
  145. it('renders the remove issue button', () => {
  146. expect(wrapper.find('AddRemoveIcon').prop('isLinked')).toBe(true);
  147. });
  148. it('deletes a Linked Issue', () => {
  149. const request = MockApiClient.addMockResponse({
  150. url: `/issues/${group.id}/external-issues/${externalIssue.id}/`,
  151. method: 'DELETE',
  152. });
  153. wrapper.find('AddRemoveIcon').simulate('click');
  154. expect(request).toHaveBeenCalled();
  155. });
  156. });
  157. });