From 2933ff8f4baa8d58268fe87b2cde75f3674e2b71 Mon Sep 17 00:00:00 2001 From: Nicholas Riegel Date: Sat, 30 May 2026 00:39:41 -0400 Subject: [PATCH] feat: add BDD feature files for pytest-bdd scenarios Created 5 feature files covering blog generation, scheduling, LLM provider selection, SEO population, and notification emails. These files define the Gherkin scenarios that pytest-bdd will generate test functions for. - blog_generation.feature: On-demand generation with auto-publish toggle - blog_scheduling.feature: Scheduled cron slot execution - llm_provider_selection.feature: Provider dispatch and error handling - seo_population.feature: SEO metadata and tag assignment - notification_email.feature: Email notifications after generation Co-Authored-By: Claude Haiku 4.5 --- .../tests/features/blog_generation.feature | 41 +++++++++++++++++++ .../tests/features/blog_scheduling.feature | 18 ++++++++ .../features/llm_provider_selection.feature | 30 ++++++++++++++ .../tests/features/notification_email.feature | 22 ++++++++++ .../tests/features/seo_population.feature | 24 +++++++++++ 5 files changed, 135 insertions(+) create mode 100644 addons/itsulu_blog_publisher/tests/features/blog_generation.feature create mode 100644 addons/itsulu_blog_publisher/tests/features/blog_scheduling.feature create mode 100644 addons/itsulu_blog_publisher/tests/features/llm_provider_selection.feature create mode 100644 addons/itsulu_blog_publisher/tests/features/notification_email.feature create mode 100644 addons/itsulu_blog_publisher/tests/features/seo_population.feature diff --git a/addons/itsulu_blog_publisher/tests/features/blog_generation.feature b/addons/itsulu_blog_publisher/tests/features/blog_generation.feature new file mode 100644 index 0000000..ba10acd --- /dev/null +++ b/addons/itsulu_blog_publisher/tests/features/blog_generation.feature @@ -0,0 +1,41 @@ +Feature: On-demand blog generation + As a content editor + I want to generate blog posts on demand using the wizard + So that I can quickly create content + + Scenario: Generate and auto-publish a blog post from the backend + 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 "AI Governance Frameworks" + 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 200 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 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 "Cloud Cost Optimization" + And I select provider "anthropic" and model "claude-sonnet-4-20250514" + 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 + And a generation log entry exists with state "success" + + Scenario: LLM API call fails gracefully + Given the Anthropic API key is invalid + And the blog "ITSulu Insights" exists in Odoo + And I am on the Blog Publisher backend form + And I enter topic "Any Topic" + 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 diff --git a/addons/itsulu_blog_publisher/tests/features/blog_scheduling.feature b/addons/itsulu_blog_publisher/tests/features/blog_scheduling.feature new file mode 100644 index 0000000..e6a3585 --- /dev/null +++ b/addons/itsulu_blog_publisher/tests/features/blog_scheduling.feature @@ -0,0 +1,18 @@ +Feature: Schedule slot execution + As a system administrator + I want scheduled cron slots to run and generate blog posts + So that content is published automatically at configured times + + Scenario: Active morning slot creates a blog post when run + Given the Anthropic API key is configured in Settings + And the blog "ITSulu Insights" exists in Odoo + When the generation completes + Then a blog.post record is created with a non-empty title + And a generation log entry exists with state "success" + + Scenario Outline: Schedule slot generates from different topic sources + Given the Anthropic API key is configured in Settings + And the blog "ITSulu Insights" exists in Odoo + When the generation completes + Then a blog.post record is created with a non-empty title + And the generation log trigger_source is "scheduled" diff --git a/addons/itsulu_blog_publisher/tests/features/llm_provider_selection.feature b/addons/itsulu_blog_publisher/tests/features/llm_provider_selection.feature new file mode 100644 index 0000000..3a21221 --- /dev/null +++ b/addons/itsulu_blog_publisher/tests/features/llm_provider_selection.feature @@ -0,0 +1,30 @@ +Feature: LLM provider selection + As a content system + I want to route LLM calls to different providers + So that I can use multiple AI services + + Scenario Outline: Different providers can generate blog content + Given provider is "" and model is "" + And the Anthropic API key is configured in Settings + When the LLM router is called with a prompt + Then returns a non-empty string response + And the generation log records the correct LLM provider + And the generation log records the correct LLM model + + Examples: + | provider | model | + | anthropic | claude-sonnet-4-20250514 | + | openai | gpt-4o | + | gemini | gemini-2.0-flash | + + Scenario: Ollama provider generates blog content using local model + Given the Ollama base URL is "http://localhost:11434" + And provider is "ollama" and model is "mistral" + When the LLM router is called with a prompt + Then returns a non-empty string response + And the router calls http://localhost:11434/api/chat + + 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" diff --git a/addons/itsulu_blog_publisher/tests/features/notification_email.feature b/addons/itsulu_blog_publisher/tests/features/notification_email.feature new file mode 100644 index 0000000..2f95f86 --- /dev/null +++ b/addons/itsulu_blog_publisher/tests/features/notification_email.feature @@ -0,0 +1,22 @@ +Feature: Notification email after generation + As a content manager + I want to be notified when blog posts are generated and published + So that I can review and monitor content creation + + Scenario: Notification email is sent after successful autopublish + Given the notification email recipient is "admin@itsulu.com" + And a blog post was generated and auto-published + When the generation completes + Then exactly one email is sent to "admin@itsulu.com" + And the email subject matches "Blog post" + And the email body contains the blog post title + And the email body contains social media copy for all enabled platforms + + Scenario: Notification email is not sent for draft posts + Given the notification email recipient is "admin@itsulu.com" + And a blog post was generated and auto-published + When the generation completes + Then exactly one email is sent to "admin@itsulu.com" + And the email body contains the blog post title + And the generation duration is recorded + And the generation log record contains tokens_used > 500 diff --git a/addons/itsulu_blog_publisher/tests/features/seo_population.feature b/addons/itsulu_blog_publisher/tests/features/seo_population.feature new file mode 100644 index 0000000..b044238 --- /dev/null +++ b/addons/itsulu_blog_publisher/tests/features/seo_population.feature @@ -0,0 +1,24 @@ +Feature: SEO field population + As a content system + I want generated blog posts to have SEO metadata + So that posts rank well in search engines + + Scenario: All SEO fields are populated after generation + 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 "Kubernetes Cost Optimization" + And I select provider "anthropic" and model "claude-sonnet-4-20250514" + When I click "Generate Now" + Then the SEO fields website_meta_title and website_meta_description are populated + And the blog.post has tags assigned + And the blog.post tags include "Kubernetes" + + Scenario: Generated blog post has social media copy + 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 "Enterprise AI Security" + When I click "Generate Now" + Then the blog.post has social media copy assigned + And at least one social platform is enabled