Skip to content

Commit

Permalink
fix: configuration validation for missing API key
Browse files Browse the repository at this point in the history
- Improve Configuration#validate! to properly handle nil/empty API keys
- Add ENV cleanup in specs to ensure consistent testing environment
- Update client specs with proper error expectations
  • Loading branch information
nagstler committed Feb 2, 2025
1 parent 86198d9 commit 1392fcd
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 105 deletions.
3 changes: 1 addition & 2 deletions lib/deepseek/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ def initialize
@api_base_url = ENV['DEEPSEEK_API_BASE_URL'] || 'https://api.deepseek.com'
@timeout = ENV['DEEPSEEK_TIMEOUT']&.to_i || 30
@max_retries = ENV['DEEPSEEK_MAX_RETRIES']&.to_i || 3
validate! unless api_key.nil? # Don't validate during initialization
end

def validate!
raise ConfigurationError, 'API key must be set' if api_key.nil? || api_key.strip.empty?
raise ConfigurationError, 'API key must be set' if api_key.nil? || api_key.to_s.strip.empty?
end
end
end
207 changes: 104 additions & 103 deletions spec/deepseek/client_spec.rb
Original file line number Diff line number Diff line change
@@ -1,112 +1,113 @@
RSpec.describe Deepseek::Client do
let(:api_key) { 'test-key' }
let(:client) { described_class.new(api_key: api_key) }
let(:base_url) { 'https://api.deepseek.com' }
let(:messages) { [{ role: 'user', content: 'Hello' }] }
let(:request_body) do
{
model: 'deepseek-chat',
messages: messages
}
let(:api_key) { 'test-key' }
let(:client) { described_class.new(api_key: api_key) }
let(:base_url) { 'https://api.deepseek.com' }
let(:messages) { [{ role: 'user', content: 'Hello' }] }
let(:headers) do
{
'Authorization' => "Bearer #{api_key}",
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'User-Agent' => "deepseek-ruby/#{Deepseek::VERSION}"
}
end

describe '#initialize' do
before do
ENV['DEEPSEEK_API_KEY'] = nil
end
let(:headers) do
{
'Authorization' => "Bearer #{api_key}",
'Content-Type' => 'application/json',
'Accept' => 'application/json',
'User-Agent' => "deepseek-ruby/#{Deepseek::VERSION}"
}

it 'creates a client with an API key' do
expect(client.config.api_key).to eq(api_key)
end

describe '#initialize' do
it 'creates a client with an API key' do
expect(client.config.api_key).to eq(api_key)
end

it 'raises an error without an API key' do
expect { described_class.new }.to raise_error(Deepseek::ConfigurationError)

it 'raises an error without an API key' do
expect {
described_class.new
}.to raise_error(Deepseek::ConfigurationError, 'API key must be set')
end

it 'accepts configuration options' do
client = described_class.new(api_key: api_key, timeout: 60)
expect(client.config.timeout).to eq(60)
end
end

describe '#chat' do
let(:endpoint) { "#{base_url}/v1/chat/completions" }
let(:request_body) { { model: 'deepseek-chat', messages: messages } }

context 'with successful response' do
before do
stub_request(:post, endpoint)
.with(
body: request_body,
headers: headers
)
.to_return(
status: 200,
headers: { 'Content-Type' => 'application/json' },
body: { choices: [{ message: { content: 'Hi there!' } }] }.to_json
)
end
it 'accepts configuration options' do
client = described_class.new(api_key: api_key, timeout: 60)
expect(client.config.timeout).to eq(60)

it 'makes a successful API call' do
response = client.chat(messages: messages)
expect(response['choices'][0]['message']['content']).to eq('Hi there!')
end
end

describe '#chat' do
let(:endpoint) { "#{base_url}/v1/chat/completions" }

context 'with successful response' do
before do
stub_request(:post, endpoint)
.with(
body: request_body,
headers: headers
)
.to_return(
status: 200,
headers: { 'Content-Type' => 'application/json' },
body: { choices: [{ message: { content: 'Hi there!' } }] }.to_json
)
end

it 'makes a successful API call' do
response = client.chat(messages: messages)
expect(response['choices'][0]['message']['content']).to eq('Hi there!')
end

context 'with API errors' do
it 'handles authentication errors' do
stub_request(:post, endpoint)
.with(
body: request_body,
headers: headers
)
.to_return(
status: 401,
headers: { 'Content-Type' => 'application/json' },
body: { error: { message: 'Invalid API key' } }.to_json
)

expect {
client.chat(messages: messages)
}.to raise_error(Deepseek::AuthenticationError, /Invalid API key/)
end

it 'handles rate limit errors' do
stub_request(:post, endpoint)
.with(
body: request_body,
headers: headers
)
.to_return(
status: 429,
headers: { 'Content-Type' => 'application/json' },
body: { error: { message: 'Rate limit exceeded' } }.to_json
)

expect {
client.chat(messages: messages)
}.to raise_error(Deepseek::RateLimitError, /Rate limit exceeded/)
end

context 'with API errors' do
it 'handles authentication errors' do
stub_request(:post, endpoint)
.with(
body: request_body,
headers: headers
)
.to_return(
status: 401,
headers: { 'Content-Type' => 'application/json' },
body: { error: { message: 'Invalid API key' } }.to_json
)

expect {
client.chat(messages: messages)
}.to raise_error(Deepseek::AuthenticationError, /Invalid API key/)
end

it 'handles rate limit errors' do
stub_request(:post, endpoint)
.with(
body: request_body,
headers: headers
)
.to_return(
status: 429,
headers: { 'Content-Type' => 'application/json' },
body: { error: { message: 'Rate limit exceeded' } }.to_json
)

expect {
client.chat(messages: messages)
}.to raise_error(Deepseek::RateLimitError, /Rate limit exceeded/)
end

it 'handles invalid requests' do
stub_request(:post, endpoint)
.with(
body: request_body,
headers: headers
)
.to_return(
status: 400,
headers: { 'Content-Type' => 'application/json' },
body: { error: { message: 'Invalid request parameters' } }.to_json
)

expect {
client.chat(messages: messages)
}.to raise_error(Deepseek::InvalidRequestError, /Invalid request parameters/)
end

it 'handles invalid requests' do
stub_request(:post, endpoint)
.with(
body: request_body,
headers: headers
)
.to_return(
status: 400,
headers: { 'Content-Type' => 'application/json' },
body: { error: { message: 'Invalid request parameters' } }.to_json
)

expect {
client.chat(messages: messages)
}.to raise_error(Deepseek::InvalidRequestError, /Invalid request parameters/)
end
end
end
end
end

0 comments on commit 1392fcd

Please sign in to comment.