twirp-ruby/test/client_json_test.rb

135 строки
3.8 KiB
Ruby

require 'minitest/autorun'
require 'rack/mock'
require 'google/protobuf'
require 'json'
require_relative '../lib/twirp/client_json'
require_relative './fake_services'
class ClientJSONTest < Minitest::Test
def test_client_json_requires_service
assert_raises ArgumentError do
Twirp::ClientJSON.new("http://localhost:8080") # missing service
end
Twirp::ClientJSON.new("http://localhost:8080", service: "FooBar") # ok
end
def test_client_json_success
c = Twirp::ClientJSON.new(conn_stub("/my.pkg.Talking/Blah") {|req|
assert_equal "application/json", req.request_headers['Content-Type']
assert_equal '{"blah1":1,"blah2":2}', req.body # body is json
[200, {}, '{"blah_resp": 3}']
}, package: "my.pkg", service: "Talking")
resp = c.rpc :Blah, blah1: 1, blah2: 2
assert_nil resp.error
refute_nil resp.data
assert_equal 3, resp.data["blah_resp"]
refute_nil resp.headers
end
def test_client_json_thennable
c = Twirp::ClientJSON.new(conn_stub_thennable("/my.pkg.Talking/Blah") {|req|
assert_equal "application/json", req.request_headers['Content-Type']
assert_equal '{"blah1":1,"blah2":2}', req.body # body is json
[200, {}, '{"blah_resp": 3}']
}, package: "my.pkg", service: "Talking")
resp_thennable = c.rpc :Blah, blah1: 1, blah2: 2
# the final `.then {}` call will yield a ClientResp
assert resp_thennable.is_a?(Thennable)
resp = resp_thennable.value
assert resp.is_a?(Twirp::ClientResp)
# the final Thennable will have come from one with a faraday response
assert resp_thennable.parent.is_a?(Thennable)
assert resp_thennable.parent.value.is_a?(Faraday::Response)
# the final ClientResp should look the same as when then isn't used
assert_nil resp.error
refute_nil resp.data
assert_equal 3, resp.data["blah_resp"]
end
def test_client_json_strict_encoding
c = Twirp::ClientJSON.new(conn_stub("/my.pkg.Talking/Blah") {|req|
assert_equal "application/json; strict=true", req.request_headers['Content-Type']
assert_equal '{"blah1":1,"blah2":2}', req.body # body is json
[200, {}, '{"blah_resp": 3}']
}, package: "my.pkg", service: "Talking", strict: true)
resp = c.rpc :Blah, blah1: 1, blah2: 2
assert_nil resp.error
refute_nil resp.data
assert_equal 3, resp.data["blah_resp"]
end
def test_client_json_error
c = Twirp::ClientJSON.new(conn_stub("/Foo/Foomo") {|req|
[400, {}, '{"code": "invalid_argument", "msg": "dont like empty"}']
}, service: "Foo")
resp = c.rpc :Foomo, foo: ""
assert_nil resp.data
refute_nil resp.error
assert_equal :invalid_argument, resp.error.code
assert_equal "dont like empty", resp.error.msg
refute_nil resp.headers
end
def test_client_bad_json_route
c = Twirp::ClientJSON.new(conn_stub("/Foo/OtherMethod") {|req|
[404, {}, 'not here buddy']
}, service: "Foo")
resp = c.rpc :OtherMethod, foo: ""
assert_nil resp.data
refute_nil resp.error
assert_equal :bad_route, resp.error.code
refute_nil resp.headers
end
def conn_stub(path)
Faraday.new do |conn|
conn.adapter :test do |stub|
stub.post(path) do |env|
yield(env)
end
end
end
end
# mock of a promise-like thennable, allowing a call to ".then" to get the real value
class Thennable
attr_reader :value, :parent
def initialize(value, parent = nil)
@value = value
@parent = parent
end
def then(&block)
# similar to a promise, but runs immediately
Thennable.new(block.call(@value), self)
end
end
module ThennableFaraday
def post(*)
Thennable.new(super)
end
end
def conn_stub_thennable(path, &block)
s = conn_stub(path, &block)
s.extend(ThennableFaraday)
s
end
end