Skip to content

Commit 575e325

Browse files
committed
Expose authenticator on Client via attr_reader
1 parent 9214a6b commit 575e325

3 files changed

Lines changed: 43 additions & 13 deletions

File tree

lib/x/client.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ class Client
4444
# client.default_object_class = OpenStruct
4545
attr_accessor :default_object_class
4646

47+
# The authenticator for API requests
48+
# @api public
49+
# @return [Authenticator] the authenticator instance
50+
# @example Check if the OAuth 2.0 token has expired
51+
# client.authenticator.token_expired?
52+
attr_reader :authenticator
53+
4754
def_delegators :@connection, :open_timeout, :read_timeout, :write_timeout, :proxy_url, :debug_output
4855
def_delegators :@connection, :open_timeout=, :read_timeout=, :write_timeout=, :proxy_url=, :debug_output=
4956
def_delegators :@redirect_handler, :max_redirects
@@ -144,9 +151,9 @@ def delete(endpoint, headers: {}, array_class: default_array_class, object_class
144151
# @return [Hash, Array, nil] the parsed response body
145152
def execute_request(http_method, endpoint, body: nil, headers: {}, array_class: default_array_class, object_class: default_object_class)
146153
uri = URI.join(base_url, endpoint)
147-
request = @request_builder.build(http_method:, uri:, body:, headers:, authenticator: @authenticator)
154+
request = @request_builder.build(http_method:, uri:, body:, headers:, authenticator:)
148155
response = @connection.perform(request:)
149-
response = @redirect_handler.handle(response:, request:, base_url:, authenticator: @authenticator)
156+
response = @redirect_handler.handle(response:, request:, base_url:, authenticator:)
150157
@response_parser.parse(response:, array_class:, object_class:)
151158
end
152159
end

sig/x.rbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ module X
274274
attr_accessor base_url: String
275275
attr_accessor default_array_class: singleton(Array)
276276
attr_accessor default_object_class: singleton(Hash)
277+
attr_reader authenticator: Authenticator | BearerTokenAuthenticator | OAuthAuthenticator | OAuth2Authenticator
277278
def initialize: (?api_key: String?, ?api_key_secret: String?, ?access_token: String?, ?access_token_secret: String?, ?bearer_token: String?, ?client_id: String?, ?client_secret: String?, ?refresh_token: String?, ?base_url: String, ?open_timeout: Integer, ?read_timeout: Integer, ?write_timeout: Integer, ?debug_output: untyped, ?proxy_url: String?, ?default_array_class: singleton(Array), ?default_object_class: singleton(Hash), ?max_redirects: Integer) -> void
278279
def get: (String endpoint, ?headers: Hash[String, String], ?array_class: Class, ?object_class: Class) -> untyped
279280
def post: (String endpoint, ?String? body, ?headers: Hash[String, String], ?array_class: Class, ?object_class: Class) -> untyped

test/x/client_initialization_test.rb

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class ClientOAuthInitializationTest < Minitest::Test
88
def test_initialize_oauth_credentials
99
client = Client.new(**test_oauth_credentials)
1010

11-
authenticator = client.instance_variable_get(:@authenticator)
11+
authenticator = client.authenticator
1212

1313
assert_instance_of OAuthAuthenticator, authenticator
1414
assert_equal TEST_API_KEY, authenticator.api_key
@@ -21,7 +21,7 @@ def test_missing_oauth_credentials
2121
test_oauth_credentials.each_key do |missing_credential|
2222
client = Client.new(**test_oauth_credentials.except(missing_credential))
2323

24-
assert_instance_of Authenticator, client.instance_variable_get(:@authenticator)
24+
assert_instance_of Authenticator, client.authenticator
2525
end
2626
end
2727

@@ -33,7 +33,7 @@ def test_setting_oauth_credentials
3333
assert_equal value, client.public_send(credential)
3434
end
3535

36-
assert_instance_of OAuthAuthenticator, client.instance_variable_get(:@authenticator)
36+
assert_instance_of OAuthAuthenticator, client.authenticator
3737
end
3838

3939
def test_setting_oauth_credentials_reinitializes_authenticator
@@ -55,7 +55,7 @@ class ClientOAuth2InitializationTest < Minitest::Test
5555
def test_initialize_oauth2_credentials
5656
client = Client.new(**test_oauth2_credentials)
5757

58-
authenticator = client.instance_variable_get(:@authenticator)
58+
authenticator = client.authenticator
5959

6060
assert_instance_of OAuth2Authenticator, authenticator
6161
assert_equal TEST_CLIENT_ID, authenticator.client_id
@@ -68,7 +68,7 @@ def test_missing_oauth2_credentials
6868
test_oauth2_credentials.each_key do |missing_credential|
6969
client = Client.new(**test_oauth2_credentials.except(missing_credential))
7070

71-
assert_instance_of Authenticator, client.instance_variable_get(:@authenticator)
71+
assert_instance_of Authenticator, client.authenticator
7272
end
7373
end
7474

@@ -80,7 +80,7 @@ def test_setting_oauth2_credentials
8080
assert_equal value, client.public_send(credential)
8181
end
8282

83-
assert_instance_of OAuth2Authenticator, client.instance_variable_get(:@authenticator)
83+
assert_instance_of OAuth2Authenticator, client.authenticator
8484
end
8585

8686
def test_setting_oauth2_credentials_reinitializes_authenticator
@@ -103,31 +103,53 @@ def test_oauth1_takes_precedence_over_oauth2
103103
client = Client.new(**test_oauth_credentials, client_id: TEST_CLIENT_ID, client_secret: TEST_CLIENT_SECRET,
104104
refresh_token: TEST_REFRESH_TOKEN)
105105

106-
assert_instance_of OAuthAuthenticator, client.instance_variable_get(:@authenticator)
106+
assert_instance_of OAuthAuthenticator, client.authenticator
107107
end
108108

109109
def test_oauth2_takes_precedence_over_bearer_token
110110
client = Client.new(**test_oauth2_credentials, bearer_token: TEST_BEARER_TOKEN)
111111

112-
assert_instance_of OAuth2Authenticator, client.instance_variable_get(:@authenticator)
112+
assert_instance_of OAuth2Authenticator, client.authenticator
113113
end
114114

115115
def test_setting_bearer_token
116116
client = Client.new
117117
client.bearer_token = "bearer_token"
118118

119119
assert_equal "bearer_token", client.bearer_token
120-
assert_instance_of BearerTokenAuthenticator, client.instance_variable_get(:@authenticator)
120+
assert_instance_of BearerTokenAuthenticator, client.authenticator
121121
end
122122

123123
def test_authenticator_remains_unchanged_if_no_new_credentials
124124
client = Client.new
125-
initial_authenticator = client.instance_variable_get(:@authenticator)
125+
initial_authenticator = client.authenticator
126126

127127
client.api_key = nil
128128
client.bearer_token = nil
129129

130-
assert_equal initial_authenticator, client.instance_variable_get(:@authenticator)
130+
assert_equal initial_authenticator, client.authenticator
131+
end
132+
133+
def test_initialize_authenticator_uses_instance_variable_not_accessor
134+
client = Client.new(**test_oauth_credentials)
135+
original_authenticator = client.authenticator
136+
clear_all_credentials(client)
137+
138+
# If code uses accessor (nil), falls through to Authenticator.new; if @authenticator, preserves original
139+
client.stub(:authenticator, nil) { client.send(:initialize_authenticator) }
140+
141+
assert_equal original_authenticator, client.authenticator
142+
end
143+
144+
private
145+
146+
def clear_all_credentials(client)
147+
%i[@api_key @api_key_secret @access_token @access_token_secret].each do |var|
148+
client.instance_variable_set(var, nil)
149+
end
150+
%i[@bearer_token @client_id @client_secret @refresh_token].each do |var|
151+
client.instance_variable_set(var, nil)
152+
end
131153
end
132154
end
133155

0 commit comments

Comments
 (0)