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
2 changes: 1 addition & 1 deletion playwright-tests/docs/test_details_home_page.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Tests to check home page behaviour.
- Clicking the CTA Button should redirect the user to the respective external event details page (e.g., GitHub, Meetup).
- The View all events link at the top right should redirect to a dedicated Events page containing all events.

**Status:** Pending :x:
**Status:** Done :white_check_mark:

---

Expand Down
2 changes: 1 addition & 1 deletion playwright-tests/docs/test_plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ This is an overview of the playwright tests planned for this repository.
| -------------------------------------------- | ----------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------ |
| [HP-001](./test_details_home_page.md#hp-001) | Done :white_check_mark: | | | |
| [HP-002](./test_details_home_page.md#hp-002) | Pending :x: | | [HP-002: Opportunities and Programmes Section](https://github.com/Women-Coding-Community/wcc-frontend/issues/133) | |
| [HP-003](./test_details_home_page.md#hp-003) | Pending :x: | [@Ptrcja](https://github.com/ptrcja) | [HP-003: Latest Events Section](https://github.com/Women-Coding-Community/wcc-frontend/issues/134) | |
| [HP-003](./test_details_home_page.md#hp-003) | Done :white_check_mark: | [@Ptrcja](https://github.com/ptrcja) | [HP-003: Latest Events Section](https://github.com/Women-Coding-Community/wcc-frontend/issues/134) | |
| [HP-004](./test_details_home_page.md#hp-004) | Done :white_check_mark: | | [HP-004: Become a Mentor Section](https://github.com/Women-Coding-Community/wcc-frontend/issues/135) | |
| [HP-005](./test_details_home_page.md#hp-005) | Done :white_check_mark: | [@Pranita](https://github.com/PranitaVPanse) | [HP-005: Volunteer Section](https://github.com/Women-Coding-Community/wcc-frontend/issues/136) | |

Expand Down
81 changes: 80 additions & 1 deletion playwright-tests/pages/home.page.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,43 @@
import { Locator, Page } from '@playwright/test';
import { expect, Locator, Page } from '@playwright/test';

import { BasePage } from '@pages/base.page';

export class EventCard extends BasePage {
readonly card: Locator;

constructor(page: Page, card: Locator) {
super(page);
this.card = card;
}

async verifyCardStructure(): Promise<void> {
await expect(this.card).toBeVisible();

const eventType = this.card.getByTestId('event-card-type');
await expect(eventType).toHaveText(/^[A-Z_]+$/);

const eventDate = this.card.getByTestId('event-card-date');
await expect(eventDate).toHaveText(
/[A-Za-z]{3}.{0,20}\d{4}.{0,10}\d{1,2}:\d{2}/,
);

const eventTitle = this.card.getByTestId('event-card-title');
await expect(eventTitle).not.toBeEmpty();

const eventSpeaker = this.card.getByTestId('event-card-speaker');
await expect(eventSpeaker).toHaveText(/^Speaker:\s{1,5}.{1,100}$/);

const eventDescription = this.card.getByTestId('event-card-description');
await expect(eventDescription).not.toBeEmpty();

const eventImage = this.card.getByTestId('event-card-image');
await expect(eventImage).toBeVisible();

const eventCTA = this.card.getByTestId('event-card-cta');
await expect(eventCTA).not.toBeEmpty();
}
}

export class HomePage extends BasePage {
readonly becomeMentorSectionTitle: Locator;
readonly becomeMentorSectionDescription: Locator;
Expand All @@ -24,6 +60,8 @@ export class HomePage extends BasePage {
readonly leetCodeLink: Locator;
readonly joinSlackButton: Locator;

readonly eventsSection: Locator;

constructor(page: Page) {
super(page);

Expand Down Expand Up @@ -76,5 +114,46 @@ export class HomePage extends BasePage {
this.leetCodeLink = page.getByRole('link', { name: 'Leetcode' });

this.joinSlackButton = page.getByRole('link', { name: 'Join our Slack' });

this.eventsSection = page.getByTestId('events-section');
}

/**
* Gets an EventCard instance by index
* @param index - Zero-based index of the event card
*/
getEventCard(index: number): EventCard {
const cards = this.eventsSection.getByTestId('event-card');
return new EventCard(this.page, cards.nth(index));
}

/**
* Gets an EventCard by matching title text
* @param titleText - The event title to search for
*/
getEventCardByTitle(titleText: string): EventCard {
const card = this.eventsSection
.getByTestId('event-card')
.filter({
has: this.page
.getByTestId('event-card-title')
.filter({ hasText: titleText }),
})
.first();
return new EventCard(this.page, card);
}

async verifyEventsSectionVisible(): Promise<void> {
const sectionTitle = this.eventsSection.getByTestId('events-section-title');
const viewAllLink = this.eventsSection.getByTestId('events-view-all-link');

await expect(this.eventsSection).toBeVisible();
await expect(sectionTitle).toBeVisible();
await expect(viewAllLink).toBeVisible();
}

async clickViewAllEventsLink(): Promise<void> {
const viewAllLink = this.eventsSection.getByTestId('events-view-all-link');
await viewAllLink.click();
}
}
38 changes: 38 additions & 0 deletions playwright-tests/tests/home.page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,44 @@ test.describe('Validate Home Page', () => {
await homePage.clickElement(homePage.leetCodeLink);
await homePage.verifyURL('/programmes/leetcode');
});
test('HP-003: Verify Events Card information and CTA link', async ({
page,
homePage,
basePage,
}) => {
await test.step('Verify events section is visible', async () => {
await homePage.verifyEventsSectionVisible();
});

await test.step('Verify event card displays all required information', async () => {
const eventCard = homePage.getEventCard(0);
await eventCard.verifyCardStructure();
});

await test.step('Verify CTA button opens external link', async () => {
const eventCard = homePage.getEventCard(0);
const ctaButton = eventCard.card.getByTestId('event-card-cta');

const [newPage] = await Promise.all([
page.context().waitForEvent('page'),
ctaButton.click(),
]);

await newPage.waitForLoadState();
const url = newPage.url();
const isValidDomain =
url.includes('github.com') || url.includes('meetup.com');
expect(isValidDomain).toBeTruthy();

await newPage.close();
});

await test.step('Verify "View all events" link navigates to events page', async () => {
await homePage.clickViewAllEventsLink();
await basePage.verifyURL('/events');
});
});

test('HP-004: Become Mentor section', async ({ homePage, basePage }) => {
await expect(homePage.becomeMentorSectionTitle).toBeVisible();
await expect(homePage.becomeMentorSectionDescription).toBeVisible();
Expand Down
10 changes: 9 additions & 1 deletion src/components/EventCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const EventCard = ({
return (
<Grid
container
data-testid="event-card"
sx={{
maxWidth: isMobile ? '362px' : '544px',
margin: '0 auto',
Expand Down Expand Up @@ -65,6 +66,7 @@ export const EventCard = ({
<Image
src={images[0].path}
alt={images[0].alt}
data-testid="event-card-image"
fill
style={{ objectFit: 'cover' }}
priority
Expand All @@ -74,6 +76,7 @@ export const EventCard = ({
<Image
src={images[0].path}
alt={images[0].alt}
data-testid="event-card-image"
width={134}
height={134}
style={{ objectFit: 'cover' }}
Expand All @@ -86,6 +89,7 @@ export const EventCard = ({
<Typography
variant="caption"
component="label"
data-testid="event-card-type"
sx={{
display: 'inline-block',
padding: '6px 12px',
Expand All @@ -111,6 +115,7 @@ export const EventCard = ({
<Typography
variant="body2"
fontSize={12}
data-testid="event-card-date"
fontWeight={500}
lineHeight={1.3}
>
Expand All @@ -119,6 +124,7 @@ export const EventCard = ({
</Box>
<Typography
variant="h5"
data-testid="event-card-title"
fontSize={24}
lineHeight={1.3}
fontWeight={400}
Expand All @@ -128,6 +134,7 @@ export const EventCard = ({
</Typography>
<Typography
variant="body2"
data-testid="event-card-speaker"
fontSize={14}
fontWeight={400}
lineHeight={1.4}
Expand All @@ -140,6 +147,7 @@ export const EventCard = ({
<Box>
<Typography
variant="body1"
data-testid="event-card-description"
fontSize={16}
fontWeight={400}
lineHeight={1.5}
Expand All @@ -150,7 +158,7 @@ export const EventCard = ({
</Box>
</Box>
<Box sx={{ marginTop: 'auto' }}>
<LinkButton href={link.uri} reversed>
<LinkButton href={link.uri} reversed data-testid="event-card-cta">
{link.label}{' '}
<LaunchIcon sx={{ paddingLeft: '5px', fontSize: '16px' }} />
</LinkButton>
Expand Down
8 changes: 6 additions & 2 deletions src/components/EventContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const EventContainer = ({ title, link, items }: EventContainerProps) => {
const isMobile = useMediaQuery(theme.breakpoints.down(750));

return (
<Box sx={theme.custom.containerBox}>
<Box sx={theme.custom.containerBox} data-testid="events-section">
<Box sx={theme.custom.innerBox}>
<Box
sx={{
Expand All @@ -22,10 +22,13 @@ export const EventContainer = ({ title, link, items }: EventContainerProps) => {
width: '100%',
}}
>
<Typography variant="h3">{title}</Typography>
<Typography variant="h3" data-testid="events-section-title">
{title}
</Typography>
<Link
href={link.uri}
underline="none"
data-testid="events-view-all-link"
sx={{
display: 'flex',
alignItems: 'center',
Expand All @@ -50,6 +53,7 @@ export const EventContainer = ({ title, link, items }: EventContainerProps) => {
gradientColors="linear-gradient(90deg, #C7E7FF 0%, #FFDEA6 100%)"
/>
<Box
data-testid="events-cards-container"
sx={{
display: 'grid',
gap: isMobile ? '20px' : '40px',
Expand Down
4 changes: 4 additions & 0 deletions src/components/LinkButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ type LinkButtonProps = {
reversed?: boolean;
small?: boolean;
children: React.ReactNode;
'data-testid'?: string;
};

export const LinkButton = ({
href,
reversed,
small,
children,
'data-testid': dataTestId,
}: LinkButtonProps) => {
const isExternal = href.startsWith('https');

Expand All @@ -25,6 +27,7 @@ export const LinkButton = ({
target="_blank"
rel="noopener noreferrer"
variant="contained"
data-testid={dataTestId}
sx={{
backgroundColor: reversed ? '#fff' : 'primary.main',
color: reversed ? 'primary.main' : '#fff',
Expand All @@ -45,6 +48,7 @@ export const LinkButton = ({
<Button
component="a"
variant="contained"
data-testid={dataTestId}
sx={{
backgroundColor: reversed ? '#fff' : 'primary.main',
color: reversed ? 'primary.main' : '#fff',
Expand Down