defmodule Cannery.AmmoTest do @moduledoc """ Tests the Ammo context """ use Cannery.DataCase alias Cannery.{Ammo, Ammo.Pack, Ammo.Type, Containers} alias Ecto.Changeset @moduletag :ammo_test @valid_attrs %{ bullet_type: "some bullet_type", case_material: "some case_material", desc: "some desc", manufacturer: "some manufacturer", name: "some name", grains: 120 } @update_attrs %{ bullet_type: "some updated bullet_type", case_material: "some updated case_material", desc: "some updated desc", manufacturer: "some updated manufacturer", name: "some updated name", grains: 456 } @invalid_attrs %{ bullet_type: nil, case_material: nil, desc: nil, manufacturer: nil, name: nil, grains: nil } describe "list_types/2" do setup do current_user = user_fixture() rifle_type = %{ name: "bullets", class: :rifle, desc: "has some pews in it", grains: 53_453 } |> type_fixture(current_user) shotgun_type = %{ name: "hollows", class: :shotgun, grains: 3_234_234 } |> type_fixture(current_user) pistol_type = %{ class: :pistol, name: "jackets", desc: "brass shell", tracer: true } |> type_fixture(current_user) _shouldnt_return = %{ name: "bullet", desc: "pews brass shell" } |> type_fixture(user_fixture()) [ rifle_type: rifle_type, shotgun_type: shotgun_type, pistol_type: pistol_type, current_user: current_user ] end test "list_types/2 returns all types", %{ rifle_type: rifle_type, shotgun_type: shotgun_type, pistol_type: pistol_type, current_user: current_user } do results = Ammo.list_types(current_user, :all) assert results |> Enum.count() == 3 assert rifle_type in results assert shotgun_type in results assert pistol_type in results end test "list_types/2 returns rifle types", %{ rifle_type: rifle_type, current_user: current_user } do assert [^rifle_type] = Ammo.list_types(current_user, :rifle) end test "list_types/2 returns shotgun types", %{ shotgun_type: shotgun_type, current_user: current_user } do assert [^shotgun_type] = Ammo.list_types(current_user, :shotgun) end test "list_types/2 returns pistol types", %{ pistol_type: pistol_type, current_user: current_user } do assert [^pistol_type] = Ammo.list_types(current_user, :pistol) end test "list_types/2 returns relevant types for a user", %{ rifle_type: rifle_type, shotgun_type: shotgun_type, pistol_type: pistol_type, current_user: current_user } do # name assert Ammo.list_types("bullet", current_user, :all) == [rifle_type] assert Ammo.list_types("bullets", current_user, :all) == [rifle_type] assert Ammo.list_types("hollow", current_user, :all) == [shotgun_type] assert Ammo.list_types("jacket", current_user, :all) == [pistol_type] # desc assert Ammo.list_types("pew", current_user, :all) == [rifle_type] assert Ammo.list_types("brass", current_user, :all) == [pistol_type] assert Ammo.list_types("shell", current_user, :all) == [pistol_type] # grains (integer) assert Ammo.list_types("53453", current_user, :all) == [rifle_type] assert Ammo.list_types("3234234", current_user, :all) == [shotgun_type] # tracer (boolean) assert Ammo.list_types("tracer", current_user, :all) == [pistol_type] end end describe "types" do setup do current_user = user_fixture() [type: type_fixture(current_user), current_user: current_user] end test "get_type!/2 returns the type with given id", %{type: type, current_user: current_user} do assert Ammo.get_type!(type.id, current_user) == type end test "get_types_count!/1 returns the correct amount of ammo", %{current_user: current_user} do assert Ammo.get_types_count!(current_user) == 1 type_fixture(current_user) assert Ammo.get_types_count!(current_user) == 2 type_fixture(current_user) assert Ammo.get_types_count!(current_user) == 3 other_user = user_fixture() assert Ammo.get_types_count!(other_user) == 0 type_fixture(other_user) assert Ammo.get_types_count!(other_user) == 1 end test "create_type/2 with valid data creates a type", %{current_user: current_user} do assert {:ok, %Type{} = type} = Ammo.create_type(@valid_attrs, current_user) assert type.bullet_type == "some bullet_type" assert type.case_material == "some case_material" assert type.desc == "some desc" assert type.manufacturer == "some manufacturer" assert type.name == "some name" assert type.grains == 120 end test "create_type/2 with invalid data returns error changeset", %{current_user: current_user} do assert {:error, %Changeset{}} = Ammo.create_type(@invalid_attrs, current_user) end test "update_type/3 with valid data updates the type", %{type: type, current_user: current_user} do assert {:ok, %Type{} = type} = Ammo.update_type(type, @update_attrs, current_user) assert type.bullet_type == "some updated bullet_type" assert type.case_material == "some updated case_material" assert type.desc == "some updated desc" assert type.manufacturer == "some updated manufacturer" assert type.name == "some updated name" assert type.grains == 456 end test "update_type/3 with invalid data returns error changeset", %{type: type, current_user: current_user} do assert {:error, %Changeset{}} = Ammo.update_type(type, @invalid_attrs, current_user) assert type == Ammo.get_type!(type.id, current_user) end test "delete_type/2 deletes the type", %{type: type, current_user: current_user} do assert {:ok, %Type{}} = Ammo.delete_type(type, current_user) assert_raise Ecto.NoResultsError, fn -> Ammo.get_type!(type.id, current_user) end end end describe "types with packs" do setup do current_user = user_fixture() type = type_fixture(current_user) container = container_fixture(current_user) [ type: type, container: container, current_user: current_user ] end test "get_average_cost_for_type/2 gets average cost for type", %{type: type, current_user: current_user, container: container} do {1, [_pack]} = pack_fixture( %{price_paid: 25.00, count: 1}, type, container, current_user ) assert 25.0 = Ammo.get_average_cost_for_type(type, current_user) {1, [_pack]} = pack_fixture( %{price_paid: 25.00, count: 1}, type, container, current_user ) assert 25.0 = Ammo.get_average_cost_for_type(type, current_user) {1, [_pack]} = pack_fixture( %{price_paid: 70.00, count: 1}, type, container, current_user ) assert 40.0 = Ammo.get_average_cost_for_type(type, current_user) {1, [_pack]} = pack_fixture( %{price_paid: 30.00, count: 1}, type, container, current_user ) assert 37.5 = Ammo.get_average_cost_for_type(type, current_user) end test "get_average_cost_for_types/2 gets average costs for types", %{ type: %{id: type_id} = type, current_user: current_user, container: container } do assert %{} == [type] |> Ammo.get_average_cost_for_types(current_user) %{id: another_type_id} = another_type = type_fixture(current_user) assert %{} == [type, another_type] |> Ammo.get_average_cost_for_types(current_user) {1, [_pack]} = pack_fixture( %{price_paid: 25.00, count: 1}, another_type, container, current_user ) assert %{another_type_id => 25.0} == [type, another_type] |> Ammo.get_average_cost_for_types(current_user) {1, [_pack]} = pack_fixture( %{price_paid: 25.00, count: 1}, type, container, current_user ) average_costs = [type, another_type] |> Ammo.get_average_cost_for_types(current_user) assert %{^type_id => 25.0} = average_costs assert %{^another_type_id => 25.0} = average_costs {1, [_pack]} = pack_fixture( %{price_paid: 25.00, count: 1}, type, container, current_user ) average_costs = [type, another_type] |> Ammo.get_average_cost_for_types(current_user) assert %{^type_id => 25.0} = average_costs assert %{^another_type_id => 25.0} = average_costs {1, [_pack]} = pack_fixture( %{price_paid: 70.00, count: 1}, type, container, current_user ) average_costs = [type, another_type] |> Ammo.get_average_cost_for_types(current_user) assert %{^type_id => 40.0} = average_costs assert %{^another_type_id => 25.0} = average_costs {1, [_pack]} = pack_fixture( %{price_paid: 30.00, count: 1}, type, container, current_user ) average_costs = [type, another_type] |> Ammo.get_average_cost_for_types(current_user) assert %{^type_id => 37.5} = average_costs assert %{^another_type_id => 25.0} = average_costs end test "get_round_count_for_type/2 gets accurate round count for type", %{type: type, current_user: current_user, container: container} do another_type = type_fixture(current_user) assert 0 = Ammo.get_round_count_for_type(another_type, current_user) {1, [first_pack]} = pack_fixture(%{count: 1}, type, container, current_user) assert 1 = Ammo.get_round_count_for_type(type, current_user) {1, [pack]} = pack_fixture(%{count: 50}, type, container, current_user) assert 51 = Ammo.get_round_count_for_type(type, current_user) shot_record_fixture(%{count: 26}, current_user, pack) assert 25 = Ammo.get_round_count_for_type(type, current_user) shot_record_fixture(%{count: 1}, current_user, first_pack) assert 24 = Ammo.get_round_count_for_type(type, current_user) end test "get_round_count_for_types/2 gets accurate round counts for types", %{ type: %{id: type_id} = type, current_user: current_user, container: container } do {1, [first_pack]} = pack_fixture(%{count: 1}, type, container, current_user) assert %{type_id => 1} == [type] |> Ammo.get_round_count_for_types(current_user) %{id: another_type_id} = another_type = type_fixture(current_user) {1, [_another_pack]} = pack_fixture(%{count: 1}, another_type, container, current_user) round_counts = [type, another_type] |> Ammo.get_round_count_for_types(current_user) assert %{^type_id => 1} = round_counts assert %{^another_type_id => 1} = round_counts {1, [pack]} = pack_fixture(%{count: 50}, type, container, current_user) round_counts = [type, another_type] |> Ammo.get_round_count_for_types(current_user) assert %{^type_id => 51} = round_counts assert %{^another_type_id => 1} = round_counts shot_record_fixture(%{count: 26}, current_user, pack) round_counts = [type, another_type] |> Ammo.get_round_count_for_types(current_user) assert %{^type_id => 25} = round_counts assert %{^another_type_id => 1} = round_counts shot_record_fixture(%{count: 1}, current_user, first_pack) round_counts = [type, another_type] |> Ammo.get_round_count_for_types(current_user) assert %{^type_id => 24} = round_counts assert %{^another_type_id => 1} = round_counts end test "get_historical_count_for_type/2 gets accurate total round count for type", %{type: type, current_user: current_user, container: container} do assert 0 = Ammo.get_historical_count_for_type(type, current_user) {1, [first_pack]} = pack_fixture(%{count: 1}, type, container, current_user) assert 1 = Ammo.get_historical_count_for_type(type, current_user) {1, [pack]} = pack_fixture(%{count: 50}, type, container, current_user) assert 51 = Ammo.get_historical_count_for_type(type, current_user) shot_record_fixture(%{count: 26}, current_user, pack) assert 51 = Ammo.get_historical_count_for_type(type, current_user) shot_record_fixture(%{count: 1}, current_user, first_pack) assert 51 = Ammo.get_historical_count_for_type(type, current_user) end test "get_historical_count_for_types/2 gets accurate total round counts for types", %{ type: %{id: type_id} = type, current_user: current_user, container: container } do assert %{} == [type] |> Ammo.get_historical_count_for_types(current_user) {1, [first_pack]} = pack_fixture(%{count: 1}, type, container, current_user) assert %{type_id => 1} == [type] |> Ammo.get_historical_count_for_types(current_user) %{id: another_type_id} = another_type = type_fixture(current_user) {1, [_pack]} = pack_fixture(%{count: 1}, another_type, container, current_user) historical_counts = [type, another_type] |> Ammo.get_historical_count_for_types(current_user) assert %{^type_id => 1} = historical_counts assert %{^another_type_id => 1} = historical_counts {1, [pack]} = pack_fixture(%{count: 50}, type, container, current_user) historical_counts = [type, another_type] |> Ammo.get_historical_count_for_types(current_user) assert %{^type_id => 51} = historical_counts assert %{^another_type_id => 1} = historical_counts shot_record_fixture(%{count: 26}, current_user, pack) historical_counts = [type, another_type] |> Ammo.get_historical_count_for_types(current_user) assert %{^type_id => 51} = historical_counts assert %{^another_type_id => 1} = historical_counts shot_record_fixture(%{count: 1}, current_user, first_pack) historical_counts = [type, another_type] |> Ammo.get_historical_count_for_types(current_user) assert %{^type_id => 51} = historical_counts assert %{^another_type_id => 1} = historical_counts end test "get_used_packs_count_for_type/2 gets accurate total ammo count for type", %{type: type, current_user: current_user, container: container} do assert 0 = Ammo.get_used_packs_count_for_type(type, current_user) {1, [first_pack]} = pack_fixture(%{count: 1}, type, container, current_user) assert 0 = Ammo.get_used_packs_count_for_type(type, current_user) {1, [pack]} = pack_fixture(%{count: 50}, type, container, current_user) assert 0 = Ammo.get_used_packs_count_for_type(type, current_user) shot_record_fixture(%{count: 50}, current_user, pack) assert 1 = Ammo.get_used_packs_count_for_type(type, current_user) shot_record_fixture(%{count: 1}, current_user, first_pack) assert 2 = Ammo.get_used_packs_count_for_type(type, current_user) end test "get_used_packs_count_for_types/2 gets accurate total ammo counts for types", %{ type: %{id: type_id} = type, current_user: current_user, container: container } do # testing empty type assert %{} == [type] |> Ammo.get_used_packs_count_for_types(current_user) # testing two empty types %{id: another_type_id} = another_type = type_fixture(current_user) assert %{} == [type, another_type] |> Ammo.get_used_packs_count_for_types(current_user) # testing type with pack {1, [first_pack]} = pack_fixture(%{count: 1}, type, container, current_user) assert %{} == [type, another_type] |> Ammo.get_used_packs_count_for_types(current_user) # testing type with used pack {1, [another_pack]} = pack_fixture(%{count: 50}, another_type, container, current_user) shot_record_fixture(%{count: 50}, current_user, another_pack) assert %{another_type_id => 1} == [type, another_type] |> Ammo.get_used_packs_count_for_types(current_user) # testing two types with zero and one used packs {1, [pack]} = pack_fixture(%{count: 50}, type, container, current_user) shot_record_fixture(%{count: 50}, current_user, pack) used_counts = [type, another_type] |> Ammo.get_used_packs_count_for_types(current_user) assert %{^type_id => 1} = used_counts assert %{^another_type_id => 1} = used_counts # testing two type with one and two used packs shot_record_fixture(%{count: 1}, current_user, first_pack) used_counts = [type, another_type] |> Ammo.get_used_packs_count_for_types(current_user) assert %{^type_id => 2} = used_counts assert %{^another_type_id => 1} = used_counts end test "get_packs_count_for_container!/2 gets accurate ammo count for container", %{type: type, current_user: current_user, container: container} do {1, [first_pack]} = pack_fixture(%{count: 5}, type, container, current_user) assert 1 = Ammo.get_packs_count_for_container!(container, current_user) {25, _packs} = pack_fixture(%{count: 5}, 25, type, container, current_user) assert 26 = Ammo.get_packs_count_for_container!(container, current_user) shot_record_fixture(%{count: 1}, current_user, first_pack) assert 26 = Ammo.get_packs_count_for_container!(container, current_user) shot_record_fixture(%{count: 4}, current_user, first_pack) assert 25 = Ammo.get_packs_count_for_container!(container, current_user) end test "get_packs_count_for_containers/2 gets accurate ammo count for containers", %{ type: type, current_user: current_user, container: %{id: container_id} = container } do %{id: another_container_id} = another_container = container_fixture(current_user) {1, [first_pack]} = pack_fixture(%{count: 5}, type, container, current_user) {1, [_first_pack]} = pack_fixture(%{count: 5}, type, another_container, current_user) packs_count = [container, another_container] |> Ammo.get_packs_count_for_containers(current_user) assert %{^container_id => 1} = packs_count assert %{^another_container_id => 1} = packs_count {25, _packs} = pack_fixture(%{count: 5}, 25, type, container, current_user) packs_count = [container, another_container] |> Ammo.get_packs_count_for_containers(current_user) assert %{^container_id => 26} = packs_count assert %{^another_container_id => 1} = packs_count shot_record_fixture(%{count: 1}, current_user, first_pack) packs_count = [container, another_container] |> Ammo.get_packs_count_for_containers(current_user) assert %{^container_id => 26} = packs_count assert %{^another_container_id => 1} = packs_count shot_record_fixture(%{count: 4}, current_user, first_pack) packs_count = [container, another_container] |> Ammo.get_packs_count_for_containers(current_user) assert %{^container_id => 25} = packs_count assert %{^another_container_id => 1} = packs_count end test "get_round_count_for_container!/2 gets accurate total round count for container", %{type: type, current_user: current_user, container: container} do {1, [first_pack]} = pack_fixture(%{count: 5}, type, container, current_user) assert 5 = Ammo.get_round_count_for_container!(container, current_user) {25, _packs} = pack_fixture(%{count: 5}, 25, type, container, current_user) assert 130 = Ammo.get_round_count_for_container!(container, current_user) shot_record_fixture(%{count: 5}, current_user, first_pack) assert 125 = Ammo.get_round_count_for_container!(container, current_user) end test "get_round_count_for_containers/2 gets accurate total round count for containers", %{ type: type, current_user: current_user, container: %{id: container_id} = container } do %{id: another_container_id} = another_container = container_fixture(current_user) {1, [first_pack]} = pack_fixture(%{count: 5}, type, container, current_user) {1, [_first_pack]} = pack_fixture(%{count: 5}, type, another_container, current_user) round_counts = [container, another_container] |> Ammo.get_round_count_for_containers(current_user) assert %{^container_id => 5} = round_counts assert %{^another_container_id => 5} = round_counts {25, _packs} = pack_fixture(%{count: 5}, 25, type, container, current_user) round_counts = [container, another_container] |> Ammo.get_round_count_for_containers(current_user) assert %{^container_id => 130} = round_counts assert %{^another_container_id => 5} = round_counts shot_record_fixture(%{count: 5}, current_user, first_pack) round_counts = [container, another_container] |> Ammo.get_round_count_for_containers(current_user) assert %{^container_id => 125} = round_counts assert %{^another_container_id => 5} = round_counts end end describe "packs" do @valid_attrs %{ count: 42, notes: "some notes", price_paid: 120.5, purchased_on: ~D[2022-11-19] } @update_attrs %{ count: 43, notes: "some updated notes", price_paid: 456.7 } @invalid_attrs %{ count: nil, notes: nil, price_paid: nil } setup do current_user = user_fixture() type = type_fixture(current_user) container = container_fixture(current_user) {1, [pack]} = pack_fixture(%{count: 50, price_paid: 36.1}, type, container, current_user) another_user = user_fixture() another_type = type_fixture(another_user) another_container = container_fixture(another_user) {1, [_shouldnt_show_up]} = pack_fixture(another_type, another_container, another_user) [ type: type, pack: pack, container: container, current_user: current_user ] end test "get_packs_count!/2 returns the correct amount of ammo", %{type: type, container: container, current_user: current_user} do assert Ammo.get_packs_count!(current_user) == 1 pack_fixture(type, container, current_user) assert Ammo.get_packs_count!(current_user) == 2 pack_fixture(type, container, current_user) assert Ammo.get_packs_count!(current_user) == 3 other_user = user_fixture() assert Ammo.get_packs_count!(other_user) == 0 assert Ammo.get_packs_count!(other_user, true) == 0 other_type = type_fixture(other_user) other_container = container_fixture(other_user) {1, [another_pack]} = pack_fixture(%{count: 30}, other_type, other_container, other_user) shot_record_fixture(%{count: 30}, other_user, another_pack) assert Ammo.get_packs_count!(other_user) == 0 assert Ammo.get_packs_count!(other_user, true) == 1 end test "list_packs/4 returns all packs for a type" do current_user = user_fixture() container = container_fixture(current_user) rifle_type = type_fixture(%{class: :rifle}, current_user) {1, [rifle_pack]} = pack_fixture(rifle_type, container, current_user) shotgun_type = type_fixture(%{class: :shotgun}, current_user) {1, [shotgun_pack]} = pack_fixture(shotgun_type, container, current_user) pistol_type = type_fixture(%{class: :pistol}, current_user) {1, [pistol_pack]} = pack_fixture(pistol_type, container, current_user) assert [^rifle_pack] = Ammo.list_packs(nil, :rifle, current_user, false) assert [^shotgun_pack] = Ammo.list_packs(nil, :shotgun, current_user, false) assert [^pistol_pack] = Ammo.list_packs(nil, :pistol, current_user, false) packs = Ammo.list_packs(nil, :all, current_user, false) assert Enum.count(packs) == 3 assert rifle_pack in packs assert shotgun_pack in packs assert pistol_pack in packs packs = Ammo.list_packs(nil, nil, current_user, false) assert Enum.count(packs) == 3 assert rifle_pack in packs assert shotgun_pack in packs assert pistol_pack in packs end test "list_packs/4 returns all relevant packs including used", %{ type: type, pack: pack, container: container, current_user: current_user } do {1, [%{id: another_pack_id} = another_pack]} = pack_fixture(%{count: 30}, type, container, current_user) shot_record_fixture(%{count: 30}, current_user, another_pack) another_pack = Ammo.get_pack!(another_pack_id, current_user) assert Ammo.list_packs(nil, :all, current_user, false) == [pack] packs = Ammo.list_packs(nil, :all, current_user, true) assert Enum.count(packs) == 2 assert another_pack in packs assert pack in packs end test "list_packs/4 returns relevant packs when searched", %{ type: type, pack: pack, container: container, current_user: current_user } do {1, [another_pack]} = %{count: 49, notes: "cool pack"} |> pack_fixture(type, container, current_user) another_type = type_fixture(%{name: "amazing ammo"}, current_user) another_container = container_fixture(%{name: "fantastic container"}, current_user) tag = tag_fixture(%{name: "stupendous tag"}, current_user) Containers.add_tag!(another_container, tag, current_user) {1, [amazing_pack]} = pack_fixture(%{count: 48}, another_type, container, current_user) {1, [fantastic_pack]} = pack_fixture(%{count: 47}, type, another_container, current_user) packs = Ammo.list_packs(nil, :all, current_user, false) assert Enum.count(packs) == 4 assert fantastic_pack in packs assert amazing_pack in packs assert another_pack in packs assert pack in packs # search works for pack attributes assert Ammo.list_packs("cool", :all, current_user, true) == [another_pack] # search works for type attributes assert Ammo.list_packs("amazing", :all, current_user, true) == [amazing_pack] # search works for container attributes assert Ammo.list_packs("fantastic", :all, current_user, true) == [fantastic_pack] # search works for container tag attributes assert Ammo.list_packs("stupendous", :all, current_user, true) == [fantastic_pack] assert Ammo.list_packs("random", :all, current_user, true) == [] end test "list_packs_for_type/3 returns all packs for a type", %{ container: container, current_user: current_user } do type = type_fixture(current_user) {1, [pack]} = pack_fixture(type, container, current_user) assert [^pack] = Ammo.list_packs_for_type(type, current_user) shot_record_fixture(current_user, pack) pack = Ammo.get_pack!(pack.id, current_user) assert [] == Ammo.list_packs_for_type(type, current_user) assert [^pack] = Ammo.list_packs_for_type(type, current_user, true) end test "list_packs_for_container/3 returns all packs for a container" do current_user = user_fixture() container = container_fixture(current_user) rifle_type = type_fixture(%{class: :rifle}, current_user) {1, [rifle_pack]} = pack_fixture(rifle_type, container, current_user) shotgun_type = type_fixture(%{class: :shotgun}, current_user) {1, [shotgun_pack]} = pack_fixture(shotgun_type, container, current_user) pistol_type = type_fixture(%{class: :pistol}, current_user) {1, [pistol_pack]} = pack_fixture(pistol_type, container, current_user) another_container = container_fixture(current_user) pack_fixture(rifle_type, another_container, current_user) pack_fixture(shotgun_type, another_container, current_user) pack_fixture(pistol_type, another_container, current_user) assert [^rifle_pack] = Ammo.list_packs_for_container(container, :rifle, current_user) assert [^shotgun_pack] = Ammo.list_packs_for_container(container, :shotgun, current_user) assert [^pistol_pack] = Ammo.list_packs_for_container(container, :pistol, current_user) packs = Ammo.list_packs_for_container(container, :all, current_user) assert Enum.count(packs) == 3 assert rifle_pack in packs assert shotgun_pack in packs assert pistol_pack in packs packs = Ammo.list_packs_for_container(container, nil, current_user) assert Enum.count(packs) == 3 assert rifle_pack in packs assert shotgun_pack in packs assert pistol_pack in packs end test "get_packs_count_for_type/2 returns count of packs for a type", %{ type: type, container: container, current_user: current_user } do assert 1 = Ammo.get_packs_count_for_type(type, current_user) another_type = type_fixture(current_user) assert 0 = Ammo.get_packs_count_for_type(another_type, current_user) {5, _packs} = pack_fixture(%{}, 5, type, container, current_user) assert 6 = Ammo.get_packs_count_for_type(type, current_user) end test "get_packs_count_for_types/2 returns counts of packs for types", %{ type: %{id: type_id} = type, container: container, current_user: current_user } do assert %{type_id => 1} == [type] |> Ammo.get_packs_count_for_types(current_user) %{id: another_type_id} = another_type = type_fixture(current_user) assert %{type_id => 1} == [type, another_type] |> Ammo.get_packs_count_for_types(current_user) {1, [_pack]} = pack_fixture(another_type, container, current_user) packs_count = [type, another_type] |> Ammo.get_packs_count_for_types(current_user) assert %{^type_id => 1} = packs_count assert %{^another_type_id => 1} = packs_count {5, _packs} = pack_fixture(%{}, 5, type, container, current_user) packs_count = [type, another_type] |> Ammo.get_packs_count_for_types(current_user) assert %{^type_id => 6} = packs_count assert %{^another_type_id => 1} = packs_count end test "list_staged_packs/1 returns all packs that are staged", %{ type: type, container: container, current_user: current_user } do {1, [another_pack]} = pack_fixture(%{staged: true}, type, container, current_user) assert Ammo.list_staged_packs(current_user) == [another_pack] end test "get_pack!/2 returns the pack with given id", %{pack: %{id: pack_id} = pack, current_user: current_user} do assert Ammo.get_pack!(pack_id, current_user) == pack end test "get_packs/2 returns the packs with given id", %{ pack: %{id: pack_id} = pack, type: type, container: container, current_user: current_user } do {1, [%{id: another_pack_id} = another_pack]} = pack_fixture(type, container, current_user) packs = Ammo.get_packs([pack_id, another_pack_id], current_user) assert %{^pack_id => ^pack} = packs assert %{^another_pack_id => ^another_pack} = packs end test "create_packs/3 with valid data creates a pack", %{ type: type, container: container, current_user: current_user } do assert {:ok, {1, [%Pack{} = pack]}} = @valid_attrs |> Map.merge(%{type_id: type.id, container_id: container.id}) |> Ammo.create_packs(1, current_user) assert pack.count == 42 assert pack.notes == "some notes" assert pack.price_paid == 120.5 end test "create_packs/3 with valid data creates multiple packs", %{ type: type, container: container, current_user: current_user } do assert {:ok, {3, packs}} = @valid_attrs |> Map.merge(%{type_id: type.id, container_id: container.id}) |> Ammo.create_packs(3, current_user) assert [%Pack{}, %Pack{}, %Pack{}] = packs packs |> Enum.map(fn %{count: count, notes: notes, price_paid: price_paid} -> assert count == 42 assert notes == "some notes" assert price_paid == 120.5 end) end test "create_packs/3 with invalid data returns error changeset", %{type: type, container: container, current_user: current_user} do assert {:error, %Changeset{}} = @invalid_attrs |> Map.merge(%{type_id: type.id, container_id: container.id}) |> Ammo.create_packs(1, current_user) end test "update_pack/3 with valid data updates the pack", %{pack: pack, current_user: current_user} do assert {:ok, %Pack{} = pack} = Ammo.update_pack(pack, @update_attrs, current_user) assert pack.count == 43 assert pack.notes == "some updated notes" assert pack.price_paid == 456.7 end test "update_pack/3 with invalid data returns error changeset", %{pack: pack, current_user: current_user} do assert {:error, %Changeset{}} = Ammo.update_pack(pack, @invalid_attrs, current_user) assert pack == Ammo.get_pack!(pack.id, current_user) end test "delete_pack/2 deletes the pack", %{pack: pack, current_user: current_user} do assert {:ok, %Pack{}} = Ammo.delete_pack(pack, current_user) assert_raise KeyError, fn -> Ammo.get_pack!(pack.id, current_user) end end test "get_percentage_remaining/2 gets accurate total round count", %{pack: %{id: pack_id} = pack, current_user: current_user} do assert 100 = pack |> Ammo.get_percentage_remaining(current_user) shot_record_fixture(%{count: 14}, current_user, pack) pack = Ammo.get_pack!(pack_id, current_user) assert 72 = pack |> Ammo.get_percentage_remaining(current_user) shot_record_fixture(%{count: 11}, current_user, pack) pack = Ammo.get_pack!(pack_id, current_user) assert 50 = pack |> Ammo.get_percentage_remaining(current_user) shot_record_fixture(%{count: 25}, current_user, pack) pack = Ammo.get_pack!(pack_id, current_user) assert 0 = pack |> Ammo.get_percentage_remaining(current_user) end test "get_percentages_remaining/2 gets accurate total round count", %{ pack: %{id: pack_id} = pack, type: type, container: container, current_user: current_user } do assert %{pack_id => 100} == [pack] |> Ammo.get_percentages_remaining(current_user) {1, [%{id: another_pack_id} = another_pack]} = %{count: 50, price_paid: 36.1} |> pack_fixture(type, container, current_user) percentages = [pack, another_pack] |> Ammo.get_percentages_remaining(current_user) assert %{^pack_id => 100} = percentages assert %{^another_pack_id => 100} = percentages shot_record_fixture(%{count: 14}, current_user, pack) pack = Ammo.get_pack!(pack_id, current_user) percentages = [pack, another_pack] |> Ammo.get_percentages_remaining(current_user) assert %{^pack_id => 72} = percentages assert %{^another_pack_id => 100} = percentages shot_record_fixture(%{count: 11}, current_user, pack) pack = Ammo.get_pack!(pack_id, current_user) percentages = [pack, another_pack] |> Ammo.get_percentages_remaining(current_user) assert %{^pack_id => 50} = percentages assert %{^another_pack_id => 100} = percentages shot_record_fixture(%{count: 25}, current_user, pack) pack = Ammo.get_pack!(pack_id, current_user) percentages = [pack, another_pack] |> Ammo.get_percentages_remaining(current_user) assert %{^pack_id => 0} = percentages assert %{^another_pack_id => 100} = percentages end test "get_cpr/2 gets accurate cpr", %{type: type, container: container, current_user: current_user} do {1, [pack]} = pack_fixture(%{count: 1}, type, container, current_user) assert pack |> Ammo.get_cpr(current_user) |> is_nil() {1, [pack]} = pack_fixture( %{count: 1, price_paid: 1.0}, type, container, current_user ) assert 1.0 = pack |> Ammo.get_cpr(current_user) {1, [pack]} = pack_fixture( %{count: 2, price_paid: 3.0}, type, container, current_user ) assert 1.5 = pack |> Ammo.get_cpr(current_user) {1, [pack]} = pack_fixture( %{count: 50, price_paid: 36.1}, type, container, current_user ) assert 0.722 = pack |> Ammo.get_cpr(current_user) # with shot record, maintains total shot_record_fixture(%{count: 14}, current_user, pack) pack = Ammo.get_pack!(pack.id, current_user) assert 0.722 = pack |> Ammo.get_cpr(current_user) end test "get_cprs/2 gets accurate cprs", %{type: type, container: container, current_user: current_user} do {1, [pack]} = pack_fixture(%{count: 1}, type, container, current_user) assert %{} == [pack] |> Ammo.get_cprs(current_user) {1, [%{id: pack_id} = pack]} = pack_fixture( %{count: 1, price_paid: 1.0}, type, container, current_user ) assert %{pack_id => 1.0} == [pack] |> Ammo.get_cprs(current_user) {1, [%{id: another_pack_id} = another_pack]} = pack_fixture( %{count: 2, price_paid: 3.0}, type, container, current_user ) cprs = [pack, another_pack] |> Ammo.get_cprs(current_user) assert %{^pack_id => 1.0} = cprs assert %{^another_pack_id => 1.5} = cprs {1, [%{id: yet_another_pack_id} = yet_another_pack]} = pack_fixture( %{count: 50, price_paid: 36.1}, type, container, current_user ) cprs = [pack, another_pack, yet_another_pack] |> Ammo.get_cprs(current_user) assert %{^pack_id => 1.0} = cprs assert %{^another_pack_id => 1.5} = cprs assert %{^yet_another_pack_id => 0.722} = cprs # with shot record, maintains total shot_record_fixture(%{count: 14}, current_user, yet_another_pack) yet_another_pack = Ammo.get_pack!(yet_another_pack.id, current_user) cprs = [pack, another_pack, yet_another_pack] |> Ammo.get_cprs(current_user) assert %{^pack_id => 1.0} = cprs assert %{^another_pack_id => 1.5} = cprs assert %{^yet_another_pack_id => 0.722} = cprs end test "get_original_count/2 gets accurate original count", %{pack: %{id: pack_id} = pack, current_user: current_user} do assert 50 = pack |> Ammo.get_original_count(current_user) shot_record_fixture(%{count: 14}, current_user, pack) pack = Ammo.get_pack!(pack_id, current_user) assert 50 = pack |> Ammo.get_original_count(current_user) shot_record_fixture(%{count: 11}, current_user, pack) pack = Ammo.get_pack!(pack_id, current_user) assert 50 = pack |> Ammo.get_original_count(current_user) shot_record_fixture(%{count: 25}, current_user, pack) pack = Ammo.get_pack!(pack_id, current_user) assert 50 = pack |> Ammo.get_original_count(current_user) end test "get_original_counts/2 gets accurate original counts", %{ pack: %{id: pack_id} = pack, type: type, container: container, current_user: current_user } do {1, [%{id: another_pack_id} = another_pack]} = pack_fixture(%{count: 25}, type, container, current_user) original_counts = [pack, another_pack] |> Ammo.get_original_counts(current_user) assert %{^pack_id => 50} = original_counts assert %{^another_pack_id => 25} = original_counts shot_record_fixture(%{count: 14}, current_user, pack) pack = Ammo.get_pack!(pack_id, current_user) original_counts = [pack, another_pack] |> Ammo.get_original_counts(current_user) assert %{^pack_id => 50} = original_counts assert %{^another_pack_id => 25} = original_counts shot_record_fixture(%{count: 11}, current_user, pack) pack = Ammo.get_pack!(pack_id, current_user) original_counts = [pack, another_pack] |> Ammo.get_original_counts(current_user) assert %{^pack_id => 50} = original_counts assert %{^another_pack_id => 25} = original_counts shot_record_fixture(%{count: 25}, current_user, pack) pack = Ammo.get_pack!(pack_id, current_user) original_counts = [pack, another_pack] |> Ammo.get_original_counts(current_user) assert %{^pack_id => 50} = original_counts assert %{^another_pack_id => 25} = original_counts end end end