summary history files

internal/cli/account_test.go
package cli

import (
	"context"
	"database/sql"
	"encoding/json"
	"gt/internal/store"
	"os"
	"testing"
)

func TestAccountCmd(t *testing.T) {
	c := &cli{}
	_, err := executeCommand(accountCmd(c), "")
	if err != nil {
		t.Fatal(err)
	}
}

func TestGetAccountCmd(t *testing.T) {
	var err error
	ctx := context.Background()

	f, _ := os.CreateTemp("", "testdb-*.sqlite")
	dsn := f.Name()
	f.Close()
	defer os.Remove(dsn)

	db, err := sql.Open("sqlite3", dsn)
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()

	if err = createTestingTables(ctx, db, t); err != nil {
		t.Fatal(err)
	}

	if _, err = db.ExecContext(ctx,
		"INSERT INTO accounts (guid, name, account_type, parent_guid, commodity_scu, non_std_scu) VALUES (?, ?, ?, ?, ?, ?)",
		"2",
		"test1",
		"EXPENSE",
		"EXPENSESGUID",
		100,
		100); err != nil {
		t.Fatal(err)
	}

	c := &cli{db: db}
	out, err := executeCommand(getAccountCmd(c), "2", "--output", "json")
	if err != nil {
		t.Fatal(err)
	}

	var resp store.Account
	if err := json.Unmarshal([]byte(out), &resp); err != nil {
		t.Fatal(err)
	}

	if resp.Name != "test1" {
		t.Fatalf("expected test1 but got %s", resp.Name)
	}

	out, err = executeCommand(getAccountCmd(c), "expenses:test1", "--output", "json")
	if err != nil {
		t.Fatal(err)
	}

	if err := json.Unmarshal([]byte(out), &resp); err != nil {
		t.Fatal(err)
	}

	if resp.Name != "test1" {
		t.Fatalf("expected test1 but got %s", resp.Name)
	}
}

func TestListAccountCmd(t *testing.T) {
	ctx := context.Background()

	f, _ := os.CreateTemp("", "testdb-*.sqlite")
	dsn := f.Name()
	f.Close()
	defer os.Remove(dsn)

	db, err := sql.Open("sqlite3", dsn)
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()

	if err = createTestingTables(ctx, db, t); err != nil {
		t.Fatal(err)
	}

	accounts := []struct {
		GUID        string
		Name        string
		AccountType string
	}{
		{GUID: "1", Name: "test1", AccountType: "EXPENSE"},
		{GUID: "2", Name: "test2", AccountType: "EXPENSE"},
	}

	for _, account := range accounts {
		_, err := db.ExecContext(ctx,
			"INSERT INTO accounts (guid, name, account_type, commodity_scu, non_std_scu) VALUES (?, ?, ?, ?, ?)",
			account.GUID,
			account.Name,
			account.AccountType,
			100,
			100,
		)
		if err != nil {
			t.Fatal(err)
		}
	}

	c := &cli{db: db}

	out, err := executeCommand(listAccountCmd(c), "--output", "json")
	if err != nil {
		t.Fatal(err)
	}

	var resp []store.Account
	if err := json.Unmarshal([]byte(out), &resp); err != nil {
		t.Fatal(err)
	}

	if len(resp) != len(accounts)+2 {
		t.Fatalf("expected lenth of %d but got %d", len(resp), len(accounts)+2)
	}

	for _, i := range accounts {
		exists := false
		for _, ii := range resp {
			if i.Name == ii.Name && i.GUID == ii.GUID {
				exists = true
				break
			}
		}
		if !exists {
			t.Fatal()
		}
	}
}

func TestUpdateAccountCmd(t *testing.T) {
	t.Run("no args", func(t *testing.T) {
		ctx := context.Background()

		f, _ := os.CreateTemp("", "testdb-*.sqlite")
		dsn := f.Name()
		f.Close()
		defer os.Remove(dsn)

		db, err := sql.Open("sqlite3", dsn)
		if err != nil {
			t.Fatal(err)
		}

		if err = createTestingTables(ctx, db, t); err != nil {
			t.Fatal(err)
		}

		c := &cli{db: db}

		_, err = executeCommand(updateAccountCmd(c), "does-not-exist", "--output", "json")
		if err != ErrAccountDoesNotExist {
			t.Fatalf("expected ErrAccountMissing error but received %v", err)
		}
	})

	t.Run("account already exists", func(t *testing.T) {
		ctx := context.Background()

		f, _ := os.CreateTemp("", "testdb-*.sqlite")
		dsn := f.Name()
		f.Close()
		defer os.Remove(dsn)

		db, err := sql.Open("sqlite3", dsn)
		if err != nil {
			t.Fatal(err)
		}

		if err = createTestingTables(ctx, db, t); err != nil {
			t.Fatal(err)
		}

		accounts := []struct {
			GUID        string
			Name        string
			AccountType string
			ParentGUID  string
		}{
			{GUID: "1", Name: "test1", AccountType: "EXPENSE", ParentGUID: "EXPENSESGUID"},
			{GUID: "2", Name: "test2", AccountType: "EXPENSE", ParentGUID: "EXPENSESGUID"},
		}

		for _, account := range accounts {
			_, err := db.ExecContext(ctx,
				"INSERT INTO accounts (guid, name, account_type, commodity_scu, non_std_scu, parent_guid) VALUES (?, ?, ?, ?, ?, ?)",
				account.GUID,
				account.Name,
				account.AccountType,
				100,
				100,
				account.ParentGUID,
			)
			if err != nil {
				t.Fatal(err)
			}
		}

		c := &cli{db: db}
		_, err = executeCommand(updateAccountCmd(c), "expenses:test1", "--name", "test2")
		if err != ErrAccountAlreadyExists {
			t.Fatalf("expecting ErrAccountAlreadyExists err but received %v", err)
		}
	})

	t.Run("update account", func(t *testing.T) {
		var err error
		ctx := context.Background()

		f, _ := os.CreateTemp("", "testdb-*.sqlite")
		dsn := f.Name()
		f.Close()
		defer os.Remove(dsn)

		db, err := sql.Open("sqlite3", dsn)
		if err != nil {
			t.Fatal(err)
		}

		if err = createTestingTables(ctx, db, t); err != nil {
			t.Fatal(err)
		}

		if _, err = db.ExecContext(ctx,
			"INSERT INTO accounts (guid, name, account_type, parent_guid, commodity_scu, non_std_scu) VALUES (?, ?, ?, ?, ?, ?)",
			"2",
			"test1",
			"EXPENSE",
			"EXPENSESGUID",
			100,
			100); err != nil {
			t.Fatal(err)
		}

		c := &cli{db: db}

		out, err := executeCommand(updateAccountCmd(c), "expenses:test1", "--name=test2", "--description=test-2", "--output=json")
		if err != nil {
			t.Fatal(err)
		}

		var resp store.Account
		if err := json.Unmarshal([]byte(out), &resp); err != nil {
			t.Fatal(err)
		}

		if resp.Name != "test2" {
			t.Fatalf("expected name test2 but got %s", resp.Name)
		}

		if *resp.Description != "test-2" {
			t.Fatalf("expected description test-2 but got %s", resp.Name)
		}
	})
}