joerglohrerde/publish/tests/publish_test.ts

144 lines
4.1 KiB
TypeScript

import { assertEquals } from '@std/assert'
import { type PostDeps, processPost } from '../src/subcommands/publish.ts'
import type { Frontmatter } from '../src/core/frontmatter.ts'
function makeDeps(overrides: Partial<PostDeps> = {}): PostDeps {
return {
readPostFile: () =>
Promise.resolve({
fm: {
title: 'T',
slug: 's',
date: new Date('2024-01-01'),
} as Frontmatter,
body: 'body',
}),
collectImages: () => Promise.resolve([]),
uploadBlossom: (args) =>
Promise.resolve({
ok: ['https://b1'],
failed: [],
primaryUrl: `https://b1/${args.fileName}-hash`,
sha256: 'hash',
}),
sign: (ev) => Promise.resolve({ ...ev, id: 'ev-id', sig: 'sig' }),
publish: () => Promise.resolve({ ok: ['wss://r1', 'wss://r2'], failed: [] }),
checkExisting: () => Promise.resolve(false),
...overrides,
}
}
function baseArgs(deps = makeDeps()) {
return {
postDir: '/p/s',
writeRelays: ['wss://r1', 'wss://r2'],
blossomServers: ['https://b1'],
pubkeyHex: 'a'.repeat(64),
clientTag: 'test-client',
minRelayAcks: 2,
deps,
}
}
Deno.test('processPost: happy-path neu, ohne bilder', async () => {
const result = await processPost(baseArgs())
assertEquals(result.status, 'success')
assertEquals(result.action, 'new')
assertEquals(result.eventId, 'ev-id')
assertEquals(result.relaysOk.length, 2)
})
Deno.test('processPost: draft wird geskippt', async () => {
const deps = makeDeps({
readPostFile: () =>
Promise.resolve({
fm: {
title: 'T',
slug: 's',
date: new Date('2024-01-01'),
draft: true,
} as Frontmatter,
body: 'b',
}),
})
const result = await processPost({ ...baseArgs(deps), writeRelays: ['wss://r1'] })
assertEquals(result.status, 'skipped-draft')
})
Deno.test('processPost: zu wenig relay-acks → failed', async () => {
const deps = makeDeps({
publish: () =>
Promise.resolve({ ok: ['wss://r1'], failed: ['wss://r2', 'wss://r3', 'wss://r4'] }),
})
const result = await processPost({
...baseArgs(deps),
writeRelays: ['wss://r1', 'wss://r2', 'wss://r3', 'wss://r4'],
})
assertEquals(result.status, 'failed')
assertEquals(String(result.error).includes('relays'), true)
})
Deno.test('processPost: konfigurierbarer minRelayAcks', async () => {
const deps = makeDeps({
publish: () => Promise.resolve({ ok: ['wss://r1'], failed: ['wss://r2'] }),
})
const result = await processPost({
...baseArgs(deps),
writeRelays: ['wss://r1', 'wss://r2'],
minRelayAcks: 1,
})
assertEquals(result.status, 'success')
})
Deno.test('processPost: bestehender d-tag → action = update', async () => {
const result = await processPost(
baseArgs(makeDeps({ checkExisting: () => Promise.resolve(true) })),
)
assertEquals(result.status, 'success')
assertEquals(result.action, 'update')
})
Deno.test('processPost: bilder landen auf blossom, body wird rewritten', async () => {
const uploaded: string[] = []
const deps = makeDeps({
readPostFile: () =>
Promise.resolve({
fm: {
title: 'T',
slug: 's',
date: new Date('2024-01-01'),
cover: { image: 'cover.png' },
} as Frontmatter,
body: 'Pic: ![x](a.png) cover ![c](cover.png)',
}),
collectImages: () =>
Promise.resolve([
{
fileName: 'a.png',
absolutePath: '/p/s/a.png',
data: new Uint8Array([1]),
mimeType: 'image/png',
},
{
fileName: 'cover.png',
absolutePath: '/p/s/cover.png',
data: new Uint8Array([2]),
mimeType: 'image/png',
},
]),
uploadBlossom: (args) => {
uploaded.push(args.fileName)
return Promise.resolve({
ok: ['https://b1'],
failed: [],
primaryUrl: `https://b1/${args.fileName}-hash`,
sha256: 'h',
})
},
})
const result = await processPost(baseArgs(deps))
assertEquals(result.status, 'success')
assertEquals(uploaded.sort(), ['a.png', 'cover.png'])
assertEquals(result.imagesUploaded, 2)
})