index.spec.jsx 5.1 KB

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