index.spec.jsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  2. import {openModal} from 'sentry/actionCreators/modal';
  3. import ProjectOwnership from 'sentry/views/settings/project/projectOwnership';
  4. jest.mock('sentry/actionCreators/modal');
  5. describe('Project Ownership', () => {
  6. let org = TestStubs.Organization();
  7. const project = TestStubs.ProjectDetails();
  8. beforeEach(() => {
  9. MockApiClient.addMockResponse({
  10. url: `/projects/${org.slug}/${project.slug}/ownership/`,
  11. method: 'GET',
  12. body: {
  13. fallthrough: false,
  14. autoAssignment: 'Auto Assign to Suspect Commits',
  15. codeownersAutoSync: false,
  16. },
  17. });
  18. MockApiClient.addMockResponse({
  19. url: `/organizations/${org.slug}/code-mappings/`,
  20. query: {project: project.id},
  21. method: 'GET',
  22. body: [],
  23. });
  24. MockApiClient.addMockResponse({
  25. url: `/organizations/${org.slug}/integrations/`,
  26. query: {features: 'codeowners'},
  27. method: 'GET',
  28. body: [TestStubs.GitHubIntegrationConfig()],
  29. });
  30. MockApiClient.addMockResponse({
  31. url: `/projects/${org.slug}/${project.slug}/codeowners/`,
  32. features: {expand: 'codeMapping'},
  33. method: 'GET',
  34. body: [],
  35. });
  36. });
  37. afterEach(() => {
  38. MockApiClient.clearMockResponses();
  39. });
  40. describe('without codeowners', () => {
  41. it('renders', () => {
  42. const wrapper = render(
  43. <ProjectOwnership
  44. params={{projectId: project.slug}}
  45. organization={org}
  46. project={project}
  47. />
  48. );
  49. expect(wrapper.container).toSnapshot();
  50. // Does not render codeowners for orgs without 'integrations-codeowners' feature
  51. expect(
  52. screen.queryByRole('button', {name: 'Add CODEOWNERS'})
  53. ).not.toBeInTheDocument();
  54. });
  55. it('renders allows users to edit ownership rules', () => {
  56. org = TestStubs.Organization({
  57. access: ['project:read'],
  58. });
  59. render(
  60. <ProjectOwnership
  61. params={{projectId: project.slug}}
  62. organization={org}
  63. project={project}
  64. />,
  65. {context: TestStubs.routerContext([{organization: org}])}
  66. );
  67. expect(screen.queryByRole('button', {name: 'Edit'})).toBeEnabled();
  68. expect(screen.getByTestId('project-permission-alert')).toHaveTextContent(
  69. 'These settings can only be edited by users with the organization owner, manager, or admin role.'
  70. );
  71. // eslint-disable-next-line jest-dom/prefer-in-document
  72. expect(screen.getAllByTestId('project-permission-alert')).toHaveLength(1);
  73. });
  74. });
  75. describe('with codeowners', () => {
  76. it('codeowners button opens modal', () => {
  77. org = TestStubs.Organization({
  78. features: ['integrations-codeowners'],
  79. access: ['org:integrations'],
  80. });
  81. render(
  82. <ProjectOwnership
  83. params={{projectId: project.slug}}
  84. organization={org}
  85. project={project}
  86. />,
  87. {context: TestStubs.routerContext([{organization: org}])}
  88. );
  89. // Renders button
  90. expect(screen.getByRole('button', {name: 'Add CODEOWNERS'})).toBeInTheDocument();
  91. // Opens modal
  92. userEvent.click(screen.getByRole('button', {name: 'Add CODEOWNERS'}));
  93. expect(openModal).toHaveBeenCalled();
  94. });
  95. });
  96. describe('issue owners settings', () => {
  97. it('should set autoAssignment with commit-context string', async () => {
  98. const updateOwnership = MockApiClient.addMockResponse({
  99. url: `/projects/${org.slug}/${project.slug}/ownership/`,
  100. method: 'PUT',
  101. body: {
  102. fallthrough: false,
  103. autoAssignment: 'Assign To Issue Owner',
  104. codeownersAutoSync: false,
  105. },
  106. });
  107. render(
  108. <ProjectOwnership
  109. params={{projectId: project.slug}}
  110. organization={org}
  111. project={project}
  112. />
  113. );
  114. // Switch to Assign To Issue Owner
  115. userEvent.click(screen.getByText('Auto-assign to suspect commits'));
  116. userEvent.click(screen.getByText('Auto-assign to issue owner'));
  117. await waitFor(() => {
  118. expect(updateOwnership).toHaveBeenCalledWith(
  119. expect.anything(),
  120. expect.objectContaining({
  121. data: {
  122. autoAssignment: 'Auto Assign to Issue Owner',
  123. },
  124. })
  125. );
  126. });
  127. });
  128. it('should hide issue owners for issue-alert-fallback-targeting flag', () => {
  129. const organization = {...org, features: ['issue-alert-fallback-targeting']};
  130. render(
  131. <ProjectOwnership
  132. params={{orgId: organization.slug, projectId: project.slug}}
  133. organization={organization}
  134. project={project}
  135. />
  136. );
  137. expect(screen.getByText('Prioritize Auto Assignment')).toBeInTheDocument();
  138. expect(
  139. screen.queryByText('Send alert to project members if there’s no assigned owner')
  140. ).not.toBeInTheDocument();
  141. });
  142. });
  143. });