Skip to content

Commit

Permalink
Merge pull request #82 from LucaBernstein/raise-test-cov
Browse files Browse the repository at this point in the history
Raise test coverage
  • Loading branch information
LucaBernstein authored Dec 27, 2021
2 parents 1696bde + b99ba3d commit 6d0fe97
Show file tree
Hide file tree
Showing 15 changed files with 887 additions and 27 deletions.
4 changes: 4 additions & 0 deletions bot/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,10 @@ func (bc *BotController) configHandleNotification(m *tb.Message, params ...strin
bc.configHelp(m, fmt.Errorf("error converting hour to number: %s: %s", params[1], err.Error()))
return
}
if hour > 23 || hour < 0 {
bc.configHelp(m, fmt.Errorf("invalid hour (%d is out of valid range 1-23)", hour))
return
}
err = bc.Repo.UserSetNotificationSetting(m, daysDelay, hour)
if err != nil {
bc.configHelp(m, fmt.Errorf("error setting notification schedule: %s", err.Error()))
Expand Down
120 changes: 107 additions & 13 deletions bot/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"log"
"strings"
"testing"
"time"

"github.com/DATA-DOG/go-sqlmock"
"github.com/LucaBernstein/beancount-bot-tg/db/crud"
Expand Down Expand Up @@ -85,19 +86,6 @@ func TestConfigTag(t *testing.T) {
log.Fatal(err)
}

mock. // SET
ExpectExec(`UPDATE "auth::user" SET "tag" = ?`).
WithArgs(chat.ID, "vacation2021").
WillReturnResult(sqlmock.NewResult(1, 1))
mock. // GET
ExpectQuery(`SELECT "tag" FROM "auth::user" WHERE "tgChatId" = ?`).
WithArgs(chat.ID).
WillReturnRows(sqlmock.NewRows([]string{"tag"}).AddRow("vacation2021"))
mock. // DELETE
ExpectExec(`UPDATE "auth::user" SET "tag" = NULL WHERE "tgChatId" = ?`).
WithArgs(chat.ID).
WillReturnResult(sqlmock.NewResult(1, 1))

bc := NewBotController(db)
bot := &MockBot{}
bc.AddBotAndStart(bot)
Expand All @@ -108,6 +96,10 @@ func TestConfigTag(t *testing.T) {
}

// SET tag
mock.
ExpectExec(`UPDATE "auth::user" SET "tag" = ?`).
WithArgs(chat.ID, "vacation2021").
WillReturnResult(sqlmock.NewResult(1, 1))
bc.commandConfig(&tb.Message{Text: "/config tag vacation2021", Chat: chat})
if strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "Usage help for /config") {
t.Errorf("/config tag vacation2021: %s", bot.LastSentWhat)
Expand All @@ -117,6 +109,10 @@ func TestConfigTag(t *testing.T) {
}

// GET tag
mock.
ExpectQuery(`SELECT "tag" FROM "auth::user" WHERE "tgChatId" = ?`).
WithArgs(chat.ID).
WillReturnRows(sqlmock.NewRows([]string{"tag"}).AddRow("vacation2021"))
bc.commandConfig(&tb.Message{Text: "/config tag", Chat: chat})
if strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "Usage help for /config") {
t.Errorf("/config tag: %s", bot.LastSentWhat)
Expand All @@ -125,7 +121,23 @@ func TestConfigTag(t *testing.T) {
t.Errorf("/config tag vacation2021 response did not contain set tag: %s", bot.LastSentWhat)
}

mock.
ExpectQuery(`SELECT "tag" FROM "auth::user" WHERE "tgChatId" = ?`).
WithArgs(chat.ID).
WillReturnRows(sqlmock.NewRows([]string{"tag"}).AddRow(nil))
bc.commandConfig(&tb.Message{Text: "/config tag", Chat: chat})
if strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "Usage help for /config") {
t.Errorf("/config tag: %s", bot.LastSentWhat)
}
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "disabled") {
t.Errorf("/config tag vacation2021 response did not contain set tag: %s", bot.LastSentWhat)
}

// DELETE tag
mock.
ExpectExec(`UPDATE "auth::user" SET "tag" = NULL WHERE "tgChatId" = ?`).
WithArgs(chat.ID).
WillReturnResult(sqlmock.NewResult(1, 1))
bc.commandConfig(&tb.Message{Text: "/config tag off", Chat: chat})
if strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "Usage help for /config") {
t.Errorf("/config tag off: %s", bot.LastSentWhat)
Expand All @@ -138,3 +150,85 @@ func TestConfigTag(t *testing.T) {
t.Errorf("there were unfulfilled expectations: %s", err)
}
}

func TestConfigHandleNotification(t *testing.T) {
// Test dependencies
crud.TEST_MODE = true
chat := &tb.Chat{ID: 12345}
db, mock, err := sqlmock.New()
if err != nil {
log.Fatal(err)
}
bc := NewBotController(db)

bot := &MockBot{}
bc.AddBotAndStart(bot)

tz, _ := time.Now().Zone()

mock.ExpectQuery(`SELECT "delayHours", "notificationHour" FROM "bot::notificationSchedule"`).
WithArgs(chat.ID).
WillReturnRows(sqlmock.NewRows([]string{"delayHours", "notificationHour"}))
bc.commandConfig(&tb.Message{Text: "/config notify", Chat: chat})
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "Notifications are disabled for open transactions") {
t.Errorf("Notifications should be disabled: %s", bot.LastSentWhat)
}

mock.ExpectQuery(`SELECT "delayHours", "notificationHour" FROM "bot::notificationSchedule"`).
WithArgs(chat.ID).
WillReturnRows(sqlmock.NewRows([]string{"delayHours", "notificationHour"}).AddRow(24, 18))
bc.commandConfig(&tb.Message{Text: "/config notify", Chat: chat})
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat),
"The bot will notify you daily at hour 18 ("+tz+") if transactions are open for more than 1 day") {
t.Errorf("Notifications should be disabled: %s", bot.LastSentWhat)
}

bc.commandConfig(&tb.Message{Text: "/config notify 17", Chat: chat})
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "invalid parameter") {
t.Errorf("Single number as param should not be allowed: %s", bot.LastSentWhat)
}

mock.ExpectExec(`DELETE FROM "bot::notificationSchedule"`).WithArgs(chat.ID).WillReturnResult(sqlmock.NewResult(1, 1))
bc.commandConfig(&tb.Message{Text: "/config notify off", Chat: chat})
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "Successfully disabled notifications") {
t.Errorf("Single param should be allowed for 'off' to disable notifications: %s", bot.LastSentWhat)
}

mock.ExpectExec(`DELETE FROM "bot::notificationSchedule"`).WithArgs(chat.ID).WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectExec(`INSERT INTO "bot::notificationSchedule"`).WithArgs(chat.ID, 4*24, 23).WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectQuery(`SELECT "delayHours", "notificationHour" FROM "bot::notificationSchedule"`).
WithArgs(chat.ID).
WillReturnRows(sqlmock.NewRows([]string{"delayHours", "notificationHour"}).AddRow(4*24, 23))
bc.commandConfig(&tb.Message{Text: "/config notify 4 23", Chat: chat})
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat),
"The bot will notify you daily at hour 23 ("+tz+") if transactions are open for more than 4 days") {
t.Errorf("Should successfully set notification: %s", bot.LastSentWhat)
}

// Invalid hour (0-23)
bc.commandConfig(&tb.Message{Text: "/config notify 4 24", Chat: chat})
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat),
"invalid hour (24 is out of valid range 1-23)") {
t.Errorf("Out of bounds notification hour: %s", bot.LastSentWhat)
}

if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("there were unfulfilled expectations: %s", err)
}
}

func TestConfigAbout(t *testing.T) {
// Test dependencies
crud.TEST_MODE = true
chat := &tb.Chat{ID: 12345}
bc := NewBotController(nil)

bot := &MockBot{}
bc.AddBotAndStart(bot)

bc.commandConfig(&tb.Message{Text: "/config about", Chat: chat})
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat),
"LucaBernstein/beancount\\-bot\\-tg") {
t.Errorf("Should contain repo link: %s", bot.LastSentWhat)
}
}
54 changes: 54 additions & 0 deletions bot/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,57 @@ func stringArr(i []interface{}) []string {
}
return arr
}

func TestCommandStartHelp(t *testing.T) {
crud.TEST_MODE = true
chat := &tb.Chat{ID: 12345}
db, mock, err := sqlmock.New()
if err != nil {
log.Fatal(err)
}

bc := NewBotController(db)
bot := &MockBot{}
bc.AddBotAndStart(bot)

mock.
ExpectQuery(`SELECT "isAdmin" FROM "auth::user"`).
WithArgs(chat.ID).
WillReturnRows(sqlmock.NewRows([]string{"isAdmin"}).AddRow(false))
bc.commandStart(&tb.Message{Chat: chat})

if !strings.Contains(fmt.Sprintf("%v", bot.AllLastSentWhat[0]), "Welcome") {
t.Errorf("Bot should welcome user first")
}
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "/help - List this command help") {
t.Errorf("Bot should send help message as well")
}
if strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "admin_") {
t.Errorf("Bot should not send admin commands in help message for default user")
}

// Admin check
mock.
ExpectQuery(`SELECT "isAdmin" FROM "auth::user"`).
WithArgs(chat.ID).
WillReturnRows(sqlmock.NewRows([]string{"isAdmin"}).AddRow(true))
bc.commandHelp(&tb.Message{Chat: chat})
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "admin_") {
t.Errorf("Bot should send admin commands in help message for admin user")
}

if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("there were unfulfilled expectations: %s", err)
}
}

func TestCommandCancel(t *testing.T) {
chat := &tb.Chat{ID: 12345}
bc := NewBotController(nil)
bot := &MockBot{}
bc.AddBotAndStart(bot)
bc.commandCancel(&tb.Message{Chat: chat})
if !strings.Contains(fmt.Sprintf("%v", bot.LastSentWhat), "no active transactions open to cancel") {
t.Errorf("Unexpectedly there were open tx before")
}
}
4 changes: 2 additions & 2 deletions db/crud/auth_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (r *Repo) EnrichUserData(m *tb.Message) error {
}
// Check whether some changeable attributes differ
if ce.TgUsername != m.Sender.Username {
LogDbf(r, helpers.TRACE, m, "Updating attributes of user in table 'auth::user'")
LogDbf(r, helpers.TRACE, m, "Updating attributes of user in table 'auth::user' (%s, %s)", ce.TgUsername, m.Sender.Username)
_, err := r.db.Exec(`UPDATE "auth::user" SET "tgUserId" = $2, "tgUsername" = $3 WHERE "tgChatId" = $1`, tgChatId, tgUserId, tgUsername)
return err
}
Expand Down Expand Up @@ -166,7 +166,7 @@ func (r *Repo) IndividualsWithNotifications(chatId string) (recipients []string)
defer rows.Close()

var rec string
if rows.Next() {
for rows.Next() {
err = rows.Scan(&rec)
if err != nil {
LogDbf(r, helpers.ERROR, nil, "Encountered error while scanning into var: %s", err.Error())
Expand Down
Loading

0 comments on commit 6d0fe97

Please sign in to comment.