Skip to content

Commit

Permalink
feat: add unit tests for AuthorAvatars , TOC , Hero , Meeting and Dem…
Browse files Browse the repository at this point in the history
…oAnimation and Figure components (#1831)

Co-authored-by: akshatnema <[email protected]>%0ACo-authored-by: Akshat Nema <[email protected]>
  • Loading branch information
reachaadrika and akshatnema authored Jul 20, 2023
1 parent 85d35a5 commit 7d5c2fd
Show file tree
Hide file tree
Showing 14 changed files with 347 additions and 43 deletions.
1 change: 1 addition & 0 deletions components/AlgoliaSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ export function SearchButton({ children, indexName = INDEX_NAME, ...props }) {
onOpen(indexName);
}}
{...props}
data-testid="Search-Button"
>
{typeof children === 'function' ? children({ actionKey }) : children}
</button>
Expand Down
30 changes: 20 additions & 10 deletions components/AuthorAvatars.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import React from 'react'
export default function AuthorAvatars({ authors = [] }) {
return (
authors.map((author, index) => {
let avatar = <img
key={index}
title={author.name}
className={`${index > 0 ? `absolute left-${index * 7} top-0` : `relative mr-${(authors.length - 1) * 7}`} z-${(authors.length - 1 - index) * 10} h-10 w-10 border-2 border-white rounded-full object-cover hover:z-50`}
src={author.photo}
loading="lazy"
/>
let avatar = (
<img
key={index}
title={author.name}
className={`${index > 0 ? `absolute left-${index * 7} top-0` : `relative mr-${(authors.length - 1) * 7}`} z-${(authors.length - 1 - index) * 10} h-10 w-10 border-2 border-white rounded-full object-cover hover:z-50`}
src={author.photo}
loading="lazy"
data-testid="AuthorAvatars-img"
/>
);

return author.link ? <a alt={author.name} href={author.link}>{avatar}</a> : {avatar}
return author.link ? (
<a alt={author.name} href={author.link} data-testid="AuthorAvatars-link">
{avatar}
</a>
) : (
<React.Fragment key={index}>{avatar}</React.Fragment>
);
})
)
}
);
}
4 changes: 2 additions & 2 deletions components/Feedback.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default function Feedback(className = '') {
<div className='block mx-auto w-fit'>
<img src='/img/illustrations/icons/icon-check.svg' className='md:w-14' />
</div>
<div className='text-center mx-auto text-lg mt-4'>
<div className='text-center mx-auto text-lg mt-4' data-testid="Feedback-div">
Thank you for your feedback!
</div>
<div className='text-center mx-auto text-md text-gray-500'>
Expand All @@ -71,7 +71,7 @@ export default function Feedback(className = '') {
<div className='block mx-auto w-fit'>
<img src='/img/illustrations/icons/icon-x.svg' className='md:w-14' />
</div>
<div className='text-center mx-auto text-lg mt-4'>
<div className='text-center mx-auto text-lg mt-4' data-testid="Feedback-error">
Oops! Something went wrong...
</div>
<div className='text-center mx-auto text-md text-gray-500'>
Expand Down
4 changes: 2 additions & 2 deletions components/Figure.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export default function Figure ({ src, caption, widthClass, className, float, al
}

return (
<figure className={`${className} ${floatClassNames} ${widthClass || 'w-full'}`}>
<figure className={`${className} ${floatClassNames} ${widthClass || 'w-full'}`} data-testid="Figure-div">
<div className='flex flex-col'>
<img className={`${imageClass}`} src={src} alt={alt} />
<img className={`${imageClass}`} src={src} alt={alt} data-testid="Figure-img" />
{ caption && (<Caption>{caption}</Caption>) }
</div>
</figure>
Expand Down
51 changes: 28 additions & 23 deletions components/Hero.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import DemoAnimation from './DemoAnimation'
import AnnouncementHero from '../components/campaigns/AnnoucementHero'
import Heading from './typography/Heading'
import Paragraph from './typography/Paragraph'
import { SearchButton } from './AlgoliaSearch';
import AlgoliaSearch, { SearchButton } from './AlgoliaSearch'; // Import AlgoliaSearch component
import IconLoupe from './icons/Loupe';

export default function Hero({ className = ''}) {
Expand All @@ -28,28 +28,32 @@ export default function Hero({ className = ''}) {
<strong>industry standard</strong> for defining asynchronous APIs.
</Heading>
<div className='flex flex-row items-center justify-center'>
<Button className="block md:inline-block" text="Read the docs" href="/docs" icon={<ArrowRight className="-mb-1 h-5 w-5" />} />
<SearchButton
className="hidden sm:flex items-center text-left space-x-3 px-4 py-3 ml-2 bg-white border-secondary-500 border text-secondary-500 hover:text-white shadow-md bg-secondary-100 hover:bg-secondary-500 transition-all duration-500 ease-in-out rounded-md"
>
{({ actionKey }) => (
<>
<IconLoupe />
<span className="flex-auto">Quick search...</span>
{actionKey && (
<kbd className="font-sans font-semibold">
<abbr
title={actionKey.key}
className="no-underline"
>
{actionKey.shortKey}
</abbr>{' '}
K
</kbd>
)}
</>
)}
</SearchButton>
<Button className="block md:inline-block" text="Read the docs" href="/docs" icon={<ArrowRight className="-mb-1 h-5 w-5" />}
data-testid="Hero-Button"/>
{/* Wrap SearchButton with AlgoliaSearch component */}
<AlgoliaSearch>
<SearchButton
className="sm:flex items-center text-left space-x-3 px-4 py-3 ml-2 bg-white border-secondary-500 border text-secondary-500 hover:text-white shadow-md bg-secondary-100 hover:bg-secondary-500 transition-all duration-500 ease-in-out rounded-md"
>
{({ actionKey }) => (
<>
<IconLoupe />
<span className="flex-auto">Quick search...</span>
{actionKey && (
<kbd className="font-sans font-semibold">
<abbr
title={actionKey.key}
className="no-underline"
>
{actionKey.shortKey}
</abbr>{' '}
K
</kbd>
)}
</>
)}
</SearchButton>
</AlgoliaSearch>
</div>
<Paragraph typeStyle="body-sm" className="mt-4" textColor="text-gray-500">
Proud to be part of the {" "}
Expand All @@ -66,3 +70,4 @@ export default function Hero({ className = ''}) {
</>
);
}

8 changes: 4 additions & 4 deletions components/Meeting.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ export default function Meeting({
}) {

return (
<a href={youtube} target="_blank" rel="noreferrer">
<a href={youtube} target="_blank" rel="noreferrer" data-testid="Meeting-link">
<div
className={`meeting-card overflow-hidden p-4 bg-${bg} w-full lg:w-[300px] h-[300px] cursor-pointer hover:bg-dark hover:text-white flex flex-col justify-between`}
>
<div>
<h3 className="text-xl">{name}</h3>
<div>
<h3 className="text-xl" data-testid="Meeting-heading">{name}</h3>
<div data-testid="Meeting-paragraph">
<Paragraph typeStyle="body-sm" className="my-4" textColor="white">
{purpose}
</Paragraph>
</div>
</div>
<div className="flex items-center justify-between">
<Paragraph typeStyle="body-md" className="my-4">
<strong>Host:</strong>
<strong data-testid="Meeting-host">Host:</strong>
{hostProfile ? (
<TextLink
href={hostProfile}
Expand Down
5 changes: 3 additions & 2 deletions components/TOC.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default function TOC({
return (
<div className={twMerge(`${className} ${tocItems.length ? '' : 'hidden'} ${cssBreakingPoint === 'xl' ? 'xl:block' : 'lg:block'} md:top-24 md:max-h-(screen-14) z-20`)} onClick={() => setOpen(!open)}>
<div className={`flex cursor-pointer ${tocItems.length ? '' : 'hidden'} ${cssBreakingPoint === 'xl' ? 'xl:cursor-auto' : 'lg:cursor-auto'} xl:mt-2`}>
<h5 className={twMerge(`${open && 'mb-4'} flex-1 text-primary-500 font-medium uppercase tracking-wide text-sm font-sans antialiased ${cssBreakingPoint === 'xl' ? 'xl:mb-4 xl:text-xs xl:text-gray-900 xl:font-bold' : 'lg:mb-4 lg:text-xs lg:text-gray-900 lg:font-bold'}`)}>
<h5 className={twMerge(`${open && 'mb-4'} flex-1 text-primary-500 font-medium uppercase tracking-wide text-sm font-sans antialiased ${cssBreakingPoint === 'xl' ? 'xl:mb-4 xl:text-xs xl:text-gray-900 xl:font-bold' : 'lg:mb-4 lg:text-xs lg:text-gray-900 lg:font-bold'}`)} data-testid="TOC-Heading">
On this page
</h5>
<div className={`text-underline text-center p4 ${cssBreakingPoint === 'xl' ? 'xl:hidden' : 'lg:hidden'}`}>
Expand All @@ -42,10 +42,11 @@ export default function TOC({
>
{
tocItems.map((item, index) => (
<a
<a
className={`pl-${Math.pow(2, item.lvl-1)} block mb-1 transition duration-100 ease-in-out text-gray-900 font-normal text-sm font-sans antialiased hover:underline`}
href={`#${item.slug}`}
key={index}
data-testid="TOC-Link"
>
{item.content.replaceAll('`', '')}
</a>
Expand Down
65 changes: 65 additions & 0 deletions cypress/test/AuthorAvatars.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react';
import { mount } from 'cypress/react'
import AuthorAvatars from '../../components/AuthorAvatars';

describe('AuthorAvatars', () => {
const authors = [
{
name: 'John Doe',
photo: 'https://example.com/john-doe.jpg',
link: 'https://example.com/john-doe'
},
{
name: 'Jane Smith',
photo: 'https://example.com/jane-smith.jpg',
link: 'https://example.com/jane-smith'
}
];


it('renders the author avatars without links', () => {
const authorsWithoutLinks = [
{
name: 'John Doe',
photo: 'https://example.com/john-doe.jpg',
link: null
},
{
name: 'Jane Smith',
photo: 'https://example.com/jane-smith.jpg',
link: null
},
];
mount(<AuthorAvatars authors={authorsWithoutLinks} />);
authorsWithoutLinks.forEach((author, index) => {
cy.get('[data-testid="AuthorAvatars-link"]')
.should('not.exist');

cy.get('[data-testid="AuthorAvatars-img"]')
.eq(index)
.should('have.attr', 'src', author.photo)
.should('have.attr', 'title', author.name)
.should('have.class', index > 0 ? `absolute left-${index * 7} top-0` : `relative mr-${(authorsWithoutLinks.length - 1) * 7}`)
.should('have.class', `z-${(authorsWithoutLinks.length - 1 - index) * 10}`)
.should('have.class', 'h-10 w-10 border-2 border-white rounded-full object-cover hover:z-50');
});
});



it('renders the author avatars with links', () => {
mount(<AuthorAvatars authors={authors} />);
authors.forEach((author, index) => {
cy.get(`[data-testid="AuthorAvatars-link"][alt="${author.name}"][href="${author.link}"]`)
.should('have.length', 1)
.within(() => {
cy.get('[data-testid="AuthorAvatars-img"]')
.should('have.attr', 'src', author.photo)
.should('have.attr', 'title', author.name)
.should('have.class', index > 0 ? `absolute left-${index * 7} top-0` : `relative mr-${(authors.length - 1) * 7}`)
.should('have.class', `z-${(authors.length - 1 - index) * 10}`)
.should('have.class', 'h-10 w-10 border-2 border-white rounded-full object-cover hover:z-50');
});
});
});
});
13 changes: 13 additions & 0 deletions cypress/test/DemoAnimation.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import { mount } from 'cypress/react';
import DemoAnimation from '../../components/DemoAnimation';

describe('DemoAnimation', () => {
it('renders without errors', () => {
mount(<DemoAnimation />);

cy.wait(100000);
cy.contains('Play with it!').should('be.visible');
});

});
46 changes: 46 additions & 0 deletions cypress/test/Feedback.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { mount } from "cypress/react";
import Feedback from '../../components/Feedback'
import MockRouter from '../../cypress/utils/router'
describe('Meeting component', () => {
beforeEach(() => {
mount(
<MockRouter><Feedback /></MockRouter>
);
});

it('shows success message on correct request', () => {
cy.get('textarea').type('Sample feedback');
cy.intercept('POST', '/.netlify/functions/github_discussions', (req) => {
req.reply({
statusCode: 200,
body: {
message: 'Feedback submitted successfully',
},
headers: {
'content-type': 'application/json',
},
});
}).as('submitFeedback');
cy.get('form').submit();
cy.wait('@submitFeedback');
cy.get('[data-testid="Feedback-div"]').should('contain.text', 'Thank you for your feedback!');

});
it('should display error message on failed submission', () => {
cy.get('textarea').type('Sample feedback');
cy.intercept('POST', '/.netlify/functions/github_discussions', (req) => {
req.reply({
statusCode: 500,
body: {
message: 'We were unable to process your feedback',
},
headers: {
'content-type': 'application/json',
},
});
}).as('submitFeedback');
cy.get('form').submit();
cy.wait('@submitFeedback');
cy.get('[data-testid="Feedback-error"]').should('contain.text', 'Oops! Something went wrong...');
});
});
38 changes: 38 additions & 0 deletions cypress/test/Figure.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import { mount } from 'cypress/react';
import Figure from '../../components/Figure';

describe('Figure', () => {
it('renders the figure with the image and caption', () => {
const src = '/img/posts/2020-summary/active-members.webp';
const caption = 'Figure 1: Slack active members weekly';
const widthClass = 'w-50';
const className = 'custom-class';
const float = 'left';
const altOnly = 'Alt Text';
const imageClass = 'custom-image-class';

mount(
<Figure
src={src}
caption={caption}
widthClass={widthClass}
className={className}
float={float}
altOnly={altOnly}
imageClass={imageClass}
/>
);

cy.get('[data-testid="Figure-div"]').should('have.class', className);
cy.get('[data-testid="Figure-div"]').should('have.class', `float-${float}`);
cy.get('[data-testid="Figure-div"]').should('have.class', widthClass);

cy.get('[data-testid="Figure-img"]').should('have.attr', 'src', src);
cy.get('[data-testid="Figure-img"]').should('have.attr', 'alt', altOnly);
cy.get('[data-testid="Figure-img"]').should('have.class', imageClass);

cy.contains(caption).should('be.visible');
cy.contains(caption).should('have.text', caption);
});
});
32 changes: 32 additions & 0 deletions cypress/test/Hero.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { mount } from 'cypress/react';
import Hero from '../../components/Hero';

describe('Hero Component', () => {
it('displays the correct content', () => {
mount(<Hero />);

cy.contains('Building the future of');
cy.contains('Event-Driven Architectures (EDA)');
cy.contains('Open-Source tools to easily build and maintain your event-driven architecture.');
cy.contains('Read the docs');
cy.contains('Quick search...');
cy.contains('Proud to be part of the Linux Foundation');
});

it('navigates to the documentation page when "Read the docs" button is clicked', () => {
mount(<Hero />);
cy.get('[data-testid="Button-link"]').contains('Read the docs');

});

it('performs a search when the search button is clicked', () => {
mount(<Hero />);

cy.get('[data-testid="Search-Button"]').contains('Quick search...').click();

// Type a search query and validate the results
const searchQuery = 'example';
cy.get('input[type="search"]').type(searchQuery);

});
});
Loading

0 comments on commit 7d5c2fd

Please sign in to comment.