index.spec.jsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import {browserHistory} from 'react-router';
  2. import {enforceActOnUseLegacyStoreHook, mountWithTheme} from 'sentry-test/enzyme';
  3. import {initializeOrg} from 'sentry-test/initializeOrg';
  4. import {mountGlobalModal} from 'sentry-test/modal';
  5. import {act} from 'sentry-test/reactTestingLibrary';
  6. import OrganizationsStore from 'sentry/stores/organizationsStore';
  7. import ProjectsStore from 'sentry/stores/projectsStore';
  8. import OrganizationGeneralSettings from 'sentry/views/settings/organizationGeneralSettings';
  9. describe('OrganizationGeneralSettings', function () {
  10. enforceActOnUseLegacyStoreHook();
  11. let organization;
  12. let routerContext;
  13. const ENDPOINT = '/organizations/org-slug/';
  14. beforeEach(function () {
  15. ({organization, routerContext} = initializeOrg());
  16. OrganizationsStore.addOrReplace(organization);
  17. MockApiClient.addMockResponse({
  18. url: `/organizations/${organization.slug}/auth-provider/`,
  19. method: 'GET',
  20. });
  21. });
  22. it('can enable "early adopter"', async function () {
  23. const wrapper = mountWithTheme(
  24. <OrganizationGeneralSettings
  25. params={{orgId: organization.slug}}
  26. organization={organization}
  27. />,
  28. routerContext
  29. );
  30. const mock = MockApiClient.addMockResponse({
  31. url: ENDPOINT,
  32. method: 'PUT',
  33. });
  34. await tick();
  35. wrapper.update();
  36. wrapper.find('Switch[id="isEarlyAdopter"]').simulate('click');
  37. expect(mock).toHaveBeenCalledWith(
  38. ENDPOINT,
  39. expect.objectContaining({
  40. data: {isEarlyAdopter: true},
  41. })
  42. );
  43. });
  44. it('changes org slug and redirects to new slug', async function () {
  45. const wrapper = mountWithTheme(
  46. <OrganizationGeneralSettings
  47. params={{orgId: organization.slug}}
  48. organization={organization}
  49. />,
  50. routerContext
  51. );
  52. const mock = MockApiClient.addMockResponse({
  53. url: ENDPOINT,
  54. method: 'PUT',
  55. });
  56. await tick();
  57. wrapper.update();
  58. // Change slug
  59. act(() => {
  60. wrapper
  61. .find('input[id="slug"]')
  62. .simulate('change', {target: {value: 'new-slug'}})
  63. .simulate('blur');
  64. });
  65. await tick();
  66. wrapper.update();
  67. act(() => {
  68. wrapper.find('button[aria-label="Save"]').simulate('click');
  69. });
  70. expect(mock).toHaveBeenCalledWith(
  71. ENDPOINT,
  72. expect.objectContaining({
  73. data: {slug: 'new-slug'},
  74. })
  75. );
  76. await tick();
  77. // Not sure why this needs to be async, but it does
  78. expect(browserHistory.replace).toHaveBeenCalledWith('/settings/new-slug/');
  79. });
  80. it('disables the entire form if user does not have write access', async function () {
  81. ({organization, routerContext} = initializeOrg({
  82. organization: TestStubs.Organization({access: ['org:read']}),
  83. }));
  84. const wrapper = mountWithTheme(
  85. <OrganizationGeneralSettings
  86. routes={[]}
  87. params={{orgId: organization.slug}}
  88. organization={organization}
  89. />,
  90. routerContext
  91. );
  92. await tick();
  93. wrapper.update();
  94. expect(wrapper.find('Form FormField[disabled=false]')).toHaveLength(0);
  95. expect(wrapper.find('PermissionAlert').first().text()).toEqual(
  96. 'These settings can only be edited by users with the organization owner or manager role.'
  97. );
  98. });
  99. it('does not have remove organization button', async function () {
  100. const wrapper = mountWithTheme(
  101. <OrganizationGeneralSettings
  102. params={{orgId: organization.slug}}
  103. organization={TestStubs.Organization({
  104. access: ['org:write'],
  105. })}
  106. />,
  107. routerContext
  108. );
  109. await tick();
  110. wrapper.update();
  111. expect(wrapper.find('Confirm[priority="danger"]')).toHaveLength(0);
  112. });
  113. it('can remove organization when org admin', async function () {
  114. act(() => ProjectsStore.loadInitialData([TestStubs.Project({slug: 'project'})]));
  115. const wrapper = mountWithTheme(
  116. <OrganizationGeneralSettings
  117. params={{orgId: organization.slug}}
  118. organization={TestStubs.Organization({access: ['org:admin']})}
  119. />,
  120. routerContext
  121. );
  122. const mock = MockApiClient.addMockResponse({
  123. url: ENDPOINT,
  124. method: 'DELETE',
  125. });
  126. await tick();
  127. wrapper.update();
  128. wrapper.find('Confirm[priority="danger"]').simulate('click');
  129. const modal = await mountGlobalModal();
  130. // Lists projects in modal
  131. const projectList = modal.find('List[data-test-id="removed-projects-list"]');
  132. expect(projectList).toHaveLength(1);
  133. expect(projectList.text()).toBe('project');
  134. // Confirm delete
  135. modal.find('Button[priority="danger"]').simulate('click');
  136. expect(mock).toHaveBeenCalledWith(
  137. ENDPOINT,
  138. expect.objectContaining({
  139. method: 'DELETE',
  140. })
  141. );
  142. });
  143. it('does not render join request switch with SSO enabled', async function () {
  144. MockApiClient.addMockResponse({
  145. url: `/organizations/${organization.slug}/auth-provider/`,
  146. method: 'GET',
  147. body: TestStubs.AuthProvider(),
  148. });
  149. const wrapper = mountWithTheme(
  150. <OrganizationGeneralSettings params={{orgId: organization.slug}} />,
  151. TestStubs.routerContext([{organization}])
  152. );
  153. await tick();
  154. wrapper.update();
  155. expect(wrapper.find('Switch[name="allowJoinRequests"]').exists()).toBe(false);
  156. });
  157. });