import {OrganizationFixture} from 'sentry-fixture/organization'; import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary'; import selectEvent from 'sentry-test/selectEvent'; import ConfigStore from 'sentry/stores/configStore'; import type {Config} from 'sentry/types/system'; import OrganizationCreate, { DATA_STORAGE_DOCS_LINK, } from 'sentry/views/organizationCreate'; describe('OrganizationCreate', function () { let configstate: Config; beforeEach(() => { ConfigStore.get('termsUrl'); ConfigStore.get('privacyUrl'); configstate = ConfigStore.getState(); // Set only a single region in the config store by default ConfigStore.set('regions', [{name: '--monolith--', url: 'https://example.com'}]); }); afterEach(() => { MockApiClient.clearMockResponses(); jest.resetAllMocks(); ConfigStore.loadInitialData(configstate); }); it('renders without terms', function () { render(); }); it('renders with terms', function () { ConfigStore.set('termsUrl', 'https://example.com/terms'); ConfigStore.set('privacyUrl', 'https://example.com/privacy'); render(); }); it('does not render relocation url for self-hosted', function () { ConfigStore.set('termsUrl', 'https://example.com/terms'); ConfigStore.set('privacyUrl', 'https://example.com/privacy'); ConfigStore.set('isSelfHosted', true); render(); expect(() => screen.getByText('Relocating from self-hosted?', {exact: false}) ).toThrow(); }); it('creates a new org', async function () { const orgCreateMock = MockApiClient.addMockResponse({ url: '/organizations/', method: 'POST', body: OrganizationFixture(), }); ConfigStore.set('termsUrl', 'https://example.com/terms'); ConfigStore.set('privacyUrl', 'https://example.com/privacy'); ConfigStore.set('isSelfHosted', false); ConfigStore.set('features', new Set(['relocation:enabled'])); render(); expect(screen.getByText('Create a New Organization')).toBeInTheDocument(); expect( screen.getByText('Relocating from self-hosted?', {exact: false}) ).toBeInTheDocument(); expect(screen.getByText('Relocating from self-hosted?')).toHaveAttribute( 'href', '/relocation/' ); await userEvent.type(screen.getByPlaceholderText('e.g. My Company'), 'Good Burger'); await userEvent.click( screen.getByRole('checkbox', { name: 'I agree to the Terms of Service and the Privacy Policy', }) ); await userEvent.click(screen.getByText('Create Organization')); await waitFor(() => { expect(orgCreateMock).toHaveBeenCalledWith('/organizations/', { success: expect.any(Function), error: expect.any(Function), method: 'POST', data: {agreeTerms: true, defaultTeam: true, name: 'Good Burger'}, host: undefined, }); }); expect(window.location.assign).toHaveBeenCalledTimes(1); expect(window.location.assign).toHaveBeenCalledWith( '/organizations/org-slug/projects/new/' ); }); it('creates a new org with customer domain feature', async function () { const orgCreateMock = MockApiClient.addMockResponse({ url: '/organizations/', method: 'POST', body: OrganizationFixture(), }); ConfigStore.set('features', new Set(['system:multi-region'])); ConfigStore.set('termsUrl', 'https://example.com/terms'); ConfigStore.set('privacyUrl', 'https://example.com/privacy'); render(); expect(screen.getByText('Create a New Organization')).toBeInTheDocument(); await userEvent.type(screen.getByPlaceholderText('e.g. My Company'), 'Good Burger'); await userEvent.click( screen.getByRole('checkbox', { name: 'I agree to the Terms of Service and the Privacy Policy', }) ); await userEvent.click(screen.getByText('Create Organization')); await waitFor(() => { expect(orgCreateMock).toHaveBeenCalledWith('/organizations/', { data: {agreeTerms: true, defaultTeam: true, name: 'Good Burger'}, method: 'POST', success: expect.any(Function), error: expect.any(Function), host: undefined, }); }); expect(window.location.assign).toHaveBeenCalledTimes(1); expect(window.location.assign).toHaveBeenCalledWith( 'https://org-slug.sentry.io/projects/new/' ); }); function multiRegionSetup() { const orgCreateMock = MockApiClient.addMockResponse({ url: '/organizations/', method: 'POST', body: OrganizationFixture(), }); ConfigStore.set('regions', [ {url: 'https://us.example.com', name: 'us'}, { url: 'https://de.example.com', name: 'de', }, ]); return orgCreateMock; } it('renders without region data and submits without host when only a single region is defined', async function () { const orgCreateMock = multiRegionSetup(); // Set only a single region in the config store ConfigStore.set('regions', [{name: '--monolith--', url: 'https://example.com'}]); ConfigStore.set('features', new Set(['system:multi-region'])); render(); expect(screen.queryByLabelText('Data Storage Location')).not.toBeInTheDocument(); await userEvent.type(screen.getByPlaceholderText('e.g. My Company'), 'Good Burger'); await userEvent.click(screen.getByText('Create Organization')); await waitFor(() => { expect(orgCreateMock).toHaveBeenCalledWith('/organizations/', { success: expect.any(Function), error: expect.any(Function), method: 'POST', host: undefined, data: {defaultTeam: true, name: 'Good Burger'}, }); }); expect(window.location.assign).toHaveBeenCalledTimes(1); expect(window.location.assign).toHaveBeenCalledWith( 'https://org-slug.sentry.io/projects/new/' ); }); it('renders without a pre-selected region, and does not submit until one is selected', async function () { ConfigStore.set('features', new Set(['system:multi-region'])); const orgCreateMock = multiRegionSetup(); render(); expect(screen.getByLabelText('Data Storage Location')).toBeInTheDocument(); const link = screen.getByText('Learn More'); expect(link).toBeInTheDocument(); expect(link.href).toBe(DATA_STORAGE_DOCS_LINK); await userEvent.type(screen.getByPlaceholderText('e.g. My Company'), 'Good Burger'); await userEvent.click(screen.getByText('Create Organization')); expect(orgCreateMock).not.toHaveBeenCalled(); expect(window.location.assign).not.toHaveBeenCalled(); await selectEvent.select( screen.getByRole('textbox', {name: 'Data Storage Location'}), 'πŸ‡ΊπŸ‡Έ United States of America (US)' ); await userEvent.click(screen.getByText('Create Organization')); const expectedHost = 'https://us.example.com'; await waitFor(() => { expect(orgCreateMock).toHaveBeenCalledWith('/organizations/', { success: expect.any(Function), error: expect.any(Function), method: 'POST', host: expectedHost, data: {defaultTeam: true, name: 'Good Burger'}, }); }); expect(window.location.assign).toHaveBeenCalledTimes(1); expect(window.location.assign).toHaveBeenCalledWith( 'https://org-slug.sentry.io/projects/new/' ); }); it('uses the host of the selected region when submitting', async function () { ConfigStore.set('features', new Set(['system:multi-region'])); const orgCreateMock = multiRegionSetup(); render(); expect(screen.getByLabelText('Data Storage Location')).toBeInTheDocument(); const link = screen.getByText('Learn More'); expect(link).toBeInTheDocument(); expect(link.href).toBe(DATA_STORAGE_DOCS_LINK); await userEvent.type(screen.getByPlaceholderText('e.g. My Company'), 'Good Burger'); await selectEvent.select( screen.getByRole('textbox', {name: 'Data Storage Location'}), 'πŸ‡ͺπŸ‡Ί European Union (EU)' ); await userEvent.click(screen.getByText('Create Organization')); const expectedHost = 'https://de.example.com'; await waitFor(() => { expect(orgCreateMock).toHaveBeenCalledWith('/organizations/', { success: expect.any(Function), error: expect.any(Function), method: 'POST', host: expectedHost, data: {defaultTeam: true, name: 'Good Burger'}, }); }); expect(window.location.assign).toHaveBeenCalledTimes(1); expect(window.location.assign).toHaveBeenCalledWith( 'https://org-slug.sentry.io/projects/new/' ); }); });