test/unit/client_test.rb in raygun4ruby-3.2.3 vs test/unit/client_test.rb in raygun4ruby-3.2.4
- old
+ new
@@ -1,792 +1,792 @@
-# -*- coding: utf-8 -*-
-require_relative "../test_helper.rb"
-require 'stringio'
-
-class ClientTest < Raygun::UnitTest
-
- class TestException < StandardError
- def initialize(message = nil)
- super(message || "A test message")
- end
- end
-
- class NilMessageError < StandardError
- def message
- nil
- end
- end
-
- class FakeActionDispatcherIp
- attr_reader :ip
- def initialize remote_ip
- @ip = remote_ip
- end
- def to_s
- return ip
- end
- end
-
- def setup
- super
- @client = Raygun::Client.new
- Raygun.configuration.record_raw_data = true
- fake_successful_entry
-
- # Force NZ time zone for utcOffset tests
- ENV['TZ'] = 'UTC-13'
- end
-
- def test_record_breadcrumb_does_not_crash_without_initialized_store
- Raygun.record_breadcrumb(
- message: 'aliens',
- category: 'exceptions',
- level: :info
- )
- end
-
- def test_api_key_required_message
- Raygun.configuration.api_key = nil
-
- $stderr.expects(:puts).with(Raygun::Client::NO_API_KEY_MESSAGE).once
- second_client = Raygun::Client.new
- end
-
- def test_track_exception
- response = Raygun.track_exceptions do
- raise TestException.new
- end
-
- assert response.success?
- end
-
- def test_error_details
- assert_equal exception_hash, @client.send(:error_details, test_exception)
- end
-
- def test_error_details_with_nil_message
- e = NilMessageError.new
- expected_message = ""
- assert_equal expected_message, @client.send(:error_details, e)[:message]
- end
-
- def test_utc_offset
- expected = 13
-
- assert_equal expected, @client.send(:build_payload_hash, test_exception, sample_env_hash)[:details][:environment][:utcOffset]
- end
-
- def test_inner_error_details
- oe = TestException.new("A test message")
- oe.set_backtrace(["/some/folder/some_file.rb:123:in `some_method_name'"])
-
- ie = TestException.new("Inner test message")
- ie.set_backtrace(["/another/path/foo.rb:1234:in `block (3 levels) run'"])
-
- e = nest_exceptions(oe, ie)
-
- expected_hash = {
- className: "ClientTest::TestException",
- message: oe.message,
- stackTrace: [
- { lineNumber: "123", fileName: "/some/folder/some_file.rb", methodName: "some_method_name" }
- ]
- }
-
- # test inner error according with its availability (ruby >= 2.1)
- if e.respond_to? :cause
- expected_hash[:innerError] = {
- className: "ClientTest::TestException",
- message: ie.message,
- stackTrace: [
- { lineNumber: "1234", fileName: "/another/path/foo.rb", methodName: "block (3 levels) run"}
- ]
- }
- end
-
- assert_equal expected_hash, @client.send(:error_details, e)
- end
-
- def test_client_details
- expected_hash = {
- name: Raygun::CLIENT_NAME,
- version: Raygun::VERSION,
- clientUrl: Raygun::CLIENT_URL
- }
-
- assert_equal expected_hash, @client.send(:client_details)
- end
-
-
- def test_version
- Raygun.setup do |config|
- config.version = 123
- end
-
- assert_equal 123, @client.send(:version)
- end
-
- def test_affected_user
- test_env = { "raygun.affected_user" => { :identifier => "somepooruser@yourapp.com" } }
- expected_hash = test_env["raygun.affected_user"]
-
- assert_equal expected_hash, @client.send(:build_payload_hash, test_exception, test_env)[:details][:user]
- end
-
- def test_tags
- configuration_tags = %w{alpha beta gaga}
- explicit_env_tags = %w{one two three four}
- rack_env_tag = %w{test}
-
- Raygun.setup do |config|
- config.tags = configuration_tags
- end
-
- test_env = { tags: explicit_env_tags }
- expected_tags = configuration_tags + explicit_env_tags + rack_env_tag
-
- assert_equal expected_tags, @client.send(:build_payload_hash, test_exception, test_env)[:details][:tags]
- end
-
- def test_tags_with_proc
- configuration_tags = %w{bar}
- explicit_env_tags = %w{one two three four}
- rack_env_tag = %w{test}
-
- Raygun.setup do |config|
- config.tags = ->(exception, env) {
- [env[:foo]]
- }
- end
-
- test_env = { tags: explicit_env_tags, foo: 'bar' }
- expected_tags = configuration_tags + explicit_env_tags + rack_env_tag
-
- assert_equal expected_tags, @client.send(:build_payload_hash, test_exception, test_env)[:details][:tags]
- end
-
- def test_hostname
- assert_equal Socket.gethostname, @client.send(:hostname)
- end
-
- def test_unicode
- e = TestException.new('日本語のメッセージ です')
-
- assert_silent { @client.track_exception(e) }
- end
-
- def test_bad_encoding
- bad_message = (100..1000).to_a.pack('c*').force_encoding('utf-8')
- bad_exception = TestException.new(bad_message)
-
- assert !bad_message.valid_encoding?
- assert_silent { @client.track_exception(bad_exception) }
- end
-
- def test_backtrace_without_method_name
-
- expected = {
- lineNumber: "123",
- fileName: "/some/folder/some_file.rb",
- methodName: "(none)"
- }
-
- # note lack of "in method name" in this stack trace line
- assert_equal expected, @client.send(:stack_trace_for, "/some/folder/some_file.rb:123")
- end
-
- def test_full_payload_hash
- Timecop.freeze do
- Raygun.configuration.version = 123
- grouping_key = "my custom group"
- correlation_id = "my correlation id"
-
- expected_hash = {
- occurredOn: Time.now.utc.iso8601,
- details: {
- machineName: Socket.gethostname,
- version: 123,
- client: {
- name: Raygun::CLIENT_NAME,
- version: Raygun::VERSION,
- clientUrl: Raygun::CLIENT_URL
- },
- error: exception_hash,
- userCustomData: {},
- tags: ["test"],
- request: {},
- groupingKey: grouping_key,
- correlationId: correlation_id,
- environment: {
- utcOffset: 13
- }
- }
- }
-
- assert_equal expected_hash, @client.send(:build_payload_hash, test_exception, { grouping_key: grouping_key, correlation_id: correlation_id })
- end
- end
-
- def test_getting_request_information
- env_hash = sample_env_hash.merge({
- "QUERY_STRING"=>"a=b&c=4945438",
- "REQUEST_URI"=>"/?a=b&c=4945438",
- })
-
- expected_hash = {
- hostName: "localhost",
- url: "/",
- httpMethod: "GET",
- iPAddress: "127.0.0.1",
- queryString: { "a" => "b", "c" => "4945438" },
- headers: { "Version"=>"HTTP/1.1", "Host"=>"localhost:3000", "Cookie"=>"cookieval" },
- form: {},
- rawData: nil
- }
-
- assert_equal expected_hash, @client.send(:request_information, env_hash)
- end
-
- def test_getting_request_information_with_nil_env
- assert_equal({}, @client.send(:request_information, nil))
- end
-
- def test_raw_post_body
- env_hash = sample_env_hash.merge({
- "CONTENT_TYPE" => "application/json",
- "REQUEST_METHOD" => "POST",
- "rack.input" => StringIO.new('{"foo": "bar"}')
- })
-
- assert_equal '{"foo": "bar"}', @client.send(:request_information, env_hash)[:rawData]
- end
-
- def test_raw_post_body_with_more_than_4096_chars
- input = "0" * 5000;
- env_hash = sample_env_hash.merge({
- "CONTENT_TYPE" => "application/json",
- "REQUEST_METHOD" => "POST",
- "rack.input" => StringIO.new(input)
- })
-
- assert_equal input.slice(0, 4096), @client.send(:request_information, env_hash)[:rawData]
- end
-
- def test_raw_post_body_with_config_disabled
- Raygun.configuration.record_raw_data = false
- env_hash = sample_env_hash.merge({
- "CONTENT_TYPE" => "application/json",
- "REQUEST_METHOD" => "POST",
- "rack.input" => StringIO.new('{"foo": "bar"}')
- })
-
- assert_equal(nil, @client.send(:request_information, env_hash)[:rawData])
- end
-
- def test_error_raygun_custom_data
- custom_data = { "kappa" => "keepo" }
- e = Raygun::Error.new("A test message", custom_data)
- test_env = {}
- expected_form_hash = test_env.merge(custom_data)
-
- assert_equal expected_form_hash, @client.send(:build_payload_hash, e, test_env)[:details][:userCustomData]
- end
-
- def test_custom_data_configuration_with_hash
- custom_data = {foo: '123'}
- Raygun.configuration.custom_data = custom_data
-
- assert_equal custom_data, @client.send(:build_payload_hash, test_exception, sample_env_hash)[:details][:userCustomData]
- end
-
- def test_custom_data_configuration_with_proc
- Raygun.configuration.custom_data do |exception, env|
- {exception_message: exception.message, server_name: env["SERVER_NAME"]}
- end
- expected = {
- exception_message: "A test message",
- server_name: "localhost"
- }
-
- assert_equal expected, @client.send(:build_payload_hash, test_exception, sample_env_hash)[:details][:userCustomData]
- end
-
- def test_filtering_parameters
- post_body_env_hash = sample_env_hash.merge(
- "REQUEST_METHOD" => "POST",
- "rack.input"=>StringIO.new("a=b&c=4945438&password=swordfish")
- )
-
- expected_form_hash = { "a" => "b", "c" => "4945438", "password" => "[FILTERED]" }
-
- assert_equal expected_form_hash, @client.send(:request_information, post_body_env_hash)[:form]
- end
-
- def test_filtering_nested_params
- post_body_env_hash = sample_env_hash.merge(
- "REQUEST_METHOD" => "POST",
- "rack.input" => StringIO.new("a=b&bank%5Bcredit_card%5D%5Bcard_number%5D=my_secret_bank_number&bank%5Bname%5D=something&c=123456&user%5Bpassword%5D=my_fancy_password")
- )
-
- expected_form_hash = { "a" => "b", "bank" => { "credit_card" => { "card_number" => "[FILTERED]" }, "name" => "something" }, "c" => "123456", "user" => { "password" => "[FILTERED]" } }
-
- assert_equal expected_form_hash, @client.send(:request_information, post_body_env_hash)[:form]
- end
-
- def test_filter_parameters_using_proc
- # filter any parameters that start with "nsa_only"
- Raygun.configuration.filter_parameters do |hash|
- hash.inject({}) do |sanitized_hash, (k, v)|
- sanitized_hash[k] = if k.start_with? "nsa_only"
- "[OUREYESONLY]"
- else
- v
- end
- sanitized_hash
- end
- end
-
- post_body_env_hash = sample_env_hash.merge(
- "REQUEST_METHOD" => "POST",
- "rack.input" => StringIO.new("nsa_only_info=123&nsa_only_metadata=seekrit&something_normal=hello")
- )
-
- expected_form_hash = { "nsa_only_info" => "[OUREYESONLY]", "nsa_only_metadata" => "[OUREYESONLY]", "something_normal" => "hello" }
-
- assert_equal expected_form_hash, @client.send(:request_information, post_body_env_hash)[:form]
- ensure
- Raygun.configuration.filter_parameters = nil
- end
-
- def test_filter_parameters_using_array
- filter_params_as_from_rails = [:password]
- Raygun.configuration.filter_parameters = filter_params_as_from_rails
-
- parameters = {
- "something_normal" => "hello",
- "password" => "wouldntyouliketoknow",
- "password_confirmation" => "wouldntyouliketoknow",
- "PasswORD_weird_case" => "anythingatall"
- }
-
- expected_form_hash = {
- "something_normal" => "hello",
- "password" => "[FILTERED]",
- "password_confirmation" => "[FILTERED]",
- "PasswORD_weird_case" => "[FILTERED]"
- }
-
- post_body_env_hash = sample_env_hash.merge(
- "REQUEST_METHOD" => "POST",
- "rack.input" => StringIO.new(URI.encode_www_form(parameters))
- )
-
- assert_equal expected_form_hash, @client.send(:request_information, post_body_env_hash)[:form]
- ensure
- Raygun.configuration.filter_parameters = nil
- end
-
- def test_ip_address_from_action_dispatch
- env_hash = sample_env_hash.merge({
- "action_dispatch.remote_ip"=> "123.456.789.012"
- })
-
- assert_equal "123.456.789.012", @client.send(:ip_address_from, env_hash)
- assert_equal "123.456.789.012", @client.send(:request_information, env_hash)[:iPAddress]
- end
-
- def test_ip_address_from_old_action_dispatch
- old_action_dispatch_ip = FakeActionDispatcherIp.new("123.456.789.012")
- env_hash = sample_env_hash.merge({
- "action_dispatch.remote_ip"=> old_action_dispatch_ip
- })
-
- assert_equal old_action_dispatch_ip, @client.send(:ip_address_from, env_hash)
- assert_equal "123.456.789.012", @client.send(:request_information, env_hash)[:iPAddress]
- end
-
- def test_ip_address_from_raygun_specific_key
- env_hash = sample_env_hash.merge({
- "raygun.remote_ip"=>"123.456.789.012"
- })
-
- assert_equal "123.456.789.012", @client.send(:ip_address_from, env_hash)
- assert_equal "123.456.789.012", @client.send(:request_information, env_hash)[:iPAddress]
- end
-
- def test_ip_address_returns_not_available_if_not_set
- env_hash = sample_env_hash.dup
- env_hash.delete("REMOTE_ADDR")
-
- assert_equal "(Not Available)", @client.send(:ip_address_from, env_hash)
- end
-
- def test_setting_up_http_proxy
- begin
- Raygun.configuration.proxy_settings[:address] = "http://proxy.com"
- Raygun::Client.expects(:http_proxy).with("http://proxy.com", "80", nil, nil)
-
- Raygun.track_exceptions do
- raise TestException.new
- end
- ensure
- Raygun.configuration.proxy_settings = {}
- end
- end
-
- def test_filter_payload_with_whitelist_never_filters_toplevel
- Timecop.freeze do
- Raygun.configuration.filter_payload_with_whitelist = true
- Raygun.configuration.whitelist_payload_shape = {}
-
- e = test_exception
-
- assert_equal Time.now.utc.iso8601, @client.send(:build_payload_hash, e)[:occurredOn]
- assert_equal Hash, @client.send(:build_payload_hash, e)[:details].class
- end
- end
-
- def test_filter_payload_with_whitelist_never_filters_client
- Raygun.configuration.filter_payload_with_whitelist = true
- Raygun.configuration.whitelist_payload_shape = {}
-
- client_details = @client.send(:client_details)
-
- assert_equal client_details, @client.send(:build_payload_hash, test_exception)[:details][:client]
- end
-
- def test_filter_payload_with_whitelist_default_error
- Raygun.configuration.filter_payload_with_whitelist = true
-
- details = @client.send(:build_payload_hash, test_exception)[:details]
-
- assert_equal exception_hash, details[:error]
- end
-
- def test_filter_payload_with_whitelist_exclude_error_keys
- Raygun.configuration.filter_payload_with_whitelist = true
- Raygun.configuration.whitelist_payload_shape = {
- error: {
- className: true,
- message: true,
- stackTrace: true
- }
- }
-
- details = @client.send(:build_payload_hash, test_exception)[:details]
-
- assert_equal exception_hash, details[:error]
- end
-
- def test_filter_payload_with_whitelist_exclude_error_except_stacktrace
- Raygun.configuration.filter_payload_with_whitelist = true
- Raygun.configuration.whitelist_payload_shape = {
- error: {
- className: true,
- message: true,
- }
- }
-
- details = @client.send(:build_payload_hash, test_exception)[:details]
-
- expected_hash = exception_hash.merge({
- stackTrace: "[FILTERED]"
- })
-
- assert_equal expected_hash, details[:error]
- end
-
- def test_filter_payload_with_whitelist_proc
- Raygun.configuration.filter_payload_with_whitelist = true
- Raygun.configuration.whitelist_payload_shape do |payload|
- payload
- end
-
- details = @client.send(:build_payload_hash, test_exception)[:details]
-
- assert_equal exception_hash, details[:error]
- end
-
- def test_filter_payload_with_whitelist_default_request_post
- Raygun.configuration.filter_payload_with_whitelist = true
-
- post_body_env_hash = sample_env_hash.merge(
- "CONTENT_TYPE" => 'application/x-www-form-urlencoded',
- "REQUEST_METHOD" => "POST",
- "rack.input"=>StringIO.new("a=b&c=4945438&password=swordfish")
- )
-
- details = @client.send(:build_payload_hash, test_exception, post_body_env_hash)[:details]
-
- expected_hash = {
- hostName: "localhost",
- url: "/",
- httpMethod: "POST",
- iPAddress: "127.0.0.1",
- queryString: { },
- headers: { "Version"=>"HTTP/1.1", "Host"=>"localhost:3000", "Cookie"=>"cookieval" },
- form: { "a" => "[FILTERED]", "c" => "[FILTERED]", "password" => "[FILTERED]" },
- rawData: {}
- }
-
- assert_equal expected_hash, details[:request]
- end
-
- def test_filter_payload_with_whitelist_request_post_except_formkey
- Raygun.configuration.filter_payload_with_whitelist = true
- shape = Raygun.configuration.whitelist_payload_shape.dup
- shape[:request] = Raygun.configuration.whitelist_payload_shape[:request].merge(
- form: {
- username: true
- }
- )
- Raygun.configuration.whitelist_payload_shape = shape
-
- post_body_env_hash = sample_env_hash.merge(
- "REQUEST_METHOD" => "POST",
- "rack.input"=>StringIO.new("username=foo&password=swordfish")
- )
-
- details = @client.send(:build_payload_hash, test_exception, post_body_env_hash)[:details]
-
- expected_hash = {
- hostName: "localhost",
- url: "/",
- httpMethod: "POST",
- iPAddress: "127.0.0.1",
- queryString: { },
- headers: { "Version"=>"HTTP/1.1", "Host"=>"localhost:3000", "Cookie"=>"cookieval" },
- form: { "username" => "foo", "password" => "[FILTERED]" },
- rawData: {}
- }
-
- assert_equal expected_hash, details[:request]
- end
-
- def test_filter_payload_with_whitelist_default_request_get
- Raygun.configuration.filter_payload_with_whitelist = true
-
- env_hash = sample_env_hash.merge({
- "QUERY_STRING"=>"a=b&c=4945438",
- "REQUEST_URI"=>"/?a=b&c=4945438",
- })
- expected_hash = {
- hostName: "localhost",
- url: "/",
- httpMethod: "GET",
- iPAddress: "127.0.0.1",
- queryString: { "a" => "b", "c" => "4945438" },
- headers: { "Version"=>"HTTP/1.1", "Host"=>"localhost:3000", "Cookie"=>"cookieval" },
- form: {},
- rawData: nil
- }
-
- details = @client.send(:build_payload_hash, test_exception, env_hash)[:details]
-
- assert_equal expected_hash, details[:request]
- end
-
- def test_filter_payload_with_whitelist_default_request_get_except_querystring
- Raygun.configuration.filter_payload_with_whitelist = true
- shape = Raygun.configuration.whitelist_payload_shape.dup
- shape[:request] = Raygun::Configuration::DEFAULT_WHITELIST_PAYLOAD_SHAPE_REQUEST.dup.tap do |h|
- h.delete(:queryString)
- end
- Raygun.configuration.whitelist_payload_shape = shape
-
- expected_hash = {
- hostName: "localhost",
- url: "/",
- httpMethod: "GET",
- iPAddress: "127.0.0.1",
- queryString: "[FILTERED]",
- headers: { "Version"=>"HTTP/1.1", "Host"=>"localhost:3000", "Cookie"=>"cookieval" },
- form: {},
- rawData: nil
- }
-
- details = @client.send(:build_payload_hash, test_exception, sample_env_hash)[:details]
-
- assert_equal expected_hash, details[:request]
- end
-
- def test_filter_payload_with_whitelist_being_false_does_not_filter_query_string
- Raygun.configuration.filter_payload_with_whitelist = false
-
- env_hash = sample_env_hash.merge({
- "QUERY_STRING"=>"a=b&c=4945438",
- "REQUEST_URI"=>"/?a=b&c=4945438",
- })
- expected_hash = {
- hostName: "localhost",
- url: "/",
- httpMethod: "GET",
- iPAddress: "127.0.0.1",
- queryString: { "a" => "b", "c" => "4945438" },
- headers: { "Version"=>"HTTP/1.1", "Host"=>"localhost:3000", "Cookie"=>"cookieval" },
- form: {},
- rawData: nil
- }
-
- details = @client.send(:build_payload_hash, test_exception, env_hash)[:details]
-
- assert_equal expected_hash, details[:request]
- end
-
- def test_filter_payload_with_whitelist_request_specific_keys
- Raygun.configuration.filter_payload_with_whitelist = true
- Raygun.configuration.whitelist_payload_shape = {
- request: {
- url: true,
- httpMethod: true,
- hostName: true
- }
- }
-
- details = @client.send(:build_payload_hash, test_exception, sample_env_hash)[:details]
-
- expected_hash = {
- hostName: "localhost",
- url: "/",
- httpMethod: "GET",
- iPAddress: "[FILTERED]",
- queryString: "[FILTERED]",
- headers: "[FILTERED]",
- form: "[FILTERED]",
- rawData: "[FILTERED]"
- }
-
- assert_equal expected_hash, details[:request]
- end
-
-
- def test_filter_payload_with_whitelist_and_filter_parameters_applies_both
- Raygun.configuration.filter_parameters = [:password]
- Raygun.configuration.filter_payload_with_whitelist = true
- Raygun.configuration.whitelist_payload_shape = proc do |payload|
- payload[:request][:headers]["Cookie"] = "[FILTERED]"
- payload
- end
-
- parameters = {
- "something_normal" => "hello",
- "password" => "wouldntyouliketoknow"
- }
-
- post_body_env_hash = sample_env_hash.merge(
- "REQUEST_METHOD" => "POST",
- "rack.input" => StringIO.new(URI.encode_www_form(parameters))
- )
-
- payload = @client.send(:build_payload_hash, test_exception, post_body_env_hash)
- request_payload = payload[:details][:request]
-
- expected_form = {
- "something_normal" => "hello",
- "password" => "[FILTERED]"
- }
-
- assert_equal expected_form, request_payload[:form]
-
- expected_headers = {
- "Version" => "HTTP/1.1",
- "Host" => "localhost:3000",
- "Cookie" => "[FILTERED]"
- }
-
- assert_equal expected_headers, request_payload[:headers]
- end
-
- def test_build_payload_hash_adds_affected_user_details_when_supplied_with_user
- user = OpenStruct.new(id: '123', email: 'test@email.com', first_name: 'Taylor')
- expected_details = {
- :isAnonymous => false,
- :identifier => '123',
- :email => 'test@email.com',
- :firstName => 'Taylor',
- }
-
- user_details = @client.send(:build_payload_hash, test_exception, sample_env_hash, user)[:details][:user]
-
- assert_equal expected_details, user_details
- end
-
- def test_build_payload_includes_breadcrumbs
- ::Raygun::Breadcrumbs::Store.initialize
- ::Raygun::Breadcrumbs::Store.record(message: "foo")
-
- breadcrumbs = @client.send(:build_payload_hash, test_exception, sample_env_hash)[:details][:breadcrumbs]
- ::Raygun::Breadcrumbs::Store.clear
-
- assert_equal breadcrumbs.length, 1
- assert breadcrumbs[0].is_a? Hash
- end
-
- def test_raw_data_does_not_crash_on_buffer_without_pos
- buffer = StringIO.new('123456789')
- rack_env = {
- REQUEST_METHOD: 'POST',
- 'rack.input' => buffer
- }
-
- buffer.instance_eval('undef :pos')
-
- raw_data = @client.send(:raw_data, rack_env)
-
- assert_equal('123456789', raw_data)
- end
-
- private
-
- def test_exception
- e = TestException.new
- e.set_backtrace(["/some/folder/some_file.rb:123:in `some_method_name'",
- "/another/path/foo.rb:1234:in `block (3 levels) run'"])
-
- e
- end
-
- def nest_exceptions(outer_exception, inner_exception)
- begin
- begin
- raise inner_exception.class, inner_exception.message
- rescue => e
- e.set_backtrace inner_exception.backtrace
- raise outer_exception.class, outer_exception.message
- end
- rescue => nested_exception
- nested_exception.set_backtrace outer_exception.backtrace
- end
-
- nested_exception
- end
-
- def exception_hash
- {
- className: "ClientTest::TestException",
- message: "A test message",
- stackTrace: [
- { lineNumber: "123", fileName: "/some/folder/some_file.rb", methodName: "some_method_name" },
- { lineNumber: "1234", fileName: "/another/path/foo.rb", methodName: "block (3 levels) run"}
- ]
- }
- end
-
- def sample_env_hash
- {
- "SERVER_NAME"=>"localhost",
- "REQUEST_METHOD"=>"GET",
- "REQUEST_PATH"=>"/",
- "PATH_INFO"=>"/",
- "QUERY_STRING"=>"",
- "REQUEST_URI"=>"/",
- "HTTP_VERSION"=>"HTTP/1.1",
- "HTTP_HOST"=>"localhost:3000",
- "HTTP_COOKIE"=>"cookieval",
- "GATEWAY_INTERFACE"=>"CGI/1.2",
- "SERVER_PORT"=>"3000",
- "SERVER_PROTOCOL"=>"HTTP/1.1",
- "SCRIPT_NAME"=>"",
- "REMOTE_ADDR"=>"127.0.0.1"
- }
- end
-end
+# -*- coding: utf-8 -*-
+require_relative "../test_helper.rb"
+require 'stringio'
+
+class ClientTest < Raygun::UnitTest
+
+ class TestException < StandardError
+ def initialize(message = nil)
+ super(message || "A test message")
+ end
+ end
+
+ class NilMessageError < StandardError
+ def message
+ nil
+ end
+ end
+
+ class FakeActionDispatcherIp
+ attr_reader :ip
+ def initialize remote_ip
+ @ip = remote_ip
+ end
+ def to_s
+ return ip
+ end
+ end
+
+ def setup
+ super
+ @client = Raygun::Client.new
+ Raygun.configuration.record_raw_data = true
+ fake_successful_entry
+
+ # Force NZ time zone for utcOffset tests
+ ENV['TZ'] = 'UTC-13'
+ end
+
+ def test_record_breadcrumb_does_not_crash_without_initialized_store
+ Raygun.record_breadcrumb(
+ message: 'aliens',
+ category: 'exceptions',
+ level: :info
+ )
+ end
+
+ def test_api_key_required_message
+ Raygun.configuration.api_key = nil
+
+ $stderr.expects(:puts).with(Raygun::Client::NO_API_KEY_MESSAGE).once
+ second_client = Raygun::Client.new
+ end
+
+ def test_track_exception
+ response = Raygun.track_exceptions do
+ raise TestException.new
+ end
+
+ assert response.success?
+ end
+
+ def test_error_details
+ assert_equal exception_hash, @client.send(:error_details, test_exception)
+ end
+
+ def test_error_details_with_nil_message
+ e = NilMessageError.new
+ expected_message = ""
+ assert_equal expected_message, @client.send(:error_details, e)[:message]
+ end
+
+ def test_utc_offset
+ expected = 13
+
+ assert_equal expected, @client.send(:build_payload_hash, test_exception, sample_env_hash)[:details][:environment][:utcOffset]
+ end
+
+ def test_inner_error_details
+ oe = TestException.new("A test message")
+ oe.set_backtrace(["/some/folder/some_file.rb:123:in `some_method_name'"])
+
+ ie = TestException.new("Inner test message")
+ ie.set_backtrace(["/another/path/foo.rb:1234:in `block (3 levels) run'"])
+
+ e = nest_exceptions(oe, ie)
+
+ expected_hash = {
+ className: "ClientTest::TestException",
+ message: oe.message,
+ stackTrace: [
+ { lineNumber: "123", fileName: "/some/folder/some_file.rb", methodName: "some_method_name" }
+ ]
+ }
+
+ # test inner error according with its availability (ruby >= 2.1)
+ if e.respond_to? :cause
+ expected_hash[:innerError] = {
+ className: "ClientTest::TestException",
+ message: ie.message,
+ stackTrace: [
+ { lineNumber: "1234", fileName: "/another/path/foo.rb", methodName: "block (3 levels) run"}
+ ]
+ }
+ end
+
+ assert_equal expected_hash, @client.send(:error_details, e)
+ end
+
+ def test_client_details
+ expected_hash = {
+ name: Raygun::CLIENT_NAME,
+ version: Raygun::VERSION,
+ clientUrl: Raygun::CLIENT_URL
+ }
+
+ assert_equal expected_hash, @client.send(:client_details)
+ end
+
+
+ def test_version
+ Raygun.setup do |config|
+ config.version = 123
+ end
+
+ assert_equal 123, @client.send(:version)
+ end
+
+ def test_affected_user
+ test_env = { "raygun.affected_user" => { :identifier => "somepooruser@yourapp.com" } }
+ expected_hash = test_env["raygun.affected_user"]
+
+ assert_equal expected_hash, @client.send(:build_payload_hash, test_exception, test_env)[:details][:user]
+ end
+
+ def test_tags
+ configuration_tags = %w{alpha beta gaga}
+ explicit_env_tags = %w{one two three four}
+ rack_env_tag = %w{test}
+
+ Raygun.setup do |config|
+ config.tags = configuration_tags
+ end
+
+ test_env = { tags: explicit_env_tags }
+ expected_tags = configuration_tags + explicit_env_tags + rack_env_tag
+
+ assert_equal expected_tags, @client.send(:build_payload_hash, test_exception, test_env)[:details][:tags]
+ end
+
+ def test_tags_with_proc
+ configuration_tags = %w{bar}
+ explicit_env_tags = %w{one two three four}
+ rack_env_tag = %w{test}
+
+ Raygun.setup do |config|
+ config.tags = ->(exception, env) {
+ [env[:foo]]
+ }
+ end
+
+ test_env = { tags: explicit_env_tags, foo: 'bar' }
+ expected_tags = configuration_tags + explicit_env_tags + rack_env_tag
+
+ assert_equal expected_tags, @client.send(:build_payload_hash, test_exception, test_env)[:details][:tags]
+ end
+
+ def test_hostname
+ assert_equal Socket.gethostname, @client.send(:hostname)
+ end
+
+ def test_unicode
+ e = TestException.new('日本語のメッセージ です')
+
+ assert_silent { @client.track_exception(e) }
+ end
+
+ def test_bad_encoding
+ bad_message = (100..1000).to_a.pack('c*').force_encoding('utf-8')
+ bad_exception = TestException.new(bad_message)
+
+ assert !bad_message.valid_encoding?
+ assert_silent { @client.track_exception(bad_exception) }
+ end
+
+ def test_backtrace_without_method_name
+
+ expected = {
+ lineNumber: "123",
+ fileName: "/some/folder/some_file.rb",
+ methodName: "(none)"
+ }
+
+ # note lack of "in method name" in this stack trace line
+ assert_equal expected, @client.send(:stack_trace_for, "/some/folder/some_file.rb:123")
+ end
+
+ def test_full_payload_hash
+ Timecop.freeze do
+ Raygun.configuration.version = 123
+ grouping_key = "my custom group"
+ correlation_id = "my correlation id"
+
+ expected_hash = {
+ occurredOn: Time.now.utc.iso8601,
+ details: {
+ machineName: Socket.gethostname,
+ version: 123,
+ client: {
+ name: Raygun::CLIENT_NAME,
+ version: Raygun::VERSION,
+ clientUrl: Raygun::CLIENT_URL
+ },
+ error: exception_hash,
+ userCustomData: {},
+ tags: ["test"],
+ request: {},
+ groupingKey: grouping_key,
+ correlationId: correlation_id,
+ environment: {
+ utcOffset: 13
+ }
+ }
+ }
+
+ assert_equal expected_hash, @client.send(:build_payload_hash, test_exception, { grouping_key: grouping_key, correlation_id: correlation_id })
+ end
+ end
+
+ def test_getting_request_information
+ env_hash = sample_env_hash.merge({
+ "QUERY_STRING"=>"a=b&c=4945438",
+ "REQUEST_URI"=>"/?a=b&c=4945438",
+ })
+
+ expected_hash = {
+ hostName: "localhost",
+ url: "/",
+ httpMethod: "GET",
+ iPAddress: "127.0.0.1",
+ queryString: { "a" => "b", "c" => "4945438" },
+ headers: { "Version"=>"HTTP/1.1", "Host"=>"localhost:3000", "Cookie"=>"cookieval" },
+ form: {},
+ rawData: nil
+ }
+
+ assert_equal expected_hash, @client.send(:request_information, env_hash)
+ end
+
+ def test_getting_request_information_with_nil_env
+ assert_equal({}, @client.send(:request_information, nil))
+ end
+
+ def test_raw_post_body
+ env_hash = sample_env_hash.merge({
+ "CONTENT_TYPE" => "application/json",
+ "REQUEST_METHOD" => "POST",
+ "rack.input" => StringIO.new('{"foo": "bar"}')
+ })
+
+ assert_equal '{"foo": "bar"}', @client.send(:request_information, env_hash)[:rawData]
+ end
+
+ def test_raw_post_body_with_more_than_4096_chars
+ input = "0" * 5000;
+ env_hash = sample_env_hash.merge({
+ "CONTENT_TYPE" => "application/json",
+ "REQUEST_METHOD" => "POST",
+ "rack.input" => StringIO.new(input)
+ })
+
+ assert_equal input.slice(0, 4096), @client.send(:request_information, env_hash)[:rawData]
+ end
+
+ def test_raw_post_body_with_config_disabled
+ Raygun.configuration.record_raw_data = false
+ env_hash = sample_env_hash.merge({
+ "CONTENT_TYPE" => "application/json",
+ "REQUEST_METHOD" => "POST",
+ "rack.input" => StringIO.new('{"foo": "bar"}')
+ })
+
+ assert_equal(nil, @client.send(:request_information, env_hash)[:rawData])
+ end
+
+ def test_error_raygun_custom_data
+ custom_data = { "kappa" => "keepo" }
+ e = Raygun::Error.new("A test message", custom_data)
+ test_env = {}
+ expected_form_hash = test_env.merge(custom_data)
+
+ assert_equal expected_form_hash, @client.send(:build_payload_hash, e, test_env)[:details][:userCustomData]
+ end
+
+ def test_custom_data_configuration_with_hash
+ custom_data = {foo: '123'}
+ Raygun.configuration.custom_data = custom_data
+
+ assert_equal custom_data, @client.send(:build_payload_hash, test_exception, sample_env_hash)[:details][:userCustomData]
+ end
+
+ def test_custom_data_configuration_with_proc
+ Raygun.configuration.custom_data do |exception, env|
+ {exception_message: exception.message, server_name: env["SERVER_NAME"]}
+ end
+ expected = {
+ exception_message: "A test message",
+ server_name: "localhost"
+ }
+
+ assert_equal expected, @client.send(:build_payload_hash, test_exception, sample_env_hash)[:details][:userCustomData]
+ end
+
+ def test_filtering_parameters
+ post_body_env_hash = sample_env_hash.merge(
+ "REQUEST_METHOD" => "POST",
+ "rack.input"=>StringIO.new("a=b&c=4945438&password=swordfish")
+ )
+
+ expected_form_hash = { "a" => "b", "c" => "4945438", "password" => "[FILTERED]" }
+
+ assert_equal expected_form_hash, @client.send(:request_information, post_body_env_hash)[:form]
+ end
+
+ def test_filtering_nested_params
+ post_body_env_hash = sample_env_hash.merge(
+ "REQUEST_METHOD" => "POST",
+ "rack.input" => StringIO.new("a=b&bank%5Bcredit_card%5D%5Bcard_number%5D=my_secret_bank_number&bank%5Bname%5D=something&c=123456&user%5Bpassword%5D=my_fancy_password")
+ )
+
+ expected_form_hash = { "a" => "b", "bank" => { "credit_card" => { "card_number" => "[FILTERED]" }, "name" => "something" }, "c" => "123456", "user" => { "password" => "[FILTERED]" } }
+
+ assert_equal expected_form_hash, @client.send(:request_information, post_body_env_hash)[:form]
+ end
+
+ def test_filter_parameters_using_proc
+ # filter any parameters that start with "nsa_only"
+ Raygun.configuration.filter_parameters do |hash|
+ hash.inject({}) do |sanitized_hash, (k, v)|
+ sanitized_hash[k] = if k.start_with? "nsa_only"
+ "[OUREYESONLY]"
+ else
+ v
+ end
+ sanitized_hash
+ end
+ end
+
+ post_body_env_hash = sample_env_hash.merge(
+ "REQUEST_METHOD" => "POST",
+ "rack.input" => StringIO.new("nsa_only_info=123&nsa_only_metadata=seekrit&something_normal=hello")
+ )
+
+ expected_form_hash = { "nsa_only_info" => "[OUREYESONLY]", "nsa_only_metadata" => "[OUREYESONLY]", "something_normal" => "hello" }
+
+ assert_equal expected_form_hash, @client.send(:request_information, post_body_env_hash)[:form]
+ ensure
+ Raygun.configuration.filter_parameters = nil
+ end
+
+ def test_filter_parameters_using_array
+ filter_params_as_from_rails = [:password]
+ Raygun.configuration.filter_parameters = filter_params_as_from_rails
+
+ parameters = {
+ "something_normal" => "hello",
+ "password" => "wouldntyouliketoknow",
+ "password_confirmation" => "wouldntyouliketoknow",
+ "PasswORD_weird_case" => "anythingatall"
+ }
+
+ expected_form_hash = {
+ "something_normal" => "hello",
+ "password" => "[FILTERED]",
+ "password_confirmation" => "[FILTERED]",
+ "PasswORD_weird_case" => "[FILTERED]"
+ }
+
+ post_body_env_hash = sample_env_hash.merge(
+ "REQUEST_METHOD" => "POST",
+ "rack.input" => StringIO.new(URI.encode_www_form(parameters))
+ )
+
+ assert_equal expected_form_hash, @client.send(:request_information, post_body_env_hash)[:form]
+ ensure
+ Raygun.configuration.filter_parameters = nil
+ end
+
+ def test_ip_address_from_action_dispatch
+ env_hash = sample_env_hash.merge({
+ "action_dispatch.remote_ip"=> "123.456.789.012"
+ })
+
+ assert_equal "123.456.789.012", @client.send(:ip_address_from, env_hash)
+ assert_equal "123.456.789.012", @client.send(:request_information, env_hash)[:iPAddress]
+ end
+
+ def test_ip_address_from_old_action_dispatch
+ old_action_dispatch_ip = FakeActionDispatcherIp.new("123.456.789.012")
+ env_hash = sample_env_hash.merge({
+ "action_dispatch.remote_ip"=> old_action_dispatch_ip
+ })
+
+ assert_equal old_action_dispatch_ip, @client.send(:ip_address_from, env_hash)
+ assert_equal "123.456.789.012", @client.send(:request_information, env_hash)[:iPAddress]
+ end
+
+ def test_ip_address_from_raygun_specific_key
+ env_hash = sample_env_hash.merge({
+ "raygun.remote_ip"=>"123.456.789.012"
+ })
+
+ assert_equal "123.456.789.012", @client.send(:ip_address_from, env_hash)
+ assert_equal "123.456.789.012", @client.send(:request_information, env_hash)[:iPAddress]
+ end
+
+ def test_ip_address_returns_not_available_if_not_set
+ env_hash = sample_env_hash.dup
+ env_hash.delete("REMOTE_ADDR")
+
+ assert_equal "(Not Available)", @client.send(:ip_address_from, env_hash)
+ end
+
+ def test_setting_up_http_proxy
+ begin
+ Raygun.configuration.proxy_settings[:address] = "http://proxy.com"
+ Raygun::Client.expects(:http_proxy).with("http://proxy.com", "80", nil, nil)
+
+ Raygun.track_exceptions do
+ raise TestException.new
+ end
+ ensure
+ Raygun.configuration.proxy_settings = {}
+ end
+ end
+
+ def test_filter_payload_with_whitelist_never_filters_toplevel
+ Timecop.freeze do
+ Raygun.configuration.filter_payload_with_whitelist = true
+ Raygun.configuration.whitelist_payload_shape = {}
+
+ e = test_exception
+
+ assert_equal Time.now.utc.iso8601, @client.send(:build_payload_hash, e)[:occurredOn]
+ assert_equal Hash, @client.send(:build_payload_hash, e)[:details].class
+ end
+ end
+
+ def test_filter_payload_with_whitelist_never_filters_client
+ Raygun.configuration.filter_payload_with_whitelist = true
+ Raygun.configuration.whitelist_payload_shape = {}
+
+ client_details = @client.send(:client_details)
+
+ assert_equal client_details, @client.send(:build_payload_hash, test_exception)[:details][:client]
+ end
+
+ def test_filter_payload_with_whitelist_default_error
+ Raygun.configuration.filter_payload_with_whitelist = true
+
+ details = @client.send(:build_payload_hash, test_exception)[:details]
+
+ assert_equal exception_hash, details[:error]
+ end
+
+ def test_filter_payload_with_whitelist_exclude_error_keys
+ Raygun.configuration.filter_payload_with_whitelist = true
+ Raygun.configuration.whitelist_payload_shape = {
+ error: {
+ className: true,
+ message: true,
+ stackTrace: true
+ }
+ }
+
+ details = @client.send(:build_payload_hash, test_exception)[:details]
+
+ assert_equal exception_hash, details[:error]
+ end
+
+ def test_filter_payload_with_whitelist_exclude_error_except_stacktrace
+ Raygun.configuration.filter_payload_with_whitelist = true
+ Raygun.configuration.whitelist_payload_shape = {
+ error: {
+ className: true,
+ message: true,
+ }
+ }
+
+ details = @client.send(:build_payload_hash, test_exception)[:details]
+
+ expected_hash = exception_hash.merge({
+ stackTrace: "[FILTERED]"
+ })
+
+ assert_equal expected_hash, details[:error]
+ end
+
+ def test_filter_payload_with_whitelist_proc
+ Raygun.configuration.filter_payload_with_whitelist = true
+ Raygun.configuration.whitelist_payload_shape do |payload|
+ payload
+ end
+
+ details = @client.send(:build_payload_hash, test_exception)[:details]
+
+ assert_equal exception_hash, details[:error]
+ end
+
+ def test_filter_payload_with_whitelist_default_request_post
+ Raygun.configuration.filter_payload_with_whitelist = true
+
+ post_body_env_hash = sample_env_hash.merge(
+ "CONTENT_TYPE" => 'application/x-www-form-urlencoded',
+ "REQUEST_METHOD" => "POST",
+ "rack.input"=>StringIO.new("a=b&c=4945438&password=swordfish")
+ )
+
+ details = @client.send(:build_payload_hash, test_exception, post_body_env_hash)[:details]
+
+ expected_hash = {
+ hostName: "localhost",
+ url: "/",
+ httpMethod: "POST",
+ iPAddress: "127.0.0.1",
+ queryString: { },
+ headers: { "Version"=>"HTTP/1.1", "Host"=>"localhost:3000", "Cookie"=>"cookieval" },
+ form: { "a" => "[FILTERED]", "c" => "[FILTERED]", "password" => "[FILTERED]" },
+ rawData: {}
+ }
+
+ assert_equal expected_hash, details[:request]
+ end
+
+ def test_filter_payload_with_whitelist_request_post_except_formkey
+ Raygun.configuration.filter_payload_with_whitelist = true
+ shape = Raygun.configuration.whitelist_payload_shape.dup
+ shape[:request] = Raygun.configuration.whitelist_payload_shape[:request].merge(
+ form: {
+ username: true
+ }
+ )
+ Raygun.configuration.whitelist_payload_shape = shape
+
+ post_body_env_hash = sample_env_hash.merge(
+ "REQUEST_METHOD" => "POST",
+ "rack.input"=>StringIO.new("username=foo&password=swordfish")
+ )
+
+ details = @client.send(:build_payload_hash, test_exception, post_body_env_hash)[:details]
+
+ expected_hash = {
+ hostName: "localhost",
+ url: "/",
+ httpMethod: "POST",
+ iPAddress: "127.0.0.1",
+ queryString: { },
+ headers: { "Version"=>"HTTP/1.1", "Host"=>"localhost:3000", "Cookie"=>"cookieval" },
+ form: { "username" => "foo", "password" => "[FILTERED]" },
+ rawData: {}
+ }
+
+ assert_equal expected_hash, details[:request]
+ end
+
+ def test_filter_payload_with_whitelist_default_request_get
+ Raygun.configuration.filter_payload_with_whitelist = true
+
+ env_hash = sample_env_hash.merge({
+ "QUERY_STRING"=>"a=b&c=4945438",
+ "REQUEST_URI"=>"/?a=b&c=4945438",
+ })
+ expected_hash = {
+ hostName: "localhost",
+ url: "/",
+ httpMethod: "GET",
+ iPAddress: "127.0.0.1",
+ queryString: { "a" => "b", "c" => "4945438" },
+ headers: { "Version"=>"HTTP/1.1", "Host"=>"localhost:3000", "Cookie"=>"cookieval" },
+ form: {},
+ rawData: nil
+ }
+
+ details = @client.send(:build_payload_hash, test_exception, env_hash)[:details]
+
+ assert_equal expected_hash, details[:request]
+ end
+
+ def test_filter_payload_with_whitelist_default_request_get_except_querystring
+ Raygun.configuration.filter_payload_with_whitelist = true
+ shape = Raygun.configuration.whitelist_payload_shape.dup
+ shape[:request] = Raygun::Configuration::DEFAULT_WHITELIST_PAYLOAD_SHAPE_REQUEST.dup.tap do |h|
+ h.delete(:queryString)
+ end
+ Raygun.configuration.whitelist_payload_shape = shape
+
+ expected_hash = {
+ hostName: "localhost",
+ url: "/",
+ httpMethod: "GET",
+ iPAddress: "127.0.0.1",
+ queryString: "[FILTERED]",
+ headers: { "Version"=>"HTTP/1.1", "Host"=>"localhost:3000", "Cookie"=>"cookieval" },
+ form: {},
+ rawData: nil
+ }
+
+ details = @client.send(:build_payload_hash, test_exception, sample_env_hash)[:details]
+
+ assert_equal expected_hash, details[:request]
+ end
+
+ def test_filter_payload_with_whitelist_being_false_does_not_filter_query_string
+ Raygun.configuration.filter_payload_with_whitelist = false
+
+ env_hash = sample_env_hash.merge({
+ "QUERY_STRING"=>"a=b&c=4945438",
+ "REQUEST_URI"=>"/?a=b&c=4945438",
+ })
+ expected_hash = {
+ hostName: "localhost",
+ url: "/",
+ httpMethod: "GET",
+ iPAddress: "127.0.0.1",
+ queryString: { "a" => "b", "c" => "4945438" },
+ headers: { "Version"=>"HTTP/1.1", "Host"=>"localhost:3000", "Cookie"=>"cookieval" },
+ form: {},
+ rawData: nil
+ }
+
+ details = @client.send(:build_payload_hash, test_exception, env_hash)[:details]
+
+ assert_equal expected_hash, details[:request]
+ end
+
+ def test_filter_payload_with_whitelist_request_specific_keys
+ Raygun.configuration.filter_payload_with_whitelist = true
+ Raygun.configuration.whitelist_payload_shape = {
+ request: {
+ url: true,
+ httpMethod: true,
+ hostName: true
+ }
+ }
+
+ details = @client.send(:build_payload_hash, test_exception, sample_env_hash)[:details]
+
+ expected_hash = {
+ hostName: "localhost",
+ url: "/",
+ httpMethod: "GET",
+ iPAddress: "[FILTERED]",
+ queryString: "[FILTERED]",
+ headers: "[FILTERED]",
+ form: "[FILTERED]",
+ rawData: "[FILTERED]"
+ }
+
+ assert_equal expected_hash, details[:request]
+ end
+
+
+ def test_filter_payload_with_whitelist_and_filter_parameters_applies_both
+ Raygun.configuration.filter_parameters = [:password]
+ Raygun.configuration.filter_payload_with_whitelist = true
+ Raygun.configuration.whitelist_payload_shape = proc do |payload|
+ payload[:request][:headers]["Cookie"] = "[FILTERED]"
+ payload
+ end
+
+ parameters = {
+ "something_normal" => "hello",
+ "password" => "wouldntyouliketoknow"
+ }
+
+ post_body_env_hash = sample_env_hash.merge(
+ "REQUEST_METHOD" => "POST",
+ "rack.input" => StringIO.new(URI.encode_www_form(parameters))
+ )
+
+ payload = @client.send(:build_payload_hash, test_exception, post_body_env_hash)
+ request_payload = payload[:details][:request]
+
+ expected_form = {
+ "something_normal" => "hello",
+ "password" => "[FILTERED]"
+ }
+
+ assert_equal expected_form, request_payload[:form]
+
+ expected_headers = {
+ "Version" => "HTTP/1.1",
+ "Host" => "localhost:3000",
+ "Cookie" => "[FILTERED]"
+ }
+
+ assert_equal expected_headers, request_payload[:headers]
+ end
+
+ def test_build_payload_hash_adds_affected_user_details_when_supplied_with_user
+ user = OpenStruct.new(id: '123', email: 'test@email.com', first_name: 'Taylor')
+ expected_details = {
+ :isAnonymous => false,
+ :identifier => '123',
+ :email => 'test@email.com',
+ :firstName => 'Taylor',
+ }
+
+ user_details = @client.send(:build_payload_hash, test_exception, sample_env_hash, user)[:details][:user]
+
+ assert_equal expected_details, user_details
+ end
+
+ def test_build_payload_includes_breadcrumbs
+ ::Raygun::Breadcrumbs::Store.initialize
+ ::Raygun::Breadcrumbs::Store.record(message: "foo")
+
+ breadcrumbs = @client.send(:build_payload_hash, test_exception, sample_env_hash)[:details][:breadcrumbs]
+ ::Raygun::Breadcrumbs::Store.clear
+
+ assert_equal breadcrumbs.length, 1
+ assert breadcrumbs[0].is_a? Hash
+ end
+
+ def test_raw_data_does_not_crash_on_buffer_without_pos
+ buffer = StringIO.new('123456789')
+ rack_env = {
+ REQUEST_METHOD: 'POST',
+ 'rack.input' => buffer
+ }
+
+ buffer.instance_eval('undef :pos')
+
+ raw_data = @client.send(:raw_data, rack_env)
+
+ assert_equal('123456789', raw_data)
+ end
+
+ private
+
+ def test_exception
+ e = TestException.new
+ e.set_backtrace(["/some/folder/some_file.rb:123:in `some_method_name'",
+ "/another/path/foo.rb:1234:in `block (3 levels) run'"])
+
+ e
+ end
+
+ def nest_exceptions(outer_exception, inner_exception)
+ begin
+ begin
+ raise inner_exception.class, inner_exception.message
+ rescue => e
+ e.set_backtrace inner_exception.backtrace
+ raise outer_exception.class, outer_exception.message
+ end
+ rescue => nested_exception
+ nested_exception.set_backtrace outer_exception.backtrace
+ end
+
+ nested_exception
+ end
+
+ def exception_hash
+ {
+ className: "ClientTest::TestException",
+ message: "A test message",
+ stackTrace: [
+ { lineNumber: "123", fileName: "/some/folder/some_file.rb", methodName: "some_method_name" },
+ { lineNumber: "1234", fileName: "/another/path/foo.rb", methodName: "block (3 levels) run"}
+ ]
+ }
+ end
+
+ def sample_env_hash
+ {
+ "SERVER_NAME"=>"localhost",
+ "REQUEST_METHOD"=>"GET",
+ "REQUEST_PATH"=>"/",
+ "PATH_INFO"=>"/",
+ "QUERY_STRING"=>"",
+ "REQUEST_URI"=>"/",
+ "HTTP_VERSION"=>"HTTP/1.1",
+ "HTTP_HOST"=>"localhost:3000",
+ "HTTP_COOKIE"=>"cookieval",
+ "GATEWAY_INTERFACE"=>"CGI/1.2",
+ "SERVER_PORT"=>"3000",
+ "SERVER_PROTOCOL"=>"HTTP/1.1",
+ "SCRIPT_NAME"=>"",
+ "REMOTE_ADDR"=>"127.0.0.1"
+ }
+ end
+end