index.spec.tsx 8.7 KB

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