addCodeOwnerModal.spec.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import selectEvent from 'react-select-event';
  2. import {Organization} from 'sentry-fixture/organization';
  3. import {Repository} from 'sentry-fixture/repository';
  4. import {RepositoryProjectPathConfig} from 'sentry-fixture/repositoryProjectPathConfig';
  5. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  6. import {
  7. makeClosableHeader,
  8. makeCloseButton,
  9. ModalBody,
  10. ModalFooter,
  11. } from 'sentry/components/globalModal/components';
  12. import {AddCodeOwnerModal} from 'sentry/views/settings/project/projectOwnership/addCodeOwnerModal';
  13. describe('AddCodeOwnerModal', function () {
  14. const org = Organization({features: ['integrations-codeowners']});
  15. const project = TestStubs.Project();
  16. const integration = TestStubs.GitHubIntegration();
  17. const repo = Repository({
  18. integrationId: integration.id,
  19. id: '5',
  20. name: 'example/hello-there',
  21. });
  22. const codeMapping = RepositoryProjectPathConfig({
  23. project,
  24. repo,
  25. integration,
  26. stackRoot: 'stack/root',
  27. sourceRoot: 'source/root',
  28. });
  29. beforeEach(function () {
  30. MockApiClient.addMockResponse({
  31. url: `/organizations/${org.slug}/code-mappings/`,
  32. method: 'GET',
  33. body: [codeMapping],
  34. });
  35. MockApiClient.addMockResponse({
  36. url: `/organizations/${org.slug}/integrations/`,
  37. method: 'GET',
  38. body: [integration],
  39. });
  40. });
  41. it('renders', function () {
  42. render(
  43. <AddCodeOwnerModal
  44. Body={ModalBody}
  45. closeModal={jest.fn()}
  46. CloseButton={makeCloseButton(jest.fn())}
  47. Header={makeClosableHeader(jest.fn())}
  48. Footer={ModalFooter}
  49. organization={org}
  50. project={project}
  51. />
  52. );
  53. expect(screen.getByRole('button', {name: 'Add File'})).toBeDisabled();
  54. });
  55. it('renders codeowner file', async function () {
  56. MockApiClient.addMockResponse({
  57. url: `/organizations/${org.slug}/code-mappings/${codeMapping.id}/codeowners/`,
  58. method: 'GET',
  59. body: {html_url: 'blah', filepath: 'CODEOWNERS', raw: '* @MeredithAnya\n'},
  60. });
  61. render(
  62. <AddCodeOwnerModal
  63. Body={ModalBody}
  64. closeModal={jest.fn()}
  65. CloseButton={makeCloseButton(jest.fn())}
  66. Header={makeClosableHeader(jest.fn())}
  67. Footer={ModalFooter}
  68. organization={org}
  69. project={project}
  70. />
  71. );
  72. await selectEvent.select(screen.getByText('--'), 'example/hello-there');
  73. expect(screen.getByTestId('icon-check-mark')).toBeInTheDocument();
  74. expect(screen.getByRole('button', {name: 'Preview File'})).toHaveAttribute(
  75. 'href',
  76. 'blah'
  77. );
  78. });
  79. it('renders no codeowner file found', async function () {
  80. MockApiClient.addMockResponse({
  81. url: `/organizations/${org.slug}/code-mappings/${codeMapping.id}/codeowners/`,
  82. method: 'GET',
  83. statusCode: 404,
  84. });
  85. render(
  86. <AddCodeOwnerModal
  87. Body={ModalBody}
  88. closeModal={jest.fn()}
  89. CloseButton={makeCloseButton(jest.fn())}
  90. Header={makeClosableHeader(jest.fn())}
  91. Footer={ModalFooter}
  92. organization={org}
  93. project={project}
  94. />
  95. );
  96. await selectEvent.select(screen.getByText('--'), 'example/hello-there');
  97. expect(screen.getByText('No codeowner file found.')).toBeInTheDocument();
  98. });
  99. it('adds codeowner file', async function () {
  100. MockApiClient.addMockResponse({
  101. url: `/organizations/${org.slug}/code-mappings/${codeMapping.id}/codeowners/`,
  102. method: 'GET',
  103. body: {html_url: 'blah', filepath: 'CODEOWNERS', raw: '* @MeredithAnya\n'},
  104. });
  105. const addFileRequest = MockApiClient.addMockResponse({
  106. url: `/projects/${org.slug}/${project.slug}/codeowners/`,
  107. method: 'POST',
  108. body: {},
  109. });
  110. const handleCloseModal = jest.fn();
  111. render(
  112. <AddCodeOwnerModal
  113. Body={ModalBody}
  114. closeModal={handleCloseModal}
  115. CloseButton={makeCloseButton(jest.fn())}
  116. Header={makeClosableHeader(jest.fn())}
  117. Footer={ModalFooter}
  118. organization={org}
  119. project={project}
  120. />
  121. );
  122. await selectEvent.select(screen.getByText('--'), 'example/hello-there');
  123. await userEvent.click(screen.getByRole('button', {name: 'Add File'}));
  124. await waitFor(() => {
  125. expect(addFileRequest).toHaveBeenCalledWith(
  126. `/projects/${org.slug}/${project.slug}/codeowners/`,
  127. expect.objectContaining({
  128. data: {codeMappingId: '2', raw: '* @MeredithAnya\n'},
  129. })
  130. );
  131. });
  132. expect(handleCloseModal).toHaveBeenCalled();
  133. });
  134. });