Merge pull request #32801 from overleaf/ii-fix-mobile-trash-delete

[web] Fix Delete/Leave dropdown items not working on mobile trashed projects list

GitOrigin-RevId: ce7c79f0c77bb1f0df023159ee6c463c577e26e1
This commit is contained in:
ilkin-overleaf
2026-04-27 12:07:24 +03:00
committed by Copybot
parent b556fd40b5
commit 5d3d58e8f4
2 changed files with 99 additions and 4 deletions
@@ -160,18 +160,28 @@ function ActionsDropdown({ project }: ActionDropdownProps) {
)}
</UntrashProjectButton>
<LeaveProjectButton project={project}>
{text => (
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem as="button" tabIndex={-1} leadingIcon="logout">
<DropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
leadingIcon="logout"
>
{text}
</DropdownItem>
</li>
)}
</LeaveProjectButton>
<DeleteProjectButton project={project}>
{text => (
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem as="button" tabIndex={-1} leadingIcon="block">
<DropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
leadingIcon="block"
>
{text}
</DropdownItem>
</li>
@@ -0,0 +1,85 @@
import { expect } from 'chai'
import { fireEvent, screen, waitFor } from '@testing-library/react'
import fetchMock from 'fetch-mock'
import ActionsDropdown from '../../../../../../../frontend/js/features/project-list/components/dropdown/actions-dropdown'
import {
trashedProject,
trashedAndNotOwnedProject,
} from '../../../fixtures/projects-data'
import {
renderWithProjectListContext,
resetProjectListContextFetch,
} from '../../../helpers/render-with-context'
describe('<ActionsDropdown />', function () {
afterEach(function () {
resetProjectListContextFetch()
window.metaAttributesCache.clear()
})
describe('Delete button for trashed project (mobile view)', function () {
it('opens the delete modal when clicking Delete in the dropdown', async function () {
window.metaAttributesCache.set('ol-user_id', trashedProject.owner?.id)
const project = Object.assign({}, trashedProject)
const deleteProjectMock = fetchMock.delete(
`express:/project/:projectId`,
{ status: 200 },
{ delay: 0 }
)
renderWithProjectListContext(<ActionsDropdown project={project} />)
const toggle = screen.getByRole('button', { name: 'Actions' })
fireEvent.click(toggle)
const deleteBtn = await screen.findByRole('menuitem', { name: /delete/i })
fireEvent.click(deleteBtn)
await screen.findByText('Delete Projects')
const confirmBtn = screen.getByRole('button', {
name: 'Confirm',
}) as HTMLButtonElement
fireEvent.click(confirmBtn)
await waitFor(
() =>
expect(deleteProjectMock.callHistory.called(`/project/${project.id}`))
.to.be.true
)
})
})
describe('Leave button for trashed non-owned project (mobile view)', function () {
it('opens the leave modal when clicking Leave in the dropdown', async function () {
const project = Object.assign({}, trashedAndNotOwnedProject)
const leaveProjectMock = fetchMock.post(
`express:/project/${project.id}/leave`,
{ status: 200 },
{ delay: 0 }
)
renderWithProjectListContext(<ActionsDropdown project={project} />)
const toggle = screen.getByRole('button', { name: 'Actions' })
fireEvent.click(toggle)
const leaveBtn = await screen.findByRole('menuitem', { name: /leave/i })
fireEvent.click(leaveBtn)
await screen.findByText('Leave Projects')
const confirmBtn = screen.getByRole('button', {
name: 'Confirm',
}) as HTMLButtonElement
fireEvent.click(confirmBtn)
await waitFor(
() =>
expect(
leaveProjectMock.callHistory.called(`/project/${project.id}/leave`)
).to.be.true
)
})
})
})