Files
volumen/internal/payloads/identifiers_test.go
T
petrbalvin f8ed33df83
Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s
Initial commit
Assisted-by: GLM 5.3
2026-09-29 10:03:32 +02:00

117 lines
3.5 KiB
Go

// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
package payloads
import (
"strings"
"testing"
"sourcedock.dev/petrbalvin/volumen/internal/frontmatter"
"sourcedock.dev/petrbalvin/volumen/internal/post"
)
// The write form normalises identifiers as it stores them: a doi.org
// URL becomes the bare DOI, an iD gains its upper-case X.
func TestIdentifiersNormaliseOnWrite(t *testing.T) {
p, err := PostFromParams(map[string]string{
"title": "A paper",
"slug": "a-paper",
"body": "b",
"doi": "https://doi.org/10.5281/zenodo.1234567",
"orcid": "0000-0000-0000-001x",
}, nil)
if err != nil {
t.Fatalf("PostFromParams: %v", err)
}
if got := p.DOI(); got != "10.5281/zenodo.1234567" {
t.Fatalf("stored doi = %q", got)
}
if got := p.ORCID(); got != "0000-0000-0000-001X" {
t.Fatalf("stored orcid = %q", got)
}
// Identifiers are reserved: they never appear in the custom fields.
if fields := p.CustomFields(); fields != nil {
t.Fatalf("CustomFields leaked identifiers: %v", fields)
}
s := newStoreWithPosts(t, nil)
if err := CreationError(p, s, nil); err != nil {
t.Fatalf("valid identifiers refused: %v", err)
}
}
func TestIdentifierValidationErrors(t *testing.T) {
s := newStoreWithPosts(t, nil)
base := func(key, value string) *post.Post {
meta := frontmatter.NewMeta()
meta.Set("slug", "x")
meta.Set("title", "T")
meta.Set(key, value)
return post.New(meta, "body")
}
cases := []struct {
key, value, want string
}{
{"doi", "20.1234/x", "DOI must look like 10.xxxx/suffix."},
{"doi", "10.1", "DOI must look like 10.xxxx/suffix."},
{"orcid", "0000-0002-1825-0098", "ORCID must look like 0000-0002-1825-0097."},
{"orcid", "not-an-orcid", "ORCID must look like 0000-0002-1825-0097."},
}
for _, tc := range cases {
err := CreationError(base(tc.key, tc.value), s, nil)
if err == nil || !strings.Contains(err.Error(), tc.want) {
t.Errorf("%s %q: error = %v, want %q", tc.key, tc.value, err, tc.want)
}
}
// Both empty stay empty: the fields remain optional.
if err := CreationError(base("doi", ""), s, nil); err != nil {
t.Errorf("empty doi refused: %v", err)
}
}
// The read shapes carry the identifiers, and the SEO block publishes
// them: an identifier property on the article, one on its author.
func TestIdentifiersInPayloads(t *testing.T) {
meta := frontmatter.NewMeta()
meta.Set("slug", "paper")
meta.Set("title", "Paper")
meta.Set("author", "Petr Balvín")
meta.Set("doi", "https://doi.org/10.1000/xyz")
meta.Set("orcid", "0000-0002-1825-0097")
p := post.New(meta, "body text here")
summary := BuildSummary(p)
if summary.DOI != "10.1000/xyz" {
t.Fatalf("summary doi = %q", summary.DOI)
}
if summary.ORCID != "0000-0002-1825-0097" {
t.Fatalf("summary orcid = %q", summary.ORCID)
}
m, err := BuildMeta(p, "https://example.com")
if err != nil {
t.Fatalf("BuildMeta: %v", err)
}
for _, want := range []string{
`"identifier":"https://doi.org/10.1000/xyz"`,
`"identifier":"https://orcid.org/0000-0002-1825-0097"`,
} {
if !strings.Contains(m.JSONLD, want) {
t.Fatalf("json_ld missing %s:\n%s", want, m.JSONLD)
}
}
// A stored value that is no identifier at all survives the read
// untouched rather than vanishing.
broken := post.New(func() *frontmatter.Meta {
m := frontmatter.NewMeta()
m.Set("slug", "broken")
m.Set("doi", "10.ONE_HUNDRED/x")
return m
}(), "b")
if got := BuildSummary(broken).DOI; got != "10.ONE_HUNDRED/x" {
t.Fatalf("invalid stored doi dropped on read: %q", got)
}
}