defmodule Aprsme.CallsignTest do use ExUnit.Case, async: true alias Aprsme.Callsign doctest Callsign describe "valid?/1" do test "validates standard callsigns" do assert Callsign.valid?("K5ABC") assert Callsign.valid?("W1XYZ") assert Callsign.valid?("N0CALL") end test "validates callsigns with SSID" do assert Callsign.valid?("K5ABC-1") assert Callsign.valid?("W1XYZ-15") assert Callsign.valid?("N0CALL-9") end test "validates callsigns with hyphens in base callsign like VE-KTKI" do assert Callsign.valid?("VE-KTKI") assert Callsign.valid?("VE-KTKI-1") assert Callsign.valid?("VE-TEST") end test "rejects only empty callsigns" do refute Callsign.valid?("") refute Callsign.valid?(" ") # Now accepts any non-empty string assert Callsign.valid?("123") assert Callsign.valid?("-ABC") assert Callsign.valid?("ABC-") assert Callsign.valid?("ABC-123") assert Callsign.valid?("ABC--1") end test "handles nil input" do refute Callsign.valid?(nil) end end describe "normalize/1" do test "converts to uppercase and trims whitespace" do assert Callsign.normalize("k5abc") == "K5ABC" assert Callsign.normalize(" W1XYZ ") == "W1XYZ" assert Callsign.normalize(" n0call-9 ") == "N0CALL-9" end test "normalizes callsigns with hyphens in base" do assert Callsign.normalize("ve-ktki") == "VE-KTKI" assert Callsign.normalize(" VE-KTKI-1 ") == "VE-KTKI-1" end test "handles nil input" do assert Callsign.normalize(nil) == "" end test "returns empty string for non-binary non-nil input" do assert Callsign.normalize(123) == "" assert Callsign.normalize(%{}) == "" end end describe "matches?/2" do test "matches identical normalized callsigns" do assert Callsign.matches?("K5ABC", "K5ABC") assert Callsign.matches?("k5abc", "K5ABC") assert Callsign.matches?(" K5ABC ", "k5abc") end test "distinguishes different callsigns" do refute Callsign.matches?("K5ABC", "K5ABD") refute Callsign.matches?("K5ABC-1", "K5ABC-2") end test "treats nil as empty string" do assert Callsign.matches?(nil, nil) refute Callsign.matches?(nil, "K5ABC") refute Callsign.matches?("K5ABC", nil) end end describe "extract_base/1" do test "returns base callsign before last hyphen" do assert Callsign.extract_base("K5ABC-9") == "K5ABC" assert Callsign.extract_base("W1XYZ-15") == "W1XYZ" end test "preserves intermediate hyphens, splitting on the last one" do assert Callsign.extract_base("VE-KTKI-1") == "VE-KTKI" end test "returns the callsign unchanged when there's no hyphen" do assert Callsign.extract_base("K5ABC") == "K5ABC" end test "handles nil and non-binary input" do assert Callsign.extract_base(nil) == "" assert Callsign.extract_base(123) == "" end end describe "extract_ssid/1" do test "returns the trailing SSID" do assert Callsign.extract_ssid("K5ABC-9") == "9" assert Callsign.extract_ssid("K5ABC-15") == "15" end test "returns the last hyphen segment when multiple are present" do assert Callsign.extract_ssid("VE-KTKI-1") == "1" end test "returns '0' when no SSID" do assert Callsign.extract_ssid("K5ABC") == "0" end test "handles nil and non-binary input" do assert Callsign.extract_ssid(nil) == "0" assert Callsign.extract_ssid(123) == "0" end end describe "extract_parts/1" do test "splits base and SSID for callsign with SSID" do assert Callsign.extract_parts("K5ABC-9") == {"K5ABC", "9"} end test "returns '0' SSID when no hyphen" do assert Callsign.extract_parts("K5ABC") == {"K5ABC", "0"} end test "handles base callsign with internal hyphen" do assert Callsign.extract_parts("VE-KTKI-1") == {"VE-KTKI", "1"} end test "handles nil and non-binary input" do assert Callsign.extract_parts(nil) == {"", "0"} assert Callsign.extract_parts(123) == {"", "0"} end test "is consistent with extract_base/1 and extract_ssid/1" do for input <- ["K5ABC", "K5ABC-9", "VE-KTKI-1"] do assert Callsign.extract_parts(input) == {Callsign.extract_base(input), Callsign.extract_ssid(input)} end end end end