diff --git a/src/components/form/RadioInput.module.css b/src/components/form/RadioInput.module.css index a5cad0628..e6380f6de 100644 --- a/src/components/form/RadioInput.module.css +++ b/src/components/form/RadioInput.module.css @@ -73,4 +73,19 @@ &:hover { color: var(--neutral-80); } -} \ No newline at end of file +} + +.disabled { + cursor: default; + color: var(--neutral-30) !important; + + input[type='radio'] { + cursor: default; + border-color: var(--neutral-30) !important; + background-color: var(--neutral-00) !important; + + &:before { + background-color: var(--neutral-30) !important; + } + } +} diff --git a/src/components/form/RadioInput.tsx b/src/components/form/RadioInput.tsx index 4fa3cc010..cbefa5fbf 100644 --- a/src/components/form/RadioInput.tsx +++ b/src/components/form/RadioInput.tsx @@ -20,7 +20,11 @@ const RadioInput = ({ } & InputHTMLAttributes) => { return (
-
{!!equivalent.carpool && type && ( diff --git a/src/components/outils/alimentation/AlimentationSubCategory.tsx b/src/components/outils/alimentation/AlimentationSubCategory.tsx index 3e1554a34..eea7cce85 100644 --- a/src/components/outils/alimentation/AlimentationSubCategory.tsx +++ b/src/components/outils/alimentation/AlimentationSubCategory.tsx @@ -35,6 +35,7 @@ const AlimentationSubCategory = ({ return (
{secondary === undefined && ( <> - {overScreens && ('hypothesis' in overScreens || 'data' in overScreens) ? ( -
+ {showButtons && overScreens && ('hypothesis' in overScreens || 'data' in overScreens) ? ( +
{'data' in overScreens && ( )}
-
- { - if (action === 'telecharger') { - takeScreenshot() - } else { - setOverscreen(slug, action) - } - }} - tracking={tracking} - withoutIntegration={withoutIntegration} - withoutShare={withoutShare} - /> -
+ {showButtons && ( +
+ { + if (action === 'telecharger') { + takeScreenshot() + } else { + setOverscreen(slug, action) + } + }} + tracking={tracking} + withoutIntegration={withoutIntegration} + withoutShare={withoutShare} + /> +
+ )}
) } diff --git a/src/components/shareable/overScreens/AlimentationIntegrate.tsx b/src/components/shareable/overScreens/AlimentationIntegrate.tsx new file mode 100644 index 000000000..a74a260d0 --- /dev/null +++ b/src/components/shareable/overScreens/AlimentationIntegrate.tsx @@ -0,0 +1,78 @@ +'use client' + +import { useTranslations } from 'next-intl' +import React, { useEffect, useMemo, useState } from 'react' +import useParamContext from 'src/providers/ParamProvider' +import ClipboardBox from 'components/base/ClipboardBox' +import AlimentationListParam from './AlimentationListParam' +import CustomParam, { CustomParamValue } from './CustomParam' +import styles from './CustomParam.module.css' +import IntegratePreview from './IntegratePreview' +import shareStyles from './Share.module.css' + +const AlimentationIntegrate = () => { + const t = useTranslations('alimentation.integrate') + const { theme, language, alimentation: alimentationParams } = useParamContext() + + const [hideButtons, setHideButtons] = useState(false) + const [category, setCategory] = useState(alimentationParams.category) + const [customList, setCustomList] = useState(alimentationParams.customList) + const [equivalents, setEquivalents] = useState(alimentationParams.equivalents) + + useEffect(() => { + setCategory(alimentationParams.category) + }, [alimentationParams.category]) + + const search = useMemo(() => { + const result = `&theme=${theme}&language=${language}` + const hideButtonsParam = hideButtons ? '&hideButtons=true' : '' + if (customList) { + return `alimentationEquivalents=${equivalents.join(',')}${hideButtonsParam}${result}` + } + return `alimentationCategory=${category}${hideButtonsParam}${result}` + }, [category, customList, equivalents, hideButtons, theme, language]) + + return ( + <> +
+ +
+
+ {t('customList')} + + {customList && } +
+
+
+ {t('hideButtons')} + +
+ + {``} + + + ) +} + +export default AlimentationIntegrate diff --git a/src/components/shareable/overScreens/AlimentationListParam.module.css b/src/components/shareable/overScreens/AlimentationListParam.module.css new file mode 100644 index 000000000..a6f9939b6 --- /dev/null +++ b/src/components/shareable/overScreens/AlimentationListParam.module.css @@ -0,0 +1,21 @@ +.categories { + display: flex; + flex-direction: column; + gap: 2.25rem; + margin-top: -0.5rem; +} + +.category { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0.5rem; +} + +.categoryName { + color: var(--neutral-50); + font-size: 0.875rem; + font-weight: 500; + line-height: 1.5rem; + text-transform: uppercase; +} diff --git a/src/components/shareable/overScreens/AlimentationListParam.tsx b/src/components/shareable/overScreens/AlimentationListParam.tsx new file mode 100644 index 000000000..0cdbc3be0 --- /dev/null +++ b/src/components/shareable/overScreens/AlimentationListParam.tsx @@ -0,0 +1,72 @@ +import classNames from 'classnames' +import { useTranslations } from 'next-intl' +import { SetStateAction } from 'preact/compat' +import React, { Dispatch } from 'react' +import useParamContext from 'src/providers/ParamProvider' +import { getNameWithoutSuffix } from 'utils/Equivalent/equivalent' +import { AlimentationCategories, equivalentsByCategory } from 'utils/alimentation' +import EquivalentIcon from 'components/base/EquivalentIcon' +import Button from 'components/base/buttons/Button' +import CheckboxInput from 'components/form/CheckboxInput' +import styles from './AlimentationListParam.module.css' +import listStyles from './TransportListParam.module.css' + +const AlimentationListParam = ({ + equivalents, + setEquivalents, +}: { + equivalents: string[] + setEquivalents: Dispatch> +}) => { + const t = useTranslations('alimentation') + const { language } = useParamContext() + return ( +
    + {equivalentsByCategory[AlimentationCategories.Group].map((category) => ( +
  • +
    +

    {t(category.name)}

    + +
    +
      + {category.equivalents.map((equivalent) => ( +
    • + + setEquivalents( + checked + ? [...equivalents, equivalent.slug] + : equivalents.filter((value) => value !== equivalent.slug) + ) + } + label={ + + + {getNameWithoutSuffix(language, equivalent)} + + } + /> +
    • + ))} +
    +
  • + ))} +
+ ) +} + +export default AlimentationListParam diff --git a/src/components/shareable/overScreens/CustomParam.tsx b/src/components/shareable/overScreens/CustomParam.tsx index 4e53c495b..f73e3ce1e 100644 --- a/src/components/shareable/overScreens/CustomParam.tsx +++ b/src/components/shareable/overScreens/CustomParam.tsx @@ -32,20 +32,26 @@ const configs: Record< values?: string[] } > = { - categoryIntegrate: { + alimentationCategoryIntegrate: { type: 'radio', options: Object.values(AlimentationCategories).map((category) => ({ value: category, label: category, })), }, - category: { + alimentationCategory: { type: 'radio', options: Object.values(AlimentationCategories).map((category) => ({ value: category, label: category, })), }, + customList: { + type: 'boolean', + }, + hideButtons: { + type: 'boolean', + }, transport: { type: 'select-equivalent', equivalents: deplacements }, presentiel: { type: 'number', unit: 'jour', min: 0, max: 7 }, homeOffice: { type: 'number', unit: 'jour', min: 0, max: 7 }, @@ -107,6 +113,7 @@ const CustomParam = ({ visible, setVisible, integration, + disabled, }: { tracking: string slug: string @@ -114,6 +121,7 @@ const CustomParam = ({ visible: boolean setVisible?: (visbile: boolean) => void integration?: boolean + disabled?: boolean }) => { const t = useTranslations('overscreen') if ('setter' in param) { @@ -145,6 +153,7 @@ const CustomParam = ({ selected={param.value as string} setSelected={(value) => param.setter(value as string)} label={t(`${slug}.${option.label}`)} + disabled={disabled} /> ))} diff --git a/src/components/shareable/overScreens/CustomParamsValues.ts b/src/components/shareable/overScreens/CustomParamsValues.ts index 72dac6489..423b1d302 100644 --- a/src/components/shareable/overScreens/CustomParamsValues.ts +++ b/src/components/shareable/overScreens/CustomParamsValues.ts @@ -4,7 +4,10 @@ import { CustomParamValue } from './CustomParam' // Warning: Add values in Integrate.tsx also const values: Record Record> = { alimentation: (params: Params) => ({ - category: { value: params.alimentation.category, setter: params.alimentation.setCategory } as CustomParamValue, + alimentationCategory: { + value: params.alimentation.category, + setter: params.alimentation.setCategory, + } as CustomParamValue, }), chauffage: (params: Params) => ({ m2: { value: params.chauffage.m2, setter: params.chauffage.setM2 } as CustomParamValue, diff --git a/src/components/shareable/overScreens/Integrate.tsx b/src/components/shareable/overScreens/Integrate.tsx index 1b8f860a1..738538c98 100644 --- a/src/components/shareable/overScreens/Integrate.tsx +++ b/src/components/shareable/overScreens/Integrate.tsx @@ -29,9 +29,6 @@ const Integrate = ({ const [theme, setTheme] = useState(allParams.theme) const [language, setLanguage] = useState(allParams.language) - // Alimentation - const [alimentationCategory, setAlimentationCategory] = useState(allParams.alimentation.category) - // Chauffage const [m2, setM2] = useState(allParams.chauffage.m2) useEffect(() => { @@ -72,12 +69,6 @@ const Integrate = ({ const params = useMemo(() => { if (category) { // Warning: Add values in CustomParamsValues.ts also - if (category.slug === 'alimentation') { - return { categoryIntegrate: { value: alimentationCategory, setter: setAlimentationCategory } } as Record< - string, - CustomParamValue - > - } if (category.slug === 'chauffage') { return { m2: { value: m2, setter: setM2 } } as Record } @@ -107,20 +98,7 @@ const Integrate = ({ return getComparateurParams(allParams, path?.includes('etiquette')) } return {} - }, [ - allParams, - category, - path, - m2, - month, - transport, - start, - end, - presentiel, - homeOffice, - toDisplay, - alimentationCategory, - ]) + }, [allParams, category, path, m2, month, transport, start, end, presentiel, homeOffice, toDisplay]) useEffect(() => { if (params) { @@ -136,7 +114,7 @@ const Integrate = ({ return params && visibility ? ( <> -
+ - {``} diff --git a/src/components/shareable/overScreens/TransportListParam.module.css b/src/components/shareable/overScreens/TransportListParam.module.css index 5269be1b1..1dea71e1f 100644 --- a/src/components/shareable/overScreens/TransportListParam.module.css +++ b/src/components/shareable/overScreens/TransportListParam.module.css @@ -1,7 +1,11 @@ +.equivalents, .modes { display: flex; flex-wrap: wrap; gap: 0.5rem; +} + +.modes { margin-top: 1.25rem; } @@ -71,7 +75,7 @@ @media screen and (max-width: 48rem) { width: 100%; - flex: unset + flex: unset; } } @@ -83,4 +87,4 @@ font-size: 0.875rem; font-weight: 500; line-height: 1.25rem; -} \ No newline at end of file +} diff --git a/src/components/shareable/overScreens/Values.tsx b/src/components/shareable/overScreens/Values.tsx index 67941573b..028b9e2ac 100644 --- a/src/components/shareable/overScreens/Values.tsx +++ b/src/components/shareable/overScreens/Values.tsx @@ -6,6 +6,7 @@ import { getName } from 'utils/Equivalent/equivalent' import Resource from 'components/base/Resource' import ComparisonOverscreen from 'components/comparateur/overscreens/ComparisonOverscreen' import EquivalentsOverscreen from 'components/comparateur/overscreens/EquivalentsOverscreen' +import AlimentationIntegrate from './AlimentationIntegrate' import AlimentationData from './Data/AlimentationData' import Integrate from './Integrate' import Share from './Share' @@ -27,7 +28,6 @@ export type OverScreenInfo = { image?: string children: ReactNode fullHeight?: boolean - noBorder?: boolean cancel?: (onClose: () => void) => ReactNode } @@ -198,16 +198,13 @@ export const overScreenCategoryValues: (category: Category) => Record - ) : ( - - ), + children: ( + + ), }, } if (category.slug === 'chauffage') { @@ -335,6 +332,10 @@ export const overScreenCategoryValues: (category: Category) => Record, + }, hypothesis: { image: '/images/icn-next-actions.svg', title: 'next-actions', @@ -432,8 +433,11 @@ export const overScreenCategoryValues: (category: Category) => Record, + }, hypothesis: { - noBorder: true, image: '/images/icn-next-actions.svg', title: 'next-actions', children: ( diff --git a/src/providers/ParamProvider.tsx b/src/providers/ParamProvider.tsx index 0e716b0a1..ce2185e93 100644 --- a/src/providers/ParamProvider.tsx +++ b/src/providers/ParamProvider.tsx @@ -92,6 +92,10 @@ export type Params = { alimentation: { category: AlimentationCategories setCategory: Dispatch> + customList: boolean + setCustomList: Dispatch> + equivalents: string[] + setEquivalents: Dispatch> } livraison: { values: LivraisonValues @@ -232,6 +236,8 @@ export function ParamProvider({ children }: { children: ReactNode }) { } // Alimentation const [category, setCategory] = useState(AlimentationCategories.Group) + const [customList, setCustomList] = useState(false) + const [alimentationEquivalents, setAlimentationEquivalents] = useState([]) // Livraison const [livraisonValues, setLivraisonValues] = useState(livraisonDefaultValues) @@ -345,17 +351,17 @@ export function ParamProvider({ children }: { children: ReactNode }) { setLanguage('fr') } - if (searchParams.get('category')) { - const category = searchParams.get('category') as AlimentationCategories + if (searchParams.get('alimentationCategory')) { + const category = searchParams.get('alimentationCategory') as AlimentationCategories if (Object.values(AlimentationCategories).includes(category)) { setCategory(category) } } - if (searchParams.get('categoryIntegrate')) { - const category = searchParams.get('categoryIntegrate') as AlimentationCategories - if (Object.values(AlimentationCategories).includes(category)) { - setCategory(category) - } + + if (searchParams.get('alimentationEquivalents')) { + const equivalents = searchParams.get('alimentationEquivalents')?.split(',') as string[] + setCustomList(true) + setAlimentationEquivalents(equivalents) } if (searchParams.get('value')) { @@ -529,6 +535,10 @@ export function ParamProvider({ children }: { children: ReactNode }) { alimentation: { category, setCategory, + customList, + setCustomList, + equivalents: alimentationEquivalents, + setEquivalents: setAlimentationEquivalents, }, livraison: { values: livraisonValues, diff --git a/src/providers/locales/fr.json b/src/providers/locales/fr.json index 6f0b64f26..061c7d116 100644 --- a/src/providers/locales/fr.json +++ b/src/providers/locales/fr.json @@ -79,18 +79,24 @@ "comparison": "Changer le mode de transport comparé", "understand": "Comprendre les données", "download": "Télécharger", - "categoryIntegrate": { + "alimentationCategoryIntegrate": { "title": "Liste à afficher par défaut", "group": "Groupe d'aliments", "rayon": "Rayons du magasin", "popularity": "Top 10" }, - "category": { + "alimentationCategory": { "title": "Liste à partager", "group": "Groupe d'aliments", "rayon": "Rayons du magasin", "popularity": "Top 10" }, + "customList": { + "title": "Créer une liste d’aliments personnalisée" + }, + "hideButtons": { + "title": "Afficher les boutons en bas de mon intégration" + }, "m2": { "title": "Afficher une surface personnalisée", "unit": "m²" @@ -538,6 +544,11 @@ "fromagerie": "Fromagerie", "boulangerie": "Boulangerie", "epiceriesalee": "Épicerie salée", - "epiceriesucree": "Épicerie sucrée" + "epiceriesucree": "Épicerie sucrée", + "deselect": "tout désélectionner", + "integrate": { + "customList": "Liste personnalisée", + "hideButtons": "Affichage des boutons" + } } } diff --git a/teste/alimentation.spec.ts b/teste/alimentation.spec.ts new file mode 100644 index 000000000..47a5b37d6 --- /dev/null +++ b/teste/alimentation.spec.ts @@ -0,0 +1,92 @@ +import { expect, test } from '@playwright/test' + +test('Alimentation simulateur', async ({ page }) => { + await page.goto('http://localhost:3000/outils/alimentation') + await expect(page.getByTestId('text-select-category')).toHaveValue('group') + await expect(page.getByTestId('alimentation-category-viandes')).toBeVisible() + await expect(page.getByTestId('alimentation-category-boucherie')).not.toBeVisible() + + await page.getByTestId('alimentation-category-viandes').click() + await expect(page.getByTestId('category-boeuf')).toHaveText('Boeuf26.2 kg CO₂e') + + await page.getByTestId('text-select-category').selectOption('rayon') + await expect(page.getByTestId('alimentation-category-viandes')).not.toBeVisible() + await expect(page.getByTestId('alimentation-category-boucherie')).toBeVisible() + + await page.getByTestId('text-select-category').selectOption('popularity') + await expect(page.getByTestId('alimentation-category-viandes')).not.toBeVisible() + await expect(page.getByTestId('alimentation-category-boucherie')).not.toBeVisible() + await expect(page.getByTestId('category-boeuf')).toHaveText('Boeuf26.2 kg CO₂e') + + await page.getByTestId('header-share-button').first().click() + await expect(page.getByTestId('clipboard-box')).toHaveText( + 'http://localhost:3000/outils/alimentation?alimentationCategory=popularity&language=fr' + ) + await page.getByText('Rayons du magasin', { exact: true }).click() + await expect(page.getByTestId('clipboard-box')).toHaveText( + 'http://localhost:3000/outils/alimentation?alimentationCategory=rayon&language=fr' + ) + + await page.getByTestId('cancel-button').click() + + await page.getByTestId('header-integrate-button').first().click() + await expect(page.getByTestId('clipboard-box')).toHaveText( + '' + ) + await page.getByLabel('Rayons du magasin').check() + await expect(page.getByTestId('clipboard-box')).toHaveText( + '' + ) + + await page.getByText('Créer une liste d’aliments').click() + await expect(page.getByLabel('Rayons du magasin')).toBeDisabled() + + await page.getByTestId('checkbox-alimentation-list-boeuf-checkbox').check() + await page.getByTestId('checkbox-alimentation-list-porc-checkbox').check() + await page.getByTestId('checkbox-alimentation-list-crevettes-checkbox').check() + await page.locator('li').filter({ hasText: 'Poissons et fruits de mertout' }).getByRole('button').click() + await expect(page.getByTestId('clipboard-box')).toHaveText( + '' + ) + + await page.getByTestId('checkbox-custom-param-hideButtons-checkbox').check() + await expect(page.getByTestId('clipboard-box')).toContainText( + '' + ) +}) + +test('Alimentation simulateur params', async ({ page }) => { + await page.goto('http://localhost:3000/outils/alimentation?alimentationCategory=popularity') + await expect(page.getByTestId('text-select-category')).toBeVisible() + await expect(page.getByTestId('alimentation-category-viandes')).not.toBeVisible() + await expect(page.getByTestId('alimentation-category-boucherie')).not.toBeVisible() + await expect(page.getByTestId('category-boeuf')).toHaveText('Boeuf26.2 kg CO₂e') + await expect(page.getByRole('button', { name: 'Comprendre les données' })).toBeVisible() + await expect(page.getByRole('button', { name: 'Aller plus loin' })).toBeVisible() + await expect(page.getByTestId('header-share-button')).toHaveCount(2) + await expect(page.getByTestId('header-integrate-button')).toHaveCount(2) + + await page.goto( + 'http://localhost:3000/outils/alimentation?alimentationEquivalents=boeuf,porc&alimentationCategory=rayon' + ) + await expect(page.getByTestId('text-select-category')).not.toBeVisible() + await expect(page.getByTestId('alimentation-category-viandes')).not.toBeVisible() + await expect(page.getByTestId('alimentation-category-boucherie')).not.toBeVisible() + await expect(page.getByTestId('category-boeuf')).toHaveText('Boeuf26.2 kg CO₂e') + await expect(page.getByTestId('category-porc')).toHaveText('Porc9.66 kg CO₂e') + await expect(page.getByRole('button', { name: 'Comprendre les données' })).toBeVisible() + await expect(page.getByRole('button', { name: 'Aller plus loin' })).toBeVisible() + await expect(page.getByTestId('header-share-button')).toHaveCount(2) + await expect(page.getByTestId('header-integrate-button')).toHaveCount(2) + + await page.goto('http://localhost:3000/outils/alimentation?alimentationEquivalents=boeuf,porc&hideButtons=true') + await expect(page.getByTestId('text-select-category')).not.toBeVisible() + await expect(page.getByTestId('alimentation-category-viandes')).not.toBeVisible() + await expect(page.getByTestId('alimentation-category-boucherie')).not.toBeVisible() + await expect(page.getByTestId('category-boeuf')).toHaveText('Boeuf26.2 kg CO₂e') + await expect(page.getByTestId('category-porc')).toHaveText('Porc9.66 kg CO₂e') + await expect(page.getByRole('button', { name: 'Comprendre les données' })).not.toBeVisible() + await expect(page.getByRole('button', { name: 'Aller plus loin' })).not.toBeVisible() + await expect(page.getByTestId('header-share-button')).not.toBeVisible() + await expect(page.getByTestId('header-integrate-button')).not.toBeVisible() +}) diff --git a/teste/usage_numerique.spec.ts b/teste/usage_numerique.spec.ts index 7e26d5bca..f8a9502ba 100644 --- a/teste/usage_numerique.spec.ts +++ b/teste/usage_numerique.spec.ts @@ -14,17 +14,13 @@ test('Load default values', async ({ page }) => { "http://localhost:3000/usagenumerique?emails=744&email . appareil='tablette'&email . transmission . émetteur . réseau='mobile FR'&email . taille=1&streaming . durée=2100&streaming . appareil='ordinateur portable'&streaming . transmission . réseau='mobile FR'&streaming . qualité='SD'&visio . durée=3100&visio . appareil='ordinateur et écran'&visio . emplacements=1&visio . transmission . réseau='mobile FR'&visio . qualité='audio'" ) await expect(page.getByTestId('usagenumerique-generated-value')).toHaveText('1.94') - await expect(page.getByTestId('category-email')).toHaveText( - "1 an d'email - 38688 emails43.9 kg CO₂eusage : 0% et construction : 100%" - ) + await expect(page.getByTestId('category-email')).toHaveText("1 an d'email - 38688 emails43.9 kg CO₂e") await page.goto( "http://localhost:3000/usagenumerique?emails=744&email . appareil='tablette'&email . transmission . émetteur . réseau='mobile FR'&email . taille=1&streaming . durée=2100&streaming . appareil='ordinateur portable'&streaming . transmission . réseau='mobile FR'&streaming . qualité='SD'&visio . durée=3100&visio . appareil='ordinateur et écran'&visio . emplacements=1&visio . transmission . réseau='mobile FR'&visio . qualité='audio'&display=graphic" ) await expect(page.getByTestId('usagenumerique-generated-value')).not.toBeVisible() - await expect(page.getByTestId('category-email')).toHaveText( - "1 an d'email - 38688 emails43.9 kg CO₂eusage : 0% et construction : 100% " - ) + await expect(page.getByTestId('category-email')).toHaveText("1 an d'email - 38688 emails43.9 kg CO₂e ") await page.goto( "http://localhost:3000/usagenumerique?emails=744&email . appareil='tablette'&email . transmission . émetteur . réseau='mobile FR'&email . taille=1&streaming . durée=2100&streaming . appareil='ordinateur portable'&streaming . transmission . réseau='mobile FR'&streaming . qualité='SD'&visio . durée=3100&visio . appareil='ordinateur et écran'&visio . emplacements=1&visio . transmission . réseau='mobile FR'&visio . qualité='audio'&display=simulator" diff --git a/teste/usagenumerique.ts b/teste/usagenumerique.ts index 262d283f8..97f9c82a1 100644 --- a/teste/usagenumerique.ts +++ b/teste/usagenumerique.ts @@ -42,16 +42,12 @@ export const usageNumeriqueTest = async (page: Page | FrameLocator, prod?: boole await expect(page.getByTestId('usagenumerique-generated-value')).toHaveText('2.74') await expect(page.getByTestId('category-visioconference')).toHaveText( - '1 an de visioconférences - 468 heures7.07 kg CO₂eusage : 0% et construction : 100% ' + '1 an de visioconférences - 468 heures7.07 kg CO₂e' ) await expect(page.getByTestId('category-visioconference-value')).toHaveText('7.07') - await expect(page.getByTestId('category-email')).toHaveText( - "1 an d'email - 7800 emails44.6 kg CO₂eusage : 0% et construction : 100% " - ) + await expect(page.getByTestId('category-email')).toHaveText("1 an d'email - 7800 emails44.6 kg CO₂") await expect(page.getByTestId('category-email-value')).toHaveText('44.6') - await expect(page.getByTestId('category-streamingvideo')).toHaveText( - '1 an de streaming - 520 heures90.7 kg CO₂eusage : 0% et construction : 100% ' - ) + await expect(page.getByTestId('category-streamingvideo')).toHaveText('1 an de streaming - 520 heures90.7 kg CO₂') await expect(page.getByTestId('category-streamingvideo-value')).toHaveText('90.7') await page.getByTestId('header-share-button').click()