From 5d3d58e8f49ea8e85f2b17505c4c5074a92c4462 Mon Sep 17 00:00:00 2001 From: ilkin-overleaf <100852799+ilkin-overleaf@users.noreply.github.com> Date: Mon, 27 Apr 2026 12:07:24 +0300 Subject: [PATCH] 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 --- .../components/dropdown/actions-dropdown.tsx | 18 +++- .../table/cells/actions-dropdown.test.tsx | 85 +++++++++++++++++++ 2 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 services/web/test/frontend/features/project-list/components/table/cells/actions-dropdown.test.tsx diff --git a/services/web/frontend/js/features/project-list/components/dropdown/actions-dropdown.tsx b/services/web/frontend/js/features/project-list/components/dropdown/actions-dropdown.tsx index 0fbdc4b30f..c6f13e8e2c 100644 --- a/services/web/frontend/js/features/project-list/components/dropdown/actions-dropdown.tsx +++ b/services/web/frontend/js/features/project-list/components/dropdown/actions-dropdown.tsx @@ -160,18 +160,28 @@ function ActionsDropdown({ project }: ActionDropdownProps) { )} - {text => ( + {(text, handleOpenModal) => (
  • - + {text}
  • )}
    - {text => ( + {(text, handleOpenModal) => (
  • - + {text}
  • diff --git a/services/web/test/frontend/features/project-list/components/table/cells/actions-dropdown.test.tsx b/services/web/test/frontend/features/project-list/components/table/cells/actions-dropdown.test.tsx new file mode 100644 index 0000000000..7543031e5b --- /dev/null +++ b/services/web/test/frontend/features/project-list/components/table/cells/actions-dropdown.test.tsx @@ -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('', 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() + + 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() + + 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 + ) + }) + }) +})