itsulu-blog-publisher/addons/itsulu_blog_publisher/features/blog_generation.feature
Nicholas Riegel 0fc4febabf Reorganize codebase into Odoo addon structure per ARCHITECTURE.md
Restructure project files to follow the addon layout:
- Move models to addons/itsulu_blog_publisher/models/
- Move services (LLM providers, routers) to addons/itsulu_blog_publisher/services/
- Move wizards to addons/itsulu_blog_publisher/wizards/
- Move views (XML templates) to addons/itsulu_blog_publisher/views/
- Move data (cron, mail templates) to addons/itsulu_blog_publisher/data/
- Move security (ACL) to addons/itsulu_blog_publisher/security/
- Move tests and factories to addons/itsulu_blog_publisher/tests/
- Move BDD features to addons/itsulu_blog_publisher/features/
- Create __init__.py files for all Python packages

This enables proper Odoo module discovery and import structure.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-29 12:11:42 -04:00

167 lines
7.2 KiB
Gherkin

# =================================================================
# addons/itsulu_blog_publisher/features/blog_generation.feature
# =================================================================
Feature: On-demand AI blog post generation
As an ITSulu content admin
I want to trigger blog post generation with a single button click
So that I no longer need CoWork running on a Windows VM
Background:
Given the Anthropic API key is configured in Settings
And the blog "ITSulu Insights" exists in Odoo
Scenario: Generate and auto-publish a blog post from the backend
Given I am on the Blog Publisher backend form
And I enter topic "Prompt Governance in Enterprise AI"
And I select provider "anthropic" and model "claude-sonnet-4-20250514"
And I set auto-publish to True
When I click "Generate Now"
Then a blog.post record is created with a non-empty title
And the blog.post body_arch contains at least 500 characters of HTML
And the blog.post is_published is True
And the SEO fields website_meta_title and website_meta_description are populated
And a generation log entry exists with state "success"
Scenario: Generate a blog post and leave it as draft
Given I am on the Blog Publisher backend form
And I enter topic "Open Source LLMs for Business"
And I set auto-publish to False
When I click "Generate Now"
Then a blog.post record is created with a non-empty title
And the blog.post is_published is False
Scenario: LLM API call fails gracefully
Given the Anthropic API key is invalid
And I enter topic "Any topic"
And I set auto-publish to True
When I click "Generate Now"
Then no blog.post record is created
And a generation log entry exists with state "error"
And the log contains a human-readable error message
And a "Retry" button is visible on the log record
# =================================================================
# addons/itsulu_blog_publisher/features/blog_scheduling.feature
# =================================================================
Feature: Scheduled blog post generation
As an ITSulu content admin
I want to schedule three blog posts per day automatically
So that content is published without manual intervention
Background:
Given the Anthropic API key is configured in Settings
And the blog "ITSulu Insights" exists in Odoo
Scenario: Active morning slot creates a blog post when run
Given I am on the Blog Publisher backend form
And I set auto-publish to True
And I enter topic "Morning AI Topic"
When I click "Generate Now"
Then a blog.post record is created with a non-empty title
And a generation log entry exists with state "success"
Scenario: Generate a blog post and leave it as draft
Given I am on the Blog Publisher backend form
And I enter topic "Scheduled Draft Topic"
And I set auto-publish to False
When I click "Generate Now"
Then a blog.post record is created with a non-empty title
And the blog.post is_published is False
# =================================================================
# addons/itsulu_blog_publisher/features/llm_provider_selection.feature
# =================================================================
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 "provider 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
# =================================================================
# addons/itsulu_blog_publisher/features/seo_population.feature
# =================================================================
Feature: SEO fields populated on every generated blog post
As an ITSulu content admin
I want all SEO fields filled automatically
So that every post is search-engine ready at publication
Background:
Given the Anthropic API key is configured in Settings
And the blog "ITSulu Insights" exists in Odoo
Scenario: All SEO fields are populated after generation
Given I am on the Blog Publisher backend form
And I enter topic "AI Governance Enterprise"
And I set auto-publish to True
When I click "Generate Now"
Then the SEO fields website_meta_title and website_meta_description are populated
And a generation log entry exists with state "success"
# =================================================================
# addons/itsulu_blog_publisher/features/notification_email.feature
# =================================================================
Feature: Post-generation notification email
As an ITSulu content admin
I want to receive one email after each successful blog post publication
So that I have the social media copy ready to paste
Background:
Given the notification email recipient is "nicholasr@itsulu.com"
Scenario: Notification email is sent after successful auto-publish
Given a blog post was generated and auto-published
When the generation completes
Then exactly one email is sent to "nicholasr@itsulu.com"
And the email subject matches "[ITSulu Insights] Blog Post Published: {title} - {date}"
Scenario: Notification email is NOT sent for draft posts
Given the Anthropic API key is configured in Settings
And the blog "ITSulu Insights" exists in Odoo
And I am on the Blog Publisher backend form
And I enter topic "Draft Topic No Email"
And I set auto-publish to False
When I click "Generate Now"
Then a blog.post record is created with a non-empty title
And the blog.post is_published is False