Migration This is my new public git source viewer. Source coming soon. Please contact with concerns/bugs. Contact me

internal/modules/structured_test.go

c0427d5fc7c0fcf8606c546071085e8af231fb81 · 3.7 KB · 158 lines raw

1 package modules
2
3 import (
4 "html/template"
5 "strings"
6 "testing"
7 )
8
9 // lines builds the Line slice annotateStructure expects, mirroring what
10 // blobMod produces before the structure pass runs.
11 func lines(raw string) []Line {
12 out := []Line{}
13 for i, t := range strings.Split(raw, "\n") {
14 out = append(out, Line{N: i + 1, Text: template.HTML(t)})
15 }
16 return out
17 }
18
19 const sampleYAML = `defaults: &defaults
20 adapter: postgres
21 pool: 5
22
23 development:
24 <<: *defaults
25 database: dev
26
27 test:
28 <<: *defaults
29 database: test
30 hosts:
31 - a
32 - b
33 `
34
35 func TestFoldRangesYAML(t *testing.T) {
36 ls := lines(sampleYAML)
37 annotateStructure(ls, []byte(sampleYAML), "yaml")
38
39 want := map[int]int{
40 1: 3, // defaults: block ends at "pool: 5", not the blank line after
41 5: 7, // development:
42 9: 14, // test:, stopping short of the empty line 15
43 12: 14, // hosts:
44 }
45 for _, l := range ls {
46 if got, ok := want[l.N]; ok {
47 if l.FoldTo != got {
48 t.Errorf("line %d: FoldTo = %d, want %d", l.N, l.FoldTo, got)
49 }
50 } else if l.FoldTo != 0 {
51 t.Errorf("line %d: FoldTo = %d, want none", l.N, l.FoldTo)
52 }
53 }
54 if ls[1].Depth != 1 {
55 t.Errorf("line 2 depth = %d, want 1", ls[1].Depth)
56 }
57 if ls[13].Depth != 2 {
58 t.Errorf("line 14 depth = %d, want 2", ls[13].Depth)
59 }
60 }
61
62 func TestKeysAndAnchors(t *testing.T) {
63 ls := lines(sampleYAML)
64 annotateStructure(ls, []byte(sampleYAML), "yaml")
65
66 if ls[0].Key != "defaults" {
67 t.Errorf("line 1 key = %q, want %q", ls[0].Key, "defaults")
68 }
69 if ls[13].Key != "" {
70 t.Errorf("line 14 (sequence item) key = %q, want none", ls[13].Key)
71 }
72
73 // The anchor is reported on the line the &token is written on, not on
74 // the line the mapping it names begins.
75 a := ls[0].Anchor
76 if a == nil {
77 t.Fatal("line 1: no anchor")
78 }
79 if a.Name != "defaults" || a.Uses != 2 {
80 t.Errorf("anchor = %+v, want {defaults 2}", *a)
81 }
82
83 for _, n := range []int{6, 10} {
84 r := ls[n-1].Ref
85 if r == nil {
86 t.Fatalf("line %d: no ref", n)
87 }
88 if r.Name != "defaults" || r.Line != 1 {
89 t.Errorf("line %d ref = %+v, want defaults@1", n, *r)
90 }
91 if !strings.Contains(r.Preview, "adapter: postgres") {
92 t.Errorf("line %d preview = %q, want the resolved mapping", n, r.Preview)
93 }
94 }
95 }
96
97 // Anchors defined in the second document of a stream are still resolved:
98 // yaml.Unmarshal would only ever see the first.
99 func TestMultiDocumentAnchors(t *testing.T) {
100 const src = `---
101 kind: First
102 ---
103 base: &b
104 x: 1
105 copy: *b
106 `
107 ls := lines(src)
108 annotateStructure(ls, []byte(src), "yaml")
109
110 if ls[3].Anchor == nil || ls[3].Anchor.Name != "b" {
111 t.Fatalf("line 4 anchor = %+v, want b", ls[3].Anchor)
112 }
113 if r := ls[5].Ref; r == nil || r.Line != 4 {
114 t.Fatalf("line 6 ref = %+v, want b@4", r)
115 }
116 }
117
118 func TestFoldRangesJSON(t *testing.T) {
119 const src = `{
120 "name": "gsg",
121 "deps": {
122 "a": 1
123 },
124 "list": [
125 2
126 ]
127 }`
128 ls := lines(src)
129 annotateStructure(ls, []byte(src), "json")
130
131 if ls[0].FoldTo != 8 {
132 t.Errorf("line 1 FoldTo = %d, want 8", ls[0].FoldTo)
133 }
134 if ls[2].FoldTo != 4 {
135 t.Errorf("line 3 FoldTo = %d, want 4", ls[2].FoldTo)
136 }
137 if ls[5].FoldTo != 7 {
138 t.Errorf("line 6 FoldTo = %d, want 7", ls[5].FoldTo)
139 }
140 if ls[1].Key != "name" {
141 t.Errorf("line 2 key = %q, want %q", ls[1].Key, "name")
142 }
143 // No anchors outside YAML, and a brace inside a string is not structure.
144 if ls[1].Anchor != nil || ls[1].Ref != nil {
145 t.Error("JSON line carries anchor/ref data")
146 }
147 }
148
149 // Minified JSON has no indentation to fold on; it must degrade to a plain
150 // view rather than producing bogus ranges.
151 func TestMinifiedJSONHasNoFolds(t *testing.T) {
152 const src = `{"a":{"b":[1,2]},"c":3}`
153 ls := lines(src)
154 annotateStructure(ls, []byte(src), "json")
155 if ls[0].FoldTo != 0 {
156 t.Errorf("FoldTo = %d, want 0", ls[0].FoldTo)
157 }
158 }