Skip to content

Commit

Permalink
[OUR415-95/TECH-RISK-4] Adds tests for HomePage component (#280)
Browse files Browse the repository at this point in the history
  • Loading branch information
rosschapman authored Nov 27, 2024
1 parent 6dafeee commit e2f9f12
Show file tree
Hide file tree
Showing 11 changed files with 326 additions and 159 deletions.
14 changes: 0 additions & 14 deletions app/components/ui/Hero/Hero.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,3 @@
margin-top: $general-spacing-xl;
gap: $general-spacing-s;
}

.desktop {
@media screen and (max-width: $break-tablet-s) {
display: none;
}
}

.mobile {
display: none;
@media screen and (max-width: $break-tablet-s) {
display: flex;
min-width: 100%;
}
}
73 changes: 25 additions & 48 deletions app/components/ui/Hero/Hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import styles from "./Hero.module.scss";
import { Button } from "../inline/Button/Button";
import { Link } from "models/Strapi";

/**
* Displays a hero section on the homepage
*/
const Hero = ({
backgroundImage,
title,
Expand All @@ -15,61 +18,35 @@ const Hero = ({
description: string;
buttons: Link[];
}) => {
const cardStyles = classNames(styles.contentCard);
return (
<>
<div data-testid={"hero"}>
<div
className={styles.hero}
style={{ backgroundImage: `url(${backgroundImage})` }}
>
<HeroCard
title={title}
description={description}
buttons={buttons}
desktop
/>
</div>
<HeroCard title={title} description={description} buttons={buttons} />
</>
);
};

export default Hero;

const HeroCard = ({
title,
description,
buttons,
desktop = false,
}: {
title: string;
description: string;
buttons: Link[];
desktop?: boolean;
}) => {
const cardStyles = classNames(
styles.contentCard,
desktop ? styles.desktop : styles.mobile
);

return (
<div className={cardStyles}>
<div className={styles.content}>
<h2 className={styles.title}>{title}</h2>
<p className={styles.description}>{description}</p>
<div className={styles.buttons}>
{buttons.map((button, i) => (
<Button
key={button.text}
variant={i === 0 ? "primary" : "secondary"}
size="lg"
arrowVariant="after"
href={button.url}
>
{button.text}
</Button>
))}
<div className={cardStyles}>
<div className={styles.content}>
<h2 className={styles.title}>{title}</h2>
<p className={styles.description}>{description}</p>
<div className={styles.buttons}>
{buttons.map((button, i) => (
<Button
key={button.text}
variant={i === 0 ? "primary" : "secondary"}
size="lg"
arrowVariant="after"
href={button.url}
>
{button.text}
</Button>
))}
</div>
</div>
</div>
</div>
</div>
);
};

export default Hero;
86 changes: 30 additions & 56 deletions app/components/ui/Section/CategorySection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,70 +4,44 @@ import { BackgroundColorVariant } from "models";
import { CATEGORIES } from "pages/constants";
import { CategoryCard } from "../Cards/CategoryCard";
import styles from "./CategorySection.module.scss";
// import { Loader } from "../Loader";

interface Category {
icon: {
name: string;
provider: string;
};
label: string;
slug: string;
name: string;
}

interface FeaturedCategoriesSection {
category: Category[];
name: string;
}

export interface FeaturedCategoriesData {
header: string;
subheader: string;
backgroundColor: BackgroundColorVariant;
featuredCategoriesSection: FeaturedCategoriesSection[];
}

export const CategorySection = () => {
// const { sectionData } = props;

// if (!sectionData) {
// return <div>Loading...</div>;
// }

// const { header, subheader, backgroundColor, featuredCategoriesSection } =
// sectionData;
// const featuredCategories = featuredCategoriesSection[0].category;

return (
<HomePageSection
title={tempCategoriesSection.header}
description={tempCategoriesSection.subheader}
backgroundColor="secondary"
>
<div className={styles.categorySection}>
<div className={styles.categoryCards}>
{CATEGORIES.map((category) => {
return (
<CategoryCard
key={category.name}
label={category.name}
href={`/${category.slug}/results`}
icon={category.icon}
/>
);
})}
<CategoryCard
key="See all services"
label="See all services"
href="/search"
icon={{ provider: "fas", name: "fa-arrow-right" }}
/>
</div>
/**
* Displays a grid of categories on the home page
*/
export const CategorySection = () => (
<HomePageSection
title={tempCategoriesSection.header}
description={tempCategoriesSection.subheader}
backgroundColor="secondary"
>
<div className={styles.categorySection}>
<div className={styles.categoryCards}>
{CATEGORIES.map((category) => {
return (
<CategoryCard
key={category.name}
label={category.name}
href={`/${category.slug}/results`}
icon={category.icon}
/>
);
})}
<CategoryCard
key="See all services"
label="See all services"
href="/search"
icon={{ provider: "fas", name: "fa-arrow-right" }}
/>
</div>
</HomePageSection>
);
};
</div>
</HomePageSection>
);

// TODO: Add to CMS
const tempCategoriesSection = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ import { Button } from "../inline/Button/Button";
import Accordion from "../Accordions/Accordion";
import { TwoColumnContentBlock } from "models/Strapi";

// TODO: media can be a video URL, update component to handle
// TODO: update use srcset and the different media sizes for images

/**
* Displays a section with two columns, typically text next to media
*
* TODO: media can be a video URL, update component to handle
* TODO: update use srcset and the different media sizes for images
*/
export const TwoColumnContentSection = (props: TwoColumnContentBlock) => {
const { link, content, media_alignment, media, faq } = props;
const altText = media[0].image?.data?.attributes?.alternativeText;
const altText = media[0].image?.data?.attributes?.alternativeText || "";

return (
<section className={styles.twoColumnContentSectionContainer}>
<section
className={styles.twoColumnContentSectionContainer}
data-testid={"two-column-content-section"}
>
<div
className={
media_alignment === "left"
Expand Down
43 changes: 22 additions & 21 deletions app/hooks/StrapiAPI.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
/**
NOTE @rosschapman: Developers may be tempted to auto-generate response types as described in the strapi docs using cli
commands from the `@strapi/strapi` module, but I've noticed the output is funky for use in a client application in its
raw form. For example, string fields from the recommended module are typed as `Attribute.String` but this type isn't compatible
with `string` 🤦. Strapi offers this cumbersome approach to sync types, but also caveats this is not an official
solution: https://strapi.io/blog/improve-your-frontend-experience-with-strapi-types-and-type-script. Even so, I still
don't trust the generated types in view of the above example.
*/
* NOTE @rosschapman: Developers may be tempted to auto-generate response types as described in the strapi docs using cli
* commands from the `@strapi/strapi` module, but I've noticed the output is funky for use in a client application in its
* raw form. For example, string fields from the recommended module are typed as `Attribute.String` but this type isn't compatible
* with `string` 🤦. Strapi offers this cumbersome approach to sync types, but also caveats this is not an official
* solution: https://strapi.io/blog/improve-your-frontend-experience-with-strapi-types-and-type-script. Even so, I still
* don't trust the generated types in view of the above example.
*
* For more information about fetching relational data using the `populate` and
* `field` selectors, see: https://docs.strapi.io/dev-docs/api/rest/populate-select
*/

import useSWR from "swr";
import fetcher from "utils/fetcher";
Expand Down Expand Up @@ -40,7 +43,7 @@ export function useFooterData() {

export function useHomepageData() {
return useStrapiHook<HomepageResponse>(
"home-page?populate[hero][populate]=*&populate[category_section][populate]=*"
"home-page?populate[hero][populate]=*&populate[category_section][populate]=*&populate[two_column_content_blocks][populate][link]=*&populate[two_column_content_blocks][populate][media][populate]=*"
);
}

Expand Down Expand Up @@ -114,7 +117,6 @@ export interface StrapiArrayResponse<T> {
}

interface BaseDatumAttributesResponse {
id: string;
createdAt: string;
updatedAt: string;
publishedAt?: string;
Expand Down Expand Up @@ -155,24 +157,24 @@ export interface ImageFormatResponse {
hash: string;
mime: string;
name: string;
path?: string;
path: string | null;
size: number;
width: number;
height: number;
sizeInBytes: number;
}

export interface FormatsResponse {
large: ImageFormatResponse;
medium: ImageFormatResponse;
small: ImageFormatResponse;
thumbnail: ImageFormatResponse;
large?: ImageFormatResponse;
medium?: ImageFormatResponse;
small?: ImageFormatResponse;
thumbnail?: ImageFormatResponse;
}

export interface ImageResponse extends BaseDatumAttributesResponse {
name: string;
alternativeText?: string;
caption?: string;
alternativeText: string | null;
caption: string | null;
width: number;
height: number;
formats: FormatsResponse;
Expand All @@ -181,7 +183,7 @@ export interface ImageResponse extends BaseDatumAttributesResponse {
mime: string;
size: number;
url: string;
previewUrl?: string;
previewUrl: string | null;
provider: string;
provider_metadata?: unknown;
}
Expand All @@ -193,7 +195,7 @@ export interface ContentBlockResponse {
subheader: string;
background_color: {
id: number;
color: "primary" | "secondary" | "tertiary";
color: string;
};
link: LinkResponse;
}
Expand All @@ -206,12 +208,12 @@ export interface FaqItem {
export interface TwoColumnContentBlockResponse
extends BaseDatumAttributesResponse {
title: string;
media_alignment: "left" | "right";
media_alignment: string;
content: string;
name: string;
link: LinkResponse;
media: DynamicMediaResponse[];
faq: FaqItem[];
faq?: FaqItem[];
}

export interface CalendarEventResponse {
Expand All @@ -224,7 +226,6 @@ export interface CalendarEventResponse {
}

export interface HomepageResponse extends BaseDatumAttributesResponse {
title: string;
hero: {
id: number;
title: string;
Expand Down
38 changes: 38 additions & 0 deletions app/pages/HomePage/HomePage.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Template for a simple component test
*
* Usage: Duplicate this file and rename it using your component name. Happy
* coding from there!
*/
import React from "react";
import { render, screen } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom";
import { HomePage } from "pages/HomePage/HomePage";
import { HOME_PAGE_DATA } from "../../../test/fixtures/HomePageData";
import { Homepage, StrapiDatum } from "models/Strapi";

const mock: {
data: {
attributes: null | StrapiDatum<Homepage>["attributes"];
};
} = {
data: {
attributes: null,
},
};
jest.mock("hooks/StrapiAPI", () => ({
useHomepageData: () => mock,
}));

describe("<HomePage />", () => {
it("renders", () => {
mock.data.attributes = HOME_PAGE_DATA;
render(<HomePage />, { wrapper: BrowserRouter });
expect(screen.getByTestId("homepage-title")).toHaveTextContent("Homepage");
expect(screen.getByTestId("hero")).toBeInTheDocument();
expect(screen.getByTestId("homepage-section")).toBeInTheDocument();
expect(
screen.getByTestId("two-column-content-section")
).toBeInTheDocument();
});
});
Loading

0 comments on commit e2f9f12

Please sign in to comment.