mirror of
https://github.com/we-promise/sure.git
synced 2026-05-30 07:49:01 +00:00
CodeRabbit flagged on PR review: the new default_model tests asserted against Provider::*::DEFAULT_MODEL, but Chat.default_model actually returns Provider::*.effective_model.presence (which reads OPENAI_MODEL / ANTHROPIC_MODEL from the environment). With either env var set, the tests would fail intermittently even though routing was correct. - New default_model tests now assert against the provider's effective_model directly, so they verify the routing decision (which provider's value wins) without coupling to the constant. - Pre-existing "creates with default model" assertions had the same brittleness; switch them to compare against Chat.default_model so the chosen model is whatever the env / Setting cascade resolves to. Verified by running `ANTHROPIC_MODEL=claude-haiku-4-5 OPENAI_MODEL=gpt-4o bin/rails test test/models/chat_test.rb` — 16 runs, 0 failures (previously 2 pre-existing failures + 0 from the new tests).
154 lines
5.1 KiB
Ruby
154 lines
5.1 KiB
Ruby
require "test_helper"
|
|
|
|
class ChatTest < ActiveSupport::TestCase
|
|
setup do
|
|
@user = users(:family_admin)
|
|
@assistant = mock
|
|
end
|
|
|
|
test "user sees all messages in debug mode" do
|
|
chat = chats(:one)
|
|
with_env_overrides AI_DEBUG_MODE: "true" do
|
|
assert_equal chat.messages.count, chat.conversation_messages.count
|
|
end
|
|
end
|
|
|
|
test "user sees assistant and user messages in normal mode" do
|
|
chat = chats(:one)
|
|
assert_equal 3, chat.conversation_messages.count
|
|
end
|
|
|
|
test "uses chat-scoped stream targets" do
|
|
first_chat = chats(:one)
|
|
second_chat = chats(:two)
|
|
|
|
assert_not_equal "messages", first_chat.messages_target
|
|
assert_not_equal "chat-error", first_chat.error_target
|
|
assert_not_equal first_chat.messages_target, second_chat.messages_target
|
|
assert_not_equal first_chat.error_target, second_chat.error_target
|
|
end
|
|
|
|
test "creates with initial message" do
|
|
prompt = "Test prompt"
|
|
|
|
assert_difference "@user.chats.count", 1 do
|
|
chat = @user.chats.start!(prompt, model: "gpt-4.1")
|
|
|
|
assert_equal 2, chat.messages.count
|
|
assert_equal 1, chat.messages.where(type: "UserMessage").count
|
|
assert_equal 1, chat.messages.where(type: "AssistantMessage", status: "pending").count
|
|
end
|
|
end
|
|
|
|
test "creates with default model when model is nil" do
|
|
prompt = "Test prompt"
|
|
|
|
assert_difference "@user.chats.count", 1 do
|
|
chat = @user.chats.start!(prompt, model: nil)
|
|
|
|
assert_equal 2, chat.messages.count
|
|
assert_equal Chat.default_model, chat.messages.find_by!(type: "UserMessage").ai_model
|
|
end
|
|
end
|
|
|
|
test "creates with default model when model is empty string" do
|
|
prompt = "Test prompt"
|
|
|
|
assert_difference "@user.chats.count", 1 do
|
|
chat = @user.chats.start!(prompt, model: "")
|
|
|
|
assert_equal 2, chat.messages.count
|
|
assert_equal Chat.default_model, chat.messages.find_by!(type: "UserMessage").ai_model
|
|
end
|
|
end
|
|
|
|
# These three tests assert routing (which provider's effective_model wins),
|
|
# not the constant value itself — the assertion side reads through
|
|
# Provider::*.effective_model so ENV overrides like ANTHROPIC_MODEL /
|
|
# OPENAI_MODEL don't make the tests flake.
|
|
test "default_model returns Anthropic's effective_model when LLM_PROVIDER=anthropic and Anthropic is configured" do
|
|
Provider::Anthropic.stubs(:configured?).returns(true)
|
|
Setting.stubs(:llm_provider).returns("anthropic")
|
|
|
|
assert_equal Provider::Anthropic.effective_model, Chat.default_model
|
|
end
|
|
|
|
test "default_model falls back to OpenAI's effective_model when Anthropic is preferred but unconfigured" do
|
|
Provider::Anthropic.stubs(:configured?).returns(false)
|
|
Provider::Openai.stubs(:configured?).returns(true)
|
|
Setting.stubs(:llm_provider).returns("anthropic")
|
|
|
|
assert_equal Provider::Openai.effective_model, Chat.default_model
|
|
end
|
|
|
|
test "default_model uses Anthropic's effective_model when OpenAI is unconfigured" do
|
|
Provider::Anthropic.stubs(:configured?).returns(true)
|
|
Provider::Openai.stubs(:configured?).returns(false)
|
|
Setting.stubs(:llm_provider).returns("openai")
|
|
|
|
assert_equal Provider::Anthropic.effective_model, Chat.default_model
|
|
end
|
|
|
|
test "creates with configured model when OPENAI_MODEL env is set" do
|
|
prompt = "Test prompt"
|
|
|
|
with_env_overrides OPENAI_MODEL: "custom-model" do
|
|
chat = @user.chats.start!(prompt, model: "")
|
|
|
|
assert_equal "custom-model", chat.messages.find_by!(type: "UserMessage").ai_model
|
|
end
|
|
end
|
|
|
|
test "returns nil presentable error message when no error is stored" do
|
|
chat = chats(:one)
|
|
|
|
chat.update!(error: nil)
|
|
|
|
assert_nil chat.presentable_error_message
|
|
end
|
|
|
|
test "surfaces a friendly rate limit error" do
|
|
chat = chats(:one)
|
|
|
|
chat.add_error(StandardError.new("OpenAI API error 429: rate limit exceeded"))
|
|
|
|
assert_equal I18n.t("chat.errors.rate_limited"), chat.presentable_error_message
|
|
assert_match "429", chat.technical_error_message
|
|
end
|
|
|
|
test "surfaces a friendly temporary provider error" do
|
|
chat = chats(:one)
|
|
|
|
chat.add_error(StandardError.new("OpenAI API error 503: service unavailable"))
|
|
|
|
assert_equal I18n.t("chat.errors.temporarily_unavailable"), chat.presentable_error_message
|
|
assert_match "503", chat.technical_error_message
|
|
end
|
|
|
|
test "surfaces a friendly auth configuration error" do
|
|
chat = chats(:one)
|
|
|
|
chat.add_error(StandardError.new("OpenAI API error: invalid api key"))
|
|
|
|
assert_equal I18n.t("chat.errors.misconfigured"), chat.presentable_error_message
|
|
assert_match "invalid api key", chat.technical_error_message
|
|
end
|
|
|
|
test "surfaces a friendly default error for unrecognized errors" do
|
|
chat = chats(:one)
|
|
|
|
chat.add_error(StandardError.new("something totally unknown happened"))
|
|
|
|
assert_equal I18n.t("chat.errors.default"), chat.presentable_error_message
|
|
end
|
|
|
|
test "falls back to a friendly message for legacy serialized errors" do
|
|
chat = chats(:one)
|
|
|
|
chat.update!(error: "OpenAI API error 429: rate limit exceeded".to_json)
|
|
|
|
assert_equal I18n.t("chat.errors.rate_limited"), chat.presentable_error_message
|
|
assert_equal "OpenAI API error 429: rate limit exceeded", chat.technical_error_message
|
|
end
|
|
end
|