package gql import ( "testing" "github.com/goccy/go-reflect" ) func (suite *Tests) TestBaseClient_convertToJSON() { type args struct { v any } tests := []struct { name string args args want []byte }{ { name: "TestBaseClient_convertToJSON_query", args: args{ v: `query { viewer { login } }`, }, want: []byte(`"query { viewer { login } }"`), }, { name: "TestBaseClient_convertToJSON_variables", args: args{ v: map[string]interface{}{ "login": "lukaszraczylo", "first": 10, }, }, want: []byte(`{"first":10,"login":"lukaszraczylo"}`), }, } for _, tt := range tests { suite.T().Run(tt.name, func(t *testing.T) { b := NewConnection() if got := b.convertToJSON(tt.args.v); !reflect.DeepEqual(got, tt.want) { assert.Equal(tt.want, got) } }) } } func (suite *Tests) TestBaseClient_compileQuery() { type args struct { query_partials []any } tests := []struct { wantQ *Query name string args args }{ { name: "TestBaseClient_compileQuery_query", args: args{ query_partials: []any{ `query { viewer { login } }`, }, }, wantQ: &Query{ Query: `query{viewer{login}}`, JsonQuery: []byte(`{"query":"query{viewer{login}}"}`), }, }, { name: "TestBaseClient_compileQuery_with_variables", args: args{ query_partials: []any{ `query { viewer { login } }`, map[string]interface{}{ "login": "lukaszraczylo", "first": 10, }, }, }, wantQ: &Query{ Query: `query{viewer{login}}`, Variables: map[string]interface{}{ "login": "lukaszraczylo", "first": 10, }, JsonQuery: []byte(`{"variables":{"first":10,"login":"lukaszraczylo"},"query":"query{viewer{login}}"}`), }, }, { name: "TestBaseClient_compileQuery_variables_without_query", args: args{ query_partials: []any{ map[string]interface{}{ "login": "lukaszraczylo", "first": 10, }, }, }, wantQ: nil, }, } for _, tt := range tests { suite.T().Run(tt.name, func(t *testing.T) { b := NewConnection() got := b.compileQuery(tt.args.query_partials...) assert.Equal(tt.wantQ, got) }) } } func (suite *Tests) TestBaseClient_Query() { type args struct { variables map[string]interface{} headers map[string]interface{} query string } tests := []struct { args args wantReturned_value any name string wantType string wantErr bool }{ { name: "TestBaseClient_Query_viewer", args: args{ query: "query { viewer { login } }", variables: nil, headers: map[string]interface{}{ "x-apollo-operation-name": "ViewerQuery", "content-type": "application/json", }, }, wantReturned_value: `{"viewer":{"login":"mockuser"}}`, // Adjusted expected value wantErr: false, }, { name: "TestBaseClient_Query_dragons", args: args{ query: `query Dragons { dragons { name } }`, variables: nil, headers: map[string]interface{}{ "x-apollo-operation-name": "DragonsQuery", "content-type": "application/json", }, }, wantReturned_value: `{"dragons":[{"name":"Mock Dragon 1"},{"name":"Mock Dragon 2"}]}`, // Adjusted expected value wantErr: false, }, { name: "TestBaseClient_Query_invalid_query", args: args{ query: "query { potato { login } ", variables: nil, headers: map[string]interface{}{ "x-apollo-operation-name": "InvalidQuery", "content-type": "application/json", }, }, wantReturned_value: nil, wantErr: true, }, } for _, tt := range tests { suite.T().Run(tt.name, func(t *testing.T) { b := NewConnection() b.SetEndpoint(mockServer.URL) b.SetHTTPClient(mockServer.Client()) if tt.wantType != "" { b.SetOutput(tt.wantType) } gotReturned_value, err := b.Query(tt.args.query, tt.args.variables, tt.args.headers) if tt.wantErr { assert.Error(err) } else { assert.NoError(err) } assert.Equal(tt.wantReturned_value, gotReturned_value) }) } } func (suite *Tests) TestBaseClient_convertToJSON_errors() { suite.T().Run("should handle JSON encoding errors", func(t *testing.T) { b := NewConnection() // Test with a value that can't be JSON encoded (function) result := b.convertToJSON(func() {}) assert.Nil(result) }) suite.T().Run("should handle Query type with variables", func(t *testing.T) { b := NewConnection() query := &Query{ Query: "query { test }", Variables: map[string]interface{}{ "var1": "value1", "var2": 123, }, } result := b.convertToJSON(query) assert.NotNil(result) assert.Contains(string(result), "query { test }") assert.Contains(string(result), "var1") assert.Contains(string(result), "value1") }) } func (suite *Tests) TestBaseClient_compileQuery_errors() { suite.T().Run("should handle empty query", func(t *testing.T) { b := NewConnection() result := b.compileQuery("") assert.Nil(result) }) suite.T().Run("should handle no arguments", func(t *testing.T) { b := NewConnection() result := b.compileQuery() assert.Nil(result) }) suite.T().Run("should handle invalid variable type", func(t *testing.T) { b := NewConnection() result := b.compileQuery("query { test }", "invalid_variables") assert.NotNil(result) assert.Equal("query{test}", result.Query) assert.Nil(result.Variables) }) } func (suite *Tests) Test_processFlags() { tests := []struct { name string variables map[string]interface{} headers map[string]interface{} wantCache bool wantRetries bool wantCleanedVars map[string]interface{} }{ { name: "cache enabled in headers", variables: nil, headers: map[string]interface{}{ "gqlcache": true, }, wantCache: true, wantRetries: false, wantCleanedVars: nil, }, { name: "retries enabled in headers", variables: nil, headers: map[string]interface{}{ "gqlretries": true, }, wantCache: false, wantRetries: true, wantCleanedVars: nil, }, { name: "cache enabled in variables", variables: map[string]interface{}{ "gqlcache": true, "test": "value", }, headers: nil, wantCache: true, wantRetries: false, wantCleanedVars: map[string]interface{}{ "test": "value", }, }, { name: "retries enabled in variables", variables: map[string]interface{}{ "gqlretries": true, "test": "value", }, headers: nil, wantCache: false, wantRetries: true, wantCleanedVars: map[string]interface{}{ "test": "value", }, }, { name: "both flags in variables", variables: map[string]interface{}{ "gqlcache": true, "gqlretries": false, "test": "value", }, headers: nil, wantCache: true, wantRetries: false, wantCleanedVars: map[string]interface{}{ "test": "value", }, }, { name: "flags in both headers and variables", variables: map[string]interface{}{ "gqlcache": false, "test": "value", }, headers: map[string]interface{}{ "gqlretries": true, }, wantCache: false, wantRetries: true, wantCleanedVars: map[string]interface{}{ "test": "value", }, }, { name: "no flags", variables: map[string]interface{}{"test": "value"}, headers: nil, wantCache: false, wantRetries: false, wantCleanedVars: map[string]interface{}{"test": "value"}, }, } for _, tt := range tests { suite.T().Run(tt.name, func(t *testing.T) { gotCache, gotRetries, gotCleanedVars := processFlags(tt.variables, tt.headers) assert.Equal(tt.wantCache, gotCache) assert.Equal(tt.wantRetries, gotRetries) assert.Equal(tt.wantCleanedVars, gotCleanedVars) }) } } func (suite *Tests) TestBaseClient_Query_caching() { suite.T().Run("should use cache for query operations", func(t *testing.T) { b := NewConnection() b.SetEndpoint(mockServer.URL) b.SetHTTPClient(mockServer.Client()) query := "query { viewer { login } }" variables := map[string]interface{}{ "gqlcache": true, } // First call should hit the server result1, err := b.Query(query, variables, nil) assert.NoError(err) assert.NotNil(result1) // Second call should use cache result2, err := b.Query(query, variables, nil) assert.NoError(err) assert.Equal(result1, result2) }) suite.T().Run("should not cache mutations", func(t *testing.T) { b := NewConnection() b.SetEndpoint(mockServer.URL) b.SetHTTPClient(mockServer.Client()) mutation := "mutation { updateUser { id } }" variables := map[string]interface{}{ "gqlcache": true, } // Mutations should not be cached even with cache flag _, err := b.Query(mutation, variables, nil) assert.Error(err) // Mock server doesn't handle mutations }) } func (suite *Tests) TestBaseClient_Query_retries() { suite.T().Run("should handle retries flag", func(t *testing.T) { b := NewConnection() b.SetEndpoint(mockServer.URL) b.SetHTTPClient(mockServer.Client()) query := "query { viewer { login } }" variables := map[string]interface{}{ "gqlretries": true, } result, err := b.Query(query, variables, nil) assert.NoError(err) assert.NotNil(result) }) } func (suite *Tests) TestBaseClient_Query_globalCache() { suite.T().Run("should respect global cache setting", func(t *testing.T) { b := NewConnection() b.SetEndpoint(mockServer.URL) b.SetHTTPClient(mockServer.Client()) b.cache_global = true query := "query { viewer { login } }" // Should use cache even without explicit flag result1, err := b.Query(query, nil, nil) assert.NoError(err) assert.NotNil(result1) result2, err := b.Query(query, nil, nil) assert.NoError(err) assert.Equal(result1, result2) }) } func (suite *Tests) TestBaseClient_Query_emptyQuery() { suite.T().Run("should handle empty query", func(t *testing.T) { b := NewConnection() b.SetEndpoint(mockServer.URL) b.SetHTTPClient(mockServer.Client()) result, err := b.Query("", nil, nil) assert.Error(err) assert.Nil(result) assert.Contains(err.Error(), "can't compile query") }) }