"""Templates: saved replies from the compose window's More menu.""" from __future__ import annotations from tests.api.conftest import HDR, UserCtx async def test_save_list_replace_delete(user_ctx: UserCtx) -> None: c = user_ctx.client assert (await c.get("/api/templates")).json() == [] resp = await c.post( "/api/templates", json={"name": " Thanks ", "subject": "Re: offer", "body_html": "

Thank you

"}, headers=HDR, ) assert resp.status_code == 200, resp.text first = resp.json() assert first["name"] == "Thanks" and first["subject"] == "Re: offer" # Same name, any case: replaces rather than adding a second one. resp = await c.post( "/api/templates", json={"name": "thanks", "body_html": "

Cheers

"}, headers=HDR ) assert resp.json()["id"] == first["id"] await c.post("/api/templates", json={"name": "Apology", "body_html": "x"}, headers=HDR) listed = (await c.get("/api/templates")).json() assert [t["name"] for t in listed] == ["Apology", "thanks"] assert listed[1]["body_html"] == "

Cheers

" assert (await c.delete(f"/api/templates/{first['id']}", headers=HDR)).status_code == 200 assert [t["name"] for t in (await c.get("/api/templates")).json()] == ["Apology"] async def test_template_html_is_cleaned(user_ctx: UserCtx) -> None: resp = await user_ctx.client.post( "/api/templates", json={ "name": "x", "body_html": '

Hi' 'l

', }, headers=HDR, ) html = resp.json()["body_html"] assert "script" not in html and "onclick" not in html and "onerror" not in html assert "javascript:" not in html and "Hi" in html async def test_template_needs_a_name(user_ctx: UserCtx) -> None: resp = await user_ctx.client.post( "/api/templates", json={"name": " ", "body_html": "x"}, headers=HDR ) assert resp.status_code == 400