createProject.spec.tsx 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. import {initializeOrg} from 'sentry-test/initializeOrg';
  2. import {
  3. render,
  4. renderGlobalModal,
  5. screen,
  6. userEvent,
  7. waitFor,
  8. } from 'sentry-test/reactTestingLibrary';
  9. import OrganizationStore from 'sentry/stores/organizationStore';
  10. import TeamStore from 'sentry/stores/teamStore';
  11. import {Organization} from 'sentry/types';
  12. import {CreateProject} from 'sentry/views/projectInstall/createProject';
  13. function renderFrameworkModalMockRequests({
  14. organization,
  15. teamSlug,
  16. }: {
  17. organization: Organization;
  18. teamSlug: string;
  19. }) {
  20. MockApiClient.addMockResponse({
  21. url: `/projects/${organization.slug}/rule-conditions/`,
  22. body: [],
  23. });
  24. MockApiClient.addMockResponse({
  25. url: `/organizations/${organization.slug}/teams/`,
  26. body: [TestStubs.Team({slug: teamSlug})],
  27. });
  28. MockApiClient.addMockResponse({
  29. url: `/organizations/${organization.slug}/`,
  30. body: organization,
  31. });
  32. MockApiClient.addMockResponse({
  33. url: `/organizations/${organization.slug}/projects/`,
  34. body: [],
  35. });
  36. const projectCreationMockRequest = MockApiClient.addMockResponse({
  37. url: `/teams/${organization.slug}/${teamSlug}/projects/`,
  38. method: 'POST',
  39. });
  40. return {projectCreationMockRequest};
  41. }
  42. describe('CreateProject', function () {
  43. const teamNoAccess = TestStubs.Team({
  44. slug: 'test',
  45. id: '1',
  46. name: 'test',
  47. access: ['team:read'],
  48. });
  49. const teamWithAccess = TestStubs.Team({
  50. access: ['team:admin', 'team:write', 'team:read'],
  51. });
  52. beforeEach(() => {
  53. TeamStore.reset();
  54. TeamStore.loadUserTeams([teamNoAccess]);
  55. MockApiClient.addMockResponse({
  56. url: `/projects/testOrg/rule-conditions/`,
  57. body: {},
  58. // Not required for these tests
  59. statusCode: 500,
  60. });
  61. });
  62. afterEach(() => {
  63. MockApiClient.clearMockResponses();
  64. });
  65. it('should block if you have access to no teams', function () {
  66. const {container} = render(<CreateProject />, {
  67. context: TestStubs.routerContext([
  68. {organization: {id: '1', slug: 'testOrg', access: ['project:read']}},
  69. ]),
  70. });
  71. expect(container).toSnapshot();
  72. });
  73. it('can create a new team', async function () {
  74. render(<CreateProject />, {
  75. context: TestStubs.routerContext([
  76. {organization: {id: '1', slug: 'testOrg', access: ['project:read']}},
  77. ]),
  78. });
  79. renderGlobalModal();
  80. await userEvent.click(screen.getByRole('button', {name: 'Create a team'}));
  81. expect(
  82. await screen.findByText(
  83. 'Members of a team have access to specific areas, such as a new release or a new application feature.'
  84. )
  85. ).toBeInTheDocument();
  86. await userEvent.click(screen.getByRole('button', {name: 'Close Modal'}));
  87. });
  88. it('should only allow teams which the user is a team-admin', async function () {
  89. const organization = TestStubs.Organization();
  90. renderFrameworkModalMockRequests({organization, teamSlug: 'team-two'});
  91. OrganizationStore.onUpdate(organization);
  92. TeamStore.loadUserTeams([
  93. TestStubs.Team({id: 1, slug: 'team-one', access: []}),
  94. TestStubs.Team({id: 2, slug: 'team-two', access: ['team:admin']}),
  95. TestStubs.Team({id: 3, slug: 'team-three', access: ['team:admin']}),
  96. ]);
  97. render(<CreateProject />, {
  98. context: TestStubs.routerContext([{organization}]),
  99. organization,
  100. });
  101. await userEvent.type(screen.getByLabelText('Select a Team'), 'team');
  102. expect(screen.queryByText('#team-one')).not.toBeInTheDocument();
  103. expect(screen.getByText('#team-two')).toBeInTheDocument();
  104. expect(screen.getByText('#team-three')).toBeInTheDocument();
  105. });
  106. it('should fill in project name if its empty when platform is chosen', async function () {
  107. const {organization} = initializeOrg({
  108. organization: {
  109. access: ['project:admin'],
  110. },
  111. });
  112. const {container} = render(<CreateProject />, {
  113. context: TestStubs.routerContext([
  114. {
  115. organization: {
  116. id: '1',
  117. slug: 'testOrg',
  118. access: ['project:read'],
  119. },
  120. },
  121. ]),
  122. organization,
  123. });
  124. await userEvent.click(screen.getByTestId('platform-apple-ios'));
  125. expect(screen.getByPlaceholderText('project-name')).toHaveValue('apple-ios');
  126. await userEvent.click(screen.getByTestId('platform-ruby-rails'));
  127. expect(screen.getByPlaceholderText('project-name')).toHaveValue('ruby-rails');
  128. // but not replace it when project name is something else:
  129. await userEvent.clear(screen.getByPlaceholderText('project-name'));
  130. await userEvent.type(screen.getByPlaceholderText('project-name'), 'another');
  131. await userEvent.click(screen.getByTestId('platform-apple-ios'));
  132. expect(screen.getByPlaceholderText('project-name')).toHaveValue('another');
  133. expect(container).toSnapshot();
  134. });
  135. it('does not render framework selection modal if vanilla js is NOT selected', async function () {
  136. const {organization} = initializeOrg({
  137. organization: {
  138. features: ['onboarding-sdk-selection'],
  139. access: ['project:read', 'project:write'],
  140. },
  141. });
  142. const frameWorkModalMockRequests = renderFrameworkModalMockRequests({
  143. organization,
  144. teamSlug: teamWithAccess.slug,
  145. });
  146. TeamStore.loadUserTeams([teamWithAccess]);
  147. OrganizationStore.onUpdate(organization, {replace: true});
  148. render(<CreateProject />, {
  149. organization,
  150. });
  151. // Select the React platform
  152. await userEvent.click(screen.getByTestId('platform-javascript-react'));
  153. await userEvent.type(screen.getByLabelText('Select a Team'), teamWithAccess.slug);
  154. await userEvent.click(screen.getByText(`#${teamWithAccess.slug}`));
  155. await waitFor(() => {
  156. expect(screen.getByRole('button', {name: 'Create Project'})).toBeEnabled();
  157. });
  158. renderGlobalModal();
  159. // Click on 'configure SDK' button
  160. await userEvent.click(screen.getByRole('button', {name: 'Create Project'}));
  161. // Modal shall not be open
  162. expect(screen.queryByText('Do you use a framework?')).not.toBeInTheDocument();
  163. expect(frameWorkModalMockRequests.projectCreationMockRequest).toHaveBeenCalled();
  164. });
  165. it('renders framework selection modal if vanilla js is selected', async function () {
  166. const {organization} = initializeOrg({
  167. organization: {
  168. features: ['onboarding-sdk-selection'],
  169. },
  170. });
  171. const frameWorkModalMockRequests = renderFrameworkModalMockRequests({
  172. organization,
  173. teamSlug: teamWithAccess.slug,
  174. });
  175. TeamStore.loadUserTeams([teamWithAccess]);
  176. OrganizationStore.onUpdate(organization, {replace: true});
  177. render(<CreateProject />, {
  178. organization,
  179. });
  180. // Select the JavaScript platform
  181. await userEvent.click(screen.getByTestId('platform-javascript'));
  182. await userEvent.type(screen.getByLabelText('Select a Team'), teamWithAccess.slug);
  183. await userEvent.click(screen.getByText(`#${teamWithAccess.slug}`));
  184. await waitFor(() => {
  185. expect(screen.getByRole('button', {name: 'Create Project'})).toBeEnabled();
  186. });
  187. renderGlobalModal();
  188. // Click on 'configure SDK' button
  189. await userEvent.click(screen.getByRole('button', {name: 'Create Project'}));
  190. // Modal is open
  191. await screen.findByText('Do you use a framework?');
  192. // Close modal
  193. await userEvent.click(screen.getByRole('button', {name: 'Close Modal'}));
  194. expect(frameWorkModalMockRequests.projectCreationMockRequest).not.toHaveBeenCalled();
  195. });
  196. describe('Issue Alerts Options', function () {
  197. const organization = TestStubs.Organization();
  198. beforeEach(() => {
  199. TeamStore.loadUserTeams([teamWithAccess]);
  200. MockApiClient.addMockResponse({
  201. url: `/projects/${organization.slug}/rule-conditions/`,
  202. // @ts-ignore TODO: fix this type
  203. body: TestStubs.MOCK_RESP_VERBOSE,
  204. });
  205. });
  206. afterEach(() => {
  207. MockApiClient.clearMockResponses();
  208. });
  209. it('should enabled the submit button if and only if all the required information has been filled', async function () {
  210. render(<CreateProject />);
  211. const createProjectButton = screen.getByRole('button', {name: 'Create Project'});
  212. await userEvent.click(screen.getByText(/When there are more than/));
  213. expect(createProjectButton).toBeDisabled();
  214. await userEvent.type(screen.getByTestId('range-input'), '2');
  215. expect(screen.getByTestId('range-input')).toHaveValue(2);
  216. expect(createProjectButton).toBeDisabled();
  217. await userEvent.click(screen.getByTestId('platform-apple-ios'));
  218. expect(createProjectButton).toBeEnabled();
  219. await userEvent.clear(screen.getByTestId('range-input'));
  220. expect(createProjectButton).toBeDisabled();
  221. await userEvent.type(screen.getByTestId('range-input'), '2712');
  222. expect(createProjectButton).toBeEnabled();
  223. await userEvent.clear(screen.getByTestId('range-input'));
  224. expect(createProjectButton).toBeDisabled();
  225. await userEvent.click(screen.getByText("I'll create my own alerts later"));
  226. expect(createProjectButton).toBeEnabled();
  227. });
  228. });
  229. });