ammocpr/test/support/fixtures.ex
Graham McIntire 16a28ac01c
Add Target Sports USA scraper, product filtering, and subsonic detection
- Add subsonic boolean field to products with composite filter indexes
- Add TextDetector utility for detecting subsonic/casing from product titles
- Wire TextDetector into SgAmmo (casing + subsonic) and LuckyGunner (subsonic + fallback casing)
- Extend latest_prices_for_caliber with casing, grain_weight, and subsonic filter options
- Add distinct_grain_weights_for_caliber and distinct_casings_for_caliber queries
- Add filter UI with toggleable casing, grain weight, and subsonic buttons
- Add grain weight column and subsonic badge to product table
- Refresh filter options on PubSub price updates for real-time UI
- Implement Target Sports USA scraper with 18 caliber mappings
- Display all prices in dollar format ($0.38 instead of 38¢)
2026-03-11 16:28:04 -05:00

97 lines
2.4 KiB
Elixir

defmodule Ammoprices.Fixtures do
@moduledoc """
Factory functions for test data.
"""
alias Ammoprices.Catalog.Caliber
alias Ammoprices.Catalog.Product
alias Ammoprices.Catalog.Retailer
alias Ammoprices.Prices.PriceSnapshot
alias Ammoprices.Repo
def retailer_fixture(attrs \\ %{}) do
{:ok, retailer} =
%Retailer{}
|> Retailer.changeset(
Map.merge(
%{
name: "Test Retailer",
slug: "test-retailer-#{System.unique_integer([:positive])}",
base_url: "https://example.com"
},
attrs
)
)
|> Repo.insert()
retailer
end
def caliber_fixture(attrs \\ %{}) do
{:ok, caliber} =
%Caliber{}
|> Caliber.changeset(
Map.merge(
%{
name: "9mm Luger",
slug: "9mm-luger-#{System.unique_integer([:positive])}",
category: "handgun",
aliases: ["9mm", "9x19"]
},
attrs
)
)
|> Repo.insert()
caliber
end
def product_fixture(attrs \\ %{}) do
retailer = Map.get_lazy(attrs, :retailer, fn -> retailer_fixture() end)
caliber = Map.get_lazy(attrs, :caliber, fn -> caliber_fixture() end)
{:ok, product} =
%Product{retailer_id: retailer.id, caliber_id: caliber.id}
|> Product.changeset(
Map.merge(
%{
title: "Test Ammo 9mm 115gr FMJ",
url: "/products/test-#{System.unique_integer([:positive])}",
brand: "TestBrand",
grain_weight: 115,
round_count: 50,
casing: "brass",
condition: "new",
in_stock: true,
subsonic: false,
last_seen_at: DateTime.truncate(DateTime.utc_now(), :second)
},
Map.drop(attrs, [:retailer, :caliber])
)
)
|> Repo.insert()
product
end
def snapshot_fixture(attrs \\ %{}) do
product = Map.get_lazy(attrs, :product, fn -> product_fixture() end)
{:ok, snapshot} =
%PriceSnapshot{product_id: product.id}
|> PriceSnapshot.changeset(
Map.merge(
%{
price_cents: 1599,
price_per_round_cents: 32,
in_stock: true,
recorded_at: DateTime.truncate(DateTime.utc_now(), :second)
},
Map.delete(attrs, :product)
)
)
|> Repo.insert()
snapshot
end
end