- 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¢)
52 lines
1.6 KiB
Elixir
52 lines
1.6 KiB
Elixir
defmodule Ammoprices.Scraping.RunnerTest do
|
|
use Ammoprices.DataCase, async: true
|
|
|
|
import Ammoprices.Fixtures
|
|
|
|
alias Ammoprices.Catalog
|
|
alias Ammoprices.Scraping.Retailers.LuckyGunner
|
|
alias Ammoprices.Scraping.Runner
|
|
|
|
@fixture_html File.read!("test/fixtures/lucky_gunner/9mm.html")
|
|
|
|
setup do
|
|
retailer = retailer_fixture(%{name: "Lucky Gunner", slug: "lucky-gunner", base_url: "https://www.luckygunner.com"})
|
|
caliber = caliber_fixture(%{name: "9mm Luger", slug: "9mm-luger", category: "handgun", aliases: ["9mm", "9x19"]})
|
|
|
|
Req.Test.stub(Ammoprices.Scraping.HttpClient, fn conn ->
|
|
Req.Test.html(conn, @fixture_html)
|
|
end)
|
|
|
|
%{retailer: retailer, caliber: caliber}
|
|
end
|
|
|
|
describe "run/2" do
|
|
test "creates products and snapshots from scrape", %{caliber: caliber} do
|
|
scraper = LuckyGunner
|
|
|
|
assert {:ok, stats} = Runner.run(scraper, caliber)
|
|
assert stats.products_count == 4
|
|
assert stats.snapshots_count == 4
|
|
|
|
products = Catalog.list_products_for_caliber(caliber.id)
|
|
assert length(products) == 4
|
|
end
|
|
|
|
test "updates retailer last_scraped_at", %{caliber: caliber} do
|
|
scraper = LuckyGunner
|
|
|
|
{:ok, _stats} = Runner.run(scraper, caliber)
|
|
|
|
retailer = Catalog.get_retailer_by_slug!("lucky-gunner")
|
|
assert retailer.last_scraped_at
|
|
end
|
|
|
|
test "handles scraper returning nil category_url", %{caliber: _caliber} do
|
|
caliber = caliber_fixture(%{name: "Unknown", slug: "unknown", category: "handgun"})
|
|
scraper = LuckyGunner
|
|
|
|
assert {:ok, stats} = Runner.run(scraper, caliber)
|
|
assert stats.products_count == 0
|
|
end
|
|
end
|
|
end
|