index.spec.tsx 4.9 KB

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