Implement integration-test based on YNAB-Export #46
13
.drone.yml
13
.drone.yml
@ -4,6 +4,11 @@ type: docker
|
|||||||
name: budgeteer
|
name: budgeteer
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: submodules
|
||||||
|
image: alpine/git
|
||||||
|
commands:
|
||||||
|
- git submodule update --recursive --init
|
||||||
|
|
||||||
- name: Taskfile.dev PR
|
- name: Taskfile.dev PR
|
||||||
image: hub.javil.eu/budgeteer:dev
|
image: hub.javil.eu/budgeteer:dev
|
||||||
commands:
|
commands:
|
||||||
@ -57,5 +62,13 @@ steps:
|
|||||||
event:
|
event:
|
||||||
- tag
|
- tag
|
||||||
|
|
||||||
|
services:
|
||||||
|
- name: db
|
||||||
|
image: postgres:alpine
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: budgeteer
|
||||||
|
POSTGRES_PASSWORD: budgeteer
|
||||||
|
POSTGRES_DB: budgeteer_test
|
||||||
|
|
||||||
image_pull_secrets:
|
image_pull_secrets:
|
||||||
- hub.javil.eu
|
- hub.javil.eu
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "testdata"]
|
||||||
|
path = testdata
|
||||||
|
url = https://git.javil.eu/jacob1123/budgeteer-testdata.git
|
@ -65,7 +65,13 @@ tasks:
|
|||||||
desc: Run CI build
|
desc: Run CI build
|
||||||
cmds:
|
cmds:
|
||||||
- task: build-prod
|
- task: build-prod
|
||||||
- go test ./...
|
- task: cover
|
||||||
|
|
||||||
|
cover:
|
||||||
|
desc: Run test and analyze coverage
|
||||||
|
cmds:
|
||||||
|
- go test ./... -coverprofile=coverage.out -covermode=atomic
|
||||||
|
- go tool cover -html=coverage.out -o=coverage.html
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
desc: Build vue frontend
|
desc: Build vue frontend
|
||||||
|
@ -2,7 +2,6 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
@ -11,24 +10,18 @@ import (
|
|||||||
"git.javil.eu/jacob1123/budgeteer/bcrypt"
|
"git.javil.eu/jacob1123/budgeteer/bcrypt"
|
||||||
"git.javil.eu/jacob1123/budgeteer/jwt"
|
"git.javil.eu/jacob1123/budgeteer/jwt"
|
||||||
"git.javil.eu/jacob1123/budgeteer/postgres"
|
"git.javil.eu/jacob1123/budgeteer/postgres"
|
||||||
txdb "github.com/DATA-DOG/go-txdb"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() { //nolint:gochecknoinits
|
func TestRegisterUser(t *testing.T) {
|
||||||
txdb.Register("pgtx", "pgx", "postgres://budgeteer_test:budgeteer_test@localhost:5432/budgeteer_test")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRegisterUser(t *testing.T) { //nolint:funlen
|
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
database, err := postgres.Connect("pgtx", "example")
|
database, err := postgres.Connect("pgtx", cfg.DatabaseConnection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("could not connect to db: %s\n", err)
|
t.Errorf("connect to DB: %v", err)
|
||||||
t.Skip()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenVerifier, _ := jwt.NewTokenVerifier("this_is_my_demo_secret_for_unit_tests")
|
tokenVerifier, _ := jwt.NewTokenVerifier(cfg.SessionSecret)
|
||||||
h := Handler{
|
h := Handler{
|
||||||
Service: database,
|
Service: database,
|
||||||
TokenVerifier: tokenVerifier,
|
TokenVerifier: tokenVerifier,
|
||||||
@ -66,22 +59,4 @@ func TestRegisterUser(t *testing.T) { //nolint:funlen
|
|||||||
t.Error("Did not get a token")
|
t.Error("Did not get a token")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("GetTransactions", func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
context.Request, err = http.NewRequest(http.MethodGet, "/account/accountid/transactions", nil)
|
|
||||||
if recorder.Code != http.StatusOK {
|
|
||||||
t.Errorf("handler returned wrong status code: got %v want %v", recorder.Code, http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
var response TransactionsResponse
|
|
||||||
err = json.NewDecoder(recorder.Body).Decode(&response)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err.Error())
|
|
||||||
t.Error("Error retreiving list of transactions.")
|
|
||||||
}
|
|
||||||
if len(response.Transactions) == 0 {
|
|
||||||
t.Error("Did not get any transactions.")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
@ -25,7 +26,6 @@ func getFirstOfMonthTime(date time.Time) time.Time {
|
|||||||
type CategoryWithBalance struct {
|
type CategoryWithBalance struct {
|
||||||
*postgres.GetCategoriesRow
|
*postgres.GetCategoriesRow
|
||||||
Available numeric.Numeric
|
Available numeric.Numeric
|
||||||
AvailableLastMonth numeric.Numeric
|
|
||||||
Activity numeric.Numeric
|
Activity numeric.Numeric
|
||||||
Assigned numeric.Numeric
|
Assigned numeric.Numeric
|
||||||
}
|
}
|
||||||
@ -34,7 +34,6 @@ func NewCategoryWithBalance(category *postgres.GetCategoriesRow) CategoryWithBal
|
|||||||
return CategoryWithBalance{
|
return CategoryWithBalance{
|
||||||
GetCategoriesRow: category,
|
GetCategoriesRow: category,
|
||||||
Available: numeric.Zero(),
|
Available: numeric.Zero(),
|
||||||
AvailableLastMonth: numeric.Zero(),
|
|
||||||
Activity: numeric.Zero(),
|
Activity: numeric.Zero(),
|
||||||
Assigned: numeric.Zero(),
|
Assigned: numeric.Zero(),
|
||||||
}
|
}
|
||||||
@ -56,46 +55,46 @@ func (h *Handler) budgetingForMonth(c *gin.Context) {
|
|||||||
|
|
||||||
firstOfMonth, err := getDate(c)
|
firstOfMonth, err := getDate(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Redirect(http.StatusTemporaryRedirect, "/budget/"+budgetUUID.String())
|
c.Redirect(http.StatusTemporaryRedirect, "/budget/"+budget.ID.String())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
categories, err := h.Service.GetCategories(c.Request.Context(), budgetUUID)
|
data, err := h.prepareBudgeting(c.Request.Context(), budget, firstOfMonth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
c.AbortWithError(http.StatusInternalServerError, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
c.JSON(http.StatusOK, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) prepareBudgeting(ctx context.Context, budget postgres.Budget, firstOfMonth time.Time) (BudgetingForMonthResponse, error) {
|
||||||
firstOfNextMonth := firstOfMonth.AddDate(0, 1, 0)
|
firstOfNextMonth := firstOfMonth.AddDate(0, 1, 0)
|
||||||
cumultativeBalances, err := h.Service.GetCumultativeBalances(c.Request.Context(), budgetUUID)
|
categories, err := h.Service.GetCategories(ctx, budget.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithStatusJSON(http.StatusInternalServerError, ErrorResponse{fmt.Sprintf("error loading balances: %s", err)})
|
return BudgetingForMonthResponse{}, fmt.Errorf("error loading categories: %w", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
categoriesWithBalance, moneyUsed := h.calculateBalances(
|
cumultativeBalances, err := h.Service.GetCumultativeBalances(ctx, budget.ID)
|
||||||
budget, firstOfNextMonth, firstOfMonth, categories, cumultativeBalances)
|
if err != nil {
|
||||||
availableBalance := h.getAvailableBalance(budget, moneyUsed, cumultativeBalances, firstOfNextMonth)
|
return BudgetingForMonthResponse{}, fmt.Errorf("error loading balances: %w", err)
|
||||||
for i := range categoriesWithBalance {
|
|
||||||
cat := &categoriesWithBalance[i]
|
|
||||||
if cat.ID != budget.IncomeCategoryID {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cat.Available = availableBalance
|
categoriesWithBalance, moneyUsed := h.calculateBalances(firstOfNextMonth, firstOfMonth, categories, cumultativeBalances)
|
||||||
cat.AvailableLastMonth = availableBalance
|
availableBalance := h.getAvailableBalance(budget, moneyUsed, cumultativeBalances, categoriesWithBalance, firstOfNextMonth)
|
||||||
|
|
||||||
|
data := BudgetingForMonthResponse{categoriesWithBalance, availableBalance}
|
||||||
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
data := struct {
|
type BudgetingForMonthResponse struct {
|
||||||
Categories []CategoryWithBalance
|
Categories []CategoryWithBalance
|
||||||
AvailableBalance numeric.Numeric
|
AvailableBalance numeric.Numeric
|
||||||
}{categoriesWithBalance, availableBalance}
|
|
||||||
c.JSON(http.StatusOK, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Handler) getAvailableBalance(budget postgres.Budget,
|
func (*Handler) getAvailableBalance(budget postgres.Budget,
|
||||||
moneyUsed numeric.Numeric, cumultativeBalances []postgres.GetCumultativeBalancesRow,
|
moneyUsed numeric.Numeric, cumultativeBalances []postgres.GetCumultativeBalancesRow,
|
||||||
firstOfNextMonth time.Time) numeric.Numeric {
|
categoriesWithBalance []CategoryWithBalance, firstOfNextMonth time.Time,
|
||||||
|
) numeric.Numeric {
|
||||||
availableBalance := moneyUsed
|
availableBalance := moneyUsed
|
||||||
|
|
||||||
for _, bal := range cumultativeBalances {
|
for _, bal := range cumultativeBalances {
|
||||||
@ -110,6 +109,15 @@ func (*Handler) getAvailableBalance(budget postgres.Budget,
|
|||||||
availableBalance.AddI(bal.Transactions)
|
availableBalance.AddI(bal.Transactions)
|
||||||
availableBalance.AddI(bal.Assignments)
|
availableBalance.AddI(bal.Assignments)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i := range categoriesWithBalance {
|
||||||
|
cat := &categoriesWithBalance[i]
|
||||||
|
if cat.ID != budget.IncomeCategoryID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cat.Available = availableBalance
|
||||||
|
}
|
||||||
return availableBalance
|
return availableBalance
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,28 +155,14 @@ func (h *Handler) returnBudgetingData(c *gin.Context, budgetUUID uuid.UUID) {
|
|||||||
c.JSON(http.StatusOK, data)
|
c.JSON(http.StatusOK, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) calculateBalances(budget postgres.Budget,
|
func (h *Handler) calculateBalances(firstOfNextMonth time.Time, firstOfMonth time.Time,
|
||||||
firstOfNextMonth time.Time, firstOfMonth time.Time, categories []postgres.GetCategoriesRow,
|
categories []postgres.GetCategoriesRow, cumultativeBalances []postgres.GetCumultativeBalancesRow,
|
||||||
cumultativeBalances []postgres.GetCumultativeBalancesRow) ([]CategoryWithBalance, numeric.Numeric) {
|
) ([]CategoryWithBalance, numeric.Numeric) {
|
||||||
categoriesWithBalance := []CategoryWithBalance{}
|
categoriesWithBalance := []CategoryWithBalance{}
|
||||||
|
|
||||||
moneyUsed2 := numeric.Zero()
|
moneyUsed := numeric.Zero()
|
||||||
moneyUsed := &moneyUsed2
|
|
||||||
for i := range categories {
|
for i := range categories {
|
||||||
cat := &categories[i]
|
cat := &categories[i]
|
||||||
// do not show hidden categories
|
|
||||||
categoryWithBalance := h.CalculateCategoryBalances(cat, cumultativeBalances,
|
|
||||||
firstOfNextMonth, moneyUsed, firstOfMonth, budget)
|
|
||||||
|
|
||||||
categoriesWithBalance = append(categoriesWithBalance, categoryWithBalance)
|
|
||||||
}
|
|
||||||
|
|
||||||
return categoriesWithBalance, *moneyUsed
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Handler) CalculateCategoryBalances(cat *postgres.GetCategoriesRow,
|
|
||||||
cumultativeBalances []postgres.GetCumultativeBalancesRow, firstOfNextMonth time.Time,
|
|
||||||
moneyUsed *numeric.Numeric, firstOfMonth time.Time, budget postgres.Budget) CategoryWithBalance {
|
|
||||||
categoryWithBalance := NewCategoryWithBalance(cat)
|
categoryWithBalance := NewCategoryWithBalance(cat)
|
||||||
for _, bal := range cumultativeBalances {
|
for _, bal := range cumultativeBalances {
|
||||||
if bal.CategoryID != cat.ID {
|
if bal.CategoryID != cat.ID {
|
||||||
@ -188,13 +182,14 @@ func (*Handler) CalculateCategoryBalances(cat *postgres.GetCategoriesRow,
|
|||||||
categoryWithBalance.Available = numeric.Zero()
|
categoryWithBalance.Available = numeric.Zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
if bal.Date.Before(firstOfMonth) {
|
if bal.Date.Year() == firstOfMonth.Year() && bal.Date.Month() == firstOfMonth.Month() {
|
||||||
categoryWithBalance.AvailableLastMonth = categoryWithBalance.Available
|
|
||||||
} else if bal.Date.Before(firstOfNextMonth) {
|
|
||||||
categoryWithBalance.Activity = bal.Transactions
|
categoryWithBalance.Activity = bal.Transactions
|
||||||
categoryWithBalance.Assigned = bal.Assignments
|
categoryWithBalance.Assigned = bal.Assignments
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return categoryWithBalance
|
categoriesWithBalance = append(categoriesWithBalance, categoryWithBalance)
|
||||||
|
}
|
||||||
|
|
||||||
|
return categoriesWithBalance, moneyUsed
|
||||||
}
|
}
|
||||||
|
226
server/main_test.go
Normal file
226
server/main_test.go
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.javil.eu/jacob1123/budgeteer/bcrypt"
|
||||||
|
"git.javil.eu/jacob1123/budgeteer/config"
|
||||||
|
"git.javil.eu/jacob1123/budgeteer/jwt"
|
||||||
|
"git.javil.eu/jacob1123/budgeteer/postgres"
|
||||||
|
"git.javil.eu/jacob1123/budgeteer/web"
|
||||||
|
|
||||||
|
txdb "github.com/DATA-DOG/go-txdb"
|
||||||
|
)
|
||||||
|
|
||||||
|
var cfg = config.Config{ //nolint:gochecknoglobals
|
||||||
|
DatabaseConnection: "postgres://budgeteer:budgeteer@db:5432/budgeteer_test",
|
||||||
|
SessionSecret: "this_is_my_demo_secret_for_unit_tests",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { //nolint:gochecknoinits
|
||||||
|
_, err := postgres.Connect("pgx", cfg.DatabaseConnection)
|
||||||
|
if err != nil {
|
||||||
|
panic("failed connecting to DB for migrations: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
txdb.Register("pgtx", "pgx", cfg.DatabaseConnection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMain(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
queries, err := postgres.Connect("pgtx", cfg.DatabaseConnection)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("connect to DB: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
static, err := fs.Sub(web.Static, "dist")
|
||||||
|
if err != nil {
|
||||||
|
panic("couldn't open static files")
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenVerifier, err := jwt.NewTokenVerifier(cfg.SessionSecret)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("couldn't create token verifier: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := &Handler{
|
||||||
|
Service: queries,
|
||||||
|
TokenVerifier: tokenVerifier,
|
||||||
|
CredentialsVerifier: &bcrypt.Verifier{},
|
||||||
|
StaticFS: http.FS(static),
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
createUserParams := postgres.CreateUserParams{
|
||||||
|
Email: "test@example.com",
|
||||||
|
Name: "test@example.com",
|
||||||
|
Password: "this is my dumb password",
|
||||||
|
}
|
||||||
|
user, err := handler.Service.CreateUser(ctx, createUserParams)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Fail()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
budget, err := handler.Service.NewBudget(ctx, "My nice Budget", user.ID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Fail()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.DoYNABImport(ctx, t, budget)
|
||||||
|
|
||||||
|
loc := time.Now().Location()
|
||||||
|
|
||||||
|
AssertCategoriesAndAvailableEqual(ctx, t, loc, handler, budget)
|
||||||
|
|
||||||
|
// check accounts
|
||||||
|
}
|
||||||
|
|
||||||
|
func AssertCategoriesAndAvailableEqual(ctx context.Context, t *testing.T, loc *time.Location, handler *Handler, budget *postgres.Budget) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
t.Run("Categories and available balance", func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
resultDir := "../testdata/production-export/results"
|
||||||
|
files, err := os.ReadDir(resultDir)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("could not load results: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
if file.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
name := file.Name()[0 : len(file.Name())-5]
|
||||||
|
parts := strings.Split(name, "-")
|
||||||
|
year, _ := strconv.Atoi(parts[0])
|
||||||
|
month, _ := strconv.Atoi(parts[1])
|
||||||
|
first := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, loc)
|
||||||
|
testCaseFile := filepath.Join(resultDir, file.Name())
|
||||||
|
handler.CheckAvailableBalance(ctx, t, testCaseFile, budget, first)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestData struct {
|
||||||
|
AvailableBalance float64
|
||||||
|
Categories map[string]CategoryTestData
|
||||||
|
}
|
||||||
|
|
||||||
|
type CategoryTestData struct {
|
||||||
|
Available float64
|
||||||
|
Activity float64
|
||||||
|
Assigned float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Handler) CheckAvailableBalance(ctx context.Context, t *testing.T, testCaseFile string, budget *postgres.Budget, first time.Time) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
t.Run(first.Format("2006-01"), func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
data, err := h.prepareBudgeting(ctx, *budget, first)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("prepare budgeting: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
testDataFile, err := os.Open(testCaseFile)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("could not load category test data: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var testData TestData
|
||||||
|
dec := json.NewDecoder(testDataFile)
|
||||||
|
err = dec.Decode(&testData)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("could not decode category test data: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEqual(t, testData.AvailableBalance, data.AvailableBalance.GetFloat64(), "available balance")
|
||||||
|
|
||||||
|
for categoryName, categoryTestData := range testData.Categories {
|
||||||
|
found := false
|
||||||
|
for _, category := range data.Categories {
|
||||||
|
name := category.Group + " : " + category.Name
|
||||||
|
|
||||||
|
if name == categoryName {
|
||||||
|
assertEqual(t, categoryTestData.Available, category.Available.GetFloat64(), "available for "+categoryName)
|
||||||
|
assertEqual(t, categoryTestData.Activity, category.Activity.GetFloat64(), "activity for "+categoryName)
|
||||||
|
assertEqual(t, categoryTestData.Assigned, category.Assigned.GetFloat64(), "assigned for "+categoryName)
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
t.Errorf("category " + categoryName + " was not found in result")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertEqual(t *testing.T, expected, actual float64, message string) {
|
||||||
|
t.Helper()
|
||||||
|
if expected == actual {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Errorf("%s: expected %f, got %f", message, expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Handler) DoYNABImport(ctx context.Context, t *testing.T, budget *postgres.Budget) {
|
||||||
|
t.Helper()
|
||||||
|
budgetID := budget.ID
|
||||||
|
ynab, err := postgres.NewYNABImport(ctx, h.Service.Queries, budgetID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Fail()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
transactions, err := os.Open("../testdata/production-export/Register.tsv")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Fail()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assignments, err := os.Open("../testdata/production-export/Budget.tsv")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Fail()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ynab.ImportTransactions(ctx, transactions)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Fail()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ynab.ImportAssignments(ctx, assignments)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
t.Fail()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
1
testdata
Submodule
1
testdata
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit b6eda7681f92c2c635555c392660cb69bec2a1ed
|
Loading…
x
Reference in New Issue
Block a user