defmodule Ammoprices.Scraping.Retailers.BulkAmmoTest do use ExUnit.Case, async: true alias Ammoprices.Scraping.Retailers.BulkAmmo @fixture_path "test/fixtures/bulk_ammo/9mm.html" describe "retailer_slug/0" do test "returns bulk-ammo" do assert BulkAmmo.retailer_slug() == "bulk-ammo" end end describe "category_url/1" do test "maps 9mm-luger caliber to correct URL" do caliber = %{slug: "9mm-luger"} assert BulkAmmo.category_url(caliber) == "/handgun/bulk-9mm-ammo" end test "maps 556-223 caliber to correct URL" do caliber = %{slug: "556-223"} assert BulkAmmo.category_url(caliber) == "/rifle/bulk-223-remington-ammo" end test "returns nil for unmapped caliber" do caliber = %{slug: "unknown-caliber"} assert BulkAmmo.category_url(caliber) == nil end end describe "parse_products/1" do setup do html = File.read!(@fixture_path) %{html: html} end test "extracts all products from HTML", %{html: html} do products = BulkAmmo.parse_products(html) assert length(products) == 4 end test "extracts product title", %{html: html} do [first | _] = BulkAmmo.parse_products(html) assert first.title == "1500 Rounds of 9mm Ammo by Sterling Steel - 115gr FMJ" end test "extracts product URL", %{html: html} do [first | _] = BulkAmmo.parse_products(html) assert first.url == "https://www.bulkammo.com/1500-rounds-of-9mm-ammo-by-sterling-115gr-fmj" end test "extracts sale price when present", %{html: html} do [first | _] = BulkAmmo.parse_products(html) # $285 sale price assert first.price_cents == 28_500 end test "extracts regular price when no sale", %{html: html} do products = BulkAmmo.parse_products(html) second = Enum.at(products, 1) # $239.99 regular price assert second.price_cents == 23_999 end test "extracts round count from title", %{html: html} do [first | _] = BulkAmmo.parse_products(html) assert first.round_count == 1500 end test "calculates price per round", %{html: html} do [first | _] = BulkAmmo.parse_products(html) # 28500 / 1500 = 19 assert first.price_per_round_cents == 19 end test "extracts brand from title", %{html: html} do products = BulkAmmo.parse_products(html) assert hd(products).brand == "Sterling Steel" assert Enum.at(products, 1).brand == "Remington" assert Enum.at(products, 2).brand == "Federal Brass" end test "extracts grain weight from title", %{html: html} do [first | _] = BulkAmmo.parse_products(html) assert first.grain_weight == 115 end test "detects in-stock status", %{html: html} do products = BulkAmmo.parse_products(html) assert hd(products).in_stock == true assert Enum.at(products, 1).in_stock == true # Fourth product is out of stock assert Enum.at(products, 3).in_stock == false end test "detects casing from title", %{html: html} do products = BulkAmmo.parse_products(html) # First product: "Sterling Steel" in title assert hd(products).casing == "steel" # Third product: "Federal Brass" in title assert Enum.at(products, 2).casing == "brass" end test "detects subsonic from title", %{html: html} do products = BulkAmmo.parse_products(html) # Fourth product: "Subsonic" in title assert Enum.at(products, 3).subsonic == true end test "non-subsonic products return false", %{html: html} do [first | _] = BulkAmmo.parse_products(html) assert first.subsonic == false end end end