index.spec.tsx 4.9 KB

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