mirror of
https://github.com/overleaf/overleaf.git
synced 2024-12-13 12:29:32 -05:00
0135236df8
Migrate left menu Clone Project modal to React GitOrigin-RevId: ad113e2b40de4007def513d40551d55bb0c913db
237 lines
5.6 KiB
JavaScript
237 lines
5.6 KiB
JavaScript
import React from 'react'
|
|
import { fireEvent, render, screen } from '@testing-library/react'
|
|
import { expect } from 'chai'
|
|
import CloneProjectModalContent from '../../../../../frontend/js/features/clone-project-modal/components/clone-project-modal-content'
|
|
import CloneProjectModal from '../../../../../frontend/js/features/clone-project-modal/components/clone-project-modal'
|
|
import sinon from 'sinon'
|
|
import fetchMock from 'fetch-mock'
|
|
|
|
const cancel = sinon.stub()
|
|
const cloneProject = sinon.stub()
|
|
const handleHide = sinon.stub()
|
|
|
|
describe('<CloneProjectModal />', function() {
|
|
afterEach(function() {
|
|
fetchMock.reset()
|
|
})
|
|
|
|
it('posts the generated project name', async function() {
|
|
const matcher = 'express:/project/:projectId/clone'
|
|
|
|
fetchMock.postOnce(
|
|
matcher,
|
|
() => {
|
|
return {
|
|
project_id: 'test'
|
|
}
|
|
},
|
|
{
|
|
body: {
|
|
projectName: 'A Project (Copy)'
|
|
}
|
|
}
|
|
)
|
|
|
|
render(
|
|
<CloneProjectModal
|
|
handleHide={handleHide}
|
|
projectId="project-1"
|
|
projectName="A Project"
|
|
show
|
|
/>
|
|
)
|
|
|
|
const button = await screen.findByRole('button', {
|
|
name: 'Copy',
|
|
hidden: true // TODO: this shouldn't be needed
|
|
})
|
|
|
|
const cancelButton = await screen.findByRole('button', {
|
|
name: 'Cancel',
|
|
hidden: true // TODO: this shouldn't be needed
|
|
})
|
|
|
|
expect(button.disabled).to.be.false
|
|
expect(cancelButton.disabled).to.be.false
|
|
|
|
fireEvent.click(button)
|
|
|
|
expect(fetchMock.done(matcher)).to.be.true
|
|
// TODO: window.location?
|
|
|
|
const errorMessage = screen.queryByText('Sorry, something went wrong')
|
|
expect(errorMessage).to.be.null
|
|
|
|
expect(button.disabled).to.be.true
|
|
expect(cancelButton.disabled).to.be.true
|
|
})
|
|
|
|
it('handles a generic error response', async function() {
|
|
const matcher = 'express:/project/:projectId/clone'
|
|
|
|
fetchMock.postOnce(matcher, {
|
|
status: 500,
|
|
body: 'There was an error!'
|
|
})
|
|
|
|
render(
|
|
<CloneProjectModal
|
|
handleHide={handleHide}
|
|
projectId="project-2"
|
|
projectName="A Project"
|
|
show
|
|
/>
|
|
)
|
|
|
|
const button = await screen.findByRole('button', {
|
|
name: 'Copy',
|
|
hidden: true // TODO: this shouldn't be needed
|
|
})
|
|
|
|
const cancelButton = await screen.findByRole('button', {
|
|
name: 'Cancel',
|
|
hidden: true // TODO: this shouldn't be needed
|
|
})
|
|
|
|
expect(button.disabled).to.be.false
|
|
expect(cancelButton.disabled).to.be.false
|
|
|
|
fireEvent.click(button)
|
|
|
|
expect(fetchMock.done(matcher)).to.be.true
|
|
|
|
await screen.findByText('Sorry, something went wrong')
|
|
|
|
expect(button.disabled).to.be.false
|
|
expect(cancelButton.disabled).to.be.false
|
|
})
|
|
|
|
it('handles a specific error response', async function() {
|
|
const matcher = 'express:/project/:projectId/clone'
|
|
|
|
fetchMock.postOnce(matcher, {
|
|
status: 400,
|
|
body: 'There was an error!'
|
|
})
|
|
|
|
render(
|
|
<CloneProjectModal
|
|
handleHide={handleHide}
|
|
projectId="project-3"
|
|
projectName="A Project"
|
|
show
|
|
/>
|
|
)
|
|
|
|
const button = await screen.findByRole('button', {
|
|
name: 'Copy',
|
|
hidden: true // TODO: this shouldn't be needed
|
|
})
|
|
|
|
const cancelButton = await screen.findByRole('button', {
|
|
name: 'Cancel',
|
|
hidden: true // TODO: this shouldn't be needed
|
|
})
|
|
|
|
expect(button.disabled).to.be.false
|
|
expect(cancelButton.disabled).to.be.false
|
|
|
|
fireEvent.click(button)
|
|
|
|
expect(fetchMock.done(matcher)).to.be.true
|
|
|
|
await screen.findByText('There was an error!')
|
|
|
|
expect(button.disabled).to.be.false
|
|
expect(cancelButton.disabled).to.be.false
|
|
})
|
|
})
|
|
|
|
describe('<CloneProjectModalContent />', function() {
|
|
it('renders the translated modal title', async function() {
|
|
render(
|
|
<CloneProjectModalContent
|
|
cloneProject={cloneProject}
|
|
cancel={cancel}
|
|
inFlight={false}
|
|
/>
|
|
)
|
|
|
|
await screen.findByText('Copy Project')
|
|
})
|
|
|
|
it('shows the copy button', async function() {
|
|
render(
|
|
<CloneProjectModalContent
|
|
cloneProject={cloneProject}
|
|
cancel={cancel}
|
|
inFlight={false}
|
|
/>
|
|
)
|
|
|
|
const button = await screen.findByRole('button', { name: 'Copy' })
|
|
|
|
expect(button.disabled).to.be.false
|
|
})
|
|
|
|
it('disables the copy button when loading', async function() {
|
|
render(
|
|
<CloneProjectModalContent
|
|
cloneProject={cloneProject}
|
|
cancel={cancel}
|
|
inFlight
|
|
/>
|
|
)
|
|
|
|
const button = await screen.findByText(
|
|
(content, element) =>
|
|
element.nodeName === 'BUTTON' &&
|
|
element.textContent.trim().match(/^Copying…$/)
|
|
)
|
|
|
|
expect(button.disabled).to.be.true
|
|
})
|
|
|
|
it('renders a generic error message', async function() {
|
|
render(
|
|
<CloneProjectModalContent
|
|
cloneProject={cloneProject}
|
|
cancel={cancel}
|
|
inFlight={false}
|
|
error
|
|
/>
|
|
)
|
|
|
|
await screen.findByText('Sorry, something went wrong')
|
|
})
|
|
|
|
it('renders a specific error message', async function() {
|
|
render(
|
|
<CloneProjectModalContent
|
|
cloneProject={cloneProject}
|
|
cancel={cancel}
|
|
inFlight={false}
|
|
error={{
|
|
message: 'Uh oh!'
|
|
}}
|
|
/>
|
|
)
|
|
|
|
await screen.findByText('Uh oh!')
|
|
})
|
|
|
|
it('displays a project name', async function() {
|
|
render(
|
|
<CloneProjectModalContent
|
|
cloneProject={cloneProject}
|
|
cancel={cancel}
|
|
inFlight={false}
|
|
projectName="A copy of a project"
|
|
/>
|
|
)
|
|
|
|
const input = await screen.getByLabelText('New Name')
|
|
|
|
expect(input.value).to.equal('A copy of a project (Copy)')
|
|
})
|
|
})
|