The adapter response now carries telegram_message_id and a t.me/c link. compose visual resolves a post's image: own visual_url, else the entry's rendered portrait, else hold an entry with only a visual prompt, else the HelixForge main image. send-post.sh resolves before touching credentials, requires an image on public posts and runs the adapter with ATTACH_VISUAL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 5457@bnt-lap001 Assistant-Session: 792bf84a-3783-4f5d-a811-cded61dd2012
74 lines
2.4 KiB
Go
74 lines
2.4 KiB
Go
package compose
|
|
|
|
import "testing"
|
|
|
|
const hallRaw = "https://forge.example/coulomb/hall-of-helix/raw/branch/main"
|
|
const fallback = "https://forge.example/coulomb/pr-hall-of-helix/raw/branch/main/assets/helix-forge.png"
|
|
|
|
func TestResolveVisualPrefersRenderedPortrait(t *testing.T) {
|
|
entry := "# Seat\n\n## Visual prompt\n\n> Constellation dialect.\n\n\n\n## Handoff\n"
|
|
v, err := ResolveVisual(entry, hallRaw, fallback)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if v.Kind != VisualPortrait || v.Path != "visuals/bernd-how-it-started.png" ||
|
|
v.URL != hallRaw+"/visuals/bernd-how-it-started.png" {
|
|
t.Fatalf("got %+v", v)
|
|
}
|
|
}
|
|
|
|
func TestResolveVisualPromptWithoutPortraitNeedsRender(t *testing.T) {
|
|
entry := "# Seat\n\n## Visual prompt\n\n> Constellation dialect. Square.\n> Brass scales.\n\n" +
|
|
"<!--  -->\n\n" +
|
|
"_Draft: portrait not yet rendered, expected as `claude-x-scales.jpg`._\n\n## Handoff\n"
|
|
v, err := ResolveVisual(entry, hallRaw, fallback)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if v.Kind != VisualNeedsRender || v.URL != "" {
|
|
t.Fatalf("a commented-out portrait or the fallback was used: %+v", v)
|
|
}
|
|
if v.Prompt != "Constellation dialect. Square. Brass scales." {
|
|
t.Fatalf("prompt = %q", v.Prompt)
|
|
}
|
|
if v.Target != "visuals/claude-x-scales.jpg" {
|
|
t.Fatalf("target = %q", v.Target)
|
|
}
|
|
}
|
|
|
|
func TestResolveVisualFallsBackOnlyWithoutPrompt(t *testing.T) {
|
|
for _, entry := range []string{"", "# Seat\n\n## Handoff\n\nNothing visual.\n"} {
|
|
v, err := ResolveVisual(entry, hallRaw, fallback)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if v.Kind != VisualFallback || v.URL != fallback {
|
|
t.Fatalf("entry %q: got %+v", entry, v)
|
|
}
|
|
}
|
|
if _, err := ResolveVisual("", hallRaw, ""); err == nil {
|
|
t.Fatal("resolved with no fallback configured")
|
|
}
|
|
}
|
|
|
|
func TestResolveVisualIgnoresExternalImages(t *testing.T) {
|
|
entry := "# Seat\n\n\n"
|
|
v, err := ResolveVisual(entry, hallRaw, fallback)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if v.Kind != VisualFallback {
|
|
t.Fatalf("got %+v", v)
|
|
}
|
|
}
|
|
|
|
func TestResolveVisualTargetFromBareFileName(t *testing.T) {
|
|
entry := "# Seat\n\n## Visual prompt\n\n> Scales.\n\n_Draft: expected under `visuals/` as `claude-y-scales.jpg`._\n"
|
|
v, err := ResolveVisual(entry, hallRaw, fallback)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if v.Target != "visuals/claude-y-scales.jpg" {
|
|
t.Fatalf("target = %q", v.Target)
|
|
}
|
|
}
|