diff --git a/snapshot/src/core/cover-probe.ts b/snapshot/src/core/cover-probe.ts new file mode 100644 index 0000000..10a47d3 --- /dev/null +++ b/snapshot/src/core/cover-probe.ts @@ -0,0 +1,23 @@ +export interface ProbeResult { + reachable: boolean + status: number +} + +export type HeadFetcher = (url: string) => Promise<{ ok: boolean; status: number }> + +export const defaultHeadFetcher: HeadFetcher = async (url) => { + const resp = await fetch(url, { method: 'HEAD' }) + return { ok: resp.ok, status: resp.status } +} + +export async function probeCover( + url: string, + fetcher: HeadFetcher = defaultHeadFetcher, +): Promise { + try { + const r = await fetcher(url) + return { reachable: r.ok, status: r.status } + } catch { + return { reachable: false, status: 0 } + } +} diff --git a/snapshot/tests/cover-probe.test.ts b/snapshot/tests/cover-probe.test.ts new file mode 100644 index 0000000..34499a1 --- /dev/null +++ b/snapshot/tests/cover-probe.test.ts @@ -0,0 +1,22 @@ +import { assertEquals } from '@std/assert' +import { probeCover, type HeadFetcher } from '../src/core/cover-probe.ts' + +Deno.test('probeCover: 200 -> reachable=true', async () => { + const fetcher: HeadFetcher = async () => ({ ok: true, status: 200 }) + const r = await probeCover('https://blossom.example/abc.jpg', fetcher) + assertEquals(r, { reachable: true, status: 200 }) +}) + +Deno.test('probeCover: 404 -> reachable=false', async () => { + const fetcher: HeadFetcher = async () => ({ ok: false, status: 404 }) + const r = await probeCover('https://blossom.example/abc.jpg', fetcher) + assertEquals(r, { reachable: false, status: 404 }) +}) + +Deno.test('probeCover: network error -> reachable=false', async () => { + const fetcher: HeadFetcher = async () => { + throw new Error('ECONNREFUSED') + } + const r = await probeCover('https://blossom.example/abc.jpg', fetcher) + assertEquals(r, { reachable: false, status: 0 }) +})