Skip to content

Commit 04f87c9

Browse files
committed
refactor remaining tests for readability
1 parent afd52ea commit 04f87c9

File tree

1 file changed

+138
-91
lines changed

1 file changed

+138
-91
lines changed

query/encode_test.go

Lines changed: 138 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package query
66

77
import (
8+
"errors"
89
"fmt"
910
"net/url"
1011
"reflect"
@@ -230,12 +231,12 @@ func TestValues_NestedTypes(t *testing.T) {
230231
}{
231232
Nested{
232233
A: SubNested{
233-
Value: "that",
234+
Value: "v",
234235
},
235236
},
236237
},
237238
url.Values{
238-
"nest[a][value]": {"that"},
239+
"nest[a][value]": {"v"},
239240
"nest[b]": {""},
240241
},
241242
},
@@ -245,14 +246,14 @@ func TestValues_NestedTypes(t *testing.T) {
245246
}{
246247
Nested{
247248
Ptr: &SubNested{
248-
Value: "that",
249+
Value: "v",
249250
},
250251
},
251252
},
252253
url.Values{
253254
"nest[a][value]": {""},
254255
"nest[b]": {""},
255-
"nest[ptr][value]": {"that"},
256+
"nest[ptr][value]": {"v"},
256257
},
257258
},
258259
{
@@ -266,132 +267,178 @@ func TestValues_NestedTypes(t *testing.T) {
266267
}
267268
}
268269

269-
func TestValues_omitEmpty(t *testing.T) {
270+
func TestValues_OmitEmpty(t *testing.T) {
270271
str := ""
271-
s := struct {
272-
a string
273-
A string
274-
B string `url:",omitempty"`
275-
C string `url:"-"`
276-
D string `url:"omitempty"` // actually named omitempty, not an option
277-
E *string `url:",omitempty"`
278-
}{E: &str}
279-
280-
v, err := Values(s)
281-
if err != nil {
282-
t.Errorf("Values(%v) returned error: %v", s, err)
283-
}
284272

285-
want := url.Values{
286-
"A": {""},
287-
"omitempty": {""},
288-
"E": {""}, // E is included because the pointer is not empty, even though the string being pointed to is
289-
}
290-
if !reflect.DeepEqual(want, v) {
291-
t.Errorf("Values(%v) returned %v, want %v", s, v, want)
273+
tests := []struct {
274+
input interface{}
275+
want url.Values
276+
}{
277+
{struct{ v string }{}, url.Values{}}, // non-exported field
278+
{
279+
struct {
280+
V string `url:",omitempty"`
281+
}{},
282+
url.Values{},
283+
},
284+
{
285+
struct {
286+
V string `url:"-"`
287+
}{},
288+
url.Values{},
289+
},
290+
{
291+
struct {
292+
V string `url:"omitempty"` // actually named omitempty
293+
}{},
294+
url.Values{"omitempty": {""}},
295+
},
296+
{
297+
// include value for a non-nil pointer to an empty value
298+
struct {
299+
V *string `url:",omitempty"`
300+
}{&str},
301+
url.Values{"V": {""}},
302+
},
292303
}
293-
}
294-
295-
type A struct {
296-
B
297-
}
298304

299-
type B struct {
300-
C string
301-
}
302-
303-
type D struct {
304-
B
305-
C string
306-
}
307-
308-
type e struct {
309-
B
310-
C string
305+
for _, tt := range tests {
306+
testValue(t, tt.input, tt.want)
307+
}
311308
}
312309

313-
type F struct {
314-
e
315-
}
310+
func TestValues_EmbeddedStructs(t *testing.T) {
311+
type Inner struct {
312+
V string
313+
}
314+
type Outer struct {
315+
Inner
316+
}
317+
type Mixed struct {
318+
Inner
319+
V string
320+
}
321+
type unexported struct {
322+
Inner
323+
V string
324+
}
325+
type Exported struct {
326+
unexported
327+
}
316328

317-
func TestValues_embeddedStructs(t *testing.T) {
318329
tests := []struct {
319-
in interface{}
320-
want url.Values
330+
input interface{}
331+
want url.Values
321332
}{
322333
{
323-
A{B{C: "foo"}},
324-
url.Values{"C": {"foo"}},
334+
Outer{Inner{V: "a"}},
335+
url.Values{"V": {"a"}},
325336
},
326337
{
327-
D{B: B{C: "bar"}, C: "foo"},
328-
url.Values{"C": {"foo", "bar"}},
338+
Mixed{Inner: Inner{V: "a"}, V: "b"},
339+
url.Values{"V": {"b", "a"}},
329340
},
330341
{
331-
F{e{B: B{C: "bar"}, C: "foo"}}, // With unexported embed
332-
url.Values{"C": {"foo", "bar"}},
342+
// values from unexported embed are still included
343+
Exported{
344+
unexported{
345+
Inner: Inner{V: "bar"},
346+
V: "foo",
347+
},
348+
},
349+
url.Values{"V": {"foo", "bar"}},
333350
},
334351
}
335352

336-
for i, tt := range tests {
337-
v, err := Values(tt.in)
338-
if err != nil {
339-
t.Errorf("%d. Values(%q) returned error: %v", i, tt.in, err)
340-
}
341-
342-
if !reflect.DeepEqual(tt.want, v) {
343-
t.Errorf("%d. Values(%q) returned %v, want %v", i, tt.in, v, tt.want)
344-
}
353+
for _, tt := range tests {
354+
testValue(t, tt.input, tt.want)
345355
}
346356
}
347357

348-
func TestValues_invalidInput(t *testing.T) {
358+
func TestValues_InvalidInput(t *testing.T) {
349359
_, err := Values("")
350360
if err == nil {
351361
t.Errorf("expected Values() to return an error on invalid input")
352362
}
353363
}
354364

355-
type EncodedArgs []string
365+
// customEncodedStrings is a slice of strings with a custom URL encoding
366+
type customEncodedStrings []string
356367

357-
func (m EncodedArgs) EncodeValues(key string, v *url.Values) error {
368+
// EncodeValues using key name of the form "{key}.N" where N increments with
369+
// each value. A value of "err" will return an error.
370+
func (m customEncodedStrings) EncodeValues(key string, v *url.Values) error {
358371
for i, arg := range m {
372+
if arg == "err" {
373+
return errors.New("encoding error")
374+
}
359375
v.Set(fmt.Sprintf("%s.%d", key, i), arg)
360376
}
361377
return nil
362378
}
363379

364-
func TestValues_Marshaler(t *testing.T) {
365-
s := struct {
366-
Args EncodedArgs `url:"arg"`
367-
}{[]string{"a", "b", "c"}}
368-
v, err := Values(s)
369-
if err != nil {
370-
t.Errorf("Values(%q) returned error: %v", s, err)
371-
}
380+
func TestValues_CustomEncoding(t *testing.T) {
381+
tests := []struct {
382+
input interface{}
383+
want url.Values
384+
}{
385+
{
386+
struct {
387+
V customEncodedStrings `url:"v"`
388+
}{},
389+
url.Values{},
390+
},
391+
{
392+
struct {
393+
V customEncodedStrings `url:"v"`
394+
}{[]string{"a", "b"}},
395+
url.Values{"v.0": {"a"}, "v.1": {"b"}},
396+
},
372397

373-
want := url.Values{
374-
"arg.0": {"a"},
375-
"arg.1": {"b"},
376-
"arg.2": {"c"},
398+
// pointers to custom encoded types
399+
{
400+
struct {
401+
V *customEncodedStrings `url:"v"`
402+
}{},
403+
url.Values{},
404+
},
405+
{
406+
struct {
407+
V *customEncodedStrings `url:"v"`
408+
}{(*customEncodedStrings)(&[]string{"a", "b"})},
409+
url.Values{"v.0": {"a"}, "v.1": {"b"}},
410+
},
377411
}
378-
if !reflect.DeepEqual(want, v) {
379-
t.Errorf("Values(%q) returned %v, want %v", s, v, want)
412+
413+
for _, tt := range tests {
414+
testValue(t, tt.input, tt.want)
380415
}
381416
}
382417

383-
func TestValues_MarshalerWithNilPointer(t *testing.T) {
384-
s := struct {
385-
Args *EncodedArgs `url:"arg"`
386-
}{}
387-
v, err := Values(s)
388-
if err != nil {
389-
t.Errorf("Values(%v) returned error: %v", s, err)
418+
// One of the few ways reflectValues will return an error is if a custom
419+
// encoder returns an error. Test all of the various ways that can happen.
420+
func TestValues_CustomEncoding_Error(t *testing.T) {
421+
type st struct {
422+
V customEncodedStrings
390423
}
391-
392-
want := url.Values{}
393-
if !reflect.DeepEqual(want, v) {
394-
t.Errorf("Values(%v) returned %v, want %v", s, v, want)
424+
tests := []struct {
425+
input interface{}
426+
}{
427+
{
428+
st{[]string{"err"}},
429+
},
430+
{ // struct field
431+
struct{ S st }{st{[]string{"err"}}},
432+
},
433+
{ // embedded struct
434+
struct{ st }{st{[]string{"err"}}},
435+
},
436+
}
437+
for _, tt := range tests {
438+
_, err := Values(tt.input)
439+
if err == nil {
440+
t.Errorf("Values(%q) did not return expected encoding error", tt.input)
441+
}
395442
}
396443
}
397444

0 commit comments

Comments
 (0)