Compare commits

...

4 Commits

Author SHA1 Message Date
4626f08b9c Merge pull request 'localization' (#23) from localization into main
All checks were successful
Badges / coveralls (push) Successful in 55s
Reviewed-on: #23
2025-12-04 17:00:37 +00:00
0d97432c6c improved error handling on translation
All checks were successful
Generate check / check-changes (pull_request) Successful in 18s
Quality / check-changes (pull_request) Successful in 17s
Generate check / verify-generate (pull_request) Has been skipped
Quality / run-tests (pull_request) Successful in 30s
2025-12-04 16:59:20 +00:00
10e1e99683 improve test coverage 2025-12-04 16:56:34 +00:00
38db50b879 add and fix tests
All checks were successful
Generate check / check-changes (pull_request) Successful in 18s
Quality / check-changes (pull_request) Successful in 18s
Generate check / verify-generate (pull_request) Has been skipped
Quality / run-tests (pull_request) Successful in 1m7s
2025-12-04 16:23:26 +00:00
4 changed files with 126 additions and 2 deletions

View File

@@ -4,6 +4,7 @@ import (
"embed"
"encoding/json"
"fmt"
"log/slog"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/text/language"
@@ -38,9 +39,14 @@ func NewLocalizer(lang string) (*Localizer, error) {
}
func (t Localizer) Translate(key string, count int, values map[string]any) string {
return t.MustLocalize(&i18n.LocalizeConfig{
txt, err := t.Localize(&i18n.LocalizeConfig{
MessageID: key,
TemplateData: values,
PluralCount: count,
})
if err != nil {
slog.Error("failed to translate message", slog.Any("err", err))
return "<ERROR>"
}
return txt
}

View File

@@ -0,0 +1,24 @@
package main
import "testing"
func TestNewLocalizer(t *testing.T) {
tests := []struct {
name string
lang string
}{
{"english", "en"},
{"portuguese", "pt"},
{"english with region", "en-US"},
{"portuguese with region", "pt-BR"},
{"unknown language falls back to default", "!!"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := NewLocalizer(tt.lang)
if err != nil {
t.Fatalf("want success call but failed: %v", err)
}
})
}
}

View File

@@ -1 +1,84 @@
package main
import (
"bytes"
"context"
"testing"
"time"
"github.com/nmoniz/any2anexoj/internal"
"github.com/shopspring/decimal"
)
func TestPrettyPrinter_Render(t *testing.T) {
// Create test data
aw := internal.NewAggregatorWriter()
ctx := context.Background()
// Add some sample report items
err := aw.Write(ctx, internal.ReportItem{
Symbol: "AAPL",
Nature: internal.NatureG01,
BrokerCountry: 826, // United Kingdom
AssetCountry: 840, // United States
BuyValue: decimal.NewFromFloat(100.50),
BuyTimestamp: time.Date(2023, 1, 15, 0, 0, 0, 0, time.UTC),
SellValue: decimal.NewFromFloat(150.75),
SellTimestamp: time.Date(2023, 6, 20, 0, 0, 0, 0, time.UTC),
Fees: decimal.NewFromFloat(2.50),
Taxes: decimal.NewFromFloat(5.00),
})
if err != nil {
t.Fatalf("failed to write first report item: %v", err)
}
err = aw.Write(ctx, internal.ReportItem{
Symbol: "GOOGL",
Nature: internal.NatureG20,
BrokerCountry: 826, // United Kingdom
AssetCountry: 840, // United States
BuyValue: decimal.NewFromFloat(200.00),
BuyTimestamp: time.Date(2023, 3, 10, 0, 0, 0, 0, time.UTC),
SellValue: decimal.NewFromFloat(225.50),
SellTimestamp: time.Date(2023, 9, 5, 0, 0, 0, 0, time.UTC),
Fees: decimal.NewFromFloat(3.00),
Taxes: decimal.NewFromFloat(7.50),
})
if err != nil {
t.Fatalf("failed to write second report item: %v", err)
}
// Create English localizer
localizer, err := NewLocalizer("en")
if err != nil {
t.Fatalf("failed to create localizer: %v", err)
}
// Create pretty printer with buffer
var buf bytes.Buffer
pp := NewPrettyPrinter(&buf, localizer)
// Render the table
pp.Render(aw)
// Get the output
got := buf.String()
// Expected output
want := `┌───┬────────────────────────────┬───────────────────────────────────┬───────────────────────────────────┬──────────────────────────────────────────────────────────┐
│ │ │ REALIZATION │ ACQUISITION │ │
│ │ SOURCE COUNTRY │ CODE │ YEAR │ MONTH │ DAY │ VALUE │ YEAR │ MONTH │ DAY │ VALUE │ EXPENSES AND CH │ TAX PAID ABROAD │ COUNTER COUNTRY │
│ │ │ │ │ │ │ │ │ │ │ │ ARGES │ │ │
├───┼─────────────────────┼──────┼──────┼───────┼─────┼──────────────┼──────┼───────┼─────┼──────────────┼─────────────────┼─────────────────┼──────────────────────┤
│ 1 │ 840 - United States │ G01 │ 2023 │ 6 │ 20 │ 150.75 € │ 2023 │ 1 │ 15 │ 100.50 € │ 2.50 € │ 5.00 € │ 826 - United Kingdom │
│ 2 │ 840 - United States │ G20 │ 2023 │ 9 │ 5 │ 225.50 € │ 2023 │ 3 │ 10 │ 200.00 € │ 3.00 € │ 7.50 € │ 826 - United Kingdom │
├───┼─────────────────────┴──────┴──────┴───────┴─────┼──────────────┼──────┴───────┴─────┼──────────────┼─────────────────┼─────────────────┼──────────────────────┤
│ │ SUM │ 376.25 € │ │ 300.5 € │ 5.5 € │ 12.5 € │ │
└───┴─────────────────────────────────────────────────┴──────────────┴────────────────────┴──────────────┴─────────────────┴─────────────────┴──────────────────────┘
`
// Compare output
if got != want {
t.Errorf("PrettyPrinter.Render() output doesn't match expected.\n\nGot:\n%s\n\nWant:\n%s", got, want)
}
}

View File

@@ -211,7 +211,7 @@ func TestAggregatorWriter_Items(t *testing.T) {
aw := &internal.AggregatorWriter{}
ctx := context.Background()
for range 10 {
for range 5 {
item := internal.ReportItem{Symbol: "TEST"}
if err := aw.Write(ctx, item); err != nil {
t.Fatalf("unexpected error: %v", err)
@@ -226,6 +226,17 @@ func TestAggregatorWriter_Items(t *testing.T) {
if count != 5 {
t.Errorf("expected for loop to stop at 5 items, got %d", count)
}
count = 0
for range aw.Iter() {
count++
if count == 3 {
break
}
}
if count != 3 {
t.Errorf("expected for loop to stop at 3 items, got %d", count)
}
}
func TestAggregatorWriter_ThreadSafety(t *testing.T) {