package service_test import ( "context" "testing" "financeiro-carvalho/internal/model" "financeiro-carvalho/internal/service" ) type mockImportTxRepo struct{} func (m *mockImportTxRepo) IsDuplicate(_ context.Context, _, _ string, _ float64) (bool, error) { return false, nil } func (m *mockImportTxRepo) IsExternalIDKnown(_ context.Context, _ string) (bool, error) { return false, nil } func (m *mockImportTxRepo) BulkInsert(_ context.Context, rows []model.ImportRow) (int, error) { return len(rows), nil } func (m *mockImportTxRepo) SaveImportLog(_ context.Context, _, _ string, _, _, _ int) error { return nil } type mockDashboardRepo struct { income float64 expenses float64 } func (m *mockDashboardRepo) MonthlySummary(_ context.Context, _ string) (float64, float64, error) { return m.income, m.expenses, nil } func (m *mockDashboardRepo) TotalTaxes(_ context.Context, _ string) (float64, error) { return 0, nil } func (m *mockDashboardRepo) ByCategory(_ context.Context, _ string) ([]model.CategoryTotal, error) { return nil, nil } func (m *mockDashboardRepo) MonthlyEvolution(_ context.Context, _ string) ([]model.MonthEvolution, error) { return nil, nil } func (m *mockDashboardRepo) RecentTransactions(_ context.Context, _ string) ([]model.RecentTransaction, error) { return nil, nil } type mockPatrimony struct{} func (m *mockPatrimony) TotalPatrimony(_ context.Context) (float64, error) { return 0, nil } type mockPendingBillRepo struct{} func (m *mockPendingBillRepo) List(_ context.Context) ([]model.PendingBillImport, error) { return nil, nil } func (m *mockPendingBillRepo) Create(_ context.Context, _, _ string, _ float64, _ []model.ImportRow) (*model.PendingBillImport, error) { return &model.PendingBillImport{}, nil } func (m *mockPendingBillRepo) GetByID(_ context.Context, _ int) (*model.PendingBillImport, error) { return nil, nil } func (m *mockPendingBillRepo) Delete(_ context.Context, _ int) error { return nil } func newDashboardSvc(income, expenses float64) *service.DashboardService { repo := &mockAccountRepo{} recurrSvc := service.NewRecurringService(newMockRecurring(nil), &mockTxRepo{}) billSvc := service.NewCreditBillService(&mockCreditBillRepo{}, repo) pendingBillSvc := service.NewPendingBillService(&mockPendingBillRepo{}, &mockImportTxRepo{}) return service.NewDashboardService(&mockDashboardRepo{income: income, expenses: expenses}, recurrSvc, &mockPatrimony{}, billSvc, pendingBillSvc) } func TestDashboard_SavingsPct_40(t *testing.T) { svc := newDashboardSvc(10000, 6000) data, err := svc.Get(context.Background(), "2024-03") if err != nil { t.Fatal(err) } if data.SavingsPct != 40.0 { t.Errorf("expected 40.0, got %.2f", data.SavingsPct) } } func TestDashboard_SavingsPct_NoIncome(t *testing.T) { svc := newDashboardSvc(0, 500) data, err := svc.Get(context.Background(), "2024-03") if err != nil { t.Fatal(err) } if data.SavingsPct != 0 { t.Errorf("expected 0.0 when no income, got %.2f", data.SavingsPct) } } func TestDashboard_SavingsPct_Above40(t *testing.T) { svc := newDashboardSvc(10000, 5000) data, err := svc.Get(context.Background(), "2024-03") if err != nil { t.Fatal(err) } if data.SavingsPct != 50.0 { t.Errorf("expected 50.0, got %.2f", data.SavingsPct) } } func TestDashboard_EmptySlices(t *testing.T) { svc := newDashboardSvc(0, 0) data, err := svc.Get(context.Background(), "2024-03") if err != nil { t.Fatal(err) } if data.ByCategory == nil { t.Error("ByCategory should not be nil") } if data.MonthlyEvolution == nil { t.Error("MonthlyEvolution should not be nil") } if data.RecentTransactions == nil { t.Error("RecentTransactions should not be nil") } }