diff --git a/src/core/browser.test.ts b/src/core/browser.test.ts new file mode 100644 index 0000000..d0c870e --- /dev/null +++ b/src/core/browser.test.ts @@ -0,0 +1,39 @@ +import { describe, it, expect, vi, beforeEach } from 'vitest' + +const openMock = vi.fn<(...args: [string]) => Promise>() + +vi.mock('open', () => ({ + default: (url: string) => openMock(url), +})) + +import { openUrlSafe } from './browser.js' + +describe('openUrlSafe', () => { + beforeEach(() => { + openMock.mockReset() + }) + + it('forwards url to open', () => { + openMock.mockResolvedValue(undefined) + const onError = vi.fn<(message: string) => void>() + + openUrlSafe('https://www.pixelmuse.studio/g/gen_123', onError) + + expect(openMock).toHaveBeenCalledWith('https://www.pixelmuse.studio/g/gen_123') + expect(onError).not.toHaveBeenCalled() + }) + + it('surfaces failures without throwing', async () => { + openMock.mockRejectedValue(new Error('No browser available')) + const onError = vi.fn<(message: string) => void>() + + expect(() => { + openUrlSafe('https://www.pixelmuse.studio/g/gen_456', onError) + }).not.toThrow() + + await Promise.resolve() + await Promise.resolve() + + expect(onError).toHaveBeenCalledWith('No browser available') + }) +}) diff --git a/src/core/browser.ts b/src/core/browser.ts new file mode 100644 index 0000000..55819e3 --- /dev/null +++ b/src/core/browser.ts @@ -0,0 +1,7 @@ +import open from 'open' + +export function openUrlSafe(url: string, onError: (message: string) => void): void { + void open(url).catch((err: unknown) => { + onError(err instanceof Error ? err.message : 'Failed to open browser') + }) +} diff --git a/src/screens/GalleryDetail.tsx b/src/screens/GalleryDetail.tsx index 5953137..6d65a89 100644 --- a/src/screens/GalleryDetail.tsx +++ b/src/screens/GalleryDetail.tsx @@ -1,9 +1,9 @@ import React, { useState, useEffect } from 'react' import { Box, Text, useInput } from 'ink' import { ConfirmInput, Spinner } from '@inkjs/ui' -import open from 'open' import type { PixelmuseClient } from '../core/client.js' import type { Generation } from '../core/types.js' +import { openUrlSafe } from '../core/browser.js' import { imageToBuffer, autoSave } from '../core/image.js' import ImagePreview from '../components/ImagePreview.js' @@ -49,7 +49,9 @@ export default function GalleryDetail({ client, generationId, back }: Props) { if (confirming) return if (input === 'd') setConfirming(true) if (input === 'o' && generation) { - open(`https://www.pixelmuse.studio/g/${generation.id}`) + openUrlSafe(`https://www.pixelmuse.studio/g/${generation.id}`, (message) => { + setError(message) + }) } })