- 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¢)
97 lines
2.4 KiB
Elixir
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
|