defmodule Microwaveprop.FormatPropertyTest do use ExUnit.Case, async: true use ExUnitProperties alias Microwaveprop.Format # Any finite non-negative number is legitimate input for distance_km/1. # StreamData floats default to the full representable range — we keep # that but reject negatives since negative distances are meaningless # (the algorithm callers always pass an already-absolute km value). defp non_negative_number do one_of([ integer(0..1_000_000_000), map(float(min: 0.0), fn f -> f end), map(integer(0..1_000_000), &(&1 * 1.0)) ]) end describe "distance_km/1" do property "returns a binary for nil" do # Not really a property, just pinned for discoverability alongside # the numeric properties. assert Format.distance_km(nil) == "—" end property "always returns a non-empty binary for any non-negative number" do check all(n <- non_negative_number()) do result = Format.distance_km(n) assert is_binary(result) assert result != "" end end property "output contains both `mi` and `km` units" do check all(n <- non_negative_number()) do result = Format.distance_km(n) assert result =~ "mi" assert result =~ "km" end end property "accepts Decimal input without crashing" do check all(n <- integer(0..10_000)) do decimal = Decimal.new(n) assert is_binary(Format.distance_km(decimal)) end end property "accepts negative distances without crashing" do # Not a valid input at the call site, but we don't want arbitrary # numeric data (e.g. a sign slip in a caller) to crash the view. check all(n <- float(min: -1.0e6, max: -0.01)) do assert is_binary(Format.distance_km(n)) end end end end