|
| 1 | +require "test_helper" |
| 2 | +require "active_agent/generation_provider/x_ai_provider" |
| 3 | + |
| 4 | +# Test for xAI Provider gem loading and configuration |
| 5 | +class XAIProviderTest < ActiveAgentTestCase |
| 6 | + # Test the gem load rescue block |
| 7 | + test "gem load rescue block provides correct error message" do |
| 8 | + # Since we can't easily simulate the gem not being available without complex mocking, |
| 9 | + # we'll test that the error message is correct by creating a minimal reproduction |
| 10 | + expected_message = "The 'ruby-openai >= 8.1.0' gem is required for XAIProvider. Please add it to your Gemfile and run `bundle install`." |
| 11 | + |
| 12 | + # Verify the rescue block pattern exists in the source code |
| 13 | + provider_file_path = File.join(Rails.root, "../../lib/active_agent/generation_provider/x_ai_provider.rb") |
| 14 | + provider_source = File.read(provider_file_path) |
| 15 | + |
| 16 | + assert_includes provider_source, "begin" |
| 17 | + assert_includes provider_source, 'gem "ruby-openai"' |
| 18 | + assert_includes provider_source, 'require "openai"' |
| 19 | + assert_includes provider_source, "rescue LoadError" |
| 20 | + assert_includes provider_source, expected_message |
| 21 | + |
| 22 | + # Test the actual error by creating a minimal scenario |
| 23 | + test_code = <<~RUBY |
| 24 | + begin |
| 25 | + gem "nonexistent-openai-gem" |
| 26 | + require "nonexistent-openai-gem" |
| 27 | + rescue LoadError |
| 28 | + raise LoadError, "#{expected_message}" |
| 29 | + end |
| 30 | + RUBY |
| 31 | + |
| 32 | + error = assert_raises(LoadError) do |
| 33 | + eval(test_code) |
| 34 | + end |
| 35 | + |
| 36 | + assert_equal expected_message, error.message |
| 37 | + end |
| 38 | + |
| 39 | + test "loads successfully when ruby-openai gem is available" do |
| 40 | + # This test ensures the provider loads correctly when the gem is present |
| 41 | + # Since the gem is already loaded in our test environment, this should work |
| 42 | + |
| 43 | + # Verify the class exists and can be instantiated with valid config |
| 44 | + assert defined?(ActiveAgent::GenerationProvider::XAIProvider) |
| 45 | + |
| 46 | + config = { |
| 47 | + "service" => "XAI", |
| 48 | + "api_key" => "test-key", |
| 49 | + "model" => "grok-2-latest" |
| 50 | + } |
| 51 | + |
| 52 | + assert_nothing_raised do |
| 53 | + ActiveAgent::GenerationProvider::XAIProvider.new(config) |
| 54 | + end |
| 55 | + end |
| 56 | + |
| 57 | + # Test configuration loading and presence |
| 58 | + test "raises error when xAI API key is missing" do |
| 59 | + config = { |
| 60 | + "service" => "XAI", |
| 61 | + "model" => "grok-2-latest" |
| 62 | + # Missing api_key |
| 63 | + } |
| 64 | + |
| 65 | + error = assert_raises(ArgumentError) do |
| 66 | + ActiveAgent::GenerationProvider::XAIProvider.new(config) |
| 67 | + end |
| 68 | + |
| 69 | + assert_includes error.message, "XAI API key is required" |
| 70 | + end |
| 71 | + |
| 72 | + test "loads configuration from active_agent.yml when present" do |
| 73 | + # Mock a configuration |
| 74 | + mock_config = { |
| 75 | + "test" => { |
| 76 | + "xai" => { |
| 77 | + "service" => "XAI", |
| 78 | + "api_key" => "test-api-key", |
| 79 | + "model" => "grok-2-latest", |
| 80 | + "temperature" => 0.7 |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + ActiveAgent.instance_variable_set(:@config, mock_config) |
| 86 | + |
| 87 | + # Set Rails environment for testing |
| 88 | + rails_env = ENV["RAILS_ENV"] |
| 89 | + ENV["RAILS_ENV"] = "test" |
| 90 | + |
| 91 | + config = ApplicationAgent.configuration(:xai) |
| 92 | + |
| 93 | + assert_equal "XAI", config.config["service"] |
| 94 | + assert_equal "test-api-key", config.config["api_key"] |
| 95 | + assert_equal "grok-2-latest", config.config["model"] |
| 96 | + assert_equal 0.7, config.config["temperature"] |
| 97 | + |
| 98 | + # Restore original environment |
| 99 | + ENV["RAILS_ENV"] = rails_env |
| 100 | + end |
| 101 | + |
| 102 | + test "loads configuration from environment-specific section" do |
| 103 | + mock_config = { |
| 104 | + "development" => { |
| 105 | + "xai" => { |
| 106 | + "service" => "XAI", |
| 107 | + "api_key" => "dev-api-key", |
| 108 | + "model" => "grok-2-latest" |
| 109 | + } |
| 110 | + }, |
| 111 | + "test" => { |
| 112 | + "xai" => { |
| 113 | + "service" => "XAI", |
| 114 | + "api_key" => "test-api-key", |
| 115 | + "model" => "grok-2-latest" |
| 116 | + } |
| 117 | + } |
| 118 | + } |
| 119 | + |
| 120 | + ActiveAgent.instance_variable_set(:@config, mock_config) |
| 121 | + |
| 122 | + # Test development configuration |
| 123 | + original_env = ENV["RAILS_ENV"] |
| 124 | + ENV["RAILS_ENV"] = "development" |
| 125 | + |
| 126 | + config = ApplicationAgent.configuration(:xai) |
| 127 | + assert_equal "dev-api-key", config.config["api_key"] |
| 128 | + |
| 129 | + # Test test configuration |
| 130 | + ENV["RAILS_ENV"] = "test" |
| 131 | + config = ApplicationAgent.configuration(:xai) |
| 132 | + assert_equal "test-api-key", config.config["api_key"] |
| 133 | + |
| 134 | + ENV["RAILS_ENV"] = original_env |
| 135 | + end |
| 136 | + |
| 137 | + test "xAI provider initialization with API key from environment variable" do |
| 138 | + # Test with XAI_API_KEY env var |
| 139 | + original_xai_key = ENV["XAI_API_KEY"] |
| 140 | + original_grok_key = ENV["GROK_API_KEY"] |
| 141 | + |
| 142 | + ENV["XAI_API_KEY"] = "env-xai-key" |
| 143 | + ENV["GROK_API_KEY"] = nil |
| 144 | + |
| 145 | + config = { |
| 146 | + "service" => "XAI", |
| 147 | + "model" => "grok-2-latest" |
| 148 | + } |
| 149 | + |
| 150 | + provider = ActiveAgent::GenerationProvider::XAIProvider.new(config) |
| 151 | + assert_equal "env-xai-key", provider.instance_variable_get(:@access_token) |
| 152 | + |
| 153 | + # Test with GROK_API_KEY env var |
| 154 | + ENV["XAI_API_KEY"] = nil |
| 155 | + ENV["GROK_API_KEY"] = "env-grok-key" |
| 156 | + |
| 157 | + provider = ActiveAgent::GenerationProvider::XAIProvider.new(config) |
| 158 | + assert_equal "env-grok-key", provider.instance_variable_get(:@access_token) |
| 159 | + |
| 160 | + # Restore original environment |
| 161 | + ENV["XAI_API_KEY"] = original_xai_key |
| 162 | + ENV["GROK_API_KEY"] = original_grok_key |
| 163 | + end |
| 164 | + |
| 165 | + test "xAI provider initialization with custom host" do |
| 166 | + config = { |
| 167 | + "service" => "XAI", |
| 168 | + "api_key" => "test-key", |
| 169 | + "model" => "grok-2-latest", |
| 170 | + "host" => "https://custom-xai-host.com" |
| 171 | + } |
| 172 | + |
| 173 | + provider = ActiveAgent::GenerationProvider::XAIProvider.new(config) |
| 174 | + client = provider.instance_variable_get(:@client) |
| 175 | + |
| 176 | + # The OpenAI client should be configured with the custom host |
| 177 | + assert_not_nil client |
| 178 | + end |
| 179 | + |
| 180 | + test "xAI provider defaults to grok-2-latest model" do |
| 181 | + config = { |
| 182 | + "service" => "XAI", |
| 183 | + "api_key" => "test-key" |
| 184 | + # Model not specified |
| 185 | + } |
| 186 | + |
| 187 | + provider = ActiveAgent::GenerationProvider::XAIProvider.new(config) |
| 188 | + assert_equal "grok-2-latest", provider.instance_variable_get(:@model_name) |
| 189 | + end |
| 190 | + |
| 191 | + test "xAI provider uses configured model" do |
| 192 | + config = { |
| 193 | + "service" => "XAI", |
| 194 | + "api_key" => "test-key", |
| 195 | + "model" => "grok-1" |
| 196 | + } |
| 197 | + |
| 198 | + provider = ActiveAgent::GenerationProvider::XAIProvider.new(config) |
| 199 | + assert_equal "grok-1", provider.instance_variable_get(:@model_name) |
| 200 | + end |
| 201 | + |
| 202 | + test "xAI provider defaults to correct API host" do |
| 203 | + config = { |
| 204 | + "service" => "XAI", |
| 205 | + "api_key" => "test-key" |
| 206 | + } |
| 207 | + |
| 208 | + provider = ActiveAgent::GenerationProvider::XAIProvider.new(config) |
| 209 | + assert_equal "https://api.x.ai", ActiveAgent::GenerationProvider::XAIProvider::XAI_API_HOST |
| 210 | + end |
| 211 | + |
| 212 | + test "embed method raises NotImplementedError for xAI" do |
| 213 | + config = { |
| 214 | + "service" => "XAI", |
| 215 | + "api_key" => "test-key" |
| 216 | + } |
| 217 | + |
| 218 | + provider = ActiveAgent::GenerationProvider::XAIProvider.new(config) |
| 219 | + mock_prompt = Minitest::Mock.new |
| 220 | + |
| 221 | + error = assert_raises(NotImplementedError) do |
| 222 | + provider.embed(mock_prompt) |
| 223 | + end |
| 224 | + |
| 225 | + assert_includes error.message, "xAI does not currently support embeddings" |
| 226 | + end |
| 227 | +end |
0 commit comments