internal/shape/build_test.go
Ref: Size: 2.5 KiB History
package shape
import (
"bytes"
"encoding/json"
"testing"
)
func sample() []rawPackage {
return []rawPackage{
{
ImportPath: module + "/internal/server/api",
Doc: "Package api serves the control plane HTTP API. More text.",
Imports: []string{"net/http", module + "/internal/pb", module + "/internal/server/store"},
},
{
ImportPath: module + "/internal/pb",
Doc: "",
Imports: []string{"google.golang.org/protobuf/runtime/protoimpl"},
},
}
}
func TestBuildStripsModuleClassifiesAndKeepsInternalImports(t *testing.T) {
m := Build(sample())
if m.Module != module {
t.Fatalf("Module = %q, want %q", m.Module, module)
}
if len(m.Packages) != 2 {
t.Fatalf("got %d packages, want 2", len(m.Packages))
}
// Packages are sorted by import path; find api explicitly.
var found Package
for _, p := range m.Packages {
if p.ImportPath == "internal/server/api" {
found = p
}
}
if found.Plane != PlaneControl {
t.Errorf("api plane = %q, want control", found.Plane)
}
if found.Synopsis != "Package api serves the control plane HTTP API." {
t.Errorf("api synopsis = %q", found.Synopsis)
}
// stdlib (net/http) and external imports dropped; internal kept + relative + sorted.
want := []string{"internal/pb", "internal/server/store"}
if len(found.Imports) != len(want) {
t.Fatalf("imports = %v, want %v", found.Imports, want)
}
for i := range want {
if found.Imports[i] != want[i] {
t.Errorf("imports[%d] = %q, want %q", i, found.Imports[i], want[i])
}
}
}
// A package with no internal imports must serialize as [] (empty array), not
// null. A nil Go slice marshals to JSON null, which the viewer's JS would try
// to iterate (`for (const imp of null)`) and crash on, blanking the whole
// diagram. So Imports must be a non-nil empty slice.
func TestBuildEmitsEmptyImportsArrayNotNull(t *testing.T) {
m := Build([]rawPackage{
{ImportPath: module + "/internal/pb", Imports: []string{"google.golang.org/protobuf/runtime/protoimpl"}},
})
if m.Packages[0].Imports == nil {
t.Fatal("Imports is nil; want non-nil empty slice")
}
b, err := json.Marshal(m.Packages[0])
if err != nil {
t.Fatal(err)
}
if !bytes.Contains(b, []byte(`"imports":[]`)) {
t.Errorf("expected \"imports\":[] in JSON, got: %s", b)
}
}
func TestBuildIsDeterministicRegardlessOfInputOrder(t *testing.T) {
a := sample()
b := []rawPackage{a[1], a[0]} // reversed input order
ja, _ := json.Marshal(Build(a))
jb, _ := json.Marshal(Build(b))
if !bytes.Equal(ja, jb) {
t.Errorf("Build output depends on input order:\n a=%s\n b=%s", ja, jb)
}
}