diff options
| -rw-r--r-- | src/i18n/en.json | 50 | ||||
| -rw-r--r-- | src/i18n/fr.json | 50 | ||||
| -rw-r--r-- | src/pages/recherche/index.tsx | 365 | ||||
| -rw-r--r-- | src/styles/pages/blog.module.scss | 4 | ||||
| -rw-r--r-- | src/utils/hooks/index.ts | 1 | ||||
| -rw-r--r-- | src/utils/hooks/use-data-from-api.tsx | 21 | ||||
| -rw-r--r-- | tests/cypress/e2e/pages/search.cy.ts | 28 |
7 files changed, 305 insertions, 214 deletions
diff --git a/src/i18n/en.json b/src/i18n/en.json index b1768a8..67880a2 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -167,6 +167,10 @@ "defaultMessage": "Sorry, it seems that the page your are looking for does not exist. If you think this path should work, feel free to <link>contact me</link> with the necessary information so that I can fix the problem.", "description": "Error404Page: page body" }, + "A0TsHP": { + "defaultMessage": "Please use the form below to start searching:", + "description": "SearchPage: search for message" + }, "A8hGaK": { "defaultMessage": "Comment:", "description": "CommentForm: comment label" @@ -219,9 +223,9 @@ "defaultMessage": "Thematics", "description": "SearchPage: thematics list widget title" }, - "EeCqAE": { - "defaultMessage": "Loading the search results...", - "description": "SearchPage: loading search results message" + "E+ROR5": { + "defaultMessage": "No results found. Would you like to try a new search?", + "description": "SearchPage: no results" }, "Es52wh": { "defaultMessage": "Blog", @@ -307,6 +311,10 @@ "defaultMessage": "CV", "description": "SiteNavbar: main nav - cv link" }, + "N+3eau": { + "defaultMessage": "Search results for \"{query}\"", + "description": "SearchPage: SEO - Page title" + }, "N804XO": { "defaultMessage": "Topics", "description": "SearchPage: topics list widget title" @@ -319,6 +327,10 @@ "defaultMessage": "{commentsCount, plural, =0 {No comments} one {# comment} other {# comments}}<a11y> about {title}</a11y>", "description": "PostPreviewMeta: comments count" }, + "NqVQYo": { + "defaultMessage": "Search - {websiteName}", + "description": "SearchPage: SEO - Page title" + }, "Nx8Jo5": { "defaultMessage": "Github profile", "description": "ProjectsPage: Github profile link" @@ -371,6 +383,10 @@ "defaultMessage": "Main navigation", "description": "SiteNavbar: main nav accessible name" }, + "QRDdye": { + "defaultMessage": "Search results for {query} - {websiteName}", + "description": "SearchPage: SEO - Page title" + }, "Qa9twM": { "defaultMessage": "Reply", "description": "CommentsList: reply button" @@ -411,10 +427,6 @@ "defaultMessage": "Send", "description": "ContactForm: send button" }, - "VkfO7t": { - "defaultMessage": "Query must be longer than one character.", - "description": "NoResults: invalid query message" - }, "Vrw5/h": { "defaultMessage": "{website} logo", "description": "SiteBranding: logo title" @@ -447,10 +459,6 @@ "defaultMessage": "Leave a comment", "description": "PageComments: the section title of the comment form" }, - "YV//MH": { - "defaultMessage": "No results found.", - "description": "SearchPage: no results" - }, "Ygea7s": { "defaultMessage": "Light theme", "description": "ThemeToggle: light theme label" @@ -471,10 +479,6 @@ "defaultMessage": "You can't load more articles without Javascript, please use the pagination instead.", "description": "BlogPage: pagination no script message" }, - "ZNBhDP": { - "defaultMessage": "Search results for {query}", - "description": "SearchPage: SEO - Page title" - }, "ZcFroC": { "defaultMessage": "Thanks, your comment was successfully sent.", "description": "PageComments: comment form success message" @@ -523,6 +527,10 @@ "defaultMessage": "Blog: development, open source - Page {number} - {websiteName}", "description": "BlogPage: SEO - Page title" }, + "e3ppRI": { + "defaultMessage": "Query must be longer than one character.", + "description": "SearchPage: invalid query message" + }, "eys2uX": { "defaultMessage": "Table of Contents", "description": "PageLayout: table of contents title" @@ -647,6 +655,10 @@ "defaultMessage": "Discover search results for {query} on {websiteName}.", "description": "SearchPage: SEO - Meta description" }, + "qFqWQH": { + "defaultMessage": "Thematics are loading...", + "description": "SearchPage: loading thematics message" + }, "rVoW4G": { "defaultMessage": "Thematics are loading...", "description": "ThematicPage: loading thematics message" @@ -675,6 +687,10 @@ "defaultMessage": "Partial", "description": "AckeeToggle: partial option name" }, + "tLflgC": { + "defaultMessage": "Topics are loading...", + "description": "SearchPage: loading topics message" + }, "tsWh8x": { "defaultMessage": "Light theme", "description": "PrismThemeToggle: light theme label" @@ -699,10 +715,6 @@ "defaultMessage": "On", "description": "MotionToggle: activate reduce motion label" }, - "vtDLzG": { - "defaultMessage": "Would you like to try a new search?", - "description": "SearchPage: try a new search message" - }, "w+BpPg": { "defaultMessage": "No comments yet. <link>Be the first!</link>", "description": "PageComments: no comments text" diff --git a/src/i18n/fr.json b/src/i18n/fr.json index 50c9ca7..39ae75c 100644 --- a/src/i18n/fr.json +++ b/src/i18n/fr.json @@ -167,6 +167,10 @@ "defaultMessage": "Désolé, il semble que la page demandée n’existe pas. Si vous pensez que le chemin devrait exister, n’hésitez pas à <link>me contacter</link> avec les informations nécessaires pour que je puisse corriger le problème.", "description": "Error404Page: page body" }, + "A0TsHP": { + "defaultMessage": "Veuillez utiliser le formulaire ci-dessous pour commencer une recherche :", + "description": "SearchPage: search for message" + }, "A8hGaK": { "defaultMessage": "Commentaire :", "description": "CommentForm: comment label" @@ -219,9 +223,9 @@ "defaultMessage": "Thématiques", "description": "SearchPage: thematics list widget title" }, - "EeCqAE": { - "defaultMessage": "Chargement des résultats…", - "description": "SearchPage: loading search results message" + "E+ROR5": { + "defaultMessage": "Aucun résultat. Souhaitez-vous tenter une nouvelle rechercher ?", + "description": "SearchPage: no results" }, "Es52wh": { "defaultMessage": "Blog", @@ -307,6 +311,10 @@ "defaultMessage": "CV", "description": "SiteNavbar: main nav - cv link" }, + "N+3eau": { + "defaultMessage": "Résultats de la recherche pour « {query} »", + "description": "SearchPage: SEO - Page title" + }, "N804XO": { "defaultMessage": "Sujets", "description": "SearchPage: topics list widget title" @@ -319,6 +327,10 @@ "defaultMessage": "{commentsCount, plural, =0 {0 commentaire} one {# commentaire} other {# commentaires}}<a11y> à propos de {title}</a11y>", "description": "PostPreviewMeta: comments count" }, + "NqVQYo": { + "defaultMessage": "Recherche - {websiteName}", + "description": "SearchPage: SEO - Page title" + }, "Nx8Jo5": { "defaultMessage": "Profil Github", "description": "ProjectsPage: Github profile link" @@ -371,6 +383,10 @@ "defaultMessage": "Navigation principale", "description": "SiteNavbar: main nav accessible name" }, + "QRDdye": { + "defaultMessage": "Résultats de la recherche pour {query} - {websiteName}", + "description": "SearchPage: SEO - Page title" + }, "Qa9twM": { "defaultMessage": "Répondre", "description": "CommentsList: reply button" @@ -411,10 +427,6 @@ "defaultMessage": "Envoyer", "description": "ContactForm: send button" }, - "VkfO7t": { - "defaultMessage": "Les mots-clés doivent être plus longs qu'un caractère.", - "description": "NoResults: invalid query message" - }, "Vrw5/h": { "defaultMessage": "Logo d’{website}", "description": "SiteBranding: logo title" @@ -447,10 +459,6 @@ "defaultMessage": "Laisser un commentaire", "description": "PageComments: the section title of the comment form" }, - "YV//MH": { - "defaultMessage": "Aucun résultat.", - "description": "SearchPage: no results" - }, "Ygea7s": { "defaultMessage": "Thème clair", "description": "ThemeToggle: light theme label" @@ -471,10 +479,6 @@ "defaultMessage": "Vous ne pouvez pas charger plus d’articles sans Javascript, veuillez utiliser la pagination.", "description": "BlogPage: pagination no script message" }, - "ZNBhDP": { - "defaultMessage": "Résultats de la recherche pour {query}", - "description": "SearchPage: SEO - Page title" - }, "ZcFroC": { "defaultMessage": "Merci, votre commentaire a été envoyé avec succès.", "description": "PageComments: comment form success message" @@ -523,6 +527,10 @@ "defaultMessage": "Blog: développement, libre et open-source - Page {number} - {websiteName}", "description": "BlogPage: SEO - Page title" }, + "e3ppRI": { + "defaultMessage": "Les mots-clés doivent être plus longs qu'un caractère.", + "description": "SearchPage: invalid query message" + }, "eys2uX": { "defaultMessage": "Table des matières", "description": "PageLayout: table of contents title" @@ -647,6 +655,10 @@ "defaultMessage": "Découvrez les résultats de recherche pour {query} sur {websiteName}.", "description": "SearchPage: SEO - Meta description" }, + "qFqWQH": { + "defaultMessage": "Les thématiques sont en cours de chargement…", + "description": "SearchPage: loading thematics message" + }, "rVoW4G": { "defaultMessage": "Les thématiques sont en cours de chargement…", "description": "ThematicPage: loading thematics message" @@ -675,6 +687,10 @@ "defaultMessage": "Partiel", "description": "AckeeToggle: partial option name" }, + "tLflgC": { + "defaultMessage": "Les sujets sont en cours de chargement…", + "description": "SearchPage: loading topics message" + }, "tsWh8x": { "defaultMessage": "Thème clair", "description": "PrismThemeToggle: light theme label" @@ -699,10 +715,6 @@ "defaultMessage": "Marche", "description": "MotionToggle: activate reduce motion label" }, - "vtDLzG": { - "defaultMessage": "Souhaitez-vous essayer une nouvelle recherche ?", - "description": "SearchPage: try a new search message" - }, "w+BpPg": { "defaultMessage": "Aucun commentaire pour le moment. <link>Soyez le premier !</link>", "description": "PageComments: no comments text" diff --git a/src/pages/recherche/index.tsx b/src/pages/recherche/index.tsx index 2bcb1c0..9eaecba 100644 --- a/src/pages/recherche/index.tsx +++ b/src/pages/recherche/index.tsx @@ -22,7 +22,6 @@ import { import { convertWPThematicPreviewToPageLink, convertWPTopicPreviewToPageLink, - fetchPostsCount, fetchThematicsCount, fetchThematicsList, fetchTopicsCount, @@ -30,6 +29,7 @@ import { } from '../../services/graphql'; import styles from '../../styles/pages/blog.module.scss'; import type { + GraphQLConnection, NextPageWithLayout, WPThematicPreview, WPTopicPreview, @@ -47,78 +47,70 @@ import { loadTranslation, type Messages } from '../../utils/helpers/server'; import { useArticlesList, useBreadcrumb, - useDataFromAPI, + useThematicsList, + useTopicsList, } from '../../utils/hooks'; +const NoResults = () => { + const intl = useIntl(); + const router = useRouter(); + + const searchSubmitHandler: SearchFormSubmit = useCallback( + async ({ query: searchQuery }) => { + if (!searchQuery) + return { + messages: { + error: intl.formatMessage({ + defaultMessage: 'Query must be longer than one character.', + description: 'SearchPage: invalid query message', + id: 'e3ppRI', + }), + }, + validator: (value) => value.query.length > 1, + }; + + await router.push({ pathname: ROUTES.SEARCH, query: { s: searchQuery } }); + + return undefined; + }, + [intl, router] + ); + + return ( + <div className={styles['no-results']}> + <p> + {router.query.s + ? intl.formatMessage({ + defaultMessage: + 'No results found. Would you like to try a new search?', + description: 'SearchPage: no results', + id: 'E+ROR5', + }) + : intl.formatMessage({ + defaultMessage: 'Please use the form below to start searching:', + description: 'SearchPage: search for message', + id: 'A0TsHP', + })} + </p> + <SearchForm isLabelHidden onSubmit={searchSubmitHandler} /> + </div> + ); +}; + type SearchPageProps = { - thematicsList: WPThematicPreview[]; - topicsList: WPTopicPreview[]; + data: { + thematics: GraphQLConnection<WPThematicPreview>; + topics: GraphQLConnection<WPTopicPreview>; + }; translation: Messages; }; /** * Search page. */ -const SearchPage: NextPageWithLayout<SearchPageProps> = ({ - thematicsList, - topicsList, -}) => { +const SearchPage: NextPageWithLayout<SearchPageProps> = ({ data }) => { const intl = useIntl(); - const { asPath, query, push: routerPush } = useRouter(); - const title = query.s - ? intl.formatMessage( - { - defaultMessage: 'Search results for {query}', - description: 'SearchPage: SEO - Page title', - id: 'ZNBhDP', - }, - { query: query.s as string } - ) - : intl.formatMessage({ - defaultMessage: 'Search', - description: 'SearchPage: SEO - Page title', - id: 'WDwNDl', - }); - const { items: breadcrumbItems, schema: breadcrumbSchema } = useBreadcrumb({ - title, - url: ROUTES.SEARCH, - }); - - const page = { - title: `${title} - ${CONFIG.name}`, - url: `${CONFIG.url}${asPath}`, - }; - const pageDescription = query.s - ? intl.formatMessage( - { - defaultMessage: - 'Discover search results for {query} on {websiteName}.', - description: 'SearchPage: SEO - Meta description', - id: 'pg26sn', - }, - { query: query.s as string, websiteName: CONFIG.name } - ) - : intl.formatMessage( - { - defaultMessage: 'Search for a post on {websiteName}.', - description: 'SearchPage: SEO - Meta description', - id: 'npisb3', - }, - { websiteName: CONFIG.name } - ); - const webpageSchema = getWebPageSchema({ - description: pageDescription, - locale: CONFIG.locales.defaultLocale, - slug: asPath, - title: page.title, - }); - const blogSchema = getBlogSchema({ - isSinglePage: false, - locale: CONFIG.locales.defaultLocale, - slug: asPath, - }); - const schemaJsonLd = getSchemaJson([webpageSchema, blogSchema]); - + const { asPath, query } = useRouter(); const { articles, error, @@ -129,68 +121,127 @@ const SearchPage: NextPageWithLayout<SearchPageProps> = ({ hasNextPage, loadMore, } = useArticlesList({ - fallback: [], perPage: CONFIG.postsPerPage, - searchQuery: query.s as string, + searchQuery: typeof query.s === 'string' ? query.s : undefined, }); - - const totalArticles = useDataFromAPI<number>(async () => - fetchPostsCount({ search: query.s as string }) - ); - - const thematicsListTitle = intl.formatMessage({ - defaultMessage: 'Thematics', - description: 'SearchPage: thematics list widget title', - id: 'Dq6+WH', - }); - - const topicsListTitle = intl.formatMessage({ - defaultMessage: 'Topics', - description: 'SearchPage: topics list widget title', - id: 'N804XO', + const { isLoading: areThematicsLoading, thematics } = useThematicsList({ + fallback: data.thematics, + input: { first: data.thematics.pageInfo.total }, }); - const loadingResults = intl.formatMessage({ - defaultMessage: 'Loading the search results...', - description: 'SearchPage: loading search results message', - id: 'EeCqAE', + const { isLoading: areTopicsLoading, topics } = useTopicsList({ + fallback: data.topics, + input: { first: data.topics.pageInfo.total }, }); - const searchSubmitHandler: SearchFormSubmit = useCallback( - ({ query: searchQuery }) => { - if (!searchQuery) - return { - messages: { - error: intl.formatMessage({ - defaultMessage: 'Query must be longer than one character.', - description: 'NoResults: invalid query message', - id: 'VkfO7t', - }), + const messages = { + loading: { + thematicsList: intl.formatMessage({ + defaultMessage: 'Thematics are loading...', + description: 'SearchPage: loading thematics message', + id: 'qFqWQH', + }), + topicsList: intl.formatMessage({ + defaultMessage: 'Topics are loading...', + description: 'SearchPage: loading topics message', + id: 'tLflgC', + }), + }, + pageTitle: query.s + ? intl.formatMessage( + { + defaultMessage: 'Search results for "{query}"', + description: 'SearchPage: SEO - Page title', + id: 'N+3eau', }, - validator: (value) => value.query.length > 1, - }; + { query: query.s as string } + ) + : intl.formatMessage({ + defaultMessage: 'Search', + description: 'SearchPage: SEO - Page title', + id: 'WDwNDl', + }), + seo: { + metaDesc: query.s + ? intl.formatMessage( + { + defaultMessage: + 'Discover search results for {query} on {websiteName}.', + description: 'SearchPage: SEO - Meta description', + id: 'pg26sn', + }, + { query: query.s as string, websiteName: CONFIG.name } + ) + : intl.formatMessage( + { + defaultMessage: 'Search for a post on {websiteName}.', + description: 'SearchPage: SEO - Meta description', + id: 'npisb3', + }, + { websiteName: CONFIG.name } + ), + title: query.s + ? intl.formatMessage( + { + defaultMessage: 'Search results for {query} - {websiteName}', + description: 'SearchPage: SEO - Page title', + id: 'QRDdye', + }, + { query: query.s as string, websiteName: CONFIG.name } + ) + : intl.formatMessage( + { + defaultMessage: 'Search - {websiteName}', + description: 'SearchPage: SEO - Page title', + id: 'NqVQYo', + }, + { websiteName: CONFIG.name } + ), + }, + widgets: { + thematicsListTitle: intl.formatMessage({ + defaultMessage: 'Thematics', + description: 'SearchPage: thematics list widget title', + id: 'Dq6+WH', + }), + topicsListTitle: intl.formatMessage({ + defaultMessage: 'Topics', + description: 'SearchPage: topics list widget title', + id: 'N804XO', + }), + }, + }; - routerPush({ pathname: ROUTES.SEARCH, query: { s: searchQuery } }); + const { items: breadcrumbItems, schema: breadcrumbSchema } = useBreadcrumb({ + title: messages.pageTitle, + url: ROUTES.SEARCH, + }); - return undefined; - }, - [intl, routerPush] - ); + const webpageSchema = getWebPageSchema({ + description: messages.seo.metaDesc, + locale: CONFIG.locales.defaultLocale, + slug: asPath, + title: messages.pageTitle, + }); + const blogSchema = getBlogSchema({ + isSinglePage: false, + locale: CONFIG.locales.defaultLocale, + slug: asPath, + }); + const schemaJsonLd = getSchemaJson([webpageSchema, blogSchema]); - const foundArticles = articles?.flatMap((p) => - p.edges.map((edge) => edge.node) - ); + const pageUrl = `${CONFIG.url}${asPath}`; return ( <Page breadcrumbs={breadcrumbItems} isBodyLastChild> <Head> - <title>{page.title}</title> + <title>{messages.seo.title}</title> {/*eslint-disable-next-line react/jsx-no-literals -- Name allowed */} - <meta name="description" content={pageDescription} /> - <meta property="og:url" content={page.url} /> + <meta name="description" content={messages.seo.metaDesc} /> + <meta property="og:url" content={pageUrl} /> {/*eslint-disable-next-line react/jsx-no-literals -- Content allowed */} <meta property="og:type" content="website" /> - <meta property="og:title" content={title} /> - <meta property="og:description" content={pageDescription} /> + <meta property="og:title" content={messages.pageTitle} /> + <meta property="og:description" content={messages.seo.title} /> </Head> <Script // eslint-disable-next-line react/jsx-no-literals -- Id allowed @@ -205,36 +256,32 @@ const SearchPage: NextPageWithLayout<SearchPageProps> = ({ id="schema-breadcrumb" type="application/ld+json" /> - <PageHeader heading={title} meta={{ total: totalArticles }} /> - <PageBody className={styles.body}> - {foundArticles ? null : <Spinner>{loadingResults}</Spinner>} - {foundArticles?.length ? ( + <PageHeader + heading={messages.pageTitle} + meta={{ total: articles ? articles[0].pageInfo.total : undefined }} + /> + <PageBody> + {query.s && + ((articles?.length && articles[0].edges.length) || isLoading) ? ( <PostsList - className={styles.list} + className={styles['posts-list']} firstNewResult={firstNewResultIndex} isLoading={isLoading || isLoadingMore || isRefreshing} onLoadMore={hasNextPage ? loadMore : undefined} - posts={getPostsWithUrl(foundArticles)} + posts={ + articles + ? getPostsWithUrl( + articles.flatMap((page) => + page.edges.map((edge) => edge.node) + ) + ) + : [] + } sortByYear + total={articles ? articles[0].pageInfo.total : undefined} /> ) : ( - <> - <p> - {intl.formatMessage({ - defaultMessage: 'No results found.', - description: 'SearchPage: no results', - id: 'YV//MH', - })} - </p> - <p> - {intl.formatMessage({ - defaultMessage: 'Would you like to try a new search?', - description: 'SearchPage: try a new search message', - id: 'vtDLzG', - })} - </p> - <SearchForm isLabelHidden onSubmit={searchSubmitHandler} /> - </> + <NoResults /> )} {error ? ( <Notice @@ -250,26 +297,34 @@ const SearchPage: NextPageWithLayout<SearchPageProps> = ({ ) : null} </PageBody> <PageSidebar> - <LinksWidget - heading={ - <Heading isFake level={3}> - {thematicsListTitle} - </Heading> - } - items={getLinksItemData( - thematicsList.map(convertWPThematicPreviewToPageLink) - )} - /> - <LinksWidget - heading={ - <Heading isFake level={3}> - {topicsListTitle} - </Heading> - } - items={getLinksItemData( - topicsList.map(convertWPTopicPreviewToPageLink) - )} - /> + {areThematicsLoading ? ( + <Spinner>{messages.loading.thematicsList}</Spinner> + ) : ( + <LinksWidget + heading={ + <Heading level={2}>{messages.widgets.thematicsListTitle}</Heading> + } + items={getLinksItemData( + thematics.edges.map((edge) => + convertWPThematicPreviewToPageLink(edge.node) + ) + )} + /> + )} + {areTopicsLoading ? ( + <Spinner>{messages.loading.topicsList}</Spinner> + ) : ( + <LinksWidget + heading={ + <Heading level={2}>{messages.widgets.topicsListTitle}</Heading> + } + items={getLinksItemData( + topics.edges.map((edge) => + convertWPTopicPreviewToPageLink(edge.node) + ) + )} + /> + )} </PageSidebar> </Page> ); @@ -288,8 +343,10 @@ export const getStaticProps: GetStaticProps<SearchPageProps> = async ({ return { props: { - thematicsList: thematics.edges.map((edge) => edge.node), - topicsList: topics.edges.map((edge) => edge.node), + data: { + thematics, + topics, + }, translation, }, }; diff --git a/src/styles/pages/blog.module.scss b/src/styles/pages/blog.module.scss index 553e9f9..6b68849 100644 --- a/src/styles/pages/blog.module.scss +++ b/src/styles/pages/blog.module.scss @@ -19,6 +19,10 @@ } } +.no-results { + margin-block-start: var(--spacing-md); +} + .pagination { margin-top: var(--spacing-md); } diff --git a/src/utils/hooks/index.ts b/src/utils/hooks/index.ts index 1e0bfe3..1ee513d 100644 --- a/src/utils/hooks/index.ts +++ b/src/utils/hooks/index.ts @@ -4,7 +4,6 @@ export * from './use-articles-list'; export * from './use-boolean'; export * from './use-breadcrumb'; export * from './use-comments'; -export * from './use-data-from-api'; export * from './use-form'; export * from './use-github-api'; export * from './use-headings-tree'; diff --git a/src/utils/hooks/use-data-from-api.tsx b/src/utils/hooks/use-data-from-api.tsx deleted file mode 100644 index 5abcf09..0000000 --- a/src/utils/hooks/use-data-from-api.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { useEffect, useState } from 'react'; - -/** - * Fetch data from an API. - * - * This hook is a wrapper to `setState` + `useEffect`. - * - * @param fetcher - A function to fetch data from API. - * @returns {T | undefined} The requested data. - */ -export const useDataFromAPI = <T,>( - fetcher: () => Promise<T> -): T | undefined => { - const [data, setData] = useState<T>(); - - useEffect(() => { - fetcher().then((apiData) => setData(apiData)); - }, [fetcher]); - - return data; -}; diff --git a/tests/cypress/e2e/pages/search.cy.ts b/tests/cypress/e2e/pages/search.cy.ts new file mode 100644 index 0000000..bde592e --- /dev/null +++ b/tests/cypress/e2e/pages/search.cy.ts @@ -0,0 +1,28 @@ +import { ROUTES } from '../../../../src/utils/constants'; + +describe('Search Page', () => { + beforeEach(() => { + cy.visit(ROUTES.SEARCH); + }); + + it('successfully loads', () => { + cy.findByRole('heading', { level: 1 }).should('exist'); + }); + + it('contains a breadcrumbs', () => { + cy.findByRole('navigation', { name: 'Fil d’Ariane' }).should('exist'); + }); + + it('contains a thematics list widget and a topics list widget', () => { + cy.findByRole('heading', { level: 2, name: 'Thématiques' }).should('exist'); + cy.findByRole('heading', { level: 2, name: 'Sujets' }).should('exist'); + }); + + it('provides a form to search for keywords', () => { + const keywords = 'coldark'; + + cy.findByRole('searchbox').type(keywords); + cy.findByRole('button', { name: /Rechercher/ }).click(); + cy.findByRole('heading', { level: 1 }).should('contain.text', keywords); + }); +}); |
