912 lines
33 KiB
Python
912 lines
33 KiB
Python
from api.v1.ppt.endpoints import presentation as presentation_endpoint
|
|
from services.chat.memory_layer import PresentationChatMemoryLayer
|
|
|
|
|
|
def test_apply_template_v2_content_to_ui_uses_schema_content_keys():
|
|
ui = {
|
|
"id": "layout-1",
|
|
"description": "Layout with generated content placeholders.",
|
|
"components": [
|
|
{
|
|
"id": "hero",
|
|
"description": "Hero content component.",
|
|
"elements": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "headline",
|
|
"runs": [{"text": "Old headline", "font": {"bold": True}}],
|
|
},
|
|
{
|
|
"type": "image",
|
|
"decorative": False,
|
|
"name": "hero_image",
|
|
"data": "/old-image.png",
|
|
"is_icon": False,
|
|
},
|
|
{
|
|
"type": "text-list",
|
|
"decorative": False,
|
|
"name": "bullets",
|
|
"items": [[{"text": "Old bullet"}]],
|
|
},
|
|
{
|
|
"type": "table",
|
|
"decorative": False,
|
|
"name": "metrics",
|
|
"columns": [{"runs": [{"text": "Old"}]}],
|
|
"rows": [[{"runs": [{"text": "Old value"}]}]],
|
|
},
|
|
{
|
|
"type": "chart",
|
|
"decorative": False,
|
|
"name": "trend",
|
|
"chart_type": "bar",
|
|
"categories": ["Old"],
|
|
"series": [{"name": "Old", "values": [1]}],
|
|
},
|
|
{
|
|
"type": "grid",
|
|
"name": "cards",
|
|
"children": [
|
|
{
|
|
"type": "group",
|
|
"name": "card_1",
|
|
"children": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "title_1",
|
|
"runs": [{"text": "Old card 1"}],
|
|
},
|
|
{
|
|
"type": "image",
|
|
"decorative": False,
|
|
"name": "icon_1",
|
|
"data": "/old-icon-1.svg",
|
|
"is_icon": True,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"type": "group",
|
|
"name": "card_2",
|
|
"children": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "title_2",
|
|
"runs": [{"text": "Old card 2"}],
|
|
},
|
|
{
|
|
"type": "image",
|
|
"decorative": False,
|
|
"name": "icon_2",
|
|
"data": "/old-icon-2.svg",
|
|
"is_icon": True,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"id": "metric_card",
|
|
"description": "First metric card.",
|
|
"elements": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "value",
|
|
"runs": [{"text": "0%"}],
|
|
}
|
|
],
|
|
},
|
|
{
|
|
"id": "metric_card",
|
|
"description": "Second metric card.",
|
|
"elements": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "value",
|
|
"runs": [{"text": "0%"}],
|
|
}
|
|
],
|
|
},
|
|
],
|
|
}
|
|
content = {
|
|
"hero": {
|
|
"headline": "Generated headline",
|
|
"hero_image": {
|
|
"image_prompt": "Team dashboard",
|
|
"image_url": "/app_data/images/hero.png",
|
|
},
|
|
"bullets": ["First generated bullet", "Second generated bullet"],
|
|
"metrics": {
|
|
"columns": ["Region", "Sales"],
|
|
"rows": [["US", 12], ["EU", True]],
|
|
},
|
|
"trend": {
|
|
"title": "Growth",
|
|
"chart_type": "line",
|
|
"categories": ["Q1", "Q2"],
|
|
"series": [{"name": "Revenue", "values": [10, 20]}],
|
|
"data_labels": "top",
|
|
},
|
|
"cards": [
|
|
{
|
|
"title": "First card",
|
|
"icon": {"icon_query": "growth", "icon_url": "/icons/one.svg"},
|
|
},
|
|
{
|
|
"title": "Second card",
|
|
"icon": {"icon_query": "support", "icon_url": "/icons/two.svg"},
|
|
},
|
|
],
|
|
},
|
|
"metric_card_0": {"value": "42%"},
|
|
"metric_card_1": {"value": "21%"},
|
|
}
|
|
|
|
hydrated = presentation_endpoint._apply_template_v2_content_to_ui(ui, content)
|
|
|
|
hero_elements = hydrated["components"][0]["elements"]
|
|
assert hero_elements[0]["runs"] == [
|
|
{"text": "Generated headline", "font": {"bold": True}}
|
|
]
|
|
assert "text" not in hero_elements[0]
|
|
assert hero_elements[1]["data"] == "/app_data/images/hero.png"
|
|
assert hero_elements[1]["prompt"] == "Team dashboard"
|
|
assert hero_elements[2]["items"] == [
|
|
[{"text": "First generated bullet"}],
|
|
[{"text": "Second generated bullet"}],
|
|
]
|
|
assert hero_elements[3]["columns"][0]["runs"][0]["text"] == "Region"
|
|
assert hero_elements[3]["rows"][0][1]["runs"][0]["text"] == "12"
|
|
assert hero_elements[3]["rows"][1][1]["runs"][0]["text"] == "true"
|
|
assert hero_elements[4]["chart_type"] == "line"
|
|
assert hero_elements[4]["categories"] == ["Q1", "Q2"]
|
|
assert hero_elements[4]["data_labels"] == "top"
|
|
|
|
cards = hero_elements[5]["children"]
|
|
assert cards[0]["children"][0]["runs"][0]["text"] == "First card"
|
|
assert cards[0]["children"][1]["data"] == "/icons/one.svg"
|
|
assert cards[0]["children"][1]["prompt"] == "growth"
|
|
assert cards[1]["children"][0]["runs"][0]["text"] == "Second card"
|
|
assert cards[1]["children"][1]["data"] == "/icons/two.svg"
|
|
assert cards[1]["children"][1]["prompt"] == "support"
|
|
|
|
assert hydrated["components"][1]["elements"][0]["runs"][0]["text"] == "42%"
|
|
assert hydrated["components"][2]["elements"][0]["runs"][0]["text"] == "21%"
|
|
assert "text" not in hydrated["components"][1]["elements"][0]
|
|
assert "text" not in hydrated["components"][2]["elements"][0]
|
|
assert ui["components"][0]["elements"][0]["runs"][0]["text"] == "Old headline"
|
|
|
|
|
|
def test_apply_template_v2_content_to_ui_handles_empty_text_runs():
|
|
ui = {
|
|
"id": "layout-1",
|
|
"components": [
|
|
{
|
|
"id": "hero",
|
|
"elements": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "headline",
|
|
"font": {"size": 24},
|
|
"runs": [],
|
|
},
|
|
{
|
|
"type": "table",
|
|
"decorative": False,
|
|
"name": "metrics",
|
|
"columns": [{"font": {"size": 10}, "runs": []}],
|
|
"rows": [[{"font": {"size": 9}, "runs": []}]],
|
|
},
|
|
],
|
|
}
|
|
],
|
|
}
|
|
content = {
|
|
"hero": {
|
|
"headline": "Generated headline",
|
|
"metrics": {
|
|
"columns": ["Metric"],
|
|
"rows": [["Revenue"]],
|
|
},
|
|
}
|
|
}
|
|
|
|
hydrated = presentation_endpoint._apply_template_v2_content_to_ui(ui, content)
|
|
|
|
elements = hydrated["components"][0]["elements"]
|
|
assert elements[0]["runs"] == [{"text": "Generated headline", "font": {"size": 24}}]
|
|
assert elements[1]["columns"][0]["runs"] == [
|
|
{"text": "Metric", "font": {"size": 10}}
|
|
]
|
|
assert elements[1]["rows"][0][0]["runs"] == [
|
|
{"text": "Revenue", "font": {"size": 9}}
|
|
]
|
|
|
|
|
|
def test_chat_template_v2_content_hydration_updates_nested_blocks_and_tables():
|
|
ui = {
|
|
"id": "layout-1",
|
|
"components": [
|
|
{
|
|
"id": "hero",
|
|
"elements": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "headline",
|
|
"runs": [{"text": "Old headline"}],
|
|
},
|
|
{
|
|
"type": "grid",
|
|
"name": "cards",
|
|
"children": [
|
|
{
|
|
"type": "group",
|
|
"name": "card_1",
|
|
"children": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "title_1",
|
|
"runs": [{"text": "Old card"}],
|
|
},
|
|
{
|
|
"type": "image",
|
|
"decorative": False,
|
|
"name": "icon_1",
|
|
"data": "/old.svg",
|
|
"is_icon": True,
|
|
},
|
|
],
|
|
}
|
|
],
|
|
},
|
|
{
|
|
"type": "table",
|
|
"decorative": False,
|
|
"name": "metrics",
|
|
"columns": [{"runs": [{"text": "Old column"}]}],
|
|
"rows": [[{"runs": [{"text": "Old value"}]}]],
|
|
},
|
|
],
|
|
}
|
|
],
|
|
}
|
|
|
|
PresentationChatMemoryLayer._apply_template_v2_content_to_ui(
|
|
ui,
|
|
{
|
|
"hero": {
|
|
"headline": "Generated headline",
|
|
"cards": [
|
|
{
|
|
"title": "Revenue up",
|
|
"icon": {
|
|
"icon_query": "growth",
|
|
"icon_url": "/app_data/icons/growth.svg",
|
|
},
|
|
}
|
|
],
|
|
"metrics": {
|
|
"columns": ["Metric", "Value"],
|
|
"rows": [["Revenue", 42]],
|
|
},
|
|
}
|
|
},
|
|
)
|
|
|
|
elements = ui["components"][0]["elements"]
|
|
assert elements[0]["runs"][0]["text"] == "Generated headline"
|
|
assert elements[1]["children"][0]["children"][0]["runs"][0]["text"] == "Revenue up"
|
|
assert elements[1]["children"][0]["children"][1]["data"] == "/app_data/icons/growth.svg"
|
|
assert elements[1]["children"][0]["children"][1]["prompt"] == "growth"
|
|
assert elements[2]["columns"][0]["runs"][0]["text"] == "Metric"
|
|
assert elements[2]["columns"][1]["runs"][0]["text"] == "Value"
|
|
assert elements[2]["rows"][0][0]["runs"][0]["text"] == "Revenue"
|
|
assert elements[2]["rows"][0][1]["runs"][0]["text"] == "42"
|
|
|
|
|
|
def test_apply_template_v2_content_to_ui_parses_markdown_text_to_runs():
|
|
ui = {
|
|
"id": "layout-1",
|
|
"description": "Layout with markdown generated content placeholders.",
|
|
"components": [
|
|
{
|
|
"id": "hero",
|
|
"description": "Hero content component.",
|
|
"elements": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "headline",
|
|
"runs": [
|
|
{
|
|
"text": "Old headline",
|
|
"font": {"family": "Inter", "size": 24},
|
|
}
|
|
],
|
|
},
|
|
{
|
|
"type": "text-list",
|
|
"decorative": False,
|
|
"name": "bullets",
|
|
"items": [
|
|
[
|
|
{
|
|
"text": "Old bullet",
|
|
"font": {"color": "#111111", "size": 14},
|
|
}
|
|
]
|
|
],
|
|
},
|
|
{
|
|
"type": "table",
|
|
"decorative": False,
|
|
"name": "metrics",
|
|
"columns": [
|
|
{
|
|
"font": {"size": 10},
|
|
"runs": [
|
|
{
|
|
"text": "Old column",
|
|
"font": {"size": 10},
|
|
}
|
|
],
|
|
}
|
|
],
|
|
"rows": [
|
|
[
|
|
{
|
|
"runs": [
|
|
{
|
|
"text": "Old value",
|
|
"font": {"size": 9},
|
|
}
|
|
]
|
|
}
|
|
]
|
|
],
|
|
},
|
|
],
|
|
}
|
|
],
|
|
}
|
|
content = {
|
|
"hero": {
|
|
"headline": "AI **agents** need _memory_",
|
|
"bullets": [
|
|
"Keep **scope** tight",
|
|
"Ship *incrementally*",
|
|
],
|
|
"metrics": {
|
|
"columns": ["__Metric__"],
|
|
"rows": [["*Retention*"]],
|
|
},
|
|
}
|
|
}
|
|
|
|
hydrated = presentation_endpoint._apply_template_v2_content_to_ui(ui, content)
|
|
|
|
elements = hydrated["components"][0]["elements"]
|
|
assert elements[0]["runs"] == [
|
|
{"text": "AI ", "font": {"family": "Inter", "size": 24}},
|
|
{
|
|
"text": "agents",
|
|
"font": {"family": "Inter", "size": 24, "bold": True},
|
|
},
|
|
{"text": " need ", "font": {"family": "Inter", "size": 24}},
|
|
{
|
|
"text": "memory",
|
|
"font": {"family": "Inter", "size": 24, "italic": True},
|
|
},
|
|
]
|
|
assert elements[1]["items"] == [
|
|
[
|
|
{"text": "Keep ", "font": {"color": "#111111", "size": 14}},
|
|
{
|
|
"text": "scope",
|
|
"font": {"color": "#111111", "size": 14, "bold": True},
|
|
},
|
|
{"text": " tight", "font": {"color": "#111111", "size": 14}},
|
|
],
|
|
[
|
|
{"text": "Ship "},
|
|
{
|
|
"text": "incrementally",
|
|
"font": {"italic": True},
|
|
},
|
|
],
|
|
]
|
|
assert elements[2]["columns"][0]["runs"] == [
|
|
{"text": "Metric", "font": {"size": 10, "bold": True}}
|
|
]
|
|
assert elements[2]["rows"][0][0]["runs"] == [
|
|
{"text": "Retention", "font": {"size": 9, "italic": True}}
|
|
]
|
|
|
|
|
|
def test_apply_template_v2_content_to_ui_markdown_overrides_inherited_emphasis():
|
|
ui = {
|
|
"id": "layout-1",
|
|
"components": [
|
|
{
|
|
"id": "information_card_grid",
|
|
"elements": [
|
|
{
|
|
"type": "group",
|
|
"name": "information_card",
|
|
"children": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "card_body",
|
|
"font": {
|
|
"size": 21.33,
|
|
"family": "HK Grotesk",
|
|
"color": "#1E1E1E",
|
|
"wrap": "word",
|
|
},
|
|
"runs": [
|
|
{
|
|
"text": "Old body",
|
|
"font": {
|
|
"size": 21.33,
|
|
"family": "HK Grotesk",
|
|
"color": "#1E1E1E",
|
|
"bold": True,
|
|
},
|
|
}
|
|
],
|
|
}
|
|
],
|
|
}
|
|
],
|
|
}
|
|
],
|
|
}
|
|
content = {
|
|
"information_card_grid": {
|
|
"card_body": "**Digital ordering** supports quick, easy meals."
|
|
}
|
|
}
|
|
|
|
hydrated = presentation_endpoint._apply_template_v2_content_to_ui(ui, content)
|
|
|
|
text_element = hydrated["components"][0]["elements"][0]["children"][0]
|
|
assert text_element["runs"] == [
|
|
{
|
|
"text": "Digital ordering",
|
|
"font": {
|
|
"size": 21.33,
|
|
"family": "HK Grotesk",
|
|
"color": "#1E1E1E",
|
|
"wrap": "word",
|
|
"bold": True,
|
|
},
|
|
},
|
|
{
|
|
"text": " supports quick, easy meals.",
|
|
"font": {
|
|
"size": 21.33,
|
|
"family": "HK Grotesk",
|
|
"color": "#1E1E1E",
|
|
"wrap": "word",
|
|
},
|
|
},
|
|
]
|
|
|
|
|
|
def test_apply_template_v2_content_to_ui_keeps_markdown_run_whitespace():
|
|
ui = {
|
|
"id": "layout-1",
|
|
"description": "Layout with markdown spacing edge cases.",
|
|
"components": [
|
|
{
|
|
"id": "left_header_block",
|
|
"description": "Header content component.",
|
|
"elements": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "introductory_paragraph",
|
|
"runs": [
|
|
{
|
|
"text": "Old paragraph",
|
|
"font": {
|
|
"family": "Public Sans",
|
|
"size": 18.68,
|
|
"color": "#1A1A1A",
|
|
"line_height": 1.45,
|
|
"wrap": "word",
|
|
},
|
|
}
|
|
],
|
|
},
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "compact_boundary",
|
|
"runs": [
|
|
{
|
|
"text": "Old compact text",
|
|
"font": {"family": "Inter", "size": 24},
|
|
}
|
|
],
|
|
},
|
|
],
|
|
}
|
|
],
|
|
}
|
|
content = {
|
|
"left_header_block": {
|
|
"introductory_paragraph": (
|
|
"Taco Bell's identity centers on **convenience, affordability, "
|
|
"bold flavors,** and a casual experience that feels playful, "
|
|
"accessible, and easy to customize."
|
|
),
|
|
"compact_boundary": "Use **guided**selling with *agentic*workflows",
|
|
}
|
|
}
|
|
|
|
hydrated = presentation_endpoint._apply_template_v2_content_to_ui(ui, content)
|
|
|
|
elements = hydrated["components"][0]["elements"]
|
|
assert elements[0]["runs"] == [
|
|
{
|
|
"text": "Taco Bell's identity centers on ",
|
|
"font": {
|
|
"family": "Public Sans",
|
|
"size": 18.68,
|
|
"color": "#1A1A1A",
|
|
"line_height": 1.45,
|
|
"wrap": "word",
|
|
},
|
|
},
|
|
{
|
|
"text": "convenience, affordability, bold flavors,",
|
|
"font": {
|
|
"family": "Public Sans",
|
|
"size": 18.68,
|
|
"color": "#1A1A1A",
|
|
"line_height": 1.45,
|
|
"wrap": "word",
|
|
"bold": True,
|
|
},
|
|
},
|
|
{
|
|
"text": " and a casual experience that feels playful, accessible, and easy to customize.",
|
|
"font": {
|
|
"family": "Public Sans",
|
|
"size": 18.68,
|
|
"color": "#1A1A1A",
|
|
"line_height": 1.45,
|
|
"wrap": "word",
|
|
},
|
|
},
|
|
]
|
|
assert elements[1]["runs"] == [
|
|
{"text": "Use ", "font": {"family": "Inter", "size": 24}},
|
|
{
|
|
"text": "guided",
|
|
"font": {"family": "Inter", "size": 24, "bold": True},
|
|
},
|
|
{"text": "selling with ", "font": {"family": "Inter", "size": 24}},
|
|
{
|
|
"text": "agentic",
|
|
"font": {"family": "Inter", "size": 24, "italic": True},
|
|
},
|
|
{"text": "workflows", "font": {"family": "Inter", "size": 24}},
|
|
]
|
|
|
|
|
|
def test_template_v2_markdown_text_runs_keep_source_boundary_spaces():
|
|
runs = presentation_endpoint._template_v2_text_runs_from_markdown(
|
|
"Hello **how are you?** and",
|
|
{"font": {"family": "Inter", "size": 24}},
|
|
)
|
|
|
|
assert runs == [
|
|
{"text": "Hello ", "font": {"family": "Inter", "size": 24}},
|
|
{
|
|
"text": "how are you?",
|
|
"font": {"family": "Inter", "size": 24, "bold": True},
|
|
},
|
|
{"text": " and", "font": {"family": "Inter", "size": 24}},
|
|
]
|
|
|
|
|
|
def test_chat_template_v2_image_content_stores_prompt():
|
|
image = {
|
|
"type": "image",
|
|
"decorative": False,
|
|
"name": "hero_image",
|
|
"data": "/old-image.png",
|
|
"is_icon": False,
|
|
}
|
|
PresentationChatMemoryLayer._set_template_v2_element_value(
|
|
image,
|
|
{
|
|
"image_prompt": "Analytics dashboard",
|
|
"image_url": "/app_data/images/dashboard.png",
|
|
},
|
|
)
|
|
|
|
assert image["data"] == "/app_data/images/dashboard.png"
|
|
assert image["prompt"] == "Analytics dashboard"
|
|
|
|
icon = {
|
|
"type": "image",
|
|
"decorative": False,
|
|
"name": "status_icon",
|
|
"data": "/old-icon.svg",
|
|
"is_icon": True,
|
|
}
|
|
PresentationChatMemoryLayer._set_template_v2_element_value(
|
|
icon,
|
|
{
|
|
"icon_query": "success check",
|
|
"icon_url": "/icons/check.svg",
|
|
},
|
|
)
|
|
|
|
assert icon["data"] == "/icons/check.svg"
|
|
assert icon["prompt"] == "success check"
|
|
|
|
|
|
def test_apply_template_v2_content_to_ui_matches_repeated_content_lengths():
|
|
ui = {
|
|
"id": "layout-1",
|
|
"description": "Layout with repeated generated content.",
|
|
"components": [
|
|
{
|
|
"id": "repeated",
|
|
"description": "Repeated content component.",
|
|
"elements": [
|
|
{
|
|
"type": "flex",
|
|
"name": "flex_cards",
|
|
"min_children": 2,
|
|
"max_children": 3,
|
|
"children": [
|
|
{
|
|
"type": "group",
|
|
"name": "flex_card_1",
|
|
"children": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "title_1",
|
|
"runs": [{"text": "Flex one"}],
|
|
}
|
|
],
|
|
},
|
|
{
|
|
"type": "group",
|
|
"name": "flex_card_2",
|
|
"children": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "title_2",
|
|
"runs": [{"text": "Flex two"}],
|
|
}
|
|
],
|
|
},
|
|
{
|
|
"type": "group",
|
|
"name": "flex_card_3",
|
|
"children": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "title_3",
|
|
"runs": [{"text": "Flex three"}],
|
|
}
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"type": "grid",
|
|
"name": "grid_cards",
|
|
"min_children": 2,
|
|
"max_children": 3,
|
|
"children": [
|
|
{
|
|
"type": "group",
|
|
"name": "grid_card_1",
|
|
"children": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "title_1",
|
|
"runs": [{"text": "Grid one"}],
|
|
}
|
|
],
|
|
},
|
|
{
|
|
"type": "group",
|
|
"name": "grid_card_2",
|
|
"children": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "title_2",
|
|
"runs": [{"text": "Grid two"}],
|
|
}
|
|
],
|
|
},
|
|
{
|
|
"type": "group",
|
|
"name": "grid_card_3",
|
|
"children": [
|
|
{
|
|
"type": "text",
|
|
"decorative": False,
|
|
"name": "title_3",
|
|
"runs": [{"text": "Grid three"}],
|
|
}
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"type": "text-list",
|
|
"decorative": False,
|
|
"name": "bullets",
|
|
"min_items": 2,
|
|
"max_items": 3,
|
|
"items": [
|
|
[{"text": "Bullet one"}],
|
|
[{"text": "Bullet two"}],
|
|
[{"text": "Bullet three"}],
|
|
],
|
|
},
|
|
],
|
|
}
|
|
],
|
|
}
|
|
content = {
|
|
"repeated": {
|
|
"flex_cards": [
|
|
{"title": "Generated flex one"},
|
|
{"title": "Generated flex two"},
|
|
],
|
|
"grid_cards": [
|
|
{"title": "Generated grid one"},
|
|
{"title": "Generated grid two"},
|
|
],
|
|
"bullets": ["Generated bullet one", "Generated bullet two"],
|
|
}
|
|
}
|
|
|
|
hydrated = presentation_endpoint._apply_template_v2_content_to_ui(ui, content)
|
|
|
|
elements = hydrated["components"][0]["elements"]
|
|
flex_children = elements[0]["children"]
|
|
grid_children = elements[1]["children"]
|
|
text_list_items = elements[2]["items"]
|
|
|
|
assert len(flex_children) == 2
|
|
assert flex_children[0]["children"][0]["runs"][0]["text"] == "Generated flex one"
|
|
assert flex_children[1]["children"][0]["runs"][0]["text"] == "Generated flex two"
|
|
assert len(grid_children) == 2
|
|
assert grid_children[0]["children"][0]["runs"][0]["text"] == "Generated grid one"
|
|
assert grid_children[1]["children"][0]["runs"][0]["text"] == "Generated grid two"
|
|
assert text_list_items == [
|
|
[{"text": "Generated bullet one"}],
|
|
[{"text": "Generated bullet two"}],
|
|
]
|
|
|
|
|
|
def test_apply_template_v2_content_to_ui_hydrates_direct_repeated_images():
|
|
ui = {
|
|
"id": "layout-1",
|
|
"components": [
|
|
{
|
|
"id": "gallery",
|
|
"elements": [
|
|
{
|
|
"type": "grid",
|
|
"name": "photo_panels",
|
|
"children": [
|
|
{
|
|
"type": "image",
|
|
"decorative": False,
|
|
"name": "gallery_photo_panel",
|
|
"data": "/static/images/replaceable_template_image.png",
|
|
"is_icon": False,
|
|
}
|
|
for _ in range(3)
|
|
],
|
|
}
|
|
],
|
|
}
|
|
],
|
|
}
|
|
content = {
|
|
"gallery": {
|
|
"photo_panels": [
|
|
{
|
|
"image_prompt": "Melting glacier",
|
|
"image_url": "/app_data/images/glacier.png",
|
|
},
|
|
{
|
|
"image_prompt": "Wildfire smoke",
|
|
"image_url": "/app_data/images/wildfire.png",
|
|
},
|
|
{
|
|
"image_prompt": "Flooded street",
|
|
"image_url": "/static/images/placeholder.jpg",
|
|
},
|
|
]
|
|
}
|
|
}
|
|
|
|
hydrated = presentation_endpoint._apply_template_v2_content_to_ui(ui, content)
|
|
|
|
images = hydrated["components"][0]["elements"][0]["children"]
|
|
assert [image["data"] for image in images] == [
|
|
"/app_data/images/glacier.png",
|
|
"/app_data/images/wildfire.png",
|
|
"/static/images/placeholder.jpg",
|
|
]
|
|
assert [image["prompt"] for image in images] == [
|
|
"Melting glacier",
|
|
"Wildfire smoke",
|
|
"Flooded street",
|
|
]
|
|
|
|
|
|
def test_chat_template_v2_content_hydrates_direct_repeated_images():
|
|
ui = {
|
|
"components": [
|
|
{
|
|
"id": "gallery",
|
|
"elements": [
|
|
{
|
|
"type": "grid",
|
|
"name": "photo_panels",
|
|
"children": [
|
|
{
|
|
"type": "image",
|
|
"decorative": False,
|
|
"name": "gallery_photo_panel",
|
|
"data": "/static/images/replaceable_template_image.png",
|
|
"is_icon": False,
|
|
}
|
|
],
|
|
}
|
|
],
|
|
}
|
|
]
|
|
}
|
|
|
|
PresentationChatMemoryLayer._apply_template_v2_content_to_ui(
|
|
ui,
|
|
{
|
|
"gallery": {
|
|
"photo_panels": [
|
|
{
|
|
"image_prompt": "Generated landscape",
|
|
"image_url": "/app_data/images/landscape.png",
|
|
}
|
|
]
|
|
}
|
|
},
|
|
)
|
|
|
|
image = ui["components"][0]["elements"][0]["children"][0]
|
|
assert image["data"] == "/app_data/images/landscape.png"
|
|
assert image["prompt"] == "Generated landscape"
|