1 package jq
2
3 import (
4 "bytes"
5 "io"
6 "strings"
7 "testing"
8
9 "github.com/MakeNowJust/heredoc"
10 "github.com/stretchr/testify/assert"
11 )
12
13 func TestEvaluateFormatted(t *testing.T) {
14 t.Setenv("CODE", "code_c")
15 type args struct {
16 json io.Reader
17 expr string
18 indent string
19 colorize bool
20 }
21 tests := []struct {
22 name string
23 args args
24 wantW string
25 wantErr bool
26 wantErrMsg string
27 }{
28 {
29 name: "simple",
30 args: args{
31 json: strings.NewReader(`{"name":"Mona", "arms":8}`),
32 expr: `.name`,
33 indent: "",
34 colorize: false,
35 },
36 wantW: "Mona\n",
37 },
38 {
39 name: "multiple queries",
40 args: args{
41 json: strings.NewReader(`{"name":"Mona", "arms":8}`),
42 expr: `.name,.arms`,
43 indent: "",
44 colorize: false,
45 },
46 wantW: "Mona\n8\n",
47 },
48 {
49 name: "object as JSON",
50 args: args{
51 json: strings.NewReader(`{"user":{"login":"monalisa"}}`),
52 expr: `.user`,
53 indent: "",
54 colorize: false,
55 },
56 wantW: "{\"login\":\"monalisa\"}\n",
57 },
58 {
59 name: "object as JSON, indented",
60 args: args{
61 json: strings.NewReader(`{"user":{"login":"monalisa"}}`),
62 expr: `.user`,
63 indent: " ",
64 colorize: false,
65 },
66 wantW: "{\n \"login\": \"monalisa\"\n}\n",
67 },
68 {
69 name: "object as JSON, indented & colorized",
70 args: args{
71 json: strings.NewReader(`{"user":{"login":"monalisa"}}`),
72 expr: `.user`,
73 indent: " ",
74 colorize: true,
75 },
76 wantW: "\x1b[1;38m{\x1b[m\n" +
77 " \x1b[1;34m\"login\"\x1b[m\x1b[1;38m:\x1b[m" +
78 " \x1b[32m\"monalisa\"\x1b[m\n" +
79 "\x1b[1;38m}\x1b[m\n",
80 },
81 {
82 name: "empty array",
83 args: args{
84 json: strings.NewReader(`[]`),
85 expr: `., [], unique`,
86 indent: "",
87 colorize: false,
88 },
89 wantW: "[]\n[]\n[]\n",
90 },
91 {
92 name: "empty array, colorized",
93 args: args{
94 json: strings.NewReader(`[]`),
95 expr: `.`,
96 indent: "",
97 colorize: true,
98 },
99 wantW: "\x1b[1;38m[\x1b[m\x1b[1;38m]\x1b[m\n",
100 },
101 {
102 name: "complex",
103 args: args{
104 json: strings.NewReader(heredoc.Doc(`[
105 {
106 "title": "First title",
107 "labels": [{"name":"bug"}, {"name":"help wanted"}]
108 },
109 {
110 "title": "Second but not last",
111 "labels": []
112 },
113 {
114 "title": "Alas, tis' the end",
115 "labels": [{}, {"name":"feature"}]
116 }
117 ]`)),
118 expr: `.[] | [.title,(.labels | map(.name) | join(","))] | @tsv`,
119 indent: "",
120 colorize: false,
121 },
122 wantW: heredoc.Doc(`
123 First title bug,help wanted
124 Second but not last
125 Alas, tis' the end ,feature
126 `),
127 },
128 {
129 name: "with env var",
130 args: args{
131 json: strings.NewReader(heredoc.Doc(`[
132 {
133 "title": "code_a",
134 "labels": [{"name":"bug"}, {"name":"help wanted"}]
135 },
136 {
137 "title": "code_b",
138 "labels": []
139 },
140 {
141 "title": "code_c",
142 "labels": [{}, {"name":"feature"}]
143 }
144 ]`)),
145 expr: `.[] | select(.title == env.CODE) | .labels`,
146 indent: " ",
147 colorize: false,
148 },
149 wantW: "[\n {},\n {\n \"name\": \"feature\"\n }\n]\n",
150 },
151 {
152 name: "mixing scalars, arrays and objects",
153 args: args{
154 json: strings.NewReader(heredoc.Doc(`[
155 "foo",
156 true,
157 42,
158 [17, 23],
159 {"foo": "bar"}
160 ]`)),
161 expr: `.[]`,
162 indent: " ",
163 colorize: true,
164 },
165 wantW: "foo\ntrue\n42\n" +
166 "\x1b[1;38m[\x1b[m\n" +
167 " 17\x1b[1;38m,\x1b[m\n" +
168 " 23\n" +
169 "\x1b[1;38m]\x1b[m\n" +
170 "\x1b[1;38m{\x1b[m\n" +
171 " \x1b[1;34m\"foo\"\x1b[m\x1b[1;38m:\x1b[m" +
172 " \x1b[32m\"bar\"\x1b[m\n" +
173 "\x1b[1;38m}\x1b[m\n",
174 },
175 {
176 name: "halt function",
177 args: args{
178 json: strings.NewReader("{}"),
179 expr: `1,halt,2`,
180 },
181 wantW: "1\n",
182 },
183 {
184 name: "halt_error function",
185 args: args{
186 json: strings.NewReader("{}"),
187 expr: `1,halt_error,2`,
188 },
189 wantW: "1\n",
190 wantErr: true,
191 wantErrMsg: "halt error: {}",
192 },
193 {
194 name: "invalid one-line query",
195 args: args{
196 json: strings.NewReader("{}"),
197 expr: `[1,2,,3]`,
198 },
199 wantErr: true,
200 wantErrMsg: `failed to parse jq expression (line 1, column 6)
201 [1,2,,3]
202 ^ unexpected token ","`,
203 },
204 {
205 name: "invalid multi-line query",
206 args: args{
207 json: strings.NewReader("{}"),
208 expr: `[
209 1,,2
210 ,3]`,
211 },
212 wantErr: true,
213 wantErrMsg: `failed to parse jq expression (line 2, column 5)
214 1,,2
215 ^ unexpected token ","`,
216 },
217 {
218 name: "invalid unterminated query",
219 args: args{
220 json: strings.NewReader("{}"),
221 expr: `[1,`,
222 },
223 wantErr: true,
224 wantErrMsg: `failed to parse jq expression (line 1, column 4)
225 [1,
226 ^ unexpected EOF`,
227 },
228 }
229 for _, tt := range tests {
230 t.Run(tt.name, func(t *testing.T) {
231 w := &bytes.Buffer{}
232 err := EvaluateFormatted(tt.args.json, w, tt.args.expr, tt.args.indent, tt.args.colorize)
233 if tt.wantErr {
234 assert.Error(t, err)
235 assert.EqualError(t, err, tt.wantErrMsg)
236 return
237 }
238 assert.NoError(t, err)
239 assert.Equal(t, tt.wantW, w.String())
240 })
241 }
242 }
243
View as plain text