From 98b60ebe93be9f19741131d7d771cbe9df5d4064 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Fri, 4 Oct 2024 10:19:22 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(frontend)=20fix=20infinity=20scrol?= =?UTF-8?q?l=20on=20invitation=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The infinity scroll had some difficulties to load the next page of invitations because the ref could be not init. This commit fixes the issue. --- .../app-impress/doc-member-list.spec.ts | 55 +++++++++++++++++++ .../components/InvitationList.tsx | 14 ++++- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-member-list.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-member-list.spec.ts index bdad423d..7fa7e70f 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-member-list.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-member-list.spec.ts @@ -66,6 +66,61 @@ test.describe('Document list members', () => { ).toBeVisible(); }); + test('it checks a big list of invitations', async ({ page }) => { + await page.route( + /.*\/documents\/.*\/invitations\/\?page=.*/, + async (route) => { + const request = route.request(); + const url = new URL(request.url()); + const pageId = url.searchParams.get('page'); + const accesses = { + count: 100, + next: 'http://anything/?page=2', + previous: null, + results: Array.from({ length: 20 }, (_, i) => ({ + id: `2ff1ec07-86c1-4534-a643-f41824a6c53a-${pageId}-${i}`, + email: `impress@impress.world-page-${pageId}-${i}`, + team: '', + role: 'editor', + abilities: { + destroy: true, + update: true, + partial_update: true, + retrieve: true, + }, + })), + }; + + if (request.method().includes('GET')) { + await route.fulfill({ + json: accesses, + }); + } else { + await route.continue(); + } + }, + ); + + await goToGridDoc(page); + + await page.getByRole('button', { name: 'Share' }).click(); + + const list = page.getByLabel('List invitation card').locator('ul'); + await expect(list.locator('li')).toHaveCount(20); + await list.getByText(`impress@impress.world-page-${1}-18`).hover(); + await page.mouse.wheel(0, 10); + + await waitForElementCount(list.locator('li'), 21, 10000); + + expect(await list.locator('li').count()).toBeGreaterThan(20); + await expect( + list.getByText(`impress@impress.world-page-1-16`), + ).toBeVisible(); + await expect( + list.getByText(`impress@impress.world-page-2-15`), + ).toBeVisible(); + }); + test('it checks the role rules', async ({ page, browserName }) => { const [docTitle] = await createDoc(page, 'Doc role rules', browserName, 1); diff --git a/src/frontend/apps/impress/src/features/docs/members/invitation-list/components/InvitationList.tsx b/src/frontend/apps/impress/src/features/docs/members/invitation-list/components/InvitationList.tsx index 73e8611e..ce743abf 100644 --- a/src/frontend/apps/impress/src/features/docs/members/invitation-list/components/InvitationList.tsx +++ b/src/frontend/apps/impress/src/features/docs/members/invitation-list/components/InvitationList.tsx @@ -1,5 +1,5 @@ import { Loader } from '@openfun/cunningham-react'; -import React, { useMemo, useRef } from 'react'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { APIError } from '@/api'; @@ -73,6 +73,7 @@ interface InvitationListProps { export const InvitationList = ({ doc }: InvitationListProps) => { const { t } = useTranslation(); const containerRef = useRef(null); + const [, setRefInitialized] = useState(false); const { data, isLoading, @@ -90,6 +91,17 @@ export const InvitationList = ({ doc }: InvitationListProps) => { }, [] as Invitation[]); }, [data?.pages]); + /** + * The "return null;" statement below blocks a necessary rerender + * for the InfiniteScroll component to work properly. + * This useEffect is a workaround to force the rerender. + */ + useEffect(() => { + if (containerRef.current) { + setRefInitialized(true); + } + }, [invitations?.length]); + if (!invitations?.length) { return null; }