a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
99 lines
3.0 KiB
Go
99 lines
3.0 KiB
Go
package contracts
|
|
|
|
import "testing"
|
|
|
|
// TestExtractTSShape_NestedAnonymousObject is the regression for the
|
|
// React duplicate-key warning that the dashboard fired on
|
|
// /v1/dashboard. The web `DashboardSnapshot` type literal contains
|
|
// an inline anonymous `stats: { ... }` whose fields collide with
|
|
// the outer ones (`repos`, `caveats`). The pre-fix extractor walked
|
|
// every line in the body, so the inner Stats fields were emitted
|
|
// alongside the outer arrays — producing duplicate `repos` /
|
|
// `caveats` rows in the shape and two React children with the same
|
|
// key in the rendered table.
|
|
//
|
|
// Fix: track brace depth and only emit fields at depth 0 (direct
|
|
// members of the outer `{`). Inline-object fields drop their nested
|
|
// members; the parent field itself still appears with type `{...}`
|
|
// so the structure isn't lost.
|
|
func TestExtractTSShape_NestedAnonymousObject(t *testing.T) {
|
|
src := []byte(`export type DashboardSnapshot = {
|
|
stats: {
|
|
total_nodes: number
|
|
total_edges: number
|
|
repos: number
|
|
caveats: number
|
|
version: string
|
|
}
|
|
kinds: KindCount[]
|
|
languages: LanguageCount[]
|
|
repos: Repo[]
|
|
activity: Activity[]
|
|
caveats: Caveat[]
|
|
processes: Process[]
|
|
}
|
|
`)
|
|
shape := extractTSShape(src, 1, 15)
|
|
if shape == nil {
|
|
t.Fatal("expected non-nil shape")
|
|
}
|
|
seen := map[string]int{}
|
|
for _, f := range shape.Fields {
|
|
seen[f.Name]++
|
|
}
|
|
for name, count := range seen {
|
|
if count > 1 {
|
|
t.Errorf("field %q appears %d times — duplicate names hoist nested object into parent", name, count)
|
|
}
|
|
}
|
|
wantTopLevel := []string{"stats", "kinds", "languages", "repos", "activity", "caveats", "processes"}
|
|
for _, name := range wantTopLevel {
|
|
if seen[name] != 1 {
|
|
t.Errorf("top-level field %q expected once, got %d", name, seen[name])
|
|
}
|
|
}
|
|
// total_nodes is unique to the inner Stats object — its presence
|
|
// proves the bug recurred.
|
|
if seen["total_nodes"] > 0 {
|
|
t.Errorf("inner Stats.total_nodes leaked into outer shape (hoisting regression)")
|
|
}
|
|
// The parent `stats` field MUST be recorded with the normalised
|
|
// inline-object label rather than a stray opening brace, so the
|
|
// dashboard renders something readable.
|
|
for _, f := range shape.Fields {
|
|
if f.Name == "stats" {
|
|
if f.Type != "{...}" {
|
|
t.Errorf("stats type: want %q, got %q", "{...}", f.Type)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestExtractTSShape_FlatInterfaceUnchanged guards against the
|
|
// brace-depth tracking accidentally suppressing fields in a normal
|
|
// flat interface — the hot path that has to keep working.
|
|
func TestExtractTSShape_FlatInterfaceUnchanged(t *testing.T) {
|
|
src := []byte(`export interface User {
|
|
id: string
|
|
name: string
|
|
email?: string
|
|
}
|
|
`)
|
|
shape := extractTSShape(src, 1, 5)
|
|
if shape == nil {
|
|
t.Fatal("expected non-nil shape")
|
|
}
|
|
if len(shape.Fields) != 3 {
|
|
t.Fatalf("want 3 fields, got %d", len(shape.Fields))
|
|
}
|
|
want := []string{"id", "name", "email"}
|
|
for i, w := range want {
|
|
if shape.Fields[i].Name != w {
|
|
t.Errorf("field %d: want %q, got %q", i, w, shape.Fields[i].Name)
|
|
}
|
|
}
|
|
if shape.Fields[2].Required {
|
|
t.Errorf("email should be optional (?:)")
|
|
}
|
|
}
|