clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

feat/tinyagent
tinyrelay / internal / views / views_test.go
views_test.go 3.1K
1package views23import (4 "crypto/sha256"5 "encoding/hex"6 "strings"7 "testing"8)910func TestBlocksFindFencesInOrderWithLanguages(t *testing.T) {11 content := "Intro\n\n```mermaid\ngraph TD;\n A-->B;\n```\n\nText\n\n~~~\nplain\n~~~\n\n ```` Python extra\nprint(1)\n```\nstill python\n````\n\n```dot\n"12 blocks := Blocks(content)13 if len(blocks) != 4 {14 t.Fatalf("blocks = %+v", blocks)15 }16 for i, want := range []Block{17 {0, "mermaid", "graph TD;\n A-->B;"},18 {1, "", "plain"},19 {2, "python", "print(1)\n```\nstill python"},20 {3, "dot", ""},21 } {22 if blocks[i] != want {23 t.Errorf("block %d = %+v, want %+v", i, blocks[i], want)24 }25 }26 matched := Matching(blocks, []string{"mermaid", "dot"})27 if len(matched) != 2 || matched[0].Index != 0 || matched[1].Index != 3 {28 t.Fatalf("matching = %+v", matched)29 }30 if got := Matching(blocks, []string{"go"}); got != nil {31 t.Fatalf("unexpected match %+v", got)32 }33}3435func TestFenceHelpersRejectShortAndMixedFences(t *testing.T) {36 if _, _, ok := OpenFence("``"); ok {37 t.Fatal("two backticks opened a fence")38 }39 if _, _, ok := OpenFence("text ```"); ok {40 t.Fatal("fence in the middle of a line opened a fence")41 }42 marker, lang, ok := OpenFence("~~~~ Mermaid title")43 if !ok || marker != "~~~~" || lang != "mermaid" {44 t.Fatalf("open = %q %q %v", marker, lang, ok)45 }46 if ClosesFence("~~~", marker) || ClosesFence("````", marker) || !ClosesFence(" ~~~~~ ", marker) {47 t.Fatal("closing fence rules")48 }49}5051func TestHashCoversLanguageAndSource(t *testing.T) {52 sum := sha256.Sum256([]byte("mermaid\ngraph TD"))53 if Hash("mermaid", "graph TD") != hex.EncodeToString(sum[:]) {54 t.Fatal("hash differs from sha256(lang + newline + source)")55 }56 if Hash("mermaid", "graph TD") == Hash("dot", "graph TD") {57 t.Fatal("language is not part of the hash")58 }59 if Blocks("```mermaid\na\n```")[0].Source != Blocks("```mermaid\r\na\r\n```")[0].Source {60 t.Fatal("line endings change the source")61 }62}6364func TestFigureEmbedsTheArtifactWithTheCodeAsFallback(t *testing.T) {65 got := Figure("diagrams", "mermaid", "graph TD;\n A-->B & <C>;")66 hash := Hash("mermaid", "graph TD;\n A-->B & <C>;")67 want := `<figure data-view="diagrams"><view-artifact><img src="/views/diagrams/` + hash + `" alt="Rendered mermaid block"><details><summary>Source</summary><pre><code data-lang="mermaid">graph TD;` + "\n" + ` A--&gt;B &amp; &lt;C&gt;;</code></pre></details></view-artifact></figure>` + "\n"68 if got != want {69 t.Fatalf("figure =\n%s\nwant\n%s", got, want)70 }71 if strings.Contains(got, "class=") {72 t.Fatal("figure carries a class attribute")73 }74}7576func TestRendererPicksTheFirstViewForALanguage(t *testing.T) {77 r := NewRenderer([]View{{Name: "first", Languages: []string{"mermaid"}}, {Name: "second", Languages: []string{"Mermaid", "dot"}}})78 if html, ok := r.Block("MERMAID", "x"); !ok || !strings.Contains(html, `data-view="first"`) {79 t.Fatalf("mermaid = %q %v", html, ok)80 }81 if html, ok := r.Block("dot", "x"); !ok || !strings.Contains(html, `data-view="second"`) {82 t.Fatalf("dot = %q %v", html, ok)83 }84 if _, ok := r.Block("go", "x"); ok {85 t.Fatal("go rendered")86 }87 if _, ok := (Renderer{}).Block("mermaid", "x"); ok {88 t.Fatal("empty renderer rendered")89 }90}