test/stripe/stripe_client_test.rb in stripe-5.1.1 vs test/stripe/stripe_client_test.rb in stripe-5.2.0

- old
+ new

@@ -15,10 +15,64 @@ assert_equal client, StripeClient.active_client end end end + context ".maybe_gc_connection_managers" do + should "garbage collect old connection managers when appropriate" do + stub_request(:post, "#{Stripe.api_base}/v1/path") + .to_return(body: JSON.generate(object: "account")) + + # Make sure we start with a blank slate (state may have been left in + # place by other tests). + StripeClient.clear_all_connection_managers + + # Establish a base time. + t = Time.new(2019) + + # And pretend that `StripeClient` was just initialized for the first + # time. (Don't access instance variables like this, but it's tricky to + # test properly otherwise.) + StripeClient.instance_variable_set(:@last_connection_manager_gc, t) + + Timecop.freeze(t) do + # Execute an initial request to ensure that a connection manager was + # created. + client = StripeClient.new + client.execute_request(:post, "/v1/path") + + # The GC shouldn't run yet (a `nil` return indicates that GC didn't run). + assert_equal nil, StripeClient.maybe_gc_connection_managers + end + + # Move time to just *before* garbage collection is eligible to run. + # Nothing should happen. + Timecop.freeze(t + StripeClient::CONNECTION_MANAGER_GC_PERIOD - 1) do + assert_equal nil, StripeClient.maybe_gc_connection_managers + end + + # Move time to just *after* garbage collection is eligible to run. + # Garbage collection will run, but because the connection manager is + # not passed its expiry age, it will not be collected. Zero is returned + # to indicate so. + Timecop.freeze(t + StripeClient::CONNECTION_MANAGER_GC_PERIOD + 1) do + assert_equal 0, StripeClient.maybe_gc_connection_managers + end + + # Move us far enough into the future that we're passed the horizons for + # both a GC run as well as well as the expiry age of a connection + # manager. That means the GC will run and collect the connection + # manager that we created above. + Timecop.freeze(t + StripeClient::CONNECTION_MANAGER_GC_LAST_USED_EXPIRY + 1) do + assert_equal 1, StripeClient.maybe_gc_connection_managers + + # And as an additional check, the connection manager of the current thread context should have been set to `nil` as it was GCed. + assert_nil StripeClient.current_thread_context.default_connection_manager + end + end + end + context ".clear_all_connection_managers" do should "clear connection managers across all threads" do stub_request(:post, "#{Stripe.api_base}/path") .to_return(body: JSON.generate(object: "account")) @@ -197,24 +251,10 @@ assert_equal(base_value * 4, StripeClient.sleep_time(3)) assert_equal(base_value * 8, StripeClient.sleep_time(4)) end end - context "#initialize" do - should "set Stripe.default_connection_manager" do - client = StripeClient.new - assert_equal StripeClient.default_connection_manager, - client.connection_manager - end - - should "set a different connection if one was specified" do - connection_manager = ConnectionManager.new - client = StripeClient.new(connection_manager) - assert_equal connection_manager, client.connection_manager - end - end - context "#execute_request" do context "headers" do should "support literal headers" do stub_request(:post, "#{Stripe.api_base}/v1/account") .with(headers: { "Stripe-Account" => "bar" }) @@ -468,61 +508,76 @@ should "handle error response with empty body" do stub_request(:post, "#{Stripe.api_base}/v1/charges") .to_return(body: "", status: 500) client = StripeClient.new + e = assert_raises Stripe::APIError do client.execute_request(:post, "/v1/charges") end - assert_equal 'Invalid response object from API: "" (HTTP response code was 500)', e.message end should "handle success response with empty body" do stub_request(:post, "#{Stripe.api_base}/v1/charges") .to_return(body: "", status: 200) client = StripeClient.new + e = assert_raises Stripe::APIError do client.execute_request(:post, "/v1/charges") end - assert_equal 'Invalid response object from API: "" (HTTP response code was 200)', e.message end + should "feed a request ID through to the error object" do + stub_request(:post, "#{Stripe.api_base}/v1/charges") + .to_return(body: JSON.generate(make_missing_id_error), + headers: { "Request-ID": "req_123" }, + status: 400) + + client = StripeClient.new + + e = assert_raises Stripe::InvalidRequestError do + client.execute_request(:post, "/v1/charges") + end + assert_equal("req_123", e.request_id) + end + should "handle low level error" do stub_request(:post, "#{Stripe.api_base}/v1/charges") .to_raise(Errno::ECONNREFUSED.new) client = StripeClient.new + e = assert_raises Stripe::APIConnectionError do client.execute_request(:post, "/v1/charges") end - assert_equal StripeClient::ERROR_MESSAGE_CONNECTION % Stripe.api_base + "\n\n(Network error: Connection refused)", e.message end should "handle error response with unknown value" do stub_request(:post, "#{Stripe.api_base}/v1/charges") .to_return(body: JSON.generate(bar: "foo"), status: 500) client = StripeClient.new + e = assert_raises Stripe::APIError do client.execute_request(:post, "/v1/charges") end - assert_equal 'Invalid response object from API: "{\"bar\":\"foo\"}" (HTTP response code was 500)', e.message end should "raise IdempotencyError on 400 of type idempotency_error" do data = make_missing_id_error data[:error][:type] = "idempotency_error" stub_request(:post, "#{Stripe.api_base}/v1/charges") .to_return(body: JSON.generate(data), status: 400) + client = StripeClient.new e = assert_raises Stripe::IdempotencyError do client.execute_request(:post, "/v1/charges") end @@ -531,87 +586,94 @@ end should "raise InvalidRequestError on other 400s" do stub_request(:post, "#{Stripe.api_base}/v1/charges") .to_return(body: JSON.generate(make_missing_id_error), status: 400) + client = StripeClient.new - begin + + e = assert_raises Stripe::InvalidRequestError do client.execute_request(:post, "/v1/charges") - rescue Stripe::InvalidRequestError => e - assert_equal(400, e.http_status) - assert_equal(true, e.json_body.is_a?(Hash)) end + assert_equal(400, e.http_status) + assert_equal(true, e.json_body.is_a?(Hash)) end should "raise AuthenticationError on 401" do stub_request(:post, "#{Stripe.api_base}/v1/charges") .to_return(body: JSON.generate(make_missing_id_error), status: 401) + client = StripeClient.new - begin + + e = assert_raises Stripe::AuthenticationError do client.execute_request(:post, "/v1/charges") - rescue Stripe::AuthenticationError => e - assert_equal(401, e.http_status) - assert_equal(true, e.json_body.is_a?(Hash)) end + assert_equal(401, e.http_status) + assert_equal(true, e.json_body.is_a?(Hash)) end should "raise CardError on 402" do stub_request(:post, "#{Stripe.api_base}/v1/charges") .to_return(body: JSON.generate(make_invalid_exp_year_error), status: 402) + client = StripeClient.new - begin + + e = assert_raises Stripe::CardError do client.execute_request(:post, "/v1/charges") - rescue Stripe::CardError => e - assert_equal(402, e.http_status) - assert_equal(true, e.json_body.is_a?(Hash)) - assert_equal("invalid_expiry_year", e.code) - assert_equal("exp_year", e.param) end + assert_equal(402, e.http_status) + assert_equal(true, e.json_body.is_a?(Hash)) + assert_equal("invalid_expiry_year", e.code) + assert_equal("exp_year", e.param) end should "raise PermissionError on 403" do stub_request(:post, "#{Stripe.api_base}/v1/charges") .to_return(body: JSON.generate(make_missing_id_error), status: 403) + client = StripeClient.new - begin + + e = assert_raises Stripe::PermissionError do client.execute_request(:post, "/v1/charges") - rescue Stripe::PermissionError => e - assert_equal(403, e.http_status) - assert_equal(true, e.json_body.is_a?(Hash)) end + assert_equal(403, e.http_status) + assert_equal(true, e.json_body.is_a?(Hash)) end should "raise InvalidRequestError on 404" do stub_request(:post, "#{Stripe.api_base}/v1/charges") .to_return(body: JSON.generate(make_missing_id_error), status: 404) + client = StripeClient.new - begin + + e = assert_raises Stripe::InvalidRequestError do client.execute_request(:post, "/v1/charges") - rescue Stripe::InvalidRequestError => e - assert_equal(404, e.http_status) - assert_equal(true, e.json_body.is_a?(Hash)) end + assert_equal(404, e.http_status) + assert_equal(true, e.json_body.is_a?(Hash)) end should "raise RateLimitError on 429" do stub_request(:post, "#{Stripe.api_base}/v1/charges") .to_return(body: JSON.generate(make_rate_limit_error), status: 429) + client = StripeClient.new - begin + + e = assert_raises Stripe::RateLimitError do client.execute_request(:post, "/v1/charges") - rescue Stripe::RateLimitError => e - assert_equal(429, e.http_status) - assert_equal(true, e.json_body.is_a?(Hash)) end + assert_equal(429, e.http_status) + assert_equal(true, e.json_body.is_a?(Hash)) end should "raise OAuth::InvalidRequestError when error is a string with value 'invalid_request'" do stub_request(:post, "#{Stripe.connect_base}/oauth/token") .to_return(body: JSON.generate(error: "invalid_request", error_description: "No grant type specified"), status: 400) client = StripeClient.new + opts = { api_base: Stripe.connect_base } e = assert_raises Stripe::OAuth::InvalidRequestError do client.execute_request(:post, "/oauth/token", opts) end @@ -623,10 +685,11 @@ stub_request(:post, "#{Stripe.connect_base}/oauth/token") .to_return(body: JSON.generate(error: "invalid_grant", error_description: "This authorization code has already been used. All tokens issued with this code have been revoked."), status: 400) client = StripeClient.new + opts = { api_base: Stripe.connect_base } e = assert_raises Stripe::OAuth::InvalidGrantError do client.execute_request(:post, "/oauth/token", opts) end @@ -639,10 +702,11 @@ stub_request(:post, "#{Stripe.connect_base}/oauth/deauthorize") .to_return(body: JSON.generate(error: "invalid_client", error_description: "This application is not connected to stripe account acct_19tLK7DSlTMT26Mk, or that account does not exist."), status: 401) client = StripeClient.new + opts = { api_base: Stripe.connect_base } e = assert_raises Stripe::OAuth::InvalidClientError do client.execute_request(:post, "/oauth/deauthorize", opts) end @@ -655,10 +719,11 @@ stub_request(:post, "#{Stripe.connect_base}/oauth/deauthorize") .to_return(body: JSON.generate(error: "new_code_not_recognized", error_description: "Something."), status: 401) client = StripeClient.new + opts = { api_base: Stripe.connect_base } e = assert_raises Stripe::OAuth::OAuthError do client.execute_request(:post, "/oauth/deauthorize", opts) end @@ -811,9 +876,25 @@ "#{Stripe.api_base}/v1/invoices/upcoming?", query: { customer: "cus_param", } ) + end + end + end + + context "#connection_manager" do + should "warn that #connection_manager is deprecated" do + old_stderr = $stderr + $stderr = StringIO.new + begin + client = StripeClient.new + client.connection_manager + message = "NOTE: Stripe::StripeClient#connection_manager is " \ + "deprecated" + assert_match Regexp.new(message), $stderr.string + ensure + $stderr = old_stderr end end end context "#request" do