package graphqlhelpers import ( "bytes" "strings" "testing" "github.com/99designs/gqlgen/graphql" "github.com/stretchr/testify/assert" "github.com/vektah/gqlparser/v2/ast" "github.com/vektah/gqlparser/v2/formatter" "github.com/vektah/gqlparser/v2/gqlerror" ) func TestGetOperation(t *testing.T) { queryOp := ast.Query mutationOp := ast.Mutation subscriptionOp := ast.Subscription testCases := []struct { title string rctx *graphql.OperationContext op *ast.Operation }{ { title: "Test Case One - Empty Context", rctx: &graphql.OperationContext{}, op: nil, }, { title: "Test Case Two - Nil Context", rctx: nil, op: nil, }, { title: "Test Case Three - Query Context", rctx: &graphql.OperationContext{ Operation: &ast.OperationDefinition{ Operation: ast.Query, Name: "GetUsersQuery", }, }, op: &queryOp, }, { title: "Test Case Four - Mutation Context", rctx: &graphql.OperationContext{ Operation: &ast.OperationDefinition{ Operation: ast.Mutation, Name: "LoginUserMutation", }, }, op: &mutationOp, }, { title: "Test Case Five - Subscription Context", rctx: &graphql.OperationContext{ Operation: &ast.OperationDefinition{ Operation: ast.Subscription, Name: "GetPollsSubscription", }, }, op: &subscriptionOp, }, } for _, testCase := range testCases { t.Run(testCase.title, func(t *testing.T) { op := GetOperation(testCase.rctx) assert.Equal(t, testCase.op, op) }) } } func TestGetRawQuery(t *testing.T) { queryOp := ast.Query mutationOp := ast.Mutation testCases := []struct { title string rctx *graphql.OperationContext op *ast.Operation }{ { title: "Test Case One - Query Raw Query", rctx: &graphql.OperationContext{ Operation: &ast.OperationDefinition{ Operation: ast.Query, Name: "GetUsersQuery", }, RawQuery: ` query GetUsersQuery { users { email username fullName familyName givenName status } } `, }, op: &queryOp, }, { title: "Test Case Two - Mutation Raw Query", rctx: &graphql.OperationContext{ Operation: &ast.OperationDefinition{ Operation: ast.Mutation, Name: "LoginUserMutation", }, RawQuery: ` mutation MyMutation { login(organization: "test-org", password: "123456", username: "test") { firstName fullName roles organization credentialsExpired sessionTime token } } `, }, op: &mutationOp, }, } for _, testCase := range testCases { t.Run(testCase.title, func(t *testing.T) { query := GetRawQuery(testCase.rctx) assert.Equal(t, testCase.rctx.RawQuery, query) }) } } func TestGetResponseStatus(t *testing.T) { testCases := []struct { title string resp *graphql.Response status string }{ { title: "Test Case One - Nil Response", resp: nil, status: "Unknown", }, { title: "Test Case Two - Empty Response", resp: &graphql.Response{}, status: "Success", }, { title: "Test Case Three - Errors and No Data Response", resp: &graphql.Response{ Errors: gqlerror.List{ &gqlerror.Error{ Message: "error no rows found for banners", }, &gqlerror.Error{ Message: "error no rows found for clusters", }, }, Data: []byte("null"), }, status: "Failure", }, { title: "Test Case Four - Errors and Data Response", resp: &graphql.Response{ Errors: gqlerror.List{ &gqlerror.Error{ Message: "error no rows found for banners", }, &gqlerror.Error{ Message: "error no rows found for clusters", }, }, Data: []byte("hello"), }, status: "Partial Failure", }, { title: "Test Case Five - Data and No Error Response", resp: &graphql.Response{ Data: []byte("hello"), }, status: "Success", }, } for _, testCase := range testCases { t.Run(testCase.title, func(t *testing.T) { status := GetResponseStatus(testCase.resp) assert.Equal(t, testCase.status, status) }) } } func TestUpdateQueryWithVariables(t *testing.T) { testcases := []struct { title string variables map[string]interface{} rawquery string expected string queryNames []string }{ { title: "Test Case 1 - String Variables", rawquery: "mutation login($username: String!, $password: String!, $organization: String!) {\n login(username: $username, password: $password, organization: $organization) {\n fullName\n firstName\n credentialsExpired\n token\n __typename\n }\n}\n", expected: `{"organization":"\"test-org\"","password":"\"123456\"","username":"\"test-user\""}`, variables: map[string]interface{}{ "USERNAME": "test-user", "PASSWORD": "123456", "ORGANIZATION": "test-org", }, queryNames: []string{ "login", }, }, { title: "Test Case 2 - Object Variables", rawquery: "mutation createLabel($newLabel: LabelInput!) {\n createLabel(newLabel: $newLabel)\n}\n", expected: `{"newLabel":"{color:\"#000\",visible:true,editable:true,unique:false,bannerEdgeId:\"4ba7b765-68e2-453e-a2f5-787dca9b30f7\",description:\"\",type:\"\",key:\"test\"}"}`, variables: map[string]interface{}{ "NEWLABEL": map[string]interface{}{ "key": "test", "color": "#000", "visible": true, "editable": true, "unique": false, "bannerEdgeId": "4ba7b765-68e2-453e-a2f5-787dca9b30f7", "description": "", "type": "", }, }, queryNames: []string{ "createLabel", }, }, { title: "Test Case 3 - Array Variables", rawquery: "mutation assignUserRoles($roles: RoleInput!) {\n assignUserRoles(roles: $roles)\n}\n", expected: `{"roles":"[\"EDGE_ORG_ADMIN\",\"EDGE_BANNER_ADMIN\"]"}`, variables: map[string]interface{}{ "ROLES": []string{ "EDGE_ORG_ADMIN", "EDGE_BANNER_ADMIN", }, }, queryNames: []string{ "assignUserRoles", }, }, { title: "Test Case 4 - Object Variables with Sub List", rawquery: "mutation createLabel($newLabel: LabelInput!) {\n createLabel(newLabel: $newLabel)\n}\n", expected: `{"newLabel":"{unique:false,bannerEdgeId:\"4ba7b765-68e2-453e-a2f5-787dca9b30f7\",description:\"\",parent:{labelEdgeId:\"4ba7b765-68e2-453e-a2f5-787dca9b32B1\"},key:\"test\",color:\"#000\",visible:true,editable:true}"}`, variables: map[string]interface{}{ "NEWLABEL": map[string]interface{}{ "key": "test", "color": "#000", "visible": true, "editable": true, "unique": false, "bannerEdgeId": "4ba7b765-68e2-453e-a2f5-787dca9b30f7", "description": "", "parent": map[string]interface{}{ "labelEdgeId": "4ba7b765-68e2-453e-a2f5-787dca9b32B1", }, }, }, queryNames: []string{ "createLabel", }, }, { title: "Test Case 5 - Multiple Variable Types", rawquery: "mutation user($username: String!, $age: String!, $nickname: String, $roles: RoleInput, $pins: PinInput, $extra: ExtraInput) {\n user(username: $username, age: $age, nickname: $nickname, roles: $roles, pins: $pins, extra: $extra) {\n fullName\n firstName\n credentialsExpired\n token\n __typename\n }\n}\n", expected: `{"age":"10","extra":"[1,\"hello\",2.4,{one:\"two\",two:3},[1,2,3],[\"hello\",[23,43],[\"Colors\",[\"Yellow\",\"Red\",\"Blue\"]]]]","nickname":"nickname","pins":"[20,30,40]","roles":"[\"EDGE_ORG_ADMIN\",\"EDGE_BANNER_ADMIN\"]","username":"\"test-user\""}`, variables: map[string]interface{}{ "USERNAME": "test-user", "AGE": 10, "NICKNAME": nil, "ROLES": []string{ "EDGE_ORG_ADMIN", "EDGE_BANNER_ADMIN", }, "PINS": []int{ 20, 30, 40, }, "EXTRA": []any{ 1, "hello", 2.4, nil, map[string]interface{}{ "one": "two", "two": 3, }, []int{ 1, 2, 3, }, []any{ "hello", []int{ 23, 43, }, []any{ "Colors", []string{ "Yellow", "Red", "Blue", }, }, }, }, }, queryNames: []string{ "user", }, }, } for _, testcase := range testcases { t.Run(testcase.title, func(t *testing.T) { schema, err := ParseQuery(testcase.rawquery) assert.NoError(t, err) UpdateQueryWithVariables(schema, testcase.variables) buf := bytes.NewBuffer(nil) formatter.NewFormatter(buf).FormatQueryDocument(schema) updatedschema, err := ParseQuery(buf.String()) assert.NoError(t, err) queryNames := GetQueryNames(updatedschema) assert.Equal(t, testcase.queryNames, queryNames) params := GetParams(nil, updatedschema) for k := range params { _, exists := testcase.variables[strings.ToUpper(k)] assert.True(t, exists) } }) } }