Adds cheapest_price, compare_at_price, in_stock, on_sale columns to products table (recomputed from variants after each sync). Shop components now work with Product structs directly instead of plain maps from PreviewData. Renames .name to .title, adds Product display helpers (primary_image, hover_image, option_types) and ProductImage helpers (display_url, direct_url, source_width). Adds Products context query functions for storefront use (list_visible_products, get_visible_product, list_categories with DB-level sort/filter). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
276 lines
7.5 KiB
Elixir
276 lines
7.5 KiB
Elixir
defmodule SimpleshopTheme.Theme.PreviewDataTest do
|
|
use ExUnit.Case, async: true
|
|
|
|
alias SimpleshopTheme.Theme.PreviewData
|
|
|
|
describe "products/0" do
|
|
test "returns a list of products" do
|
|
products = PreviewData.products()
|
|
|
|
assert is_list(products)
|
|
assert products != []
|
|
end
|
|
|
|
test "each product has required fields" do
|
|
products = PreviewData.products()
|
|
product = List.first(products)
|
|
|
|
assert is_map(product)
|
|
assert Map.has_key?(product, :id)
|
|
assert Map.has_key?(product, :title)
|
|
assert Map.has_key?(product, :description)
|
|
assert Map.has_key?(product, :cheapest_price)
|
|
assert Map.has_key?(product, :images)
|
|
assert Map.has_key?(product, :category)
|
|
assert Map.has_key?(product, :in_stock)
|
|
assert Map.has_key?(product, :on_sale)
|
|
end
|
|
|
|
test "products have valid prices" do
|
|
products = PreviewData.products()
|
|
|
|
for product <- products do
|
|
assert is_integer(product.cheapest_price)
|
|
assert product.cheapest_price > 0
|
|
|
|
if product.compare_at_price do
|
|
assert is_integer(product.compare_at_price)
|
|
assert product.compare_at_price > product.cheapest_price
|
|
end
|
|
end
|
|
end
|
|
|
|
test "products have images" do
|
|
products = PreviewData.products()
|
|
|
|
for product <- products do
|
|
assert is_list(product.images)
|
|
assert length(product.images) >= 1
|
|
|
|
for image <- product.images do
|
|
assert is_integer(image.position)
|
|
assert is_binary(image.src) or not is_nil(image.image_id)
|
|
end
|
|
end
|
|
end
|
|
|
|
test "some products are on sale" do
|
|
products = PreviewData.products()
|
|
on_sale_products = Enum.filter(products, & &1.on_sale)
|
|
|
|
assert on_sale_products != []
|
|
end
|
|
|
|
test "on-sale products have compare_at_price" do
|
|
products = PreviewData.products()
|
|
on_sale_products = Enum.filter(products, & &1.on_sale)
|
|
|
|
for product <- on_sale_products do
|
|
assert product.compare_at_price != nil
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "cart_items/0" do
|
|
test "returns a list of cart items" do
|
|
cart_items = PreviewData.cart_items()
|
|
|
|
assert is_list(cart_items)
|
|
assert cart_items != []
|
|
end
|
|
|
|
test "each cart item has required fields" do
|
|
cart_items = PreviewData.cart_items()
|
|
item = List.first(cart_items)
|
|
|
|
assert is_map(item)
|
|
assert Map.has_key?(item, :product)
|
|
assert Map.has_key?(item, :quantity)
|
|
assert Map.has_key?(item, :variant)
|
|
end
|
|
|
|
test "cart items have valid quantities" do
|
|
cart_items = PreviewData.cart_items()
|
|
|
|
for item <- cart_items do
|
|
assert is_integer(item.quantity)
|
|
assert item.quantity > 0
|
|
end
|
|
end
|
|
|
|
test "cart items reference valid products" do
|
|
cart_items = PreviewData.cart_items()
|
|
|
|
for item <- cart_items do
|
|
product = item.product
|
|
assert is_map(product)
|
|
assert Map.has_key?(product, :id)
|
|
assert Map.has_key?(product, :title)
|
|
assert Map.has_key?(product, :cheapest_price)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "testimonials/0" do
|
|
test "returns a list of testimonials" do
|
|
testimonials = PreviewData.testimonials()
|
|
|
|
assert is_list(testimonials)
|
|
assert testimonials != []
|
|
end
|
|
|
|
test "each testimonial has required fields" do
|
|
testimonials = PreviewData.testimonials()
|
|
testimonial = List.first(testimonials)
|
|
|
|
assert is_map(testimonial)
|
|
assert Map.has_key?(testimonial, :id)
|
|
assert Map.has_key?(testimonial, :author)
|
|
assert Map.has_key?(testimonial, :content)
|
|
assert Map.has_key?(testimonial, :rating)
|
|
assert Map.has_key?(testimonial, :date)
|
|
end
|
|
|
|
test "testimonials have valid ratings" do
|
|
testimonials = PreviewData.testimonials()
|
|
|
|
for testimonial <- testimonials do
|
|
assert is_integer(testimonial.rating)
|
|
assert testimonial.rating >= 1
|
|
assert testimonial.rating <= 5
|
|
end
|
|
end
|
|
|
|
test "testimonials have content" do
|
|
testimonials = PreviewData.testimonials()
|
|
|
|
for testimonial <- testimonials do
|
|
assert is_binary(testimonial.content)
|
|
assert String.length(testimonial.content) > 0
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "categories/0" do
|
|
test "returns a list of categories" do
|
|
categories = PreviewData.categories()
|
|
|
|
assert is_list(categories)
|
|
assert categories != []
|
|
end
|
|
|
|
test "each category has required fields" do
|
|
categories = PreviewData.categories()
|
|
category = List.first(categories)
|
|
|
|
assert is_map(category)
|
|
assert Map.has_key?(category, :id)
|
|
assert Map.has_key?(category, :name)
|
|
assert Map.has_key?(category, :slug)
|
|
assert Map.has_key?(category, :product_count)
|
|
assert Map.has_key?(category, :image_url)
|
|
end
|
|
|
|
test "categories have valid slugs" do
|
|
categories = PreviewData.categories()
|
|
|
|
for category <- categories do
|
|
assert is_binary(category.slug)
|
|
assert String.match?(category.slug, ~r/^[a-z0-9-]+$/)
|
|
end
|
|
end
|
|
|
|
test "categories have product counts" do
|
|
categories = PreviewData.categories()
|
|
|
|
for category <- categories do
|
|
assert is_integer(category.product_count)
|
|
assert category.product_count >= 0
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "has_real_products?/0" do
|
|
test "returns false when no real products exist" do
|
|
assert PreviewData.has_real_products?() == false
|
|
end
|
|
end
|
|
|
|
describe "category_by_slug/1" do
|
|
test "returns category when slug exists" do
|
|
category = PreviewData.category_by_slug("art-prints")
|
|
|
|
assert category != nil
|
|
assert category.slug == "art-prints"
|
|
assert is_binary(category.name)
|
|
end
|
|
|
|
test "returns nil when slug does not exist" do
|
|
assert PreviewData.category_by_slug("nonexistent") == nil
|
|
end
|
|
|
|
test "finds all known categories by slug" do
|
|
categories = PreviewData.categories()
|
|
|
|
for category <- categories do
|
|
found = PreviewData.category_by_slug(category.slug)
|
|
assert found != nil
|
|
assert found.id == category.id
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "products_by_category/1" do
|
|
test "returns all products for nil" do
|
|
all_products = PreviewData.products()
|
|
filtered = PreviewData.products_by_category(nil)
|
|
|
|
assert filtered == all_products
|
|
end
|
|
|
|
test "returns all products for 'all'" do
|
|
all_products = PreviewData.products()
|
|
filtered = PreviewData.products_by_category("all")
|
|
|
|
assert filtered == all_products
|
|
end
|
|
|
|
test "returns empty list for nonexistent category" do
|
|
assert PreviewData.products_by_category("nonexistent") == []
|
|
end
|
|
|
|
test "returns only products matching the category" do
|
|
category = List.first(PreviewData.categories())
|
|
products = PreviewData.products_by_category(category.slug)
|
|
|
|
assert is_list(products)
|
|
|
|
for product <- products do
|
|
assert product.category == category.name
|
|
end
|
|
end
|
|
|
|
test "products are filtered correctly for each category" do
|
|
categories = PreviewData.categories()
|
|
|
|
for category <- categories do
|
|
products = PreviewData.products_by_category(category.slug)
|
|
|
|
for product <- products do
|
|
assert product.category == category.name
|
|
end
|
|
end
|
|
end
|
|
|
|
test "all products belong to at least one category" do
|
|
all_products = PreviewData.products()
|
|
categories = PreviewData.categories()
|
|
category_names = Enum.map(categories, & &1.name)
|
|
|
|
for product <- all_products do
|
|
assert product.category in category_names
|
|
end
|
|
end
|
|
end
|
|
end
|