diff --git a/src/app/components/content/IsaacCard.tsx b/src/app/components/content/IsaacCard.tsx index 0372ec600e..4a64a78dfd 100644 --- a/src/app/components/content/IsaacCard.tsx +++ b/src/app/components/content/IsaacCard.tsx @@ -5,19 +5,18 @@ import { apiHelper, isAppLink } from "../../services"; import { Link } from "react-router-dom"; import { IsaacCardDTO } from "../../../IsaacApiTypes"; -// NOTE: Currently not in use by CS. See ticket #212 for more details. - interface IsaacCardProps { doc: IsaacCardDTO; imageClassName?: string; } export const IsaacCard = ({ doc, imageClassName }: IsaacCardProps) => { - const { title, subtitle, image, clickUrl, disabled, verticalContent } = doc; + const { title, subtitle, image, clickUrl, disabled, verticalContent, buttonText } = doc; const classes = classNames({ "menu-card": true, disabled: disabled, "isaac-card-vertical": verticalContent }); const imgSrc = image?.src && apiHelper.determineImageUrl(image.src); + const showButton = Boolean(buttonText && clickUrl); - const link = + const stretchedLink = clickUrl && isAppLink(clickUrl) ? ( ) : ( @@ -25,6 +24,28 @@ export const IsaacCard = ({ doc, imageClassName }: IsaacCardProps) => { ); + const button = ( +
+ {clickUrl && isAppLink(clickUrl) ? ( + + {buttonText} + + ) : ( + + {buttonText} + + )} +
+ ); + + const footer = showButton ? button : clickUrl && stretchedLink; + return verticalContent ? ( {image && ( @@ -44,7 +65,7 @@ export const IsaacCard = ({ doc, imageClassName }: IsaacCardProps) => { {subtitle} - {clickUrl && link} + {footer} ) : ( @@ -65,7 +86,7 @@ export const IsaacCard = ({ doc, imageClassName }: IsaacCardProps) => { - {clickUrl && link} + {footer} ); }; diff --git a/src/scss/common/cards.scss b/src/scss/common/cards.scss index ef9610d0de..b3c232ac45 100644 --- a/src/scss/common/cards.scss +++ b/src/scss/common/cards.scss @@ -272,3 +272,22 @@ .card-deck + .card-deck { margin-top: 1.5rem; } + +.isaac-card-link-container { + display: flex; + justify-content: center; + margin-top: 1.5rem; + padding: 0 0 1rem; +} + +.isaac-card-link { + color: #6b009a; + font-size: 1.1875rem; + text-decoration: none; + + &:hover, + &:focus { + color: #6b009a; + text-decoration: underline; + } +} diff --git a/src/test/components/content/IsaacCard.test.tsx b/src/test/components/content/IsaacCard.test.tsx new file mode 100644 index 0000000000..cdf8570e40 --- /dev/null +++ b/src/test/components/content/IsaacCard.test.tsx @@ -0,0 +1,63 @@ +import { screen } from "@testing-library/react"; +import { renderTestEnvironment } from "../../utils"; +import { IsaacCard } from "../../../app/components/content/IsaacCard"; +import { IsaacCardDTO } from "../../../IsaacApiTypes"; + +const renderIsaacCard = (doc: IsaacCardDTO) => { + renderTestEnvironment({ + PageComponent: IsaacCard, + componentProps: { doc }, + initialRouteEntries: ["/"], + role: "ANONYMOUS", + }); +}; + +describe("IsaacCard", () => { + it("renders the title and subtitle", () => { + renderIsaacCard({ title: "Card title", subtitle: "Card subtitle", verticalContent: true }); + expect(screen.getByText("Card title")).toBeInTheDocument(); + expect(screen.getByText("Card subtitle")).toBeInTheDocument(); + }); + + it("renders a custom, centred button when buttonText and clickUrl are provided", () => { + renderIsaacCard({ + title: "Careers", + subtitle: "Explore computing careers", + clickUrl: "/careers_in_computer_science", + buttonText: "Read more", + verticalContent: true, + }); + const button = screen.getByRole("link", { name: "Read more" }); + expect(button).toBeInTheDocument(); + expect(button).toHaveAttribute("href", "/careers_in_computer_science"); + expect(button).toHaveClass("isaac-card-link"); + expect(button.parentElement).toHaveClass("isaac-card-link-container"); + }); + + it("opens external button links in a new tab", () => { + renderIsaacCard({ + title: "External", + subtitle: "An external resource", + clickUrl: "https://example.com/resource", + buttonText: "Visit resource", + verticalContent: true, + }); + const button = screen.getByRole("link", { name: "Visit resource" }); + expect(button).toHaveAttribute("href", "https://example.com/resource"); + expect(button).toHaveAttribute("target", "_blank"); + expect(button).toHaveAttribute("rel", "noopener noreferrer"); + }); + + it("falls back to a stretched whole-card link when no buttonText is provided", () => { + renderIsaacCard({ + title: "Create a Group", + subtitle: "Create and manage student groups.", + clickUrl: "/groups", + verticalContent: true, + }); + expect(screen.queryByRole("link", { name: /read more/i })).not.toBeInTheDocument(); + const link = document.querySelector("a.stretched-link"); + expect(link).toBeInTheDocument(); + expect(link).toHaveAttribute("href", "/groups"); + }); +});