Download ledger/validations_test.go from Leon4gr45/openmeter: direct link, hf CLI and curl.
- Browser
- Download file 5.27 kB
-
https://huggingface.co/spaces/Leon4gr45/openmeter/resolve/main/ledger/validations_test.go
- Command line
-
hf download hf://spaces/Leon4gr45/openmeter/ledger/validations_test.go
-
curl -L -o validations_test.go https://huggingface.co/spaces/Leon4gr45/openmeter/resolve/main/ledger/validations_test.go
5.27 kB
| package ledger_test | |
| import ( | |
| "testing" | |
| "time" | |
| "github.com/alpacahq/alpacadecimal" | |
| "github.com/samber/mo" | |
| "github.com/stretchr/testify/require" | |
| "github.com/openmeterio/openmeter/openmeter/ledger" | |
| ledgeraccount "github.com/openmeterio/openmeter/openmeter/ledger/account" | |
| "github.com/openmeterio/openmeter/openmeter/ledger/transactions/testutils" | |
| "github.com/openmeterio/openmeter/pkg/currencyx" | |
| "github.com/openmeterio/openmeter/pkg/models" | |
| ) | |
| func TestValidateTransactionInputEntryAmountPrecision(t *testing.T) { | |
| tests := []struct { | |
| name string | |
| currency currencyx.Code | |
| amount string | |
| wantErr bool | |
| }{ | |
| { | |
| name: "USD accepts cents", | |
| currency: currencyx.Code("USD"), | |
| amount: "10.01", | |
| }, | |
| { | |
| name: "USD rejects sub-cent amount", | |
| currency: currencyx.Code("USD"), | |
| amount: "10.001", | |
| wantErr: true, | |
| }, | |
| { | |
| name: "USD accepts negative cents", | |
| currency: currencyx.Code("USD"), | |
| amount: "-10.01", | |
| }, | |
| { | |
| name: "JPY accepts whole amount", | |
| currency: currencyx.Code("JPY"), | |
| amount: "10", | |
| }, | |
| { | |
| name: "JPY rejects fractional amount", | |
| currency: currencyx.Code("JPY"), | |
| amount: "10.1", | |
| wantErr: true, | |
| }, | |
| } | |
| for _, tt := range tests { | |
| t.Run(tt.name, func(t *testing.T) { | |
| amount := mustDecimal(t, tt.amount) | |
| address := mustPostingAddress(t, tt.currency) | |
| txInput := &testutils.AnyTransactionInput{ | |
| BookedAtValue: time.Now(), | |
| EntryInputsValues: []*testutils.AnyEntryInput{ | |
| { | |
| Address: address, | |
| AmountValue: amount, | |
| }, | |
| { | |
| Address: address, | |
| AmountValue: amount.Neg(), | |
| }, | |
| }, | |
| } | |
| err := ledger.ValidateTransactionInput(t.Context(), txInput) | |
| if !tt.wantErr { | |
| require.NoError(t, err) | |
| return | |
| } | |
| require.Error(t, err) | |
| require.ErrorIs(t, err, ledger.ErrTransactionAmountInvalid) | |
| issues, issueErr := models.AsValidationIssues(err) | |
| require.NoError(t, issueErr) | |
| require.Len(t, issues, 1) | |
| require.Equal(t, ledger.ErrCodeTransactionAmountInvalid, issues[0].Code()) | |
| attrs := issues[0].Attributes() | |
| require.Equal(t, "amount_not_rounded_to_currency_precision", attrs["reason"]) | |
| currencyCode, ok := (attrs["currency"]).(currencyx.Code) | |
| require.True(t, ok, "expected currency to be a currencyx.Code, got %T", attrs["currency"]) | |
| require.Equal(t, tt.currency, currencyCode) | |
| require.Equal(t, amount.String(), attrs["amount"]) | |
| require.NotEmpty(t, attrs["rounded_amount"]) | |
| }) | |
| } | |
| } | |
| func TestListTransactionsInputValidateRouteFilter(t *testing.T) { | |
| costBasis := alpacadecimal.NewFromFloat(0.7) | |
| taxCode := "vat" | |
| taxBehavior := ledger.TaxBehaviorInclusive | |
| creditPriority := 1 | |
| authStatus := ledger.TransactionAuthorizationStatusAuthorized | |
| tests := []struct { | |
| name string | |
| route ledger.RouteFilter | |
| wantErr bool | |
| }{ | |
| { | |
| name: "currency route filter is supported", | |
| route: ledger.RouteFilter{ | |
| Currency: currencyx.Code("USD"), | |
| }, | |
| }, | |
| { | |
| name: "exact features route filter is supported", | |
| route: ledger.RouteFilter{ | |
| Features: mo.Some([]string{"feature-a"}), | |
| }, | |
| }, | |
| { | |
| name: "match feature route filter is supported", | |
| route: ledger.RouteFilter{ | |
| MatchFeature: "feature-a", | |
| }, | |
| }, | |
| { | |
| name: "cost basis route filter is rejected", | |
| route: ledger.RouteFilter{ | |
| CostBasis: mo.Some(&costBasis), | |
| }, | |
| wantErr: true, | |
| }, | |
| { | |
| name: "tax code route filter is rejected", | |
| route: ledger.RouteFilter{ | |
| TaxCode: mo.Some(&taxCode), | |
| }, | |
| wantErr: true, | |
| }, | |
| { | |
| name: "tax behavior route filter is rejected", | |
| route: ledger.RouteFilter{ | |
| TaxBehavior: mo.Some(&taxBehavior), | |
| }, | |
| wantErr: true, | |
| }, | |
| { | |
| name: "credit priority route filter is rejected", | |
| route: ledger.RouteFilter{ | |
| CreditPriority: &creditPriority, | |
| }, | |
| wantErr: true, | |
| }, | |
| { | |
| name: "transaction authorization route filter is rejected", | |
| route: ledger.RouteFilter{ | |
| TransactionAuthorizationStatus: &authStatus, | |
| }, | |
| wantErr: true, | |
| }, | |
| { | |
| name: "exact features and match feature cannot be combined", | |
| route: ledger.RouteFilter{ | |
| Features: mo.Some([]string{"feature-a"}), | |
| MatchFeature: "feature-a", | |
| }, | |
| wantErr: true, | |
| }, | |
| } | |
| for _, tt := range tests { | |
| t.Run(tt.name, func(t *testing.T) { | |
| err := ledger.ListTransactionsInput{ | |
| Namespace: "ns-test", | |
| Limit: 1, | |
| Route: tt.route, | |
| }.Validate() | |
| if tt.wantErr { | |
| require.Error(t, err) | |
| require.ErrorIs(t, err, ledger.ErrListTransactionsInputInvalid) | |
| return | |
| } | |
| require.NoError(t, err) | |
| }) | |
| } | |
| } | |
| func mustPostingAddress(t *testing.T, currency currencyx.Code) ledger.PostingAddress { | |
| t.Helper() | |
| route := ledger.Route{Currency: currency} | |
| key, err := ledger.BuildRoutingKey(route) | |
| require.NoError(t, err) | |
| address, err := ledgeraccount.NewAddressFromData(ledgeraccount.AddressData{ | |
| SubAccountID: "sub_" + string(currency), | |
| AccountType: ledger.AccountTypeCustomerFBO, | |
| Route: route, | |
| RouteID: "route_" + string(currency), | |
| RoutingKey: key, | |
| }) | |
| require.NoError(t, err) | |
| return address | |
| } | |
| func mustDecimal(t *testing.T, raw string) alpacadecimal.Decimal { | |
| t.Helper() | |
| value, err := alpacadecimal.NewFromString(raw) | |
| require.NoError(t, err) | |
| return value | |
| } | |