From b06b409cd548939fb0abf59fffdadb7be3377012 Mon Sep 17 00:00:00 2001 From: Aaron Lindsay Date: Mon, 20 Nov 2017 21:14:34 -0500 Subject: [PATCH] Add initial gnucash importing test This is woefully incomplete, but tests to make sure at least one balance on one account is correct... --- internal/handlers/gnucash_test.go | 103 ++++++++++++++++++ .../handlers_testdata/example.gnucash | Bin 0 -> 4858 bytes 2 files changed, 103 insertions(+) create mode 100644 internal/handlers/gnucash_test.go create mode 100644 internal/handlers/handlers_testdata/example.gnucash diff --git a/internal/handlers/gnucash_test.go b/internal/handlers/gnucash_test.go new file mode 100644 index 0000000..86501ea --- /dev/null +++ b/internal/handlers/gnucash_test.go @@ -0,0 +1,103 @@ +package handlers_test + +import ( + "bytes" + "github.com/aclindsa/moneygo/internal/handlers" + "io" + "io/ioutil" + "mime/multipart" + "net/http" + "os" + "testing" +) + +func importGnucash(client *http.Client, filename string) error { + var buf bytes.Buffer + mw := multipart.NewWriter(&buf) + + file, err := os.Open(filename) + if err != nil { + return err + } + defer file.Close() + + filewriter, err := mw.CreateFormFile("gnucash", filename) + if err != nil { + return err + } + if _, err := io.Copy(filewriter, file); err != nil { + return err + } + + mw.Close() + + response, err := client.Post(server.URL+"/v1/imports/gnucash", mw.FormDataContentType(), &buf) + if err != nil { + return err + } + + body, err := ioutil.ReadAll(response.Body) + response.Body.Close() + if err != nil { + return err + } + + var e handlers.Error + err = (&e).Read(string(body)) + if err != nil { + return err + } + if e.ErrorId != 0 || len(e.ErrorString) != 0 { + return &e + } + + return nil +} + +func TestImportGnucash(t *testing.T) { + RunWith(t, &data[0], func(t *testing.T, d *TestData) { + // Ensure there's only one USD currency + oldDefault, err := getSecurity(d.clients[0], d.users[0].DefaultCurrency) + if err != nil { + t.Fatalf("Error fetching default security: %s\n", err) + } + d.users[0].DefaultCurrency = d.securities[0].SecurityId + if _, err := updateUser(d.clients[0], &d.users[0]); err != nil { + t.Fatalf("Error updating user: %s\n", err) + } + if err := deleteSecurity(d.clients[0], oldDefault); err != nil { + t.Fatalf("Error removing default security: %s\n", err) + } + + // Import and ensure it didn't return a nasty error code + if err = importGnucash(d.clients[0], "handlers_testdata/example.gnucash"); err != nil { + t.Fatalf("Error importing from Gnucash: %s\n", err) + } + + // Next, find the Expenses/Groceries account + var groceries *handlers.Account + accounts, err := getAccounts(d.clients[0]) + if err != nil { + t.Fatalf("Error fetching accounts: %s\n", err) + } + for _, account := range *accounts.Accounts { + if account.Name == "Groceries" { + groceries = &account + break + } + } + if groceries == nil { + t.Fatalf("Couldn't find 'Expenses/Groceries' account") + } + + grocerytransactions, err := getAccountTransactions(d.clients[0], groceries.AccountId, 0, 0, "") + if err != nil { + t.Fatalf("Couldn't fetch account transactions for 'Expenses/Groceries': %s\n", err) + } + + // 87.19 from preexisting transactions and 200.37 from Gnucash + if grocerytransactions.EndingBalance != "287.56" { + t.Errorf("Expected ending balance for 'Expenses/Groceries' to be '287.56', but found %s\n", grocerytransactions.EndingBalance) + } + }) +} diff --git a/internal/handlers/handlers_testdata/example.gnucash b/internal/handlers/handlers_testdata/example.gnucash new file mode 100644 index 0000000000000000000000000000000000000000..f6097e1d35e598d8ece340d585561f8b97b776a1 GIT binary patch literal 4858 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 literal 0 HcmV?d00001