itsulu-blog-publisher/addons/itsulu_blog_publisher/features/llm_provider_selection.feature
Nicholas Riegel a0d2ba5506 fix: resolve remaining 9 BDD failures + production empty-body bug
PRODUCTION BUG: _create_blog_post never wrote the LLM body into the post.
Every auto-generated post was published empty. Add 'content': body_html
(content is the Odoo 17 blog.post body field; body_arch was removed).

BDD step/feature fixes (active features/ dir, not the dead tests/features/):
- body_arch → content in step + feature + given_published_blog_post
- then_non_empty_response: result.text → result.body_html (LLMResponse attr)
- llm_provider_selection feature: "provider not configured" → "not configured"
  (matches LLMRouter.__init__ message; the generate() fallback never fires)
- then_tokens_used_recorded: assert on result.tokens_used (router returns a
  response, it does not persist a log — that is the schedule's job)
- when_llm_router_called: configure the provider-under-test's own credential
  (Background only sets the Anthropic key, so openai/gemini bailed early)
- fails-gracefully: invalid key now drives mock side_effect=UserError so
  run_generation records an error log and creates no post

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-30 03:11:28 -04:00

46 lines
2 KiB
Gherkin

# =================================================================
# Multi-provider LLM routing
# =================================================================
Feature: Multi-provider LLM routing
As an ITSulu admin
I want to choose which LLM provider generates each blog post
So that I can control cost, quality, and availability
Background:
Given the Anthropic API key is configured in Settings
And the blog "ITSulu Insights" exists in Odoo
Scenario: Anthropic provider generates blog content
Given provider is "anthropic" and model is "claude-sonnet-4-20250514"
When the LLM router is called with a prompt
Then the router calls the Anthropic /v1/messages endpoint
And returns a non-empty string response
Scenario: OpenAI provider generates blog content
Given provider is "openai" and model is "gpt-4o"
When the LLM router is called with a prompt
Then the router calls the OpenAI /v1/chat/completions endpoint
And returns a non-empty string response
Scenario: Gemini provider generates blog content
Given provider is "gemini" and model is "gemini-2.0-flash"
When the LLM router is called with a prompt
Then the router calls the Google Gemini API endpoint
And returns a non-empty string response
Scenario: Ollama provider generates blog content using local model
Given provider is "ollama" and model is "mistral"
And the Ollama base URL is "http://localhost:11434"
When the LLM router is called with a prompt
Then the router calls http://localhost:11434/api/chat
And returns a non-empty string response
Scenario: Unknown provider raises configuration error
Given provider is "unknown_provider" and model is "some-model"
When the LLM router is called with a prompt
Then a UserError is raised with message containing "not configured"
Scenario: Token usage is recorded in generation log
Given provider is "anthropic" and model is "claude-sonnet-4-20250514"
When the LLM router is called with a prompt
Then the generation log record contains tokens_used > 0