My logo component, based on my next-theme’s theme I change the logo and src url for the svg:
import { useEffect, useState } from 'react';
import Image from 'next/image';
import { useTheme } from 'next-themes';
function MainLogo() {
const [themeClass, setThemeClass] = useState('');
const [weight, setWeight] = useState(200); // Default weight
const [height, setHeight] = useState(40); // Default height
const { theme } = useTheme() || {}; // Prevents destructuring from undefined
useEffect(() => {
let newThemeClass = '';
if (theme) {
switch (theme) {
case 'acme':
setWeight(100);
setHeight(30);
newThemeClass = 'acme';
break;
case 'bitcoin':
setWeight(144);
setHeight(30);
newThemeClass = 'bitcoin';
break;
case 'bounty':
default:
setWeight(200);
setHeight(40);
newThemeClass = 'bounty';
break;
}
setThemeClass(newThemeClass);
}
}, [theme]); // Run the effect whenever the theme changes
return (
<div>
<Image
src={`/internal/logo_${themeClass}.svg`}
alt="Logo"
width={weight}
height={height}
title={themeClass}
/>
</div>
);
}
export default MainLogo;
The test
Before each test I clearAllMocks, and inside of each test I use jest.mock to change the theme.
The theme is undefined.
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import MainLogo from './logo';
jest.mock('next-themes');
describe('MainLogo Component', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('renders the logo properly with the "bounty" theme', async () => {
jest.mock('next-themes', () => ({
useTheme: () => ({
theme: 'bounty', // Set the desired theme value for testing with bounty theme
}),
}));
render(<MainLogo />);
// Wait for the state to be updated
await waitFor(() => {
// Ensure that the image element with the correct alt text is rendered
const logoElement = screen.getByAltText('Logo');
expect(logoElement).toBeInTheDocument();
// Ensure that the image element has the correct width and height attributes
// expect(logoElement).toHaveAttribute('width', '200');
// expect(logoElement).toHaveAttribute('height', '40');
// Ensure that the image element has the correct title attribute
expect(logoElement).toHaveAttribute('title', 'bounty');
});
});
it('renders the logo properly with the "bitcoin" theme', async () => {
jest.mock('next-themes', () => ({
useTheme: () => ({
theme: 'bitcoin', // Set the desired theme value for testing with bitcoin theme
}),
}));
render(<MainLogo />);
// Wait for the state to be updated
await waitFor(() => {
// Ensure that the image element with the correct alt text is rendered
const logoElement = screen.getByAltText('Logo');
expect(logoElement).toBeInTheDocument();
// Ensure that the image element has the correct width and height attributes
// expect(logoElement).toHaveAttribute('width', '144');
// expect(logoElement).toHaveAttribute('height', '30');
// Ensure that the image element has the correct title attribute
expect(logoElement).toHaveAttribute('title', 'bitcoin');
});
});
});
The Error:
● MainLogo Component › renders the logo properly with the "bitcoin" theme
expect(element).toHaveAttribute("title", "bitcoin") // element.getAttribute("title") === "bitcoin"
Expected the element to have attribute:
title="bitcoin"
Received:
title=""
Ignored nodes: comments, script, style
<html>
<head />
<body>
<div>
<div>
<img
alt="Logo"
data-nimg="1"
decoding="async"
height="40"
loading="lazy"
src="/internal/logo_.svg"
style="color: transparent;"
title=""
width="200"
/>
</div>
</div>
</body>
</html>
```