import { expect } from 'chai'
import sinon from 'sinon'
import { fireEvent, screen, render, waitFor } from '@testing-library/react'
import fetchMock, { type FetchMock } from 'fetch-mock'
import LeaveModalForm from '../../../../../../frontend/js/features/settings/components/leave/modal-form'
import { location } from '@/shared/components/location'
import getMeta from '@/utils/meta'
describe('', function () {
beforeEach(function () {
window.metaAttributesCache.set('ol-usersEmail', 'foo@bar.com')
Object.assign(getMeta('ol-ExposedSettings'), { isOverleaf: true })
})
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
})
it('validates form', async function () {
const setIsFormValid = sinon.stub()
render(
{}}
isFormValid={false}
setIsFormValid={setIsFormValid}
/>
)
const emailInput = screen.getByLabelText('Email')
fireEvent.change(emailInput, { target: { value: 'FOO@bar.com' } })
const passwordInput = screen.getByLabelText('Password')
fireEvent.change(passwordInput, { target: { value: 'foobar' } })
const checkbox = screen.getByLabelText(
'I understand this will delete all projects in my Overleaf account with email address foo@bar.com'
)
fireEvent.click(checkbox)
const setIsFormValidCalls = setIsFormValid.getCalls()
const lastSetIsFormValidCall = setIsFormValidCalls.pop()
expect(lastSetIsFormValidCall!.args[0]).to.be.true
for (const setIsFormValidCall of setIsFormValidCalls) {
expect(setIsFormValidCall.args[0]).to.be.false
}
})
describe('submits', async function () {
let setInFlight: sinon.SinonStub
let setIsFormValid: sinon.SinonStub
let deleteMock: FetchMock
beforeEach(function () {
setInFlight = sinon.stub()
setIsFormValid = sinon.stub()
deleteMock = fetchMock.post('/user/delete', 200)
this.locationWrapperSandbox = sinon.createSandbox()
this.locationWrapperStub = this.locationWrapperSandbox.stub(location)
Object.assign(getMeta('ol-ExposedSettings'), { isOverleaf: true })
})
afterEach(function () {
fetchMock.removeRoutes().clearHistory()
this.locationWrapperSandbox.restore()
})
it('with valid form', async function () {
render(
)
fireEvent.submit(screen.getByLabelText('Email'))
sinon.assert.calledOnce(setInFlight)
sinon.assert.calledWithMatch(setInFlight, true)
expect(deleteMock.callHistory.called()).to.be.true
const assignStub = this.locationWrapperStub.assign
await waitFor(() => {
sinon.assert.calledTwice(setInFlight)
sinon.assert.calledWithMatch(setInFlight, false)
sinon.assert.calledOnce(assignStub)
sinon.assert.calledWith(assignStub, '/')
})
})
it('with invalid form', async function () {
render(
)
fireEvent.submit(screen.getByLabelText('Email'))
expect(deleteMock.callHistory.called()).to.be.false
sinon.assert.notCalled(setInFlight)
})
})
it('handles credentials error without Saas tip', async function () {
Object.assign(getMeta('ol-ExposedSettings'), { isOverleaf: false })
fetchMock.post('/user/delete', 403)
render(
{}}
isFormValid
setIsFormValid={() => {}}
/>
)
fireEvent.submit(screen.getByLabelText('Email'))
await waitFor(() => {
screen.getByText(/Your email or password is incorrect. Please try again/)
})
expect(screen.queryByText(/If you cannot remember your password/)).to.not
.exist
})
it('handles credentials error with Saas tip', async function () {
fetchMock.post('/user/delete', 403)
render(
{}}
isFormValid
setIsFormValid={() => {}}
/>
)
fireEvent.submit(screen.getByLabelText('Email'))
await waitFor(() => {
screen.getByText(/Your email or password is incorrect. Please try again/)
})
screen.getByText(/If you cannot remember your password/)
const link = screen.getByRole('link', { name: 'reset your password' })
expect(link.getAttribute('href')).to.equal('/user/password/reset')
})
it('handles subscription error', async function () {
fetchMock.post('/user/delete', {
status: 422,
body: {
error: 'SubscriptionAdminDeletionError',
},
})
render(
{}}
isFormValid
setIsFormValid={() => {}}
/>
)
fireEvent.submit(screen.getByLabelText('Email'))
await waitFor(() => {
screen.getByText(
'You cannot delete your account while on a subscription. Please cancel your subscription and try again. If you keep seeing this message please contact us.'
)
})
})
it('handles generic error', async function () {
fetchMock.post('/user/delete', 500)
render(
{}}
isFormValid
setIsFormValid={() => {}}
/>
)
fireEvent.submit(screen.getByLabelText('Email'))
await waitFor(() => {
screen.getByText(
'Sorry, something went wrong deleting your account. Please try again in a minute.'
)
})
})
})