import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom';
import { TripCard } from '../TripCard';
import { TripCardApiData } from '../types';
import { tealiumTrackingHandler } from '../../../helpers/tracking/TrackingHandler';
jest.mock('../../../helpers/tracking/TrackingHandler', () => ({
tealiumTrackingHandler: jest.fn()
}));
const mockCard: TripCardApiData = {
cruise_id: '2074350',
image: 'https://example.com/image.jpg',
headline: 'Mediterranean from Barcelona',
date: 'Oct 2025 - Oct 2025',
duration: 'Seven Days',
destination: 'Barcelona → Marseille',
ship: 'MSC Seaside',
price: '£2000',
logo: 'https://example.com/logo.png',
logo_url: 'https://example.com',
logo_name: 'MSC Cruises',
cta_url: 'https://example.com/cruise',
cta_text: 'View Itinerary'
};
describe('TripCard', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('renders card with all required data', () => {
render();
expect(
screen.getByText('Mediterranean from Barcelona')
).toBeInTheDocument();
expect(screen.getByText('Oct 2025 - Oct 2025')).toBeInTheDocument();
expect(screen.getByText('Seven Days')).toBeInTheDocument();
expect(screen.getByText('Barcelona → Marseille')).toBeInTheDocument();
expect(screen.getByText('MSC Seaside')).toBeInTheDocument();
expect(screen.getByText('£2000')).toBeInTheDocument();
expect(screen.getByText('From')).toBeInTheDocument();
expect(screen.getByText('View Itinerary')).toBeInTheDocument();
});
it('renders image with correct src and alt', () => {
render();
const image = screen.getByAltText('Mediterranean from Barcelona');
expect(image).toHaveAttribute('src', 'https://example.com/image.jpg');
});
it('renders offer label when provided', () => {
const cardWithOffer = {
...mockCard,
offer_label: 'Special Offer'
};
render();
expect(screen.getByText('Special Offer')).toBeInTheDocument();
});
it('renders gift banner when provided', () => {
const cardWithGift = {
...mockCard,
gift_banner: 'Free gift with purchase'
};
render();
expect(screen.getByText('Free gift with purchase')).toBeInTheDocument();
});
it('renders original price when provided', () => {
const cardWithOriginalPrice = {
...mockCard,
original_price: '£2500'
};
render();
expect(screen.getByText('£2500pp')).toBeInTheDocument();
});
it('does not render "From" when price is "Enquire now"', () => {
const cardWithEnquire = {
...mockCard,
price: 'Enquire now'
};
render();
expect(screen.queryByText('From')).not.toBeInTheDocument();
expect(screen.getByText('Enquire now')).toBeInTheDocument();
});
it('renders all CTA links with correct href and target', () => {
render();
const links = screen.getAllByRole('link');
const imageLink = links[0];
const headlineLink = links[1];
const ctaButton = screen.getByText('View Itinerary').closest('a');
expect(imageLink).toHaveAttribute('href', 'https://example.com/cruise');
expect(imageLink).toHaveAttribute('target', '_blank');
expect(headlineLink).toHaveAttribute('href', 'https://example.com/cruise');
expect(ctaButton).toHaveAttribute('href', 'https://example.com/cruise');
});
it('renders logo with link when provided', () => {
render();
const logoLink = screen.getByRole('link', { name: /partner logo/i });
expect(logoLink).toHaveAttribute('href', 'https://example.com');
const logoImg = screen.getByAltText('Partner logo');
expect(logoImg).toHaveAttribute('src', 'https://example.com/logo.png');
});
it('shows card image after it loads', () => {
render();
const cardImage = screen.getByAltText('Mediterranean from Barcelona');
expect(cardImage).toHaveStyle({ display: 'none' });
fireEvent.load(cardImage);
expect(cardImage).toHaveStyle({ display: 'block' });
});
describe('Tracking', () => {
it('calls tealiumTrackingHandler when headline is clicked', () => {
render();
const headlineLink = screen.getAllByRole('link')[1];
fireEvent.click(headlineLink);
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
'trip card: Mediterranean from Barcelona',
'navigation',
'click',
'Mediterranean from Barcelona',
undefined,
{
app_content_location: expect.any(String)
}
);
});
it('calls tealiumTrackingHandler when image is clicked', () => {
render();
const imageLink = screen.getAllByRole('link')[0];
fireEvent.click(imageLink);
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
'trip card: img click',
'navigation',
'click',
'Mediterranean from Barcelona',
undefined,
{
app_content_location: expect.any(String)
}
);
});
it('calls tealiumTrackingHandler when CTA button is clicked', () => {
render();
const ctaButton = screen.getByText('View Itinerary');
fireEvent.click(ctaButton);
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
'trip card: View Itinerary',
'navigation',
'click',
'Mediterranean from Barcelona',
undefined,
{
app_content_location: expect.any(String)
}
);
});
it('calls tealiumTrackingHandler with default CTA text when not provided', () => {
const cardWithoutCTAText = {
...mockCard,
cta_text: undefined
};
render();
const ctaButton = screen.getByText('View Itinerary');
fireEvent.click(ctaButton);
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
'trip card: View Itinerary',
'navigation',
'click',
'Mediterranean from Barcelona',
undefined,
{
app_content_location: expect.any(String)
}
);
});
it('calls tealiumTrackingHandler when logo is clicked with empty logo_name', () => {
const cardWithoutLogoName = {
...mockCard,
logo_name: ''
};
render();
const logoLink = screen.getByRole('link', { name: /partner logo/i });
fireEvent.click(logoLink);
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
'trip card: ',
'navigation',
'click',
'Mediterranean from Barcelona',
undefined,
{
app_content_location: expect.any(String)
}
);
});
it('calls tealiumTrackingHandler with logo_name when provided', () => {
const cardWithLogoName = {
...mockCard,
logo_name: 'MSC Cruises'
};
render();
const logoLink = screen.getByRole('link', { name: /partner logo/i });
fireEvent.click(logoLink);
expect(tealiumTrackingHandler).toHaveBeenCalledWith(
'trip card: MSC Cruises',
'navigation',
'click',
'Mediterranean from Barcelona',
undefined,
{
app_content_location: expect.any(String)
}
);
});
});
});