mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 14:43:46 +01:00
Merge pull request #7225 from overleaf/ta-leave-modal
[DeleteAccount] Create Modal with Form GitOrigin-RevId: 611f08c7253f59d91c6937b79c80a386b9d21ccd
This commit is contained in:
@@ -54,7 +54,7 @@ describe('Captcha', function () {
|
||||
expect(response.statusCode).to.equal(401)
|
||||
expect(body).to.deep.equal({
|
||||
message: {
|
||||
text: 'Your email or password is incorrect. Please try again',
|
||||
text: 'Your email or password is incorrect. Please try again.',
|
||||
type: 'error',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -97,7 +97,9 @@ describe('Registration', function () {
|
||||
it('should produce the correct responses so far', function () {
|
||||
expect(results.length).to.equal(9)
|
||||
expect(results).to.deep.equal(
|
||||
Array(9).fill('Your email or password is incorrect. Please try again')
|
||||
Array(9).fill(
|
||||
'Your email or password is incorrect. Please try again.'
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
@@ -115,7 +117,7 @@ describe('Registration', function () {
|
||||
expect(results.length).to.equal(15)
|
||||
expect(results).to.deep.equal(
|
||||
Array(10)
|
||||
.fill('Your email or password is incorrect. Please try again')
|
||||
.fill('Your email or password is incorrect. Please try again.')
|
||||
.concat(
|
||||
Array(5).fill(
|
||||
'This account has had too many login requests. Please wait 2 minutes before trying to log in again'
|
||||
@@ -145,7 +147,7 @@ describe('Registration', function () {
|
||||
|
||||
it('should not rate limit their request', function () {
|
||||
expect(messages).to.deep.equal([
|
||||
'Your email or password is incorrect. Please try again',
|
||||
'Your email or password is incorrect. Please try again.',
|
||||
])
|
||||
})
|
||||
|
||||
@@ -194,7 +196,7 @@ describe('Registration', function () {
|
||||
expect(results.length).to.equal(9)
|
||||
expect(results).to.deep.equal(
|
||||
Array(9).fill(
|
||||
'Your email or password is incorrect. Please try again'
|
||||
'Your email or password is incorrect. Please try again.'
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import {
|
||||
fireEvent,
|
||||
screen,
|
||||
waitForElementToBeRemoved,
|
||||
render,
|
||||
} from '@testing-library/react'
|
||||
|
||||
import LeaveSection from '../../../../../frontend/js/features/settings/components/leave-section'
|
||||
|
||||
describe('<LeaveSection />', function () {
|
||||
it('opens modal', async function () {
|
||||
render(<LeaveSection />)
|
||||
|
||||
const button = screen.getByRole('button', {
|
||||
name: 'Delete your account',
|
||||
})
|
||||
|
||||
fireEvent.click(button)
|
||||
await screen.findByText('Delete Account')
|
||||
})
|
||||
|
||||
it('closes modal', async function () {
|
||||
render(<LeaveSection />)
|
||||
fireEvent.click(
|
||||
screen.getByRole('button', {
|
||||
name: 'Delete your account',
|
||||
})
|
||||
)
|
||||
|
||||
const cancelButton = screen.getByRole('button', {
|
||||
name: 'Close',
|
||||
})
|
||||
|
||||
fireEvent.click(cancelButton)
|
||||
|
||||
await waitForElementToBeRemoved(() => screen.getByText('Delete Account'))
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,26 @@
|
||||
import { expect } from 'chai'
|
||||
import { screen, render } from '@testing-library/react'
|
||||
import fetchMock from 'fetch-mock'
|
||||
|
||||
import LeaveModalContent from '../../../../../../frontend/js/features/settings/components/leave/modal-content'
|
||||
|
||||
describe('<LeaveModalContent />', function () {
|
||||
afterEach(function () {
|
||||
fetchMock.reset()
|
||||
})
|
||||
|
||||
it('disable delete button if form is not valid', function () {
|
||||
render(
|
||||
<LeaveModalContent
|
||||
handleHide={() => {}}
|
||||
inFlight={false}
|
||||
setInFlight={() => {}}
|
||||
/>
|
||||
)
|
||||
|
||||
const deleteButton = screen.getByRole('button', {
|
||||
name: 'Delete',
|
||||
})
|
||||
expect(deleteButton.hasAttribute('disabled')).to.be.true
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,196 @@
|
||||
import { expect } from 'chai'
|
||||
import sinon from 'sinon'
|
||||
import { fireEvent, screen, render, waitFor } from '@testing-library/react'
|
||||
import fetchMock from 'fetch-mock'
|
||||
|
||||
import LeaveModalForm from '../../../../../../frontend/js/features/settings/components/leave/modal-form'
|
||||
|
||||
describe('<LeaveModalForm />', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
window.metaAttributesCache.set('ol-userDefaultEmail', 'foo@bar.com')
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
fetchMock.reset()
|
||||
})
|
||||
|
||||
it('validates form', async function () {
|
||||
const setIsFormValid = sinon.stub()
|
||||
render(
|
||||
<LeaveModalForm
|
||||
setInFlight={() => {}}
|
||||
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
|
||||
let setIsFormValid
|
||||
let deleteMock
|
||||
let locationStub
|
||||
const originalLocation = window.location
|
||||
|
||||
beforeEach(function () {
|
||||
setInFlight = sinon.stub()
|
||||
setIsFormValid = sinon.stub()
|
||||
deleteMock = fetchMock.post('/user/delete', 200)
|
||||
locationStub = sinon.stub()
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: {
|
||||
assign: locationStub,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
fetchMock.reset()
|
||||
Object.defineProperty(window, 'location', {
|
||||
value: originalLocation,
|
||||
})
|
||||
})
|
||||
|
||||
it('with valid form', async function () {
|
||||
render(
|
||||
<LeaveModalForm
|
||||
setInFlight={setInFlight}
|
||||
isFormValid
|
||||
setIsFormValid={setIsFormValid}
|
||||
/>
|
||||
)
|
||||
|
||||
fireEvent.submit(screen.getByLabelText('Email'))
|
||||
|
||||
sinon.assert.calledOnce(setInFlight)
|
||||
sinon.assert.calledWithMatch(setInFlight, true)
|
||||
expect(deleteMock.called()).to.be.true
|
||||
await waitFor(() => {
|
||||
sinon.assert.calledTwice(setInFlight)
|
||||
sinon.assert.calledWithMatch(setInFlight, false)
|
||||
sinon.assert.calledOnce(locationStub)
|
||||
sinon.assert.calledWithMatch(locationStub, '/login')
|
||||
})
|
||||
})
|
||||
|
||||
it('with invalid form', async function () {
|
||||
render(
|
||||
<LeaveModalForm
|
||||
setInFlight={setInFlight}
|
||||
isFormValid={false}
|
||||
setIsFormValid={setIsFormValid}
|
||||
/>
|
||||
)
|
||||
|
||||
fireEvent.submit(screen.getByLabelText('Email'))
|
||||
|
||||
expect(deleteMock.called()).to.be.false
|
||||
sinon.assert.notCalled(setInFlight)
|
||||
})
|
||||
})
|
||||
|
||||
it('handles credentials error with Saas tip', async function () {
|
||||
fetchMock.post('/user/delete', 403)
|
||||
render(
|
||||
<LeaveModalForm
|
||||
setInFlight={() => {}}
|
||||
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 without Saas tip', async function () {
|
||||
fetchMock.post('/user/delete', 403)
|
||||
window.metaAttributesCache.set('ol-isSaas', true)
|
||||
render(
|
||||
<LeaveModalForm
|
||||
setInFlight={() => {}}
|
||||
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(
|
||||
<LeaveModalForm
|
||||
setInFlight={() => {}}
|
||||
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(
|
||||
<LeaveModalForm
|
||||
setInFlight={() => {}}
|
||||
isFormValid
|
||||
setIsFormValid={() => {}}
|
||||
/>
|
||||
)
|
||||
|
||||
fireEvent.submit(screen.getByLabelText('Email'))
|
||||
|
||||
await waitFor(() => {
|
||||
screen.getByText(
|
||||
'Sorry, something went wrong deleting your account. Please try again in a minute.'
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,65 @@
|
||||
import sinon from 'sinon'
|
||||
import { fireEvent, screen, render, waitFor } from '@testing-library/react'
|
||||
import fetchMock from 'fetch-mock'
|
||||
|
||||
import LeaveModal from '../../../../../../frontend/js/features/settings/components/leave/modal'
|
||||
|
||||
describe('<LeaveModal />', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
window.metaAttributesCache.set('ol-userDefaultEmail', 'foo@bar.com')
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
window.metaAttributesCache = new Map()
|
||||
fetchMock.reset()
|
||||
})
|
||||
|
||||
it('closes modal on cancel', async function () {
|
||||
const handleClose = sinon.stub()
|
||||
render(<LeaveModal isOpen handleClose={handleClose} />)
|
||||
|
||||
const cancelButton = screen.getByRole('button', {
|
||||
name: 'Cancel',
|
||||
})
|
||||
fireEvent.click(cancelButton)
|
||||
|
||||
sinon.assert.calledOnce(handleClose)
|
||||
})
|
||||
|
||||
it('does not close modal while in flight', async function () {
|
||||
fetchMock.post('/user/delete', new Promise(() => {}))
|
||||
const handleClose = sinon.stub()
|
||||
render(<LeaveModal isOpen handleClose={handleClose} />)
|
||||
|
||||
fillValidForm()
|
||||
|
||||
const deleteButton = screen.getByRole('button', {
|
||||
name: 'Delete',
|
||||
})
|
||||
fireEvent.click(deleteButton)
|
||||
|
||||
await waitFor(() => {
|
||||
screen.getByRole('button', {
|
||||
name: 'Deleting…',
|
||||
})
|
||||
})
|
||||
|
||||
const cancelButton = screen.getByRole('button', {
|
||||
name: 'Cancel',
|
||||
})
|
||||
fireEvent.click(cancelButton)
|
||||
|
||||
sinon.assert.notCalled(handleClose)
|
||||
})
|
||||
})
|
||||
|
||||
function fillValidForm() {
|
||||
fireEvent.change(screen.getByLabelText('Email'), {
|
||||
target: { value: 'foo@bar.com' },
|
||||
})
|
||||
fireEvent.change(screen.getByLabelText('Password'), {
|
||||
target: { value: 'foobar' },
|
||||
})
|
||||
fireEvent.click(screen.getByLabelText(/I understand/))
|
||||
}
|
||||
Reference in New Issue
Block a user