clone-project-modal.test.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import { fireEvent, render, screen, waitFor } from '@testing-library/react'
  2. import { expect } from 'chai'
  3. import CloneProjectModal from '../../../../../frontend/js/features/clone-project-modal/components/clone-project-modal'
  4. import sinon from 'sinon'
  5. import fetchMock from 'fetch-mock'
  6. describe('<CloneProjectModal />', function () {
  7. afterEach(function () {
  8. fetchMock.reset()
  9. })
  10. const modalProps = {
  11. handleHide: sinon.stub(),
  12. projectId: 'project-1',
  13. projectName: 'Test Project',
  14. openProject: sinon.stub(),
  15. show: true,
  16. }
  17. it('renders the translated modal title', async function () {
  18. render(<CloneProjectModal {...modalProps} />)
  19. await screen.findByText('Copy Project')
  20. })
  21. it('posts the generated project name', async function () {
  22. fetchMock.post(
  23. 'express:/project/:projectId/clone',
  24. {
  25. status: 200,
  26. body: { project_id: modalProps.projectId },
  27. },
  28. { delay: 10 }
  29. )
  30. const openProject = sinon.stub()
  31. render(<CloneProjectModal {...modalProps} openProject={openProject} />)
  32. const cancelButton = await screen.findByRole('button', { name: 'Cancel' })
  33. expect(cancelButton.disabled).to.be.false
  34. const submitButton = await screen.findByRole('button', { name: 'Copy' })
  35. expect(submitButton.disabled).to.be.false
  36. const input = await screen.getByLabelText('New Name')
  37. fireEvent.change(input, {
  38. target: { value: '' },
  39. })
  40. expect(submitButton.disabled).to.be.true
  41. fireEvent.change(input, {
  42. target: { value: 'A Cloned Project' },
  43. })
  44. expect(submitButton.disabled).to.be.false
  45. fireEvent.click(submitButton)
  46. expect(submitButton.disabled).to.be.true
  47. await fetchMock.flush(true)
  48. expect(fetchMock.done()).to.be.true
  49. const [url, options] = fetchMock.lastCall(
  50. 'express:/project/:projectId/clone'
  51. )
  52. expect(url).to.equal('/project/project-1/clone')
  53. expect(JSON.parse(options.body)).to.deep.equal({
  54. projectName: 'A Cloned Project',
  55. })
  56. expect(openProject).to.be.calledOnce
  57. const errorMessage = screen.queryByText('Sorry, something went wrong')
  58. expect(errorMessage).to.be.null
  59. await waitFor(() => {
  60. expect(submitButton.disabled).to.be.false
  61. expect(cancelButton.disabled).to.be.false
  62. })
  63. })
  64. it('handles a generic error response', async function () {
  65. const matcher = 'express:/project/:projectId/clone'
  66. fetchMock.postOnce(matcher, {
  67. status: 500,
  68. body: 'There was an error!',
  69. })
  70. const openProject = sinon.stub()
  71. render(<CloneProjectModal {...modalProps} openProject={openProject} />)
  72. const button = await screen.findByRole('button', { name: 'Copy' })
  73. expect(button.disabled).to.be.false
  74. const cancelButton = await screen.findByRole('button', { name: 'Cancel' })
  75. expect(cancelButton.disabled).to.be.false
  76. fireEvent.click(button)
  77. expect(fetchMock.done(matcher)).to.be.true
  78. expect(openProject).not.to.be.called
  79. await screen.findByText('Sorry, something went wrong')
  80. expect(button.disabled).to.be.false
  81. expect(cancelButton.disabled).to.be.false
  82. })
  83. it('handles a specific error response', async function () {
  84. const matcher = 'express:/project/:projectId/clone'
  85. fetchMock.postOnce(matcher, {
  86. status: 400,
  87. body: 'There was an error!',
  88. })
  89. const openProject = sinon.stub()
  90. render(<CloneProjectModal {...modalProps} openProject={openProject} />)
  91. const button = await screen.findByRole('button', { name: 'Copy' })
  92. expect(button.disabled).to.be.false
  93. const cancelButton = await screen.findByRole('button', { name: 'Cancel' })
  94. expect(cancelButton.disabled).to.be.false
  95. fireEvent.click(button)
  96. await fetchMock.flush(true)
  97. expect(fetchMock.done(matcher)).to.be.true
  98. expect(openProject).not.to.be.called
  99. await screen.findByText('There was an error!')
  100. expect(button.disabled).to.be.false
  101. expect(cancelButton.disabled).to.be.false
  102. })
  103. })