Files
2026-06-28 17:52:49 +02:00

224 lines
5.1 KiB
Go

package tax
import (
"encoding/json"
"testing"
)
func TestStatic_Name(t *testing.T) {
p := NewStatic()
if got := p.Name(); got != "static" {
t.Errorf("Name() = %q, want %q", got, "static")
}
}
func TestStatic_Compute(t *testing.T) {
// rateBp is basis points (2500 = 25%).
p := NewStatic()
tests := []struct {
total int64
rateBp int
want int64
}{
{1250, 2500, 250},
{25000, 2500, 5000},
{1000, 2000, 167},
{0, 2500, 0},
}
for _, tt := range tests {
got := p.Compute(tt.total, tt.rateBp)
if got != tt.want {
t.Errorf("Compute(%d, %d) = %d; want %d", tt.total, tt.rateBp, got, tt.want)
}
}
}
func TestStatic_DefaultTaxRate(t *testing.T) {
p := NewStatic()
if got := p.DefaultTaxRate("SE"); got != 0 {
t.Errorf("DefaultTaxRate(\"SE\") = %d; want 0", got)
}
}
func TestNordic_Name(t *testing.T) {
p := NewNordic("SE")
if got := p.Name(); got != "nordic" {
t.Errorf("Name() = %q, want %q", got, "nordic")
}
}
func TestNordic_Compute(t *testing.T) {
// rateBp is basis points (2500 = 25%).
tests := []struct {
total int64
rateBp int
want int64
desc string
}{
{0, 2500, 0, "zero total"},
{1250, 2500, 250, "25 % VAT on 1250"},
{1000, 2000, 167, "20 % VAT on 1000"},
{1200, 2500, 240, "25 % VAT on 1200"},
{25000, 2500, 5000, "25 % VAT on 25000"},
{100, 1000, 10, "10 % VAT on 100"},
{100, 10000, 50, "100 % VAT on 100"},
{100, 0, 0, "zero-rate"},
{100, -1, 0, "negative rate -> zero"},
}
for _, tt := range tests {
p := NewNordic("SE")
got := p.Compute(tt.total, tt.rateBp)
if got != tt.want {
t.Errorf("Compute(%d, %d) [%s] = %d; want %d", tt.total, tt.rateBp, tt.desc, got, tt.want)
}
}
}
func TestNordic_DefaultTaxRate(t *testing.T) {
tests := []struct {
country string
want int
desc string
}{
{"SE", 2500, "Sweden"},
{"NO", 2500, "Norway"},
{"DK", 2500, "Denmark"},
{"FI", 2550, "Finland (25.5%)"},
{"", 2500, "empty -> default SE"},
{"DE", 2500, "unknown -> fallback SE"},
}
for _, tt := range tests {
p := NewNordic("SE")
got := p.DefaultTaxRate(tt.country)
if got != tt.want {
t.Errorf("DefaultTaxRate(%q) [%s] = %d; want %d", tt.country, tt.desc, got, tt.want)
}
}
}
func TestCompute(t *testing.T) {
// rateBp is basis points (2500 = 25%).
tests := []struct {
total int64
rateBp int
want int64
desc string
}{
{1250, 2500, 250, "canonical: 25 %"},
{25000, 2500, 5000, "25k with 25 % -> 5k tax"},
{0, 2500, 0, "zero total"},
{1000, 1250, 112, "fractional: 12.5 %"}, // exVat 1000*10000/11250=888, tax 112
}
for _, tt := range tests {
got := Compute(tt.total, tt.rateBp)
if got != tt.want {
t.Errorf("Compute(%d, %d) [%s] = %d; want %d", tt.total, tt.rateBp, tt.desc, got, tt.want)
}
}
}
func TestProviderInterface(t *testing.T) {
var p Provider = NewNordic("SE")
_ = p
p2 := NewStatic()
_ = p2
}
func TestPrice_NewAndString(t *testing.T) {
p := NewPrice()
if p.IncVat != 0 {
t.Errorf("NewPrice().IncVat = %d; want 0", p.IncVat)
}
}
func TestPrice_NewPriceFromIncVat(t *testing.T) {
p := NewPriceFromIncVat(1250, 2500) // 25% in basis points
if p.IncVat != 1250 {
t.Errorf("IncVat = %d; want 1250", p.IncVat)
}
if len(p.VatRates) != 1 {
t.Errorf("expected 1 vat rate, got %d", len(p.VatRates))
}
}
func TestPrice_ValueExVat(t *testing.T) {
p := NewPriceFromIncVat(1250, 2500) // 25%
exVat := p.ValueExVat()
if exVat != 1000 {
t.Errorf("ValueExVat() = %d; want 1000", exVat)
}
}
func TestPrice_TotalVat(t *testing.T) {
p := NewPriceFromIncVat(1250, 2500) // 25%
totalVat := p.TotalVat()
if totalVat != 250 {
t.Errorf("TotalVat() = %d; want 250", totalVat)
}
}
func TestPrice_Multiply(t *testing.T) {
p := NewPriceFromIncVat(1250, 2500)
p.Multiply(2)
if p.IncVat != 2500 {
t.Errorf("IncVat after Multiply(2) = %d; want 2500", p.IncVat)
}
}
func TestPrice_MultiplyPrice(t *testing.T) {
p := NewPriceFromIncVat(1250, 2500)
p2 := MultiplyPrice(*p, 3)
if p2.IncVat != 3750 {
t.Errorf("IncVat = %d; want 3750", p2.IncVat)
}
}
func TestPrice_Add(t *testing.T) {
a := NewPriceFromIncVat(1250, 2500)
b := NewPriceFromIncVat(2500, 2500)
a.Add(*b)
if a.IncVat != 3750 {
t.Errorf("IncVat after Add = %d; want 3750", a.IncVat)
}
}
func TestPrice_Subtract(t *testing.T) {
a := NewPriceFromIncVat(2500, 2500)
b := NewPriceFromIncVat(1250, 2500)
a.Subtract(*b)
if a.IncVat != 1250 {
t.Errorf("IncVat after Subtract = %d; want 1250", a.IncVat)
}
}
func TestPrice_SumPrices(t *testing.T) {
a := NewPriceFromIncVat(1250, 2500)
b := NewPriceFromIncVat(2500, 2500)
total := SumPrices(*a, *b)
if total.IncVat != 3750 {
t.Errorf("SumPrices IncVat = %d; want 3750", total.IncVat)
}
}
func TestPrice_JSONRoundTrip(t *testing.T) {
p := NewPriceFromIncVat(1250, 2500)
data, err := json.Marshal(p)
if err != nil {
t.Fatalf("marshal error: %v", err)
}
var p2 Price
if err := json.Unmarshal(data, &p2); err != nil {
t.Fatalf("unmarshal error: %v", err)
}
if p2.IncVat != p.IncVat {
t.Errorf("IncVat mismatch: have %d, want %d", p2.IncVat, p.IncVat)
}
}
func TestPrice_SumPricesEmpty(t *testing.T) {
total := SumPrices()
if total.IncVat != 0 {
t.Errorf("SumPrices() IncVat = %d; want 0", total.IncVat)
}
}