berrypod/test/berrypod/legal_pages_test.exs
jamey 933f685b63
All checks were successful
deploy / deploy (push) Successful in 1m23s
add legal page generator for privacy, delivery, and terms
Replaces hardcoded PreviewData placeholders with generated content
derived from real shop state: connected providers (production lead
times), shipping countries (grouped by region), shop country
(jurisdiction language and governing law), and feature flags
(abandoned cart recovery section, newsletter, VAT clause).

Returns policy correctly cites Consumer Contracts Regulations Reg
28(1)(b) for POD exemption and Consumer Rights Act for defective goods.
Cart recovery section uses jurisdiction-specific wording: PECR Reg 22
for UK, GDPR Art 6(1)(f) for EU, generic otherwise.

About page unchanged — shop owner's story to tell.

26 new tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 13:48:49 +00:00

256 lines
7.7 KiB
Elixir

defmodule Berrypod.LegalPagesTest do
use Berrypod.DataCase, async: true
alias Berrypod.LegalPages
alias Berrypod.Settings
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
defp has_heading?(blocks, text) do
Enum.any?(blocks, &(&1.type == :heading and &1.text == text))
end
defp has_text_containing?(blocks, fragment) do
Enum.any?(blocks, fn block ->
case block do
%{text: text} when is_binary(text) -> String.contains?(text, fragment)
%{items: items} -> Enum.any?(items, &String.contains?(&1, fragment))
_ -> false
end
end)
end
# ---------------------------------------------------------------------------
# privacy_content/0
# ---------------------------------------------------------------------------
describe "privacy_content/0" do
test "returns a list of blocks with :lead as the first" do
blocks = LegalPages.privacy_content()
assert is_list(blocks)
assert hd(blocks).type == :lead
end
test "last block is a :closing disclaimer" do
blocks = LegalPages.privacy_content()
assert List.last(blocks).type == :closing
assert String.contains?(List.last(blocks).text, "legal advice")
end
test "always includes core sections" do
blocks = LegalPages.privacy_content()
assert has_heading?(blocks, "What we collect")
assert has_heading?(blocks, "Payment")
assert has_heading?(blocks, "Cookies")
assert has_heading?(blocks, "Third parties")
assert has_heading?(blocks, "Your rights")
assert has_heading?(blocks, "Contact")
end
test "includes PECR cart recovery wording for GB shop" do
Settings.put_setting("shop_country", "GB")
Settings.set_abandoned_cart_recovery(true)
blocks = LegalPages.privacy_content()
assert has_heading?(blocks, "Cart recovery")
assert has_text_containing?(blocks, "PECR")
assert has_text_containing?(blocks, "Regulation 22")
end
test "includes GDPR legitimate interests wording for EU shop" do
Settings.put_setting("shop_country", "DE")
Settings.set_abandoned_cart_recovery(true)
blocks = LegalPages.privacy_content()
assert has_heading?(blocks, "Cart recovery")
assert has_text_containing?(blocks, "Article 6(1)(f)")
refute has_text_containing?(blocks, "PECR")
end
test "includes generic cart recovery wording for non-UK/EU shop" do
Settings.put_setting("shop_country", "US")
Settings.set_abandoned_cart_recovery(true)
blocks = LegalPages.privacy_content()
assert has_heading?(blocks, "Cart recovery")
refute has_text_containing?(blocks, "PECR")
refute has_text_containing?(blocks, "Article 6(1)(f)")
end
test "omits cart recovery section when feature is disabled" do
Settings.set_abandoned_cart_recovery(false)
blocks = LegalPages.privacy_content()
refute has_heading?(blocks, "Cart recovery")
end
test "includes newsletter section when enabled" do
Settings.put_setting("newsletter_enabled", true, "boolean")
blocks = LegalPages.privacy_content()
assert has_heading?(blocks, "Newsletter")
end
test "omits newsletter section when disabled" do
Settings.put_setting("newsletter_enabled", false, "boolean")
blocks = LegalPages.privacy_content()
refute has_heading?(blocks, "Newsletter")
end
test "includes jurisdiction language in lead for GB" do
Settings.put_setting("shop_country", "GB")
blocks = LegalPages.privacy_content()
assert has_text_containing?(blocks, "UK GDPR")
assert has_text_containing?(blocks, "PECR")
end
test "includes GDPR jurisdiction language for EU country" do
Settings.put_setting("shop_country", "FR")
blocks = LegalPages.privacy_content()
assert has_text_containing?(blocks, "EU General Data Protection Regulation")
end
test "includes contact email when set" do
Settings.put_setting("contact_email", "hello@example.com")
blocks = LegalPages.privacy_content()
assert has_text_containing?(blocks, "hello@example.com")
end
end
# ---------------------------------------------------------------------------
# delivery_content/0
# ---------------------------------------------------------------------------
describe "delivery_content/0" do
test "returns a list of blocks with :lead as the first" do
blocks = LegalPages.delivery_content()
assert is_list(blocks)
assert hd(blocks).type == :lead
end
test "always includes returns, cancellations, and production sections" do
blocks = LegalPages.delivery_content()
assert has_heading?(blocks, "Production time")
assert has_heading?(blocks, "Returns & exchanges")
assert has_heading?(blocks, "Cancellations")
end
test "cites Consumer Contracts Regulations in returns section" do
blocks = LegalPages.delivery_content()
assert has_text_containing?(blocks, "Consumer Contracts")
assert has_text_containing?(blocks, "Regulation 28(1)(b)")
end
test "cites Consumer Rights Act for defective goods" do
blocks = LegalPages.delivery_content()
assert has_text_containing?(blocks, "Consumer Rights Act 2015")
end
test "handles empty shipping countries gracefully" do
# No shipping rates seeded — list will be empty in test
blocks = LegalPages.delivery_content()
# Should not crash and should include a fallback paragraph
assert is_list(blocks)
assert has_text_containing?(blocks, "worldwide")
end
test "last block is a :closing disclaimer" do
blocks = LegalPages.delivery_content()
assert List.last(blocks).type == :closing
end
end
# ---------------------------------------------------------------------------
# terms_content/0
# ---------------------------------------------------------------------------
describe "terms_content/0" do
test "returns a list of blocks with :lead as the first" do
blocks = LegalPages.terms_content()
assert is_list(blocks)
assert hd(blocks).type == :lead
end
test "always includes core sections" do
blocks = LegalPages.terms_content()
assert has_heading?(blocks, "Products")
assert has_heading?(blocks, "Payment")
assert has_heading?(blocks, "Returns")
assert has_heading?(blocks, "Governing law")
assert has_heading?(blocks, "Changes")
end
test "governing law is English law for GB shop" do
Settings.put_setting("shop_country", "GB")
blocks = LegalPages.terms_content()
assert has_text_containing?(blocks, "English law")
end
test "governing law references EU regulations for EU shop" do
Settings.put_setting("shop_country", "DE")
blocks = LegalPages.terms_content()
assert has_text_containing?(blocks, "EU regulations")
end
test "includes VAT clause when vat_enabled is true" do
Settings.put_setting("vat_enabled", true, "boolean")
blocks = LegalPages.terms_content()
assert has_text_containing?(blocks, "VAT")
end
test "omits VAT clause when vat_enabled is false" do
Settings.put_setting("vat_enabled", false, "boolean")
blocks = LegalPages.terms_content()
refute has_text_containing?(blocks, "VAT")
end
test "includes shop name in lead" do
Settings.put_setting("shop_name", "Petal & Ink")
blocks = LegalPages.terms_content()
assert has_text_containing?(blocks, "Petal & Ink")
end
test "last block is a :closing disclaimer" do
blocks = LegalPages.terms_content()
assert List.last(blocks).type == :closing
end
end
end