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' }) })); });