Files

150 lines
4.6 KiB
Go
Raw Permalink Normal View History

2026-09-18 12:03:35 +02:00
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
package post
import (
"strings"
"testing"
"sourcedock.dev/petrbalvin/volumen/internal/biblio"
)
// refsSample is a full post file with a [[refs]] array of tables, run
// through the real frontmatter parser so the metadata shape the store
// actually delivers is what is under test.
const refsSample = `+++
title = "Citující práce"
slug = "cite"
lang = "cs"
date = 2026-08-18
[[refs]]
title = "Observational evidence from supernovae"
authors = ["Riess, A. G. a kol."]
venue = "The Astronomical Journal"
year = 1998
doi = "doi:10.1103/PhysRevD.59.103502"
[[refs]]
raw = "Goldhaber, G. a kol., arXiv:astro-ph/0408076"
+++
První tvrzení [1], druhé tvrzení [2] a inline kód ` + "`list[2] = 3`" + `.
` + "```" + `go
pole[1] se nemění
` + "```" + `
` + biblio.Marker + `
`
func TestRefsParseAndWeave(t *testing.T) {
p := mustParse(t, refsSample)
refs := p.Refs()
if len(refs) != 2 {
t.Fatalf("refs = %d, want 2", len(refs))
}
if refs[0].Title == "" || refs[0].DOI != "10.1103/PhysRevD.59.103502" {
t.Fatalf("structured ref = %+v", refs[0])
}
if refs[1].ArXiv != "astro-ph/0408076" {
t.Fatalf("raw ref not enriched: %+v", refs[1])
}
// refs is reserved: it never leaks into the custom fields object.
if fields := p.CustomFields(); fields != nil {
if _, ok := fields["refs"]; ok {
t.Fatal("refs leaked into custom fields")
}
}
htmlOut, err := p.HTML()
if err != nil {
t.Fatalf("HTML: %v", err)
}
// Inline citations become anchors, the list is spliced at the marker,
// identifiers in entries become resolver links, and bracketed
// numbers inside code stay exactly as written.
for _, want := range []string{
`<a class="ref-cite" href="#ref-1">[1]</a>`,
`<section class="refs" id="references">`,
`<li id="ref-2">`,
`href="https://doi.org/10.1103/PhysRevD.59.103502"`,
"list[2] = 3",
"pole[1] se nemění",
} {
if !strings.Contains(htmlOut, want) {
t.Fatalf("html missing %q:\n%s", want, htmlOut)
}
}
if strings.Contains(htmlOut, biblio.Marker) {
t.Fatalf("marker not replaced:\n%s", htmlOut)
}
// A post without refs renders unchanged and carries none.
bare := mustParse(t, "+++\ntitle = \"T\"\nslug = \"t\"\n+++\ntext [1]\n")
if len(bare.Refs()) != 0 {
t.Fatal("bare post has refs")
}
if html, _ := bare.HTML(); strings.Contains(html, "ref-cite") {
t.Fatal("bare post got citation links")
}
}
// A save from the editor must not drop the bibliography: the form never
// carries refs, and the merge keeps untouched keys.
func TestToFileSyncPreservesRefs(t *testing.T) {
p := mustParse(t, refsSample)
out, err := p.ToFile()
if err != nil {
t.Fatalf("ToFile: %v", err)
}
if !strings.Contains(out, "[[refs]]") || !strings.Contains(out, "10.1103/PhysRevD.59.103502") {
t.Fatalf("refs lost on serialise:\n%s", out)
}
}
func TestInternalCrossLinksAtRender(t *testing.T) {
// The cited work is published under another slug in the instance:
// the rendered list links to that post, and the entry's resolver
// link disappears from the page.
p := mustParse(t, refsSample)
p.SetLinkIndex(map[string]string{"10.1103/physrevd.59.103502": "riess-1998"})
htmlOut, err := p.HTML()
if err != nil {
t.Fatalf("HTML: %v", err)
}
if !strings.Contains(htmlOut, `href="/api/volumen/posts/riess-1998"`) {
t.Fatalf("internal link missing:\n%s", htmlOut)
}
if strings.Contains(htmlOut, `href="https://doi.org/10.1103/PhysRevD.59.103502"`) {
t.Fatal("external resolver survived")
}
// The arXiv entry is not published here: it keeps its resolver.
if !strings.Contains(htmlOut, `href="https://arxiv.org/abs/astro-ph/0408076"`) {
t.Fatalf("unmatched entry lost its link:\n%s", htmlOut)
}
// A post citing its own DOI must not link to itself.
self := mustParse(t, strings.Replace(refsSample, `slug = "cite"`, `slug = "cite"
doi = "10.1103/PhysRevD.59.103502"`, 1))
self.SetLinkIndex(map[string]string{"10.1103/physrevd.59.103502": "cite"})
htmlOut, err = self.HTML()
if err != nil {
t.Fatalf("HTML: %v", err)
}
if strings.Contains(htmlOut, `href="/api/volumen/posts/cite"`) {
t.Fatal("self-link was built")
}
if !strings.Contains(htmlOut, `href="https://doi.org/10.1103/PhysRevD.59.103502"`) {
t.Fatalf("self cite lost its resolver link:\n%s", htmlOut)
}
// RefsLinked exposes the resolution to the API layer.
linked := p.RefsLinked()
if linked[0].Internal != "/api/volumen/posts/riess-1998" {
t.Fatalf("RefsLinked[0] = %+v", linked[0])
}
if linked[1].Internal != "" {
t.Fatalf("RefsLinked[1] should be external: %+v", linked[1])
}
}