github.com/fortexxx/gqlgen@v0.10.3-0.20191216030626-ca5ea8b21ead/graphql/handler/testserver/testserver.go (about) 1 package testserver 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 "github.com/99designs/gqlgen/graphql" 9 "github.com/99designs/gqlgen/graphql/handler" 10 "github.com/vektah/gqlparser" 11 "github.com/vektah/gqlparser/ast" 12 ) 13 14 // New provides a server for use in tests that isn't relying on generated code. It isnt a perfect reproduction of 15 // a generated server, but it aims to be good enough to test the handler package without relying on codegen. 16 func New() *TestServer { 17 next := make(chan struct{}) 18 now := time.Unix(0, 0) 19 20 graphql.Now = func() time.Time { 21 defer func() { 22 now = now.Add(100 * time.Nanosecond) 23 }() 24 return now 25 } 26 27 schema := gqlparser.MustLoadSchema(&ast.Source{Input: ` 28 type Query { 29 name: String! 30 find(id: Int!): String! 31 } 32 type Mutation { 33 name: String! 34 } 35 type Subscription { 36 name: String! 37 } 38 `}) 39 40 srv := &TestServer{ 41 next: next, 42 } 43 44 srv.Server = handler.New(&graphql.ExecutableSchemaMock{ 45 ExecFunc: func(ctx context.Context) graphql.ResponseHandler { 46 rc := graphql.GetOperationContext(ctx) 47 switch rc.Operation.Operation { 48 case ast.Query: 49 ran := false 50 return func(ctx context.Context) *graphql.Response { 51 if ran { 52 return nil 53 } 54 ran = true 55 // Field execution happens inside the generated code, lets simulate some of it. 56 ctx = graphql.WithFieldContext(ctx, &graphql.FieldContext{ 57 Object: "Query", 58 Field: graphql.CollectedField{ 59 Field: &ast.Field{ 60 Name: "name", 61 Alias: "name", 62 Definition: schema.Types["Query"].Fields.ForName("name"), 63 }, 64 }, 65 }) 66 res, err := graphql.GetOperationContext(ctx).ResolverMiddleware(ctx, func(ctx context.Context) (interface{}, error) { 67 return &graphql.Response{Data: []byte(`{"name":"test"}`)}, nil 68 }) 69 if err != nil { 70 panic(err) 71 } 72 return res.(*graphql.Response) 73 } 74 case ast.Mutation: 75 return graphql.OneShot(graphql.ErrorResponse(ctx, "mutations are not supported")) 76 case ast.Subscription: 77 return func(context context.Context) *graphql.Response { 78 select { 79 case <-ctx.Done(): 80 return nil 81 case <-next: 82 return &graphql.Response{ 83 Data: []byte(`{"name":"test"}`), 84 } 85 } 86 } 87 default: 88 return graphql.OneShot(graphql.ErrorResponse(ctx, "unsupported GraphQL operation")) 89 } 90 }, 91 SchemaFunc: func() *ast.Schema { 92 return schema 93 }, 94 ComplexityFunc: func(typeName string, fieldName string, childComplexity int, args map[string]interface{}) (i int, b bool) { 95 return srv.complexity, true 96 }, 97 }) 98 return srv 99 } 100 101 type TestServer struct { 102 *handler.Server 103 next chan struct{} 104 complexity int 105 } 106 107 func (s *TestServer) SendNextSubscriptionMessage() { 108 select { 109 case s.next <- struct{}{}: 110 case <-time.After(1 * time.Second): 111 fmt.Println("WARNING: no active subscription") 112 } 113 114 } 115 116 func (s *TestServer) SetCalculatedComplexity(complexity int) { 117 s.complexity = complexity 118 }