From d375e5c9f162cbd84a6e6462977db56519d09f75 Mon Sep 17 00:00:00 2001
From: Armand Philippot <git@armandphilippot.com>
Date: Thu, 7 Dec 2023 18:48:53 +0100
Subject: refactor(pages): refine Project pages

* refactor ProjectOverview component to let consumers handle the value
* extract project overview depending on Github to avoid fetching
Github API if the project is not on Github
* wrap dynamic import in a useMemo hook to avoid infinite rerender
* fix table of contents by adding a useMutationObserver hook to refresh
headings tree (without it useHeadingsTree is not retriggered once the
dynamic import is done)
* add Cypress tests
---
 .../project-overview/project-overview.test.tsx     | 64 +++++++++++-----------
 1 file changed, 33 insertions(+), 31 deletions(-)

(limited to 'src/components/organisms/project-overview/project-overview.test.tsx')

diff --git a/src/components/organisms/project-overview/project-overview.test.tsx b/src/components/organisms/project-overview/project-overview.test.tsx
index 6234368..f798a7b 100644
--- a/src/components/organisms/project-overview/project-overview.test.tsx
+++ b/src/components/organisms/project-overview/project-overview.test.tsx
@@ -1,13 +1,14 @@
 import { describe, expect, it } from '@jest/globals';
 import NextImage from 'next/image';
 import { render, screen as rtlScreen } from '../../../../tests/utils';
-import { type ProjectMeta, ProjectOverview } from './project-overview';
+import { type OverviewMeta, ProjectOverview } from './project-overview';
+import { SocialLink } from 'src/components/atoms';
 
 describe('ProjectOverview', () => {
   it('can render a meta for the creation date', () => {
     const meta = {
       creationDate: '2023-11-01',
-    } satisfies Partial<ProjectMeta>;
+    } satisfies Partial<OverviewMeta>;
 
     render(<ProjectOverview meta={meta} name="quo" />);
 
@@ -17,7 +18,7 @@ describe('ProjectOverview', () => {
   it('can render a meta for the update date', () => {
     const meta = {
       lastUpdateDate: '2023-11-02',
-    } satisfies Partial<ProjectMeta>;
+    } satisfies Partial<OverviewMeta>;
 
     render(<ProjectOverview meta={meta} name="quo" />);
 
@@ -27,7 +28,7 @@ describe('ProjectOverview', () => {
   it('can render a meta for the license', () => {
     const meta = {
       license: 'MIT',
-    } satisfies Partial<ProjectMeta>;
+    } satisfies Partial<OverviewMeta>;
 
     render(<ProjectOverview meta={meta} name="quo" />);
 
@@ -37,38 +38,26 @@ describe('ProjectOverview', () => {
 
   it('can render a meta for the popularity', () => {
     const meta = {
-      popularity: { count: 5 },
-    } satisfies Partial<ProjectMeta>;
+      popularity: '5 stars',
+    } satisfies Partial<OverviewMeta>;
 
     render(<ProjectOverview meta={meta} name="quo" />);
 
     expect(rtlScreen.getByRole('term')).toHaveTextContent('Popularity:');
     expect(rtlScreen.getByRole('definition')).toHaveTextContent(
-      `${meta.popularity.count} stars`
-    );
-  });
-
-  it('can render a meta for the popularity with a link', () => {
-    const meta = {
-      popularity: { count: 3, url: '#popularity' },
-    } satisfies Partial<ProjectMeta>;
-
-    render(<ProjectOverview meta={meta} name="quo" />);
-
-    expect(rtlScreen.getByRole('term')).toHaveTextContent('Popularity:');
-    expect(rtlScreen.getByRole('definition')).toHaveTextContent(
-      `${meta.popularity.count} stars`
-    );
-    expect(rtlScreen.getByRole('link')).toHaveAttribute(
-      'href',
-      meta.popularity.url
+      meta.popularity
     );
   });
 
   it('can render a meta for the technologies', () => {
     const meta = {
-      technologies: ['Javascript', 'React'],
-    } satisfies Partial<ProjectMeta>;
+      technologies: ['Javascript', 'React'].map((techno) => {
+        return {
+          id: techno,
+          value: techno,
+        };
+      }),
+    } satisfies Partial<OverviewMeta>;
 
     render(<ProjectOverview meta={meta} name="quo" />);
 
@@ -79,9 +68,22 @@ describe('ProjectOverview', () => {
   });
 
   it('can render a meta for the repositories', () => {
+    const repos = [{ id: 'Github' as const, label: 'Github', url: '#github' }];
     const meta = {
-      repositories: [{ id: 'Github', label: 'Github', url: '#github' }],
-    } satisfies Partial<ProjectMeta>;
+      repositories: repos.map((repo) => {
+        return {
+          id: repo.id,
+          value: (
+            <SocialLink
+              icon={repo.id}
+              key={repo.id}
+              label={repo.label}
+              url={repo.url}
+            />
+          ),
+        };
+      }),
+    } satisfies Partial<OverviewMeta>;
 
     render(<ProjectOverview meta={meta} name="quo" />);
 
@@ -90,8 +92,8 @@ describe('ProjectOverview', () => {
       meta.repositories.length
     );
     expect(
-      rtlScreen.getByRole('link', { name: meta.repositories[0].label })
-    ).toHaveAttribute('href', meta.repositories[0].url);
+      rtlScreen.getByRole('link', { name: repos[0].label })
+    ).toHaveAttribute('href', repos[0].url);
   });
 
   it('can render a cover', () => {
@@ -118,7 +120,7 @@ describe('ProjectOverview', () => {
   it('does not render a meta if the key is undefined', () => {
     const meta = {
       creationDate: undefined,
-    } satisfies Partial<ProjectMeta>;
+    } satisfies Partial<OverviewMeta>;
 
     render(<ProjectOverview meta={meta} name="quo" />);
 
-- 
cgit v1.2.3

