index.spec.tsx 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  3. import selectEvent from 'sentry-test/selectEvent';
  4. import ConfigStore from 'sentry/stores/configStore';
  5. import OrganizationCreate, {
  6. DATA_STORAGE_DOCS_LINK,
  7. } from 'sentry/views/organizationCreate';
  8. describe('OrganizationCreate', function () {
  9. let oldRegions: any[] = [];
  10. beforeEach(() => {
  11. ConfigStore.get('termsUrl');
  12. ConfigStore.get('privacyUrl');
  13. oldRegions = ConfigStore.get('regions');
  14. // Set only a single region in the config store by default
  15. ConfigStore.set('regions', [{name: '--monolith--', url: 'https://example.com'}]);
  16. });
  17. afterEach(() => {
  18. MockApiClient.clearMockResponses();
  19. jest.resetAllMocks();
  20. ConfigStore.set('regions', oldRegions);
  21. });
  22. it('renders without terms', function () {
  23. render(<OrganizationCreate />);
  24. });
  25. it('renders with terms', function () {
  26. ConfigStore.set('termsUrl', 'https://example.com/terms');
  27. ConfigStore.set('privacyUrl', 'https://example.com/privacy');
  28. render(<OrganizationCreate />);
  29. });
  30. it('does not render relocation url for self-hosted', function () {
  31. ConfigStore.set('termsUrl', 'https://example.com/terms');
  32. ConfigStore.set('privacyUrl', 'https://example.com/privacy');
  33. ConfigStore.set('isSelfHosted', true);
  34. render(<OrganizationCreate />);
  35. expect(() =>
  36. screen.getByText('Relocating from self-hosted?', {exact: false})
  37. ).toThrow();
  38. });
  39. it('creates a new org', async function () {
  40. const orgCreateMock = MockApiClient.addMockResponse({
  41. url: '/organizations/',
  42. method: 'POST',
  43. body: OrganizationFixture(),
  44. });
  45. ConfigStore.set('termsUrl', 'https://example.com/terms');
  46. ConfigStore.set('privacyUrl', 'https://example.com/privacy');
  47. ConfigStore.set('isSelfHosted', false);
  48. ConfigStore.set('features', new Set(['relocation:enabled']));
  49. render(<OrganizationCreate />);
  50. expect(screen.getByText('Create a New Organization')).toBeInTheDocument();
  51. expect(
  52. screen.getByText('Relocating from self-hosted?', {exact: false})
  53. ).toBeInTheDocument();
  54. expect(screen.getByText('Relocating from self-hosted?')).toHaveAttribute(
  55. 'href',
  56. '/relocation/'
  57. );
  58. await userEvent.type(screen.getByPlaceholderText('e.g. My Company'), 'Good Burger');
  59. await userEvent.click(
  60. screen.getByRole('checkbox', {
  61. name: 'I agree to the Terms of Service and the Privacy Policy',
  62. })
  63. );
  64. await userEvent.click(screen.getByText('Create Organization'));
  65. await waitFor(() => {
  66. expect(orgCreateMock).toHaveBeenCalledWith('/organizations/', {
  67. success: expect.any(Function),
  68. error: expect.any(Function),
  69. method: 'POST',
  70. data: {agreeTerms: true, defaultTeam: true, name: 'Good Burger'},
  71. host: undefined,
  72. });
  73. });
  74. expect(window.location.assign).toHaveBeenCalledTimes(1);
  75. expect(window.location.assign).toHaveBeenCalledWith(
  76. '/organizations/org-slug/projects/new/'
  77. );
  78. });
  79. it('creates a new org with customer domain feature', async function () {
  80. const orgCreateMock = MockApiClient.addMockResponse({
  81. url: '/organizations/',
  82. method: 'POST',
  83. body: OrganizationFixture({
  84. features: ['customer-domains'],
  85. }),
  86. });
  87. ConfigStore.set('termsUrl', 'https://example.com/terms');
  88. ConfigStore.set('privacyUrl', 'https://example.com/privacy');
  89. render(<OrganizationCreate />);
  90. expect(screen.getByText('Create a New Organization')).toBeInTheDocument();
  91. await userEvent.type(screen.getByPlaceholderText('e.g. My Company'), 'Good Burger');
  92. await userEvent.click(
  93. screen.getByRole('checkbox', {
  94. name: 'I agree to the Terms of Service and the Privacy Policy',
  95. })
  96. );
  97. await userEvent.click(screen.getByText('Create Organization'));
  98. await waitFor(() => {
  99. expect(orgCreateMock).toHaveBeenCalledWith('/organizations/', {
  100. data: {agreeTerms: true, defaultTeam: true, name: 'Good Burger'},
  101. method: 'POST',
  102. success: expect.any(Function),
  103. error: expect.any(Function),
  104. host: undefined,
  105. });
  106. });
  107. expect(window.location.assign).toHaveBeenCalledTimes(1);
  108. expect(window.location.assign).toHaveBeenCalledWith(
  109. 'https://org-slug.sentry.io/projects/new/'
  110. );
  111. });
  112. function multiRegionSetup() {
  113. const orgCreateMock = MockApiClient.addMockResponse({
  114. url: '/organizations/',
  115. method: 'POST',
  116. body: OrganizationFixture({
  117. features: ['customer-domains'],
  118. }),
  119. });
  120. ConfigStore.set('regions', [
  121. {url: 'https://us.example.com', name: 'us'},
  122. {
  123. url: 'https://de.example.com',
  124. name: 'de',
  125. },
  126. ]);
  127. return orgCreateMock;
  128. }
  129. it('renders without region data and submits without host when only a single region is defined', async function () {
  130. const orgCreateMock = multiRegionSetup();
  131. // Set only a single region in the config store
  132. ConfigStore.set('regions', [{name: '--monolith--', url: 'https://example.com'}]);
  133. render(<OrganizationCreate />);
  134. expect(screen.queryByLabelText('Data Storage Location')).not.toBeInTheDocument();
  135. await userEvent.type(screen.getByPlaceholderText('e.g. My Company'), 'Good Burger');
  136. await userEvent.click(screen.getByText('Create Organization'));
  137. await waitFor(() => {
  138. expect(orgCreateMock).toHaveBeenCalledWith('/organizations/', {
  139. success: expect.any(Function),
  140. error: expect.any(Function),
  141. method: 'POST',
  142. host: undefined,
  143. data: {defaultTeam: true, name: 'Good Burger'},
  144. });
  145. });
  146. expect(window.location.assign).toHaveBeenCalledTimes(1);
  147. expect(window.location.assign).toHaveBeenCalledWith(
  148. 'https://org-slug.sentry.io/projects/new/'
  149. );
  150. });
  151. it('renders without a pre-selected region, and does not submit until one is selected', async function () {
  152. const orgCreateMock = multiRegionSetup();
  153. render(<OrganizationCreate />);
  154. expect(screen.getByLabelText('Data Storage Location')).toBeInTheDocument();
  155. const link = screen.getByText<HTMLAnchorElement>('Learn More');
  156. expect(link).toBeInTheDocument();
  157. expect(link.href).toBe(DATA_STORAGE_DOCS_LINK);
  158. await userEvent.type(screen.getByPlaceholderText('e.g. My Company'), 'Good Burger');
  159. await userEvent.click(screen.getByText('Create Organization'));
  160. expect(orgCreateMock).not.toHaveBeenCalled();
  161. expect(window.location.assign).not.toHaveBeenCalled();
  162. await selectEvent.select(
  163. screen.getByRole('textbox', {name: 'Data Storage Location'}),
  164. '🇺🇸 United States of America (US)'
  165. );
  166. await userEvent.click(screen.getByText('Create Organization'));
  167. const expectedHost = 'https://us.example.com';
  168. await waitFor(() => {
  169. expect(orgCreateMock).toHaveBeenCalledWith('/organizations/', {
  170. success: expect.any(Function),
  171. error: expect.any(Function),
  172. method: 'POST',
  173. host: expectedHost,
  174. data: {defaultTeam: true, name: 'Good Burger'},
  175. });
  176. });
  177. expect(window.location.assign).toHaveBeenCalledTimes(1);
  178. expect(window.location.assign).toHaveBeenCalledWith(
  179. 'https://org-slug.sentry.io/projects/new/'
  180. );
  181. });
  182. it('uses the host of the selected region when submitting', async function () {
  183. const orgCreateMock = multiRegionSetup();
  184. render(<OrganizationCreate />);
  185. expect(screen.getByLabelText('Data Storage Location')).toBeInTheDocument();
  186. const link = screen.getByText<HTMLAnchorElement>('Learn More');
  187. expect(link).toBeInTheDocument();
  188. expect(link.href).toBe(DATA_STORAGE_DOCS_LINK);
  189. await userEvent.type(screen.getByPlaceholderText('e.g. My Company'), 'Good Burger');
  190. await selectEvent.select(
  191. screen.getByRole('textbox', {name: 'Data Storage Location'}),
  192. '🇪🇺 European Union (EU)'
  193. );
  194. await userEvent.click(screen.getByText('Create Organization'));
  195. const expectedHost = 'https://de.example.com';
  196. await waitFor(() => {
  197. expect(orgCreateMock).toHaveBeenCalledWith('/organizations/', {
  198. success: expect.any(Function),
  199. error: expect.any(Function),
  200. method: 'POST',
  201. host: expectedHost,
  202. data: {defaultTeam: true, name: 'Good Burger'},
  203. });
  204. });
  205. expect(window.location.assign).toHaveBeenCalledTimes(1);
  206. expect(window.location.assign).toHaveBeenCalledWith(
  207. 'https://org-slug.sentry.io/projects/new/'
  208. );
  209. });
  210. });