From c7f7b0f7ad16d26722fb832ea48e432e907fb98e Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Wed, 14 Aug 2024 12:29:39 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=90(frontend)=20add=20Content-Language?= =?UTF-8?q?=20on=20invitation=20endpoint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to adapt the email language depend the website choosen language. We sent the language in the request header, the backend will use this information to send the email in the correct language. --- .../app-impress/doc-member-create.spec.ts | 43 +++++++++++++++++++ .../api/useCreateDocInvitation.tsx | 6 +++ .../members-add/components/AddMembers.tsx | 3 ++ .../impress/src/i18n/hooks/useLanguage.tsx | 15 +++++++ src/frontend/apps/impress/src/i18n/types.ts | 2 + 5 files changed, 69 insertions(+) create mode 100644 src/frontend/apps/impress/src/i18n/hooks/useLanguage.tsx create mode 100644 src/frontend/apps/impress/src/i18n/types.ts diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-member-create.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-member-create.spec.ts index fbb0db78..a4445ff9 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-member-create.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-member-create.spec.ts @@ -111,6 +111,9 @@ test.describe('Document create member', () => { await expect(page.getByText(`Invitation sent to ${email}`)).toBeVisible(); const responseCreateInvitation = await responsePromiseCreateInvitation; expect(responseCreateInvitation.ok()).toBeTruthy(); + expect( + responseCreateInvitation.request().headers()['content-language'], + ).toBe('en-us'); // Check user added await expect( @@ -209,4 +212,44 @@ test.describe('Document create member', () => { await responsePromiseCreateInvitationFail; expect(responseCreateInvitationFail.ok()).toBeFalsy(); }); + + test('The invitation endpoint get the language of the website', async ({ + page, + browserName, + }) => { + await createDoc(page, 'user-invitation', browserName, 1); + + const header = page.locator('header').first(); + await header.getByRole('combobox').getByText('EN').click(); + await header.getByRole('option', { name: 'FR' }).click(); + + await page.getByRole('button', { name: 'Partager' }).click(); + + const inputSearch = page.getByLabel( + /Trouver un membre à ajouter au document/, + ); + + const email = randomName('test@test.fr', browserName, 1)[0]; + await inputSearch.fill(email); + await page.getByRole('option', { name: email }).click(); + + // Choose a role + await page.getByRole('combobox', { name: /Choisissez un rôle/ }).click(); + await page.getByRole('option', { name: 'Administrateur' }).click(); + + const responsePromiseCreateInvitation = page.waitForResponse( + (response) => + response.url().includes('/invitations/') && response.status() === 201, + ); + + await page.getByRole('button', { name: 'Valider' }).click(); + + // Check invitation sent + await expect(page.getByText(`Invitation envoyée à ${email}`)).toBeVisible(); + const responseCreateInvitation = await responsePromiseCreateInvitation; + expect(responseCreateInvitation.ok()).toBeTruthy(); + expect( + responseCreateInvitation.request().headers()['content-language'], + ).toBe('fr-fr'); + }); }); diff --git a/src/frontend/apps/impress/src/features/docs/members/members-add/api/useCreateDocInvitation.tsx b/src/frontend/apps/impress/src/features/docs/members/members-add/api/useCreateDocInvitation.tsx index cc26f4e3..c443a112 100644 --- a/src/frontend/apps/impress/src/features/docs/members/members-add/api/useCreateDocInvitation.tsx +++ b/src/frontend/apps/impress/src/features/docs/members/members-add/api/useCreateDocInvitation.tsx @@ -3,6 +3,7 @@ import { useMutation } from '@tanstack/react-query'; import { APIError, errorCauses, fetchAPI } from '@/api'; import { User } from '@/core/auth'; import { Doc, Role } from '@/features/docs/doc-management'; +import { ContentLanguage } from '@/i18n/types'; import { DocInvitation, OptionType } from '../types'; @@ -10,15 +11,20 @@ interface CreateDocInvitationParams { email: User['email']; role: Role; docId: Doc['id']; + contentLanguage: ContentLanguage; } export const createDocInvitation = async ({ email, role, docId, + contentLanguage, }: CreateDocInvitationParams): Promise => { const response = await fetchAPI(`documents/${docId}/invitations/`, { method: 'POST', + headers: { + 'Content-Language': contentLanguage, + }, body: JSON.stringify({ email, role, diff --git a/src/frontend/apps/impress/src/features/docs/members/members-add/components/AddMembers.tsx b/src/frontend/apps/impress/src/features/docs/members/members-add/components/AddMembers.tsx index d33a5082..51d183c1 100644 --- a/src/frontend/apps/impress/src/features/docs/members/members-add/components/AddMembers.tsx +++ b/src/frontend/apps/impress/src/features/docs/members/members-add/components/AddMembers.tsx @@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next'; import { APIError } from '@/api'; import { Box, Card, IconBG } from '@/components'; import { Doc, Role } from '@/features/docs/doc-management'; +import { useLanguage } from '@/i18n/hooks/useLanguage'; import { useCreateDocAccess, useCreateInvitation } from '../api'; import { @@ -33,6 +34,7 @@ interface ModalAddMembersProps { } export const AddMembers = ({ currentRole, doc }: ModalAddMembersProps) => { + const { contentLanguage } = useLanguage(); const { t } = useTranslation(); const [selectedUsers, setSelectedUsers] = useState([]); const [selectedRole, setSelectedRole] = useState(); @@ -51,6 +53,7 @@ export const AddMembers = ({ currentRole, doc }: ModalAddMembersProps) => { email: selectedUser.value.email, role: selectedRole, docId: doc.id, + contentLanguage, }); break; diff --git a/src/frontend/apps/impress/src/i18n/hooks/useLanguage.tsx b/src/frontend/apps/impress/src/i18n/hooks/useLanguage.tsx new file mode 100644 index 00000000..4879bda8 --- /dev/null +++ b/src/frontend/apps/impress/src/i18n/hooks/useLanguage.tsx @@ -0,0 +1,15 @@ +import { useTranslation } from 'react-i18next'; + +import { ContentLanguage } from '../types'; + +export const useLanguage = (): { + language: string; + contentLanguage: ContentLanguage; +} => { + const { i18n } = useTranslation(); + + return { + language: i18n.language, + contentLanguage: i18n.language === 'fr' ? 'fr-fr' : 'en-us', + }; +}; diff --git a/src/frontend/apps/impress/src/i18n/types.ts b/src/frontend/apps/impress/src/i18n/types.ts new file mode 100644 index 00000000..d9b0064a --- /dev/null +++ b/src/frontend/apps/impress/src/i18n/types.ts @@ -0,0 +1,2 @@ +// See: https://github.com/numerique-gouv/impress/blob/ac58341984c99c10ebfac7f8bbe1e8756c48e4d4/src/backend/impress/settings.py#L156-L161 +export type ContentLanguage = 'en-us' | 'fr-fr';