Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 63 additions & 55 deletions packages/app-webdir-ui/src/ProfileCard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ import { profileCardType } from "./models";
*/

const ProfileCard = ({ ...props }) => {
const hasSocialsOrWebsiteOrShortBio =
const hasSocialLinks =
props.facebookLink ||
props.linkedinLink ||
props.twitterLink ||
props.website ||
props.shortBio;
props.website;
const hasSocialsOrWebsiteOrShortBio = hasSocialLinks || props.shortBio;
const title = props.matchedAffiliationTitle
? `${props.matchedAffiliationTitle}`
: "";
Expand Down Expand Up @@ -143,58 +143,66 @@ const ProfileCard = ({ ...props }) => {
<p className="person-description">
{props.shortBio?.slice(0, 250)}
</p>
<ul className="person-social-medias">
{props.facebookLink && (
<li>
<a
onClick={() => sendEvent("facebook icon")}
href={props.facebookLink}
aria-label="Go to user Facebook profile"
>
<span
className="fab fa-facebook-square"
title="Facebook Link"
/>
</a>
</li>
)}
{props.linkedinLink && (
<li>
<a
onClick={() => sendEvent("linkedin icon")}
href={props.linkedinLink}
aria-label="Go to user Linkedin profile"
>
<span className="fab fa-linkedin" title="LinkedIn Link" />
</a>
</li>
)}
{props.twitterLink && (
<li>
<a
onClick={() => sendEvent("twitter icon")}
href={props.twitterLink}
aria-label="Go to user Twitter profile"
>
<span
className="fab fa-square-x-twitter"
title="Twitter Link"
/>
</a>
</li>
)}
{props.website && (
<li>
<a
onClick={() => sendEvent("website icon")}
href={props.website}
aria-label="Go to user Website"
>
<span className="fa fa-globe" title="User Website Link" />
</a>
</li>
)}
</ul>
{hasSocialLinks && (
<ul className="person-social-medias">
{props.facebookLink && (
<li>
<a
onClick={() => sendEvent("facebook icon")}
href={props.facebookLink}
aria-label="Go to user Facebook profile"
>
<span
className="fab fa-facebook-square"
title="Facebook Link"
/>
</a>
</li>
)}
{props.linkedinLink && (
<li>
<a
onClick={() => sendEvent("linkedin icon")}
href={props.linkedinLink}
aria-label="Go to user Linkedin profile"
>
<span
className="fab fa-linkedin"
title="LinkedIn Link"
/>
</a>
</li>
)}
{props.twitterLink && (
<li>
<a
onClick={() => sendEvent("twitter icon")}
href={props.twitterLink}
aria-label="Go to user Twitter profile"
>
<span
className="fab fa-square-x-twitter"
title="Twitter Link"
/>
</a>
</li>
)}
{props.website && (
<li>
<a
onClick={() => sendEvent("website icon")}
href={props.website}
aria-label="Go to user Website"
>
<span
className="fa fa-globe"
title="User Website Link"
/>
</a>
</li>
)}
</ul>
)}
</div>
)}
{props.size === "small" && (
Expand Down
35 changes: 35 additions & 0 deletions packages/app-webdir-ui/src/ProfileCard/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { render } from "@testing-library/react";
import React from "react";

import { ProfileCard } from "./index";

const defaultProps = {
name: "John Smith",
matchedAffiliationTitle: "Regents Professor",
imgURL: "/test-image.jpg",
profileURL: "https://search.asu.edu/profile/12345",
email: "email@asu.edu",
size: "default",
GASource: "profile card",
};

describe("ProfileCard social media list", () => {
it("should not render the social media list when there are no social links", () => {
const { container } = render(
<ProfileCard {...defaultProps} shortBio="A short bio with no socials" />
);
expect(container.querySelector("ul.person-social-medias")).toBeNull();
expect(container.querySelector(".person-description")).toHaveTextContent(
"A short bio with no socials"
);
});

it("should render the social media list when at least one social link exists", () => {
const { container } = render(
<ProfileCard {...defaultProps} linkedinLink="https://linkedin.com/in/x" />
);
const list = container.querySelector("ul.person-social-medias");
expect(list).toBeInTheDocument();
expect(list.querySelectorAll("li")).toHaveLength(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,33 @@ describe("PersonProfile tests", () => {
expect(socialLink).toHaveAttribute("href", "https://example.com");
});

it("should not render the social media list when socialMedia is empty", () => {
cleanup();
const { container } = renderComponent({ ...defaultProps, socialMedia: [] });
expect(container.querySelector("ul.person-social-medias")).toBeNull();
});

it("should not render the social media list when socialMedia is undefined", () => {
cleanup();
const { container } = renderComponent({
...defaultProps,
socialMedia: undefined,
});
expect(container.querySelector("ul.person-social-medias")).toBeNull();
});

describe("accessibility tests", () => {
it("should have proper aria labels for contact links", () => {
expect(screen.getByLabelText(`Email ${component.container.querySelector("a[href*='mailto:']").innerHTML}`)).toBeInTheDocument();
expect(screen.getByLabelText(`Phone ${component.container.querySelector("a[href*='tel:']").innerHTML.replace(/\-/g, " ").replace(/\(/g, "").replace(/\)/g, "")}`)).toBeInTheDocument();
expect(
screen.getByLabelText(
`Email ${component.container.querySelector("a[href*='mailto:']").innerHTML}`
)
).toBeInTheDocument();
expect(
screen.getByLabelText(
`Phone ${component.container.querySelector("a[href*='tel:']").innerHTML.replace(/\-/g, " ").replace(/\(/g, "").replace(/\)/g, "")}`
)
).toBeInTheDocument();
});

it("should use semantic HTML elements", () => {
Expand All @@ -95,5 +118,4 @@ describe("PersonProfile tests", () => {
expect(component.container.querySelector("h4")).toBeInTheDocument();
});
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,21 @@ const PersonProfile: React.FC<PersonProfileProps> = ({

<ul className="person-contact-info">
<li>
<GaEventWrapper
gaData={{ ...gaData, section: name.toLowerCase() }}
>
<a href={`mailto:${contactInfo.email}`} aria-label={`Email ${contactInfo.email}`}>
<GaEventWrapper gaData={{ ...gaData, section: name.toLowerCase() }}>
<a
href={`mailto:${contactInfo.email}`}
aria-label={`Email ${contactInfo.email}`}
>
{contactInfo.email}
</a>
</GaEventWrapper>
</li>
<li>
<GaEventWrapper gaData={{ ...gaData, section: name.toLowerCase() }}>
<a href={`tel:${contactInfo.phone}`} aria-label={`Phone ${contactInfo.phone.replace(/\-/g, " ").replace(/\(/g, "").replace(/\)/g, "")}`}>
<a
href={`tel:${contactInfo.phone}`}
aria-label={`Phone ${contactInfo.phone.replace(/\-/g, " ").replace(/\(/g, "").replace(/\)/g, "")}`}
>
{contactInfo.phone}
</a>
</GaEventWrapper>
Expand All @@ -124,24 +128,26 @@ const PersonProfile: React.FC<PersonProfileProps> = ({

<div>
<p className="person-description">{description}</p>
<ul className="person-social-medias">
{socialMedia.map((social, index) => (
<li key={index}>
<GaEventWrapper
gaData={{ ...gaData, section: name.toLowerCase() }}
>
<a
href={social.url}
aria-label={`Go to user ${social.platform} profile`}
{socialMedia && socialMedia.length > 0 && (
<ul className="person-social-medias">
{socialMedia.map((social, index) => (
<li key={index}>
<GaEventWrapper
gaData={{ ...gaData, section: name.toLowerCase() }}
>
<span
className={getSocialMediaIcon(social.platform)}
></span>
</a>
</GaEventWrapper>
</li>
))}
</ul>
<a
href={social.url}
aria-label={`Go to user ${social.platform} profile`}
>
<span
className={getSocialMediaIcon(social.platform)}
></span>
</a>
</GaEventWrapper>
</li>
))}
</ul>
)}
</div>
</div>
</div>
Expand Down