File: string_spec.rb

package info (click to toggle)
ruby-graphql 2.5.19-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 13,868 kB
  • sloc: ruby: 80,420; ansic: 1,808; yacc: 845; javascript: 480; makefile: 6
file content (148 lines) | stat: -rw-r--r-- 4,678 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# frozen_string_literal: true
require "spec_helper"

describe GraphQL::Types::String do
  let(:string_type) { GraphQL::Types::String }

  it "is a default scalar" do
    assert_equal(true, string_type.default_scalar?)
  end

  describe "coerce_result" do
    let(:utf_8_str) { "foobar" }
    let(:ascii_str) { "foobar".encode(Encoding::ASCII_8BIT) }
    let(:binary_str) { "\0\0\0foo\255\255\255".dup.force_encoding("BINARY") }

    describe "encoding" do
      subject { string_type.coerce_isolated_result(string) }

      describe "when result is encoded as UTF-8" do
        let(:string) { utf_8_str }

        it "returns the string" do
          assert_equal subject, string
        end
      end

      describe "when the result is not UTF-8 but can be transcoded" do
        let(:string) { ascii_str }

        it "returns the string transcoded to UTF-8" do
          assert_equal subject, string.encode(Encoding::UTF_8)
        end
      end

      describe "when the result is not UTF-8 and cannot be transcoded" do
        let(:string) { binary_str }

        it "raises GraphQL::StringEncodingError" do
          err = assert_raises(GraphQL::StringEncodingError) { subject }
          assert_equal "String \"\\x00\\x00\\x00foo\\xAD\\xAD\\xAD\" was encoded as ASCII-8BIT. GraphQL requires an encoding compatible with UTF-8.", err.message
          assert_equal string, err.string
        end
      end

      describe "In queries" do
        let(:schema) {
          query_type = Class.new(GraphQL::Schema::Object) do
            graphql_name "Query"

            field :bad_string, String
            def bad_string
              "\0\0\0foo\255\255\255".dup.force_encoding("BINARY")
            end
          end

          Class.new(GraphQL::Schema) do
            query(query_type)
          end
        }

        it "includes location in the error message" do
          err = assert_raises GraphQL::StringEncodingError do
            schema.execute("{ badString }")
          end
          expected_err = "String \"\\x00\\x00\\x00foo\\xAD\\xAD\\xAD\" was encoded as ASCII-8BIT @ badString (Query.badString). GraphQL requires an encoding compatible with UTF-8."
          assert_equal expected_err, err.message
        end
      end
    end

    describe "when the schema defines a custom handler" do
      let(:schema) {
        Class.new(GraphQL::Schema) do
          def self.type_error(err, ctx)
            ctx.errors << err
            "🌾"
          end
        end
      }

      let(:context) {
        OpenStruct.new(schema: schema, errors: [])
      }

      it "calls the handler" do
        assert_equal "🌾", string_type.coerce_result(binary_str, context)
        err = context.errors.last
        assert_instance_of GraphQL::StringEncodingError, err
      end
    end
  end

  describe "coerce_input" do
    it "accepts strings" do
      assert_equal "str", string_type.coerce_isolated_input("str")
    end

    it "doesn't accept other types" do
      assert_nil string_type.coerce_isolated_input(100)
      assert_nil string_type.coerce_isolated_input(true)
      assert_nil string_type.coerce_isolated_input(0.999)
    end
  end


  describe "unicode escapes" do
    class UnicodeEscapeSchema < GraphQL::Schema
      class QueryType < GraphQL::Schema::Object
        field :get_string, String do
          argument :string, String
        end

        def get_string(string:)
          string
        end
      end

      query(QueryType)
    end

    it "parses escapes properly in single-quoted strings" do
      query_str = File.read("./spec/fixtures/unicode_escapes/query1.graphql")
      res = UnicodeEscapeSchema.execute(query_str)
      assert_equal "d", res["data"]["example1"]
      assert_equal "\\u0064", res["data"]["example2"]
      assert_equal "\\u006", res["data"]["example4"]

      error_query_str = query_str.gsub("  # ", "  ")
      res2 = UnicodeEscapeSchema.execute(error_query_str)
      expected_err = if USING_C_PARSER
        "syntax error, unexpected invalid token (\"\\\"\") at [4, 31]"
      else
        "Expected string or block string, but it was malformed"
      end
      assert_equal [expected_err], res2["errors"].map { |err| err["message"] }
    end

    it "parses escapes properly in triple-quoted strings" do
      query_str = File.read("./spec/fixtures/unicode_escapes/query2.graphql")
      res = UnicodeEscapeSchema.execute(query_str)
      # No replacing in block strings:
      assert_equal "\\a", res["data"]["example1"]
      assert_equal "\\u006", res["data"]["example2"]
      assert_equal "\\n", res["data"]["example3"]
      assert_equal "\\u0064", res["data"]["example4"]
    end
  end
end