Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

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 (?:)")
}
}