Phoenix 1.8 app that scrapes ammunition retailers (Lucky Gunner, SGAmmo) for price data and displays historical price trends. - Data model: retailers, calibers, products, price snapshots - Scraper infrastructure with Req, Floki, realistic browser headers - Oban-scheduled scrape jobs (every 4h with randomized delays) - LiveView pages: homepage with category cards, caliber detail with price table, Chart.js price history, and price stats banner - 18 seeded calibers across handgun/rifle/rimfire/shotgun categories - 77 tests
37 lines
1.2 KiB
Elixir
37 lines
1.2 KiB
Elixir
defmodule AmmopricesWeb.HomeLiveTest do
|
|
use AmmopricesWeb.ConnCase, async: true
|
|
|
|
import Ammoprices.Fixtures
|
|
import Phoenix.LiveViewTest
|
|
|
|
describe "HomeLive" do
|
|
test "renders category sections", %{conn: conn} do
|
|
{:ok, view, _html} = live(conn, "/")
|
|
|
|
assert has_element?(view, "#category-handgun")
|
|
assert has_element?(view, "#category-rifle")
|
|
assert has_element?(view, "#category-rimfire")
|
|
assert has_element?(view, "#category-shotgun")
|
|
end
|
|
|
|
test "renders caliber links", %{conn: conn} do
|
|
caliber_fixture(%{name: "9mm Luger", slug: "9mm-luger", category: "handgun"})
|
|
|
|
{:ok, view, _html} = live(conn, "/")
|
|
|
|
assert has_element?(view, "#caliber-9mm-luger")
|
|
end
|
|
|
|
test "shows cheapest price when snapshots exist", %{conn: conn} do
|
|
caliber = caliber_fixture(%{name: "9mm Luger", slug: "9mm-luger", category: "handgun"})
|
|
retailer = retailer_fixture()
|
|
product = product_fixture(%{caliber: caliber, retailer: retailer, in_stock: true})
|
|
now = DateTime.truncate(DateTime.utc_now(), :second)
|
|
snapshot_fixture(%{product: product, price_per_round_cents: 25, in_stock: true, recorded_at: now})
|
|
|
|
{:ok, _view, html} = live(conn, "/")
|
|
|
|
assert html =~ "25"
|
|
end
|
|
end
|
|
end
|