func Graphql(p GraphqlParams, resultChannel chan *types.GraphQLResult) { source := source.NewSource(&source.Source{ Body: p.RequestString, Name: "GraphQL request", }) AST, err := parser.Parse(parser.ParseParams{Source: source}) if err != nil { result := types.GraphQLResult{ Errors: graphqlerrors.FormatErrors(err), } resultChannel <- &result return } validationResult := validator.ValidateDocument(p.Schema, AST) if !validationResult.IsValid { result := types.GraphQLResult{ Errors: validationResult.Errors, } resultChannel <- &result return } else { ep := executor.ExecuteParams{ Schema: p.Schema, Root: p.RootObject, AST: AST, Ctx: p.Ctx, OperationName: p.OperationName, Args: p.VariableValues, } executor.Execute(ep, resultChannel) return } }
func TestLexRerportsUsefulInformationForDashesInNames(t *testing.T) { q := "a-b" lexer := Lex(source.NewSource(q, "")) firstToken, err := lexer(0) if err != nil { t.Fatalf("unexpected error: %v", err) } firstTokenExpected := Token{ Kind: TokenKind[NAME], Start: 0, End: 1, Value: "a", } if !reflect.DeepEqual(firstToken, firstTokenExpected) { t.Fatalf("unexpected token, expected: %v, got: %v", firstTokenExpected, firstToken) } errExpected := `Syntax Error GraphQL (1:3) Invalid number, expected digit but got: "b". 1: a-b ^ ` token, err := lexer(0) if err == nil { t.Fatalf("unexpected nil error: %v", err) } if err.Error() != errExpected { t.Fatalf("unexpected error, token:%v\nexpected:\n%v\n\ngot:\n%v", token, errExpected, err.Error()) } }
func TestParseProvidesUsefulErrorsWhenUsingSource(t *testing.T) { test := errorMessageTest{ source.NewSource(&source.Source{Body: "query", Name: "MyQuery.graphql"}), `Syntax Error MyQuery.graphql (1:6) Expected Name, found EOF`, false, } testGraphQLErrorMessage(t, test) }
func TestErrorsRespectWhitespace(t *testing.T) { body := ` ? ` source := source.NewSource(body, "") _, err := Lex(source)(0) expected := "Syntax Error GraphQL (3:5) Unexpected character \"?\".\n\n2: \n3: ?\n ^\n4: \n" if err == nil { t.Fatalf("unexpected nil error\nexpected:\n%v\n\ngot:\n%v", expected, err) } if err.Error() != expected { t.Fatalf("unexpected error.\nexpected:\n%v\n\ngot:\n%v", expected, err.Error()) } }
func Parse(p ParseParams) (*ast.Document, error) { var sourceObj *source.Source switch p.Source.(type) { case *source.Source: sourceObj = p.Source.(*source.Source) default: s, _ := p.Source.(string) sourceObj = source.NewSource(s, "") } parser, err := makeParser(sourceObj, p.Options) if err != nil { return nil, err } doc, err := parseDocument(parser) if err != nil { return nil, err } return doc, nil }
// TODO: test and expose parseValue as a public func parseValue(p ParseParams) (ast.Value, error) { var value ast.Value var sourceObj *source.Source switch p.Source.(type) { case *source.Source: sourceObj = p.Source.(*source.Source) default: s, _ := p.Source.(string) sourceObj = source.NewSource(s, "") } parser, err := makeParser(sourceObj, p.Options) if err != nil { return value, err } value, err = parseValueLiteral(parser, false) if err != nil { return value, err } return value, nil }
func TestLexReportsUsefulUnknownCharacterError(t *testing.T) { tests := []Test{ Test{ Body: "..", Expected: `Syntax Error GraphQL (1:1) Unexpected character ".". 1: .. ^ `, }, Test{ Body: "?", Expected: `Syntax Error GraphQL (1:1) Unexpected character "?". 1: ? ^ `, }, Test{ Body: "\u203B", Expected: `Syntax Error GraphQL (1:1) Unexpected character "※". 1: ※ ^ `, }, } for _, test := range tests { _, err := Lex(source.NewSource(test.Body, ""))(0) if err == nil { t.Fatalf("unexpected nil error\nexpected:\n%v\n\ngot:\n%v", test.Expected, err) } if err.Error() != test.Expected { t.Fatalf("unexpected error.\nexpected:\n%v\n\ngot:\n%v", test.Expected, err.Error()) } } }
func TestLexesPunctuation(t *testing.T) { tests := []Test{ Test{ Body: "!", Expected: Token{ Kind: TokenKind[BANG], Start: 0, End: 1, Value: "", }, }, Test{ Body: "$", Expected: Token{ Kind: TokenKind[DOLLAR], Start: 0, End: 1, Value: "", }, }, Test{ Body: "(", Expected: Token{ Kind: TokenKind[PAREN_L], Start: 0, End: 1, Value: "", }, }, Test{ Body: ")", Expected: Token{ Kind: TokenKind[PAREN_R], Start: 0, End: 1, Value: "", }, }, Test{ Body: "...", Expected: Token{ Kind: TokenKind[SPREAD], Start: 0, End: 3, Value: "", }, }, Test{ Body: ":", Expected: Token{ Kind: TokenKind[COLON], Start: 0, End: 1, Value: "", }, }, Test{ Body: "=", Expected: Token{ Kind: TokenKind[EQUALS], Start: 0, End: 1, Value: "", }, }, Test{ Body: "@", Expected: Token{ Kind: TokenKind[AT], Start: 0, End: 1, Value: "", }, }, Test{ Body: "[", Expected: Token{ Kind: TokenKind[BRACKET_L], Start: 0, End: 1, Value: "", }, }, Test{ Body: "]", Expected: Token{ Kind: TokenKind[BRACKET_R], Start: 0, End: 1, Value: "", }, }, Test{ Body: "{", Expected: Token{ Kind: TokenKind[BRACE_L], Start: 0, End: 1, Value: "", }, }, Test{ Body: "|", Expected: Token{ Kind: TokenKind[PIPE], Start: 0, End: 1, Value: "", }, }, Test{ Body: "}", Expected: Token{ Kind: TokenKind[BRACE_R], Start: 0, End: 1, Value: "", }, }, } for _, test := range tests { token, err := Lex(source.NewSource(test.Body, ""))(0) if err != nil { t.Fatalf("unexpected error :%v, test: %v", err, test) } if !reflect.DeepEqual(token, test.Expected) { t.Fatalf("unexpected token, expected: %v, got: %v, test: %v", test.Expected, token, test) } } }
func TestLexReportsUsefulNumbeErrors(t *testing.T) { tests := []Test{ Test{ Body: "00", Expected: `Syntax Error GraphQL (1:2) Invalid number, unexpected digit after 0: "0". 1: 00 ^ `, }, Test{ Body: "+1", Expected: `Syntax Error GraphQL (1:1) Unexpected character "+". 1: +1 ^ `, }, Test{ Body: "1.", Expected: `Syntax Error GraphQL (1:3) Invalid number, expected digit but got: EOF. 1: 1. ^ `, }, Test{ Body: ".123", Expected: `Syntax Error GraphQL (1:1) Unexpected character ".". 1: .123 ^ `, }, Test{ Body: "1.A", Expected: `Syntax Error GraphQL (1:3) Invalid number, expected digit but got: "A". 1: 1.A ^ `, }, Test{ Body: "-A", Expected: `Syntax Error GraphQL (1:2) Invalid number, expected digit but got: "A". 1: -A ^ `, }, Test{ Body: "1.0e", Expected: `Syntax Error GraphQL (1:5) Invalid number, expected digit but got: EOF. 1: 1.0e ^ `, }, Test{ Body: "1.0eA", Expected: `Syntax Error GraphQL (1:5) Invalid number, expected digit but got: "A". 1: 1.0eA ^ `, }, } for _, test := range tests { _, err := Lex(source.NewSource(test.Body, ""))(0) if err == nil { t.Fatalf("unexpected nil error\nexpected:\n%v\n\ngot:\n%v", test.Expected, err) } if err.Error() != test.Expected { t.Fatalf("unexpected error.\nexpected:\n%v\n\ngot:\n%v", test.Expected, err.Error()) } } }
func TestLexesNumbers(t *testing.T) { tests := []Test{ Test{ Body: "4", Expected: Token{ Kind: TokenKind[INT], Start: 0, End: 1, Value: "4", }, }, Test{ Body: "4.123", Expected: Token{ Kind: TokenKind[FLOAT], Start: 0, End: 5, Value: "4.123", }, }, Test{ Body: "-4", Expected: Token{ Kind: TokenKind[INT], Start: 0, End: 2, Value: "-4", }, }, Test{ Body: "9", Expected: Token{ Kind: TokenKind[INT], Start: 0, End: 1, Value: "9", }, }, Test{ Body: "0", Expected: Token{ Kind: TokenKind[INT], Start: 0, End: 1, Value: "0", }, }, Test{ Body: "-4.123", Expected: Token{ Kind: TokenKind[FLOAT], Start: 0, End: 6, Value: "-4.123", }, }, Test{ Body: "0.123", Expected: Token{ Kind: TokenKind[FLOAT], Start: 0, End: 5, Value: "0.123", }, }, Test{ Body: "123e4", Expected: Token{ Kind: TokenKind[FLOAT], Start: 0, End: 5, Value: "123e4", }, }, Test{ Body: "123E4", Expected: Token{ Kind: TokenKind[FLOAT], Start: 0, End: 5, Value: "123E4", }, }, Test{ Body: "123e-4", Expected: Token{ Kind: TokenKind[FLOAT], Start: 0, End: 6, Value: "123e-4", }, }, Test{ Body: "123e+4", Expected: Token{ Kind: TokenKind[FLOAT], Start: 0, End: 6, Value: "123e+4", }, }, Test{ Body: "-1.123e4", Expected: Token{ Kind: TokenKind[FLOAT], Start: 0, End: 8, Value: "-1.123e4", }, }, Test{ Body: "-1.123E4", Expected: Token{ Kind: TokenKind[FLOAT], Start: 0, End: 8, Value: "-1.123E4", }, }, Test{ Body: "-1.123e-4", Expected: Token{ Kind: TokenKind[FLOAT], Start: 0, End: 9, Value: "-1.123e-4", }, }, Test{ Body: "-1.123e+4", Expected: Token{ Kind: TokenKind[FLOAT], Start: 0, End: 9, Value: "-1.123e+4", }, }, Test{ Body: "-1.123e4567", Expected: Token{ Kind: TokenKind[FLOAT], Start: 0, End: 11, Value: "-1.123e4567", }, }, } for _, test := range tests { token, err := Lex(source.NewSource(test.Body, ""))(0) if err != nil { t.Fatalf("unexpected error: %v, test: %s", err, test) } if !reflect.DeepEqual(token, test.Expected) { t.Fatalf("unexpected token, expected: %v, got: %v, test: %v", test.Expected, token, test) } } }
func TestLexReportsUsefulStringErrors(t *testing.T) { tests := []Test{ Test{ Body: "\"no end quote", Expected: `Syntax Error GraphQL (1:14) Unterminated string. 1: "no end quote ^ `, }, Test{ Body: "\"multi\nline\"", Expected: `Syntax Error GraphQL (1:7) Unterminated string. 1: "multi ^ 2: line" `, }, Test{ Body: "\"multi\rline\"", Expected: `Syntax Error GraphQL (1:7) Unterminated string. 1: "multi ^ 2: line" `, }, Test{ Body: "\"multi\u2028line\"", Expected: `Syntax Error GraphQL (1:7) Unterminated string. 1: "multi ^ 2: line" `, }, Test{ Body: "\"multi\u2029line\"", Expected: `Syntax Error GraphQL (1:7) Unterminated string. 1: "multi ^ 2: line" `, }, Test{ Body: "\"bad \\z esc\"", Expected: `Syntax Error GraphQL (1:7) Bad character escape sequence. 1: "bad \z esc" ^ `, }, Test{ Body: "\"bad \\x esc\"", Expected: `Syntax Error GraphQL (1:7) Bad character escape sequence. 1: "bad \x esc" ^ `, }, Test{ Body: "\"bad \\u1 esc\"", Expected: `Syntax Error GraphQL (1:7) Bad character escape sequence. 1: "bad \u1 esc" ^ `, }, Test{ Body: "\"bad \\u0XX1 esc\"", Expected: `Syntax Error GraphQL (1:7) Bad character escape sequence. 1: "bad \u0XX1 esc" ^ `, }, Test{ Body: "\"bad \\uXXXX esc\"", Expected: `Syntax Error GraphQL (1:7) Bad character escape sequence. 1: "bad \uXXXX esc" ^ `, }, Test{ Body: "\"bad \\uFXXX esc\"", Expected: `Syntax Error GraphQL (1:7) Bad character escape sequence. 1: "bad \uFXXX esc" ^ `, }, Test{ Body: "\"bad \\uXXXF esc\"", Expected: `Syntax Error GraphQL (1:7) Bad character escape sequence. 1: "bad \uXXXF esc" ^ `, }, } for _, test := range tests { _, err := Lex(source.NewSource(test.Body, ""))(0) if err == nil { t.Fatalf("unexpected nil error\nexpected:\n%v\n\ngot:\n%v", test.Expected, err) } if err.Error() != test.Expected { t.Fatalf("unexpected error.\nexpected:\n%v\n\ngot:\n%v", test.Expected, err.Error()) } } }
func TestParseCreatesAst(t *testing.T) { body := `{ node(id: 4) { id, name } } ` source := source.NewSource(&source.Source{Body: body}) document, err := Parse( ParseParams{ Source: source, Options: ParseOptions{ NoSource: true, }, }, ) if err != nil { t.Fatalf("unexpected error: %v", err) } oDef := ast.OperationDefinition{ Kind: "OperationDefinition", Loc: &ast.Location{ Start: 0, End: 40, }, Operation: "query", Directives: []*ast.Directive{}, SelectionSet: &ast.SelectionSet{ Kind: "SelectionSet", Loc: &ast.Location{ Start: 0, End: 40, }, Selections: []ast.Selection{ &ast.Field{ Kind: "Field", Loc: &ast.Location{ Start: 4, End: 38, }, Name: &ast.Name{ Kind: "Name", Loc: &ast.Location{ Start: 4, End: 8, }, Value: "node", }, Arguments: []*ast.Argument{ { Kind: "Argument", Name: &ast.Name{ Kind: "Name", Loc: &ast.Location{ Start: 9, End: 11, }, Value: "id", }, Value: &ast.IntValue{ Kind: "IntValue", Loc: &ast.Location{ Start: 13, End: 14, }, Value: "4", }, Loc: &ast.Location{ Start: 9, End: 14, }, }, }, Directives: []*ast.Directive{}, SelectionSet: &ast.SelectionSet{ Kind: "SelectionSet", Loc: &ast.Location{ Start: 16, End: 38, }, Selections: []ast.Selection{ &ast.Field{ Kind: "Field", Loc: &ast.Location{ Start: 22, End: 24, }, Name: &ast.Name{ Kind: "Name", Loc: &ast.Location{ Start: 22, End: 24, }, Value: "id", }, Arguments: []*ast.Argument{}, Directives: []*ast.Directive{}, SelectionSet: nil, }, &ast.Field{ Kind: "Field", Loc: &ast.Location{ Start: 30, End: 34, }, Name: &ast.Name{ Kind: "Name", Loc: &ast.Location{ Start: 30, End: 34, }, Value: "name", }, Arguments: []*ast.Argument{}, Directives: []*ast.Directive{}, SelectionSet: nil, }, }, }, }, }, }, } expectedDocument := ast.NewDocument(&ast.Document{ Loc: &ast.Location{ Start: 0, End: 41, }, Definitions: []ast.Node{&oDef}, }) if !reflect.DeepEqual(document, expectedDocument) { t.Fatalf("unexpected document, expected: %v, got: %v", expectedDocument, document) } }