|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +require 'spec_helper' |
| 4 | + |
| 5 | +RSpec.describe Slack::Web::Client do |
| 6 | + subject(:client) { described_class.new(token: 'example-token') } |
| 7 | + |
| 8 | + it 'observes Slack errors and re-raises the same exception' do |
| 9 | + stub_request(:post, 'https://slack.com/api/auth.test').to_return( |
| 10 | + body: '{"ok":false,"error":"invalid_arguments","response_metadata":{"messages":["missing field"]}}' |
| 11 | + ) |
| 12 | + errors = [] |
| 13 | + observed = client.with_error { |error| errors << error } |
| 14 | + expect { observed.auth_test }.to(raise_error do |error| |
| 15 | + expect(error).to equal(errors.first) |
| 16 | + expect(error.response_metadata.messages).to eq(['missing field']) |
| 17 | + expect(error.backtrace.first).to include('raise_error.rb') |
| 18 | + end) |
| 19 | + expect(errors.size).to eq(1) |
| 20 | + end |
| 21 | + |
| 22 | + it 'does not mutate the original client' do |
| 23 | + stub_request(:post, 'https://slack.com/api/auth.test').to_timeout |
| 24 | + errors = [] |
| 25 | + client.with_error { |error| errors << error } |
| 26 | + expect { client.auth_test }.to raise_error(Slack::Web::Api::Errors::TimeoutError) |
| 27 | + expect(errors).to be_empty |
| 28 | + end |
| 29 | + |
| 30 | + it 'observes transport errors' do |
| 31 | + stub_request(:post, 'https://slack.com/api/auth.test').to_timeout |
| 32 | + errors = [] |
| 33 | + observed = client.with_error { |error| errors << error } |
| 34 | + expect { observed.auth_test }.to raise_error(Slack::Web::Api::Errors::TimeoutError) |
| 35 | + expect(errors.first).to be_a(Slack::Web::Api::Errors::TimeoutError) |
| 36 | + end |
| 37 | + |
| 38 | + it 'observes translated parsing errors' do |
| 39 | + stub_request(:post, 'https://slack.com/api/auth.test').to_return(body: 'not json') |
| 40 | + errors = [] |
| 41 | + observed = client.with_error { |error| errors << error } |
| 42 | + expect { observed.auth_test }.to(raise_error do |error| |
| 43 | + expect(error).to be_a(Slack::Web::Api::Errors::ParsingError) |
| 44 | + expect(error).to equal(errors.first) |
| 45 | + expect(error.cause).to be_a(Faraday::ParsingError) |
| 46 | + end) |
| 47 | + end |
| 48 | + |
| 49 | + it 'observes each pagination retry without stopping retries' do |
| 50 | + stub_request(:post, 'https://slack.com/api/users.list') |
| 51 | + .to_return(status: 429, headers: { 'Retry-After' => '0' }, body: '{"ok":false}') |
| 52 | + .then.to_return(body: '{"ok":true,"members":[]}') |
| 53 | + errors = [] |
| 54 | + responses = [] |
| 55 | + observed = client.with_error { |error| errors << error } |
| 56 | + observed = observed.with_response { |response| responses << response } |
| 57 | + pages = [] |
| 58 | + observed.users_list { |page| pages << page } |
| 59 | + expect(errors.first).to be_a(Slack::Web::Api::Errors::TooManyRequestsError) |
| 60 | + expect(errors.size).to eq(1) |
| 61 | + expect(responses.map(&:body)).to eq(pages) |
| 62 | + expect(pages.size).to eq(1) |
| 63 | + end |
| 64 | + |
| 65 | + it 'registers chained error callbacks in order' do |
| 66 | + stub_request(:post, 'https://slack.com/api/auth.test').to_timeout |
| 67 | + calls = [] |
| 68 | + observed = client.with_error { calls << 1 }.with_error { calls << 2 } |
| 69 | + expect { observed.auth_test }.to raise_error(Slack::Web::Api::Errors::TimeoutError) |
| 70 | + expect(calls).to eq([1, 2]) |
| 71 | + end |
| 72 | + |
| 73 | + %i[with_request with_response].each do |callback_method| |
| 74 | + it "does not observe exceptions from #{callback_method} callbacks" do |
| 75 | + stub_request(:post, 'https://slack.com/api/auth.test').to_return(body: '{"ok":true}') |
| 76 | + errors = [] |
| 77 | + observed = client.with_error { |error| errors << error } |
| 78 | + callback_error = Faraday::ParsingError.new('callback error') |
| 79 | + observed = observed.public_send(callback_method) { raise callback_error } |
| 80 | + expect { observed.auth_test }.to(raise_error { |error| expect(error).to equal(callback_error) }) |
| 81 | + expect(errors).to be_empty |
| 82 | + end |
| 83 | + end |
| 84 | + |
| 85 | + it 'propagates error callback failures without recursive notification' do |
| 86 | + stub_request(:post, 'https://slack.com/api/auth.test').to_timeout |
| 87 | + calls = [] |
| 88 | + observed = client.with_error do |
| 89 | + calls << :called |
| 90 | + raise ArgumentError, 'observer failed' |
| 91 | + end |
| 92 | + expect { observed.auth_test }.to raise_error(ArgumentError, 'observer failed') |
| 93 | + expect(calls).to eq([:called]) |
| 94 | + end |
| 95 | + |
| 96 | + it 'requires a block' do |
| 97 | + expect { client.with_error }.to raise_error(ArgumentError, 'error callback block is required') |
| 98 | + end |
| 99 | +end |
0 commit comments