1 package integration_test
2
3 import (
4 "bytes"
5 "context"
6 "encoding/json"
7 "fmt"
8 "io"
9 "net/http"
10
11 "edge-infra.dev/pkg/edge/api/graph/resolver"
12 "edge-infra.dev/pkg/edge/api/middleware"
13 "edge-infra.dev/test/framework/integration"
14
15 "github.com/99designs/gqlgen/client"
16 "github.com/mitchellh/mapstructure"
17 )
18
19
20 type GraphqlClient interface {
21 MustPost(query string, response interface{}, options ...client.Option)
22 Post(query string, response interface{}, options ...client.Option) error
23 RawPost(query string, options ...client.Option) (*client.Response, error)
24 }
25
26 type BffGraphqlClient struct {
27 Endpoint string
28 Client *http.Client
29 Options []client.Option
30 }
31
32 func NewGraphQlClient(endpoint string, options ...client.Option) *BffGraphqlClient {
33 return &BffGraphqlClient{
34 Endpoint: endpoint,
35 Client: &http.Client{},
36 Options: options,
37 }
38 }
39
40 func (g *BffGraphqlClient) MustPost(query string, response interface{}, options ...client.Option) {
41 if err := g.Post(query, response, options...); err != nil {
42 panic(err)
43 }
44 }
45
46 func (g *BffGraphqlClient) Post(query string, response interface{}, options ...client.Option) error {
47 respDataRaw, err := g.RawPost(query, options...)
48 if err != nil {
49 return err
50 }
51
52
53 unpackErr := unpack(respDataRaw.Data, response)
54
55 if respDataRaw.Errors != nil {
56 return client.RawJsonError{RawMessage: respDataRaw.Errors}
57 }
58 return unpackErr
59 }
60
61 func (g *BffGraphqlClient) RawPost(query string, options ...client.Option) (*client.Response, error) {
62 fmt.Println("Graphql call:", query)
63 req, err := g.newRequest(query, options...)
64 if err != nil {
65 return nil, fmt.Errorf("failed to build http request: %s", err.Error())
66 }
67
68 res, err := g.Client.Do(req)
69 if err != nil {
70 return nil, err
71 }
72
73 body, err := io.ReadAll(res.Body)
74 if !validStatus(res.StatusCode) {
75 return nil, fmt.Errorf("failed to make graphql request %d: %s. %s", res.StatusCode, res.Status, string(body))
76 }
77 if err != nil {
78 return nil, fmt.Errorf("failed to parse read response body. %w", err)
79 }
80
81
82
83 respDataRaw := &client.Response{}
84 if err := json.Unmarshal(body, &respDataRaw); err != nil {
85 return nil, fmt.Errorf("failed parse response body to json: %w", err)
86 }
87 return respDataRaw, nil
88 }
89
90
91 func (g *BffGraphqlClient) newRequest(query string, options ...client.Option) (*http.Request, error) {
92 bd := &client.Request{Query: query}
93 requestBody, err := json.Marshal(bd)
94 if err != nil {
95 return nil, fmt.Errorf("failed to encode request body: %w", err)
96 }
97 if bd.HTTP, err = http.NewRequest(http.MethodPost, g.Endpoint, io.NopCloser(bytes.NewBuffer(requestBody))); err != nil {
98 return nil, fmt.Errorf("failed to build new request: %w", err)
99 }
100 bd.HTTP.Header.Add("Content-Type", "application/json")
101 bd.HTTP.Header.Add("Accept", "application/json")
102
103
104 for _, option := range g.Options {
105 option(bd)
106 }
107
108 for _, option := range options {
109 option(bd)
110 }
111 return bd.HTTP, nil
112 }
113
114 func unpack(data interface{}, into interface{}) error {
115 d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
116 Result: into,
117 TagName: "json",
118 ErrorUnused: true,
119 ZeroFields: true,
120 })
121 if err != nil {
122 return fmt.Errorf("mapstructure: %s", err.Error())
123 }
124
125 return d.Decode(data)
126 }
127
128 func validStatus(status int) bool {
129 for _, s := range []int{http.StatusOK, http.StatusCreated, http.StatusNoContent} {
130 if status == s {
131 return true
132 }
133 }
134 return false
135 }
136
137
138 func WithAuth(res *resolver.Resolver, org, username, password, role string) client.Option {
139 return func(bd *client.Request) {
140 if integration.IsIntegrationTest() {
141 p, _ := res.UserManagementService.Login(context.Background(), username, password, org)
142 bd.HTTP.Header.Set("Authorization", "bearer "+p.Token)
143 } else {
144 token, _ := middleware.CreateToken(testUser, testEmail, testOrg, jwtSecret, []string{role}, "bslToken", "bsl", "refreshToken")
145 bd.HTTP.Header.Set("Authorization", "bearer "+token)
146 }
147 }
148 }
149
View as plain text