diff --git a/src/shared/ui/ImageLightbox/ui/ImageLightbox.test.tsx b/src/shared/ui/ImageLightbox/ui/ImageLightbox.test.tsx
new file mode 100644
index 0000000..07e1537
--- /dev/null
+++ b/src/shared/ui/ImageLightbox/ui/ImageLightbox.test.tsx
@@ -0,0 +1,68 @@
+import { fireEvent, render, screen } from '@testing-library/react';
+import { ImageLightbox } from './ImageLightbox';
+
+// jsdom does not implement dialog methods — mock them
+beforeAll(() => {
+ HTMLDialogElement.prototype.showModal = vi.fn();
+ HTMLDialogElement.prototype.close = vi.fn();
+});
+
+beforeEach(() => {
+ vi.clearAllMocks();
+});
+
+const DEFAULT_PROPS = { src: '/project.jpg', alt: 'My Project' };
+
+describe('ImageLightbox', () => {
+ describe('thumbnail', () => {
+ it('renders a thumbnail image', () => {
+ render();
+ expect(screen.getByRole('img', { name: 'My Project' })).toBeInTheDocument();
+ });
+
+ it('thumbnail button has cursor-zoom-in', () => {
+ render();
+ const btn = screen.getByRole('button', { name: 'My Project' });
+ expect(btn).toHaveClass('cursor-zoom-in');
+ });
+
+ it('forwards className to the thumbnail button', () => {
+ render();
+ expect(screen.getByRole('button', { name: 'My Project' })).toHaveClass('extra-class');
+ });
+ });
+
+ describe('dialog', () => {
+ it('clicking the thumbnail opens the dialog', () => {
+ render();
+ fireEvent.click(screen.getByRole('button', { name: 'My Project' }));
+ expect(HTMLDialogElement.prototype.showModal).toHaveBeenCalledTimes(1);
+ });
+
+ it('clicking the close button closes the dialog', () => {
+ render();
+ fireEvent.click(screen.getByRole('button', { name: /close/i }));
+ expect(HTMLDialogElement.prototype.close).toHaveBeenCalledTimes(1);
+ });
+
+ it('clicking the backdrop (dialog element itself) closes the dialog', () => {
+ render();
+ const dialog = document.querySelector('dialog')!;
+ fireEvent.click(dialog, { target: dialog });
+ expect(HTMLDialogElement.prototype.close).toHaveBeenCalledTimes(1);
+ });
+
+ it('clicking inside the dialog (not backdrop) does not close', () => {
+ render();
+ const dialog = document.querySelector('dialog')!;
+ const inner = dialog.querySelector('div')!;
+ fireEvent.click(inner);
+ expect(HTMLDialogElement.prototype.close).not.toHaveBeenCalled();
+ });
+
+ it('dialog has accessible label matching alt text', () => {
+ render();
+ expect(document.querySelector('dialog')).toHaveAttribute('aria-label', 'My Project');
+ });
+ });
+});