diff --git a/package.json b/package.json index 5d1773107..1eac92e6d 100644 --- a/package.json +++ b/package.json @@ -132,6 +132,7 @@ "@storybook/react-vite": "^8.4.7", "@storybook/test": "^8.4.7", "@tanstack/router-plugin": "1.95.1", + "@testing-library/dom": "10.4.0", "@testing-library/jest-dom": "6.6.3", "@testing-library/react": "16.1.0", "@testing-library/user-event": "14.5.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d26d9649..de1411916 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -243,6 +243,9 @@ importers: '@tanstack/router-plugin': specifier: 1.95.1 version: 1.95.1(@tanstack/react-router@1.95.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(terser@5.37.0)(tsx@4.19.2))(webpack@5.97.1(esbuild@0.24.2)) + '@testing-library/dom': + specifier: 10.4.0 + version: 10.4.0 '@testing-library/jest-dom': specifier: 6.6.3 version: 6.6.3 diff --git a/src/locales/en/map.json b/src/locales/en/map.json index b36ebc3d8..19f4519df 100644 --- a/src/locales/en/map.json +++ b/src/locales/en/map.json @@ -20,5 +20,6 @@ "Select a country": "Select a country", "VIEW_ITEM_BUILDER_TOOLTIP": "View item in Graasp Builder", "VIEW_ITEM_PLAYER_TOOLTIP": "View item in Graasp Player", - "FUNCTIONALITIES_REDUCED_FOR_LOGGED_OUT_MESSAGE": "Some functionalities are disabled for logged out users." + "FUNCTIONALITIES_REDUCED_FOR_LOGGED_OUT_MESSAGE": "Some functionalities are disabled for logged out users.", + "Add a new item at this location": "Add a new item at this location" } diff --git a/src/modules/builder/components/main/NotificationButton.tsx b/src/modules/builder/components/main/NotificationButton.tsx index 354e93fc7..0b2532c55 100644 --- a/src/modules/builder/components/main/NotificationButton.tsx +++ b/src/modules/builder/components/main/NotificationButton.tsx @@ -1,4 +1,5 @@ -// import { MentionButton } from '@graasp/chatbox'; +import { MentionButton } from '@graasp/chatbox'; + import { hooks, mutations } from '@/config/queryClient'; export function NotificationButton(): JSX.Element | null { @@ -27,13 +28,13 @@ export function NotificationButton(): JSX.Element | null { const clearAllMentionsFunction = () => clearAllMentionsMutate(); return ( - // + ); } diff --git a/src/modules/builder/map/components/GeolocationPicker/GeolocationPicker.stories.tsx b/src/modules/builder/map/components/GeolocationPicker/GeolocationPicker.stories.tsx index efbf09b02..7c637b3d1 100644 --- a/src/modules/builder/map/components/GeolocationPicker/GeolocationPicker.stories.tsx +++ b/src/modules/builder/map/components/GeolocationPicker/GeolocationPicker.stories.tsx @@ -1,12 +1,11 @@ import { TextField } from '@mui/material'; import type { Meta, StoryObj } from '@storybook/react'; -import { userEvent, within } from '@storybook/testing-library'; +import { userEvent, within } from '@storybook/test'; import type { BoundFunctions } from '@testing-library/dom'; -// eslint-disable-next-line import/no-extraneous-dependencies import { queries } from '@testing-library/dom'; -import { MOCK_USE_SUGGESTIONS } from '../../../.storybook/fixtures'; +import { MOCK_USE_SUGGESTIONS } from '../../fixture'; import GeolocationPicker from './GeolocationPicker'; const meta = { @@ -79,8 +78,8 @@ export const Background = { }, play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); - await expect(canvas.getByLabelText('Geolocation')).toHaveTextContent( - args.initialValue!, + expect(canvas.getByLabelText('Geolocation')).toHaveTextContent( + 'initial value', ); await checkSuggestions(canvas); diff --git a/src/modules/builder/map/components/Map.stories.tsx b/src/modules/builder/map/components/Map.stories.tsx index 0afd02f37..ae0a66949 100644 --- a/src/modules/builder/map/components/Map.stories.tsx +++ b/src/modules/builder/map/components/Map.stories.tsx @@ -7,21 +7,9 @@ import { import type { Meta, StoryObj } from '@storybook/react'; import { fn } from '@storybook/test'; +import { MOCK_USE_SUGGESTIONS } from '../fixture'; import MapComponent from './Map'; -const MOCK_USE_SUGGESTIONS = ({ address }: { address: string }) => { - if (address) { - return { - data: [ - { addressLabel: 'suggestion 1' }, - { addressLabel: 'suggestion 2' }, - { addressLabel: 'suggestion 3' }, - ], - }; - } - return { data: undefined }; -}; - const meta = { title: 'Map', component: MapComponent, diff --git a/src/modules/builder/map/fixture.ts b/src/modules/builder/map/fixture.ts new file mode 100644 index 000000000..61b804a5f --- /dev/null +++ b/src/modules/builder/map/fixture.ts @@ -0,0 +1,12 @@ +export const MOCK_USE_SUGGESTIONS = ({ address }: { address: string }) => { + if (address) { + return { + data: [ + { addressLabel: 'suggestion 1' }, + { addressLabel: 'suggestion 2' }, + { addressLabel: 'suggestion 3' }, + ], + }; + } + return { data: undefined }; +}; diff --git a/src/ui/Authorization/PreventGuestWrapper.stories.tsx b/src/ui/Authorization/PreventGuestWrapper.stories.tsx index 8eb64889a..874d09a2b 100644 --- a/src/ui/Authorization/PreventGuestWrapper.stories.tsx +++ b/src/ui/Authorization/PreventGuestWrapper.stories.tsx @@ -1,9 +1,9 @@ +import { AccountType, CompleteGuest, CompleteMember } from '@graasp/sdk'; + import type { Meta, StoryObj } from '@storybook/react'; import { expect, within } from '@storybook/test'; -import { AccountType, CompleteGuest, CompleteMember } from '@graasp/sdk'; - -import BuildIcon from '@/icons/BuildIcon.js'; +import BuildIcon from '@/ui/icons/BuildIcon.js'; import PreventGuestWrapper from './PreventGuestWrapper.js'; @@ -17,7 +17,7 @@ const meta = { errorText: 'An error occured.', text: 'You are currently using Graasp with a guest account. In order to use all features of Graasp, you have to log out and create a Graasp account.', children: ( -
+
diff --git a/src/ui/Authorization/Redirect.stories.tsx b/src/ui/Authorization/Redirect.stories.tsx index 606beca21..92c540890 100644 --- a/src/ui/Authorization/Redirect.stories.tsx +++ b/src/ui/Authorization/Redirect.stories.tsx @@ -1,8 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; import { expect, within } from '@storybook/test'; -import { BrowserRouter } from 'react-router-dom'; - import SignedInWrapper from './SignedInWrapper.js'; // this story is separated from the others @@ -19,15 +17,10 @@ const meta: Meta = { }, }, render: () => ( - +
), - decorators: [ - (story) => { - return {story()}; - }, - ], }; export default meta; diff --git a/src/ui/Authorization/SignedInWrapper.stories.tsx b/src/ui/Authorization/SignedInWrapper.stories.tsx index a83435bef..02110f770 100644 --- a/src/ui/Authorization/SignedInWrapper.stories.tsx +++ b/src/ui/Authorization/SignedInWrapper.stories.tsx @@ -1,9 +1,9 @@ +import { CompleteMember } from '@graasp/sdk'; + import type { Meta, StoryObj } from '@storybook/react'; import { expect, within } from '@storybook/test'; -import { CompleteMember } from '@graasp/sdk'; - -import BuildIcon from '@/icons/BuildIcon.js'; +import BuildIcon from '@/ui/icons/BuildIcon.js'; import SignedInWrapper from './SignedInWrapper.js'; @@ -19,7 +19,7 @@ const meta: Meta = { args: { redirectionLink, children: ( -
+
diff --git a/src/ui/Card/Card.stories.tsx b/src/ui/Card/Card.stories.tsx index 180ca5849..a28e7533b 100644 --- a/src/ui/Card/Card.stories.tsx +++ b/src/ui/Card/Card.stories.tsx @@ -1,11 +1,9 @@ +import { Box, IconButton, Stack } from '@mui/material'; + import type { Meta, StoryObj } from '@storybook/react'; import { fn } from '@storybook/test'; import { Grip, Snowflake } from 'lucide-react'; -import { Box, IconButton, Stack } from '@mui/material'; - -import { BrowserRouter } from 'react-router-dom'; - import ItemBadges from '../ItemBadges/ItemBadges.js'; import { TABLE_CATEGORIES } from '../utils/storybook.js'; import Card from './Card.js'; @@ -40,10 +38,10 @@ export const Example: Story = { creator: 'graasp', footer: ( @@ -93,11 +91,6 @@ export const Dense: Story = { ), }, - decorators: [ - (story) => { - return {story()}; - }, - ], } satisfies Story; export const FullWidth = { @@ -116,10 +109,10 @@ export const FullWidth = { footer: ( @@ -168,10 +161,10 @@ export const TallCard: Story = { height: 300, footer: ( @@ -206,11 +199,6 @@ export const DenseMobile: Story = { alt: 'graasp', footer: 'myfooter', }, - decorators: [ - (story) => { - return {story()}; - }, - ], } satisfies Story; export const Selected: Story = { @@ -227,9 +215,4 @@ export const Selected: Story = { className: 'class-card', onThumbnailClick: fn(), }, - decorators: [ - (story) => { - return {story()}; - }, - ], } satisfies Story; diff --git a/src/ui/Card/Cards.stories.tsx b/src/ui/Card/Cards.stories.tsx index ca2889bdd..03a358e78 100644 --- a/src/ui/Card/Cards.stories.tsx +++ b/src/ui/Card/Cards.stories.tsx @@ -1,11 +1,11 @@ -import { Meta, StoryObj, composeStories } from '@storybook/react'; -import { v4 } from 'uuid'; - import { Grid2 as Grid } from '@mui/material'; import { PackedFolderItemFactory } from '@graasp/sdk'; -import ItemBadges from '@/ItemBadges/ItemBadges.js'; +import { Meta, StoryObj, composeStories } from '@storybook/react'; +import { v4 } from 'uuid'; + +import ItemBadges from '@/ui/ItemBadges/ItemBadges.js'; import * as CardStories from './Card.stories.js'; diff --git a/src/ui/Card/FolderCard.stories.tsx b/src/ui/Card/FolderCard.stories.tsx index 6f8802db0..f62cf1af3 100644 --- a/src/ui/Card/FolderCard.stories.tsx +++ b/src/ui/Card/FolderCard.stories.tsx @@ -1,7 +1,5 @@ import { Meta, StoryObj, composeStories } from '@storybook/react'; -import { BrowserRouter } from 'react-router-dom'; - import TextDisplay from '../TextDisplay/TextDisplay.js'; import * as TextDisplayStories from '../TextDisplay/TextDisplay.stories.js'; import FolderCard from './FolderCard.js'; @@ -19,11 +17,6 @@ const meta = { }, }, }, - decorators: [ - (story) => { - return {story()}; - }, - ], args: { name: 'Example folder', description: 'Optional description', @@ -55,7 +48,7 @@ export const LongHtmlDescription = { args: { thumbnail: undefined, description: ( - + ), }, } satisfies Story; diff --git a/src/ui/Card/FolderCard.tsx b/src/ui/Card/FolderCard.tsx index e0d7db364..b3f285452 100644 --- a/src/ui/Card/FolderCard.tsx +++ b/src/ui/Card/FolderCard.tsx @@ -1,5 +1,3 @@ -import { ChevronRight } from 'lucide-react'; - import { Card, CardActionArea, @@ -8,10 +6,11 @@ import { useTheme, } from '@mui/material'; -import { Link, LinkProps } from 'react-router-dom'; - import { ItemType } from '@graasp/sdk'; +import { Link } from '@tanstack/react-router'; +import { ChevronRight } from 'lucide-react'; + import CardThumbnail from './CardThumbnail.js'; // FIX: use the same constant @@ -22,10 +21,7 @@ type Props = { name: string; description?: string | null | JSX.Element; thumbnail?: string; - /** - * React Router Link target - */ - to: LinkProps['to']; + to: string; }; const FolderCard = ({ id, @@ -49,7 +45,7 @@ const FolderCard = ({ }} > - + { - return {story()}; - }, - ], args: { title: 'Default link name', url: 'https://graasp.org', diff --git a/src/ui/CookiesBanner/CookiesBanner.stories.tsx b/src/ui/CookiesBanner/CookiesBanner.stories.tsx deleted file mode 100644 index fd8fe1b88..000000000 --- a/src/ui/CookiesBanner/CookiesBanner.stories.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import CookiesBanner from './CookiesBanner.js'; - -const cookieName = 'cookieName'; - -const meta: Meta = { - title: 'Common/CookiesBanner', - component: CookiesBanner, - parameters: { - layout: 'fullscreen', - docs: { - source: { - type: 'dynamic', - excludeDecorators: true, - }, - }, - }, - decorators: [ - (story) => { - // delete cookie on mount - document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`; - return <>{story()}; - }, - ], - render: (args) => , -}; -export default meta; - -type Story = StoryObj; - -export const Banner: Story = { - args: {}, -}; - -export const Mobile = { - args: { - declineButtonText: 'Rejeter les cookies non-essentiels', - acceptText: 'Accepter tous les cookies', - }, - parameters: { - viewport: { - defaultViewport: 'mobile2', - }, - }, -} satisfies Story; diff --git a/src/ui/CookiesBanner/CookiesBanner.tsx b/src/ui/CookiesBanner/CookiesBanner.tsx deleted file mode 100644 index d906576bb..000000000 --- a/src/ui/CookiesBanner/CookiesBanner.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { Box, Button, Typography, styled } from '@mui/material'; - -import { CookieConsent } from 'react-cookie-consent'; - -// used to keep track of the decline button internally -const DECLINE_BUTTON_ID = 'decline-button-id'; - -// string classnames used to pass to CookieConsent -const CONTAINER_CLASS_NAME = 'cookie-container'; -const BUTTON_CLASS_NAME = 'cookie-button'; -const BUTTON_CONTAINER_CLASS_NAME = 'cookie-button-container'; -const CONTENT_CLASS_NAME = 'cookie-content'; - -const StyledCookieConsent = styled(Box)(({ theme }) => ({ - zIndex: theme.zIndex.modal, - position: 'fixed', - bottom: '0px', - left: '0px', - right: '0px', - width: '100%', - [theme.breakpoints.up('sm')]: { - bottom: '10px', - right: '10px', - left: 'unset', - maxWidth: '500px', - borderRadius: theme.spacing(2), - overflow: 'hidden', - outline: '1px solid #f2f2f2', - boxShadow: theme.shadows[6], - [`& .${BUTTON_CONTAINER_CLASS_NAME}`]: { - width: '100%', - flexDirection: 'row', - justifyContent: 'space-between', - }, - }, - - [`& .${BUTTON_CONTAINER_CLASS_NAME}`]: { - display: 'flex', - width: '100%', - flexDirection: 'column-reverse', - justifyContent: 'space-between', - gap: theme.spacing(1), - [theme.breakpoints.up('sm')]: { - flexDirection: 'row', - }, - }, - - [`& .${CONTAINER_CLASS_NAME}`]: { - padding: theme.spacing(2), - display: 'flex', - flexDirection: 'column', - gap: theme.spacing(2), - - zIndex: `${(theme?.zIndex?.drawer ?? 0) + 1}`, - backgroundColor: 'rgb(224,235,255,70%)', - backdropFilter: 'blur(15px) saturate(30%) ', - color: `${theme.palette.text.primary}`, - }, -})); - -type CookieButtonProps = { - id: string; - onClick: () => void; -}; - -const CookieButton = (props: CookieButtonProps): JSX.Element => { - const { id } = props; - const isDeclinedButton = id === DECLINE_BUTTON_ID; - return ( -