import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { vi, test, expect, beforeEach } from 'vitest';
vi.mock('../utils/verseCard.js', async (orig) => ({
...(await orig()),
renderVerseCard: vi.fn(async () => new Blob(['png'], { type: 'image/png' })),
shareOrSaveImage: vi.fn(async () => 'saved'),
}));
vi.mock('./Toasts.jsx', () => ({ useToast: () => ({ toast: vi.fn() }) }));
import VerseShareImage from './VerseShareImage.jsx';
import { renderVerseCard, shareOrSaveImage } from '../utils/verseCard.js';
beforeEach(() => {
localStorage.clear();
vi.clearAllMocks();
URL.createObjectURL = vi.fn(() => 'blob:card');
URL.revokeObjectURL = vi.fn();
});
const props = { text: 'For God so loved the world.', reference: 'John 3:16', translation: 'BSB' };
test('previews the card, redraws when the look changes, and remembers the look', async () => {
const user = userEvent.setup();
render();
expect(await screen.findByAltText(/John 3:16 \(BSB\) as a picture/)).toBeInTheDocument();
expect(renderVerseCard).toHaveBeenLastCalledWith(expect.objectContaining({ themeId: 'paper', reference: 'John 3:16' }));
await user.click(screen.getByRole('button', { name: 'Dark' }));
await screen.findByAltText(/as a picture/);
expect(renderVerseCard).toHaveBeenLastCalledWith(expect.objectContaining({ themeId: 'dark' }));
expect(localStorage.getItem('verse-card-style')).toBe('dark');
});
test('Save/Share sends the image under a file name from the reference', async () => {
const user = userEvent.setup();
render();
await screen.findByAltText(/as a picture/);
await user.click(screen.getByRole('button', { name: /save image|share image/i }));
expect(shareOrSaveImage).toHaveBeenCalledWith(expect.any(Blob), 'john-3-16.png', expect.objectContaining({ title: 'John 3:16' }));
});
test('says so if the picture can\'t be drawn', async () => {
renderVerseCard.mockRejectedValueOnce(new Error('This browser can’t draw the image.'));
render();
expect(await screen.findByRole('alert')).toHaveTextContent(/can’t draw/);
});
test('a background picture can be chosen, and is passed to the card; the plain looks come back with Plain', async () => {
const user = userEvent.setup();
render();
await screen.findByAltText(/as a picture/);
expect(screen.getByRole('group', { name: /image style/i })).toBeInTheDocument();
await user.selectOptions(screen.getByLabelText('Image background'), 'sea');
await screen.findByAltText(/as a picture/);
expect(renderVerseCard).toHaveBeenLastCalledWith(expect.objectContaining({ background: { kind: 'scene', id: 'sea' } }));
expect(screen.queryByRole('group', { name: /image style/i })).toBeNull(); // theme looks only apply to the plain card
await user.selectOptions(screen.getByLabelText('Image background'), 'plain');
expect(renderVerseCard).toHaveBeenLastCalledWith(expect.objectContaining({ background: null }));
});
test('the picture of the day is used when the Home card passes it in', async () => {
render();
await screen.findByAltText(/as a picture/);
expect(renderVerseCard).toHaveBeenLastCalledWith(expect.objectContaining({ background: expect.objectContaining({ kind: 'scene' }) }));
});