import React from 'react';
import { render, screen } from '@testing-library/react';
import { SocialMediaEmbed, SocialMediaEmbedProps } from '../SocialMediaEmbed';
import { BlockedEmbedMessage } from '../BlockedEmbedMessage';
import { Vendor } from '../SocialVendor';
import { checkVendorConsentAsync } from '../helpers/vendorConsent';
import { eventStatus } from '../constants';
import '@testing-library/jest-dom/extend-expect';
import { useSocialEmbedsContext } from '../../../contexts/SocialEmbedsProvider';
jest.mock('../../../contexts/SocialEmbedsProvider', () => ({
useSocialEmbedsContext: jest.fn()
}));
jest.mock('../BlockedEmbedMessage', () => ({
BlockedEmbedMessage: jest.fn(() =>
Blocked Embed Message
)
}));
jest.mock('../SocialVendor', () => ({
Vendor: jest.fn(() => Vendor Component
)
}));
jest.mock('../helpers/vendorConsent', () => ({
checkVendorConsentAsync: jest.fn()
}));
describe('SocialMediaEmbed Component', () => {
const vendorName = 'twitter';
const defaultProps: SocialMediaEmbedProps = {
id: 'test-id',
url: 'https://twitter.com/test/status/12345',
vendorName
};
const mockContext = {
setIsSocialEmbedAllowed: jest.fn(),
isAllowedOnce: { twitter: false },
isSocialEmbedAllowed: { twitter: false }
};
beforeEach(() => {
jest.clearAllMocks();
(useSocialEmbedsContext as jest.Mock).mockReturnValue(mockContext);
// Mock __tcfapi
(window as any).__tcfapi = jest.fn();
});
afterEach(() => {
delete (window as any).__tcfapi;
});
it('renders BlockedEmbedMessage when social embed is not allowed', () => {
render();
expect(screen.getByText('Blocked Embed Message')).toBeInTheDocument();
expect(BlockedEmbedMessage).toHaveBeenCalledWith(
expect.objectContaining({
vendorName: defaultProps.vendorName
}),
{}
);
});
it('renders Vendor component when social embed is allowed', () => {
(useSocialEmbedsContext as jest.Mock).mockReturnValue({
...mockContext,
isSocialEmbedAllowed: { twitter: true }
});
render();
expect(screen.getByText('Vendor Component')).toBeInTheDocument();
expect(Vendor).toHaveBeenCalledWith(
expect.objectContaining({
vendorName: defaultProps.vendorName,
url: defaultProps.url
}),
{}
);
});
it('calls checkVendorConsentAsync and updates context state when __tcfapi is available', () => {
const tcData = { eventStatus: eventStatus.tcLoaded };
const updatedProps = {
...defaultProps
};
render();
// First call is from the mount useEffect
expect(checkVendorConsentAsync).toHaveBeenCalledWith(
vendorName,
mockContext.setIsSocialEmbedAllowed
);
// Find the addEventListener call
const addEventListenerCall = (window.__tcfapi as jest.Mock).mock.calls.find(
(call: any[]) => call[0] === 'addEventListener'
);
expect(addEventListenerCall).toBeDefined();
expect(addEventListenerCall[1]).toBe(2);
// Simulate the callback
addEventListenerCall[2](tcData, true);
// Should have been called again from the event listener
expect(checkVendorConsentAsync).toHaveBeenCalledWith(
vendorName,
mockContext.setIsSocialEmbedAllowed
);
});
it('does not render Twitter widget if __tcfapi is unavailable', () => {
delete (window as any).__tcfapi;
render();
expect(screen.getByText('Blocked Embed Message')).toBeInTheDocument();
expect(BlockedEmbedMessage).toHaveBeenCalled();
});
it('renders Vendor component if isAllowedOnce for the vendor is true', () => {
(useSocialEmbedsContext as jest.Mock).mockReturnValue({
...mockContext,
isAllowedOnce: { twitter: true }
});
render();
expect(screen.getByText('Vendor Component')).toBeInTheDocument();
expect(Vendor).toHaveBeenCalledWith(
expect.objectContaining({
vendorName: defaultProps.vendorName,
url: defaultProps.url
}),
{}
);
});
});