forked from graph-gophers/graphql-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathselection_test.go
More file actions
164 lines (151 loc) · 5.06 KB
/
selection_test.go
File metadata and controls
164 lines (151 loc) · 5.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package graphql_test
import (
"context"
"testing"
"github.com/graph-gophers/graphql-go"
)
const selectionTestSchema = `
schema { query: Query }
type Query { hero: Human }
type Human { id: ID! name: String }
`
type selectionRoot struct {
t *testing.T
expectNames []string
expectSorted []string
hasChecks map[string]bool
}
type selectionHuman struct {
t *testing.T
id string
name string
}
func (r *selectionRoot) Hero(ctx context.Context) *selectionHuman {
names := graphql.SelectedFieldNames(ctx)
sorted := graphql.SortedSelectedFieldNames(ctx)
if !equalStringSlices(names, r.expectNames) {
r.t.Errorf("SelectedFieldNames = %v, want %v", names, r.expectNames)
}
if !equalStringSlices(sorted, r.expectSorted) {
r.t.Errorf("SortedSelectedFieldNames = %v, want %v", sorted, r.expectSorted)
}
for name, want := range r.hasChecks {
if got := graphql.HasSelectedField(ctx, name); got != want {
r.t.Errorf("HasSelectedField(%q) = %v, want %v", name, got, want)
}
}
return &selectionHuman{t: r.t, id: "h1", name: "Luke"}
}
// Object-level assertions happen in Hero via a wrapper test function; leaf behavior tested here.
func (h *selectionHuman) ID() graphql.ID { return graphql.ID(h.id) }
func (h *selectionHuman) Name(ctx context.Context) *string {
// Leaf field: should always produce empty selections regardless of enable/disable.
if got := graphql.SelectedFieldNames(ctx); len(got) != 0 {
h.t.Errorf("leaf field SelectedFieldNames = %v, want empty", got)
}
if graphql.HasSelectedField(ctx, "anything") {
h.t.Errorf("leaf field HasSelectedField unexpectedly true")
}
if sorted := graphql.SortedSelectedFieldNames(ctx); len(sorted) != 0 {
h.t.Errorf("leaf field SortedSelectedFieldNames = %v, want empty", sorted)
}
return &h.name
}
func TestFieldSelectionHelpers(t *testing.T) {
tests := []struct {
name string
schemaOpts []graphql.SchemaOpt
query string
expectNames []string // expected order from SelectedFieldNames at object boundary
expectSorted []string // expected from SortedSelectedFieldNames at object boundary
hasChecks map[string]bool
}{
{
name: "enabled object order preserved and sorted copy",
query: `query { hero { name id } }`, // order intentionally name,id
expectNames: []string{"name", "id"},
expectSorted: []string{"id", "name"},
hasChecks: map[string]bool{"id": true, "name": true, "missing": false},
},
{
name: "enabled only one field selected",
query: `query { hero { id } }`, // order intentionally name,id
expectNames: []string{"id"},
expectSorted: []string{"id"},
hasChecks: map[string]bool{"id": true, "name": false, "missing": false},
},
{
name: "disabled object returns empty",
schemaOpts: []graphql.SchemaOpt{graphql.DisableFieldSelections()},
query: `query { hero { name id } }`,
expectNames: []string{},
expectSorted: []string{},
hasChecks: map[string]bool{"id": false, "name": false},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
root := &selectionRoot{t: t, expectNames: tt.expectNames, expectSorted: tt.expectSorted, hasChecks: tt.hasChecks}
s := graphql.MustParseSchema(selectionTestSchema, root, tt.schemaOpts...)
resp := s.Exec(context.Background(), tt.query, "", nil)
if len(resp.Errors) > 0 {
t.Fatalf("execution errors: %v", resp.Errors)
}
})
}
}
func TestSelectedFieldNames_FragmentsAliasesMeta(t *testing.T) {
tests := []struct {
name string
query string
expectNames []string
hasChecks map[string]bool
}{
{
name: "alias ignored order preserved",
query: `query { hero { idAlias: id name } }`,
expectNames: []string{"id", "name"},
hasChecks: map[string]bool{"id": true, "idAlias": false, "name": true},
},
{
name: "fragment spread flattened",
query: `fragment HFields on Human { id name } query { hero { ...HFields } }`,
expectNames: []string{"id", "name"},
hasChecks: map[string]bool{"id": true, "name": true},
},
{
name: "inline fragment dedup",
query: `query { hero { id ... on Human { id name } } }`,
expectNames: []string{"id", "name"},
hasChecks: map[string]bool{"id": true, "name": true},
},
{
name: "meta field excluded",
query: `query { hero { id __typename name } }`,
expectNames: []string{"id", "name"},
hasChecks: map[string]bool{"id": true, "name": true, "__typename": false},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
root := &selectionRoot{t: t, expectNames: tt.expectNames, expectSorted: tt.expectNames, hasChecks: tt.hasChecks}
s := graphql.MustParseSchema(selectionTestSchema, root)
resp := s.Exec(context.Background(), tt.query, "", nil)
if len(resp.Errors) > 0 {
t.Fatalf("execution errors: %v", resp.Errors)
}
})
}
}
// equalStringSlices compares content and order.
func equalStringSlices(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}