diff --git a/addons/itsulu_blog_publisher/data/mail_template_data.xml b/addons/itsulu_blog_publisher/data/mail_template_data.xml index ddb6148..23ab502 100644 --- a/addons/itsulu_blog_publisher/data/mail_template_data.xml +++ b/addons/itsulu_blog_publisher/data/mail_template_data.xml @@ -5,42 +5,42 @@ Blog Publisher — Post Published Notification - [ITSulu Insights] Blog Post Published: ${object.blog_post_id.name} - ${user.email_formatted} + [ITSulu Insights] Blog Post Published: {{ object.blog_post_id.name }} + {{ user.email_formatted }} True -

Blog Post Published

-

Title: ${object.blog_post_id.name}

-

Blog: ${object.blog_post_id.blog_id.name}

-

URL: https://itsulu.com${object.blog_post_id.website_url}

+

Title:

+

Blog:

+

URL: https://itsulu.com

Social Media Posts — Ready to Post

-% for social in object.blog_post_id.itsulu_social_id: -% if social.twitter_post_a: + +

Twitter

-

${social.twitter_post_a}

-% endif -% if social.twitter_post_b: +

+
+

Twitter

-

${social.twitter_post_b}

-% endif -% if social.bluesky_post_a: +

+
+

BlueSky

-

${social.bluesky_post_a}

-% endif -% if social.bluesky_post_b: +

+
+

BlueSky

-

${social.bluesky_post_b}

-% endif -% if social.mastodon_post: +

+
+

Mastodon

-

${social.mastodon_post}

-% endif -% if social.linkedin_post: +

+
+

LinkedIn

-

${social.linkedin_post}

-% endif -% endfor +

+
+
]]>
diff --git a/addons/itsulu_blog_publisher/tests/test_bdd_steps.py b/addons/itsulu_blog_publisher/tests/test_bdd_steps.py index c82b24c..d3356e1 100644 --- a/addons/itsulu_blog_publisher/tests/test_bdd_steps.py +++ b/addons/itsulu_blog_publisher/tests/test_bdd_steps.py @@ -226,10 +226,31 @@ def given_ollama_base_url(odoo_env, url): ) +def _valid_llm_json(): + """Return a JSON string with all fields LLMRouter._parse_response requires.""" + import json + return json.dumps({ + 'title': 'Generated Blog Post', + 'body_html': '

' + ('Generated content. ' * 30) + '

', + 'meta_title': 'Generated SEO Title', + 'meta_description': 'Generated meta description for the post.', + 'meta_keywords': 'ai, testing, blog', + 'tags': ['AI', 'Testing'], + 'social': { + 'twitter_a': 'Tweet A', 'twitter_b': 'Tweet B', + 'bluesky_a': 'BlueSky A', 'bluesky_b': 'BlueSky B', + 'mastodon': 'Mastodon post', 'linkedin': 'LinkedIn post', + }, + 'sources': [], + }) + + @when('the LLM router is called with a prompt') def when_llm_router_called(odoo_env, ctx): from odoo.addons.itsulu_blog_publisher.services.llm_router import LLMRouter - mock_resp = MagicMock(text='

Generated

', tokens_used=500) + # The router parses provider_response.text as JSON, so the mock must + # return a valid JSON blob with all required fields — not raw HTML. + mock_resp = MagicMock(text=_valid_llm_json(), tokens_used=500) provider_map = { 'anthropic': 'odoo.addons.itsulu_blog_publisher.services.anthropic_provider.AnthropicProvider.generate', @@ -243,10 +264,11 @@ def when_llm_router_called(odoo_env, ctx): try: if patch_target: with patch(patch_target, return_value=mock_resp) as mock_gen: - router = LLMRouter(odoo_env, provider=provider, model=ctx.get('model', '')) - result = router.generate(topic='Write a blog post') - ctx['result'] = result + # Record the mock before generate() so assertions can see it + # even if generate() raises. ctx['mock_generate'] = mock_gen + router = LLMRouter(odoo_env, provider=provider, model=ctx.get('model', '')) + ctx['result'] = router.generate(topic='Write a blog post') else: router = LLMRouter(odoo_env, provider=provider, model=ctx.get('model', '')) ctx['result'] = router.generate(topic='Write a blog post')