From b85b14cddd204a89563cdc74645dc9778df1e2c2 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 09:12:00 +0200 Subject: [PATCH 01/18] user tests --- internal/database/user_test.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 internal/database/user_test.go diff --git a/internal/database/user_test.go b/internal/database/user_test.go new file mode 100644 index 0000000..1627a87 --- /dev/null +++ b/internal/database/user_test.go @@ -0,0 +1,24 @@ +package database + +import ( + "testing" + "time" +) + +func TestIsActive(t *testing.T) { + yesterday := time.Now().AddDate(0, 0, -1) + + user := User{ + Timestamp: &yesterday, + } + if !user.IsActive() { + t.Error("Expected user to be active, got inactive") + } + + tenDaysAgo := time.Now().AddDate(0, 0, -10) + user.Timestamp = &tenDaysAgo + + if user.IsActive() { + t.Error("Expected user to be inactive, got active") + } +} From 518aac21581863bdf29ed80922362c8e30c40aaf Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 09:14:27 +0200 Subject: [PATCH 02/18] clean up --- internal/app/account.go | 3 --- internal/app/vars.go | 4 +++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/app/account.go b/internal/app/account.go index 68deb8d..07b73e3 100644 --- a/internal/app/account.go +++ b/internal/app/account.go @@ -9,11 +9,8 @@ import ( "github.com/capymind/internal/botservice" "github.com/capymind/internal/database" - "github.com/capymind/third_party/googledrive" ) -var fileStorage googledrive.GoogleDrive - func handleDownloadData(session *Session) { sendMessage("download_all_notes_waiting", session) diff --git a/internal/app/vars.go b/internal/app/vars.go index 82eb15d..7bec174 100644 --- a/internal/app/vars.go +++ b/internal/app/vars.go @@ -2,6 +2,7 @@ package app import ( "github.com/capymind/third_party/firestore" + "github.com/capymind/third_party/googledrive" "github.com/capymind/third_party/openai" "github.com/capymind/third_party/telegram" ) @@ -9,9 +10,10 @@ import ( var bot telegram.Telegram var aiService openai.OpenAI -// Use Firestore for the database var db firestore.Firestore var userStorage firestore.UserStorage var noteStorage firestore.NoteStorage var adminStorage firestore.AdminStorage var feedbackStorage firestore.FeedbackStorage + +var fileStorage googledrive.GoogleDrive From 18f23e48c3245639db1a2e642d55569d7cbe8a66 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 09:18:45 +0200 Subject: [PATCH 03/18] refactoring --- internal/app/account.go | 5 +++-- internal/app/session.go | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/internal/app/account.go b/internal/app/account.go index 07b73e3..9418b91 100644 --- a/internal/app/account.go +++ b/internal/app/account.go @@ -9,9 +9,10 @@ import ( "github.com/capymind/internal/botservice" "github.com/capymind/internal/database" + "github.com/capymind/internal/filestorage" ) -func handleDownloadData(session *Session) { +func handleDownloadData(session *Session, noteStorage database.NoteStorage, fileStorage filestorage.FileStorage) { sendMessage("download_all_notes_waiting", session) userID := session.User.ID @@ -85,7 +86,7 @@ func handleDeleteAccount(session *Session) { setOutputTextWithButtons("delete_account_are_you_sure", []botservice.BotResultTextButton{deleteButton}, session) } -func handleForceDeleteAccount(session *Session) { +func handleForceDeleteAccount(session *Session, noteStorage database.NoteStorage, userStorage database.UserStorage) { sendMessage("delete_account_waiting", session) // Delete all notes diff --git a/internal/app/session.go b/internal/app/session.go index 1090bc2..8e23edb 100644 --- a/internal/app/session.go +++ b/internal/app/session.go @@ -90,11 +90,11 @@ func handleSession(session *Session) { case NoteCount: handleNoteCount(session) case DownloadData: - handleDownloadData(session) + handleDownloadData(session, noteStorage, fileStorage) case DeleteAccount: handleDeleteAccount(session) case ForceDeleteAccount: - handleForceDeleteAccount(session) + handleForceDeleteAccount(session, noteStorage, userStorage) case TotalUserCount: handleTotalUserCount(session) case TotalActiveUserCount: From 85c9e407738cd5d2ce8d6e14481f39dc578f9002 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 09:24:00 +0200 Subject: [PATCH 04/18] zip func test --- internal/app/account_test.go | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 internal/app/account_test.go diff --git a/internal/app/account_test.go b/internal/app/account_test.go new file mode 100644 index 0000000..41bf63b --- /dev/null +++ b/internal/app/account_test.go @@ -0,0 +1,37 @@ +package app + +import ( + "os" + "testing" + + "github.com/capymind/internal/database" +) + +func TestCreateZipFile(t *testing.T) { + userID := "123" + + note1 := database.Note{ + Text: "Test note 1", + } + note2 := database.Note{ + Text: "Test note 2", + } + notes := []database.Note{note1, note2} + + zipFile, err := createZipFile(userID, notes) + + if err != nil { + t.Error("Expected nil error, got", err) + } + + if zipFile == nil { + t.Error("Expected zip file, got nil") + } + // Check if the file name starts with notes_123 + if zipFile.Name()[:9] != "notes_123" { + t.Error("Expected file name notes_123, got", zipFile.Name()) + } + + os.Remove(zipFile.Name()) + zipFile.Close() +} From 8e513342fa6623fa6dcb82a1045cd4f7629afc54 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 09:35:56 +0200 Subject: [PATCH 05/18] mocks --- internal/app/account_test.go | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/internal/app/account_test.go b/internal/app/account_test.go index 41bf63b..96fb698 100644 --- a/internal/app/account_test.go +++ b/internal/app/account_test.go @@ -1,12 +1,69 @@ package app import ( + "context" "os" "testing" "github.com/capymind/internal/database" ) +type NoteStorageMock struct{} + +func (storage NoteStorageMock) NewNote(ctx *context.Context, user database.User, note database.Note) error { + return nil +} + +func (storage NoteStorageMock) LastNote(ctx *context.Context, userID string) (*database.Note, error) { + note := database.Note{ + Text: "Test note", + } + return ¬e, nil +} + +func (storage NoteStorageMock) GetNotesForLastWeek(ctx *context.Context, userID string) ([]database.Note, error) { + note1 := database.Note{ + Text: "Test note", + } + note2 := database.Note{ + Text: "Test note 2", + } + notes := []database.Note{note1, note2} + return notes, nil +} + +func (storage NoteStorageMock) GetNotes(ctx *context.Context, userID string, count int) ([]database.Note, error) { + note3 := database.Note{ + Text: "Test note 3", + } + note4 := database.Note{ + Text: "Test note 4", + } + notes := []database.Note{note3, note4} + return notes, nil +} + +func (storage NoteStorageMock) GetAllNotes(ctx *context.Context, userID string) ([]database.Note, error) { + note5 := database.Note{ + Text: "Test note 5", + } + note6 := database.Note{ + Text: "Test note 6", + } + notes := []database.Note{note5, note6} + return notes, nil +} + +func (storage NoteStorageMock) NotesCount(ctx *context.Context, userID string) (int64, error) { + return 10, nil +} + +func (storage NoteStorageMock) DeleteAllNotes(ctx *context.Context, userID string) error { + return nil +} + +type UserStorageMock struct{} + func TestCreateZipFile(t *testing.T) { userID := "123" From e4578995edb47f239898ce769add30b0186a2e73 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 09:43:33 +0200 Subject: [PATCH 06/18] mocks folder --- internal/analysis/analysis_test.go | 22 +++++----------------- internal/mocks/aiservice_mock.go | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 17 deletions(-) create mode 100644 internal/mocks/aiservice_mock.go diff --git a/internal/analysis/analysis_test.go b/internal/analysis/analysis_test.go index 050910c..215869d 100644 --- a/internal/analysis/analysis_test.go +++ b/internal/analysis/analysis_test.go @@ -4,24 +4,12 @@ import ( "context" "testing" + "github.com/capymind/internal/mocks" "github.com/capymind/internal/translator" ) -type validServiceMock struct{} - -func (service validServiceMock) Request(name string, description string, systemPrompt string, userPrompt string, ctx *context.Context) *string { - response := "valid response" - return &response -} - -type invalidServiceMock struct{} - -func (service invalidServiceMock) Request(name string, description string, systemPrompt string, userPrompt string, ctx *context.Context) *string { - return nil -} - func TestValidAnalysis(t *testing.T) { - service := validServiceMock{} + service := mocks.ValidAIServiceMock{} notes := []string{"note1", "note2", "note3"} ctx := context.Background() response := AnalyzeQuickly(service, notes, translator.EN, &ctx) @@ -31,7 +19,7 @@ func TestValidAnalysis(t *testing.T) { } func TestInvalidAnalysis(t *testing.T) { - service := invalidServiceMock{} + service := mocks.InvalidAIServiceMock{} notes := []string{"note1", "note2", "note3"} ctx := context.Background() response := AnalyzeQuickly(service, notes, translator.EN, &ctx) @@ -41,7 +29,7 @@ func TestInvalidAnalysis(t *testing.T) { } func TestAnalysisWithHeader(t *testing.T) { - service := validServiceMock{} + service := mocks.ValidAIServiceMock{} notes := []string{"note1", "note2", "note3"} ctx := context.Background() response := AnalyzeLastWeek(service, notes, translator.EN, &ctx) @@ -51,7 +39,7 @@ func TestAnalysisWithHeader(t *testing.T) { } func TestAnalyzeSleep(t *testing.T) { - service := validServiceMock{} + service := mocks.ValidAIServiceMock{} text := "I slept well last night" ctx := context.Background() response := AnalyzeSleep(service, text, translator.EN, &ctx) diff --git a/internal/mocks/aiservice_mock.go b/internal/mocks/aiservice_mock.go new file mode 100644 index 0000000..85143b3 --- /dev/null +++ b/internal/mocks/aiservice_mock.go @@ -0,0 +1,16 @@ +package mocks + +import "context" + +type ValidAIServiceMock struct{} + +func (service ValidAIServiceMock) Request(name string, description string, systemPrompt string, userPrompt string, ctx *context.Context) *string { + response := "valid response" + return &response +} + +type InvalidAIServiceMock struct{} + +func (service InvalidAIServiceMock) Request(name string, description string, systemPrompt string, userPrompt string, ctx *context.Context) *string { + return nil +} From 88c079f9a3378d131a75d6abf7d15e9c784312d5 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 09:49:04 +0200 Subject: [PATCH 07/18] mocks clean up --- internal/helpers/stats_test.go | 58 ++------------------------------- internal/mocks/admin_mock.go | 17 ++++++++++ internal/mocks/feedback_mock.go | 45 +++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 55 deletions(-) create mode 100644 internal/mocks/admin_mock.go create mode 100644 internal/mocks/feedback_mock.go diff --git a/internal/helpers/stats_test.go b/internal/helpers/stats_test.go index 1dd8526..67fe925 100644 --- a/internal/helpers/stats_test.go +++ b/internal/helpers/stats_test.go @@ -4,65 +4,13 @@ import ( "context" "testing" - "github.com/capymind/internal/database" + "github.com/capymind/internal/mocks" "github.com/capymind/internal/translator" ) -type adminStatsMock struct{} - -func (storage adminStatsMock) GetTotalUserCount(ctx *context.Context) (int64, error) { - return 100, nil -} - -func (storage adminStatsMock) GetActiveUserCount(ctx *context.Context) (int64, error) { - return 75, nil -} - -func (storage adminStatsMock) GetTotalNoteCount(ctx *context.Context) (int64, error) { - return 999, nil -} - -type feedbackStatsMock struct{} - -func (storage feedbackStatsMock) GetFeedbackForLastWeek(ctx *context.Context) ([]database.UserFeedback, error) { - var array []database.UserFeedback - - firstName := "John" - lastName := "Doe" - user := database.User{ - ID: "1", - FirstName: &firstName, - LastName: &lastName, - } - feedback1 := database.Feedback{ - Text: "Test feedback", - } - feedback2 := database.Feedback{ - Text: "Test feedback 2", - } - - userFeedback1 := database.UserFeedback{ - User: user, - Feedback: feedback1, - } - userFeedback2 := database.UserFeedback{ - User: user, - Feedback: feedback2, - } - - array = append(array, userFeedback1) - array = append(array, userFeedback2) - - return array, nil -} - -func (storage feedbackStatsMock) NewFeedback(ctx *context.Context, user database.User, feedback database.Feedback) error { - return nil -} - func TestGetStats(t *testing.T) { - adminStorage := adminStatsMock{} - feedbackStorage := feedbackStatsMock{} + adminStorage := mocks.AdminStorageMock{} + feedbackStorage := mocks.FeedbackStorageMock{} context := context.Background() stats := GetStats(&context, translator.EN, adminStorage, feedbackStorage) diff --git a/internal/mocks/admin_mock.go b/internal/mocks/admin_mock.go new file mode 100644 index 0000000..b2c0dbf --- /dev/null +++ b/internal/mocks/admin_mock.go @@ -0,0 +1,17 @@ +package mocks + +import "context" + +type AdminStorageMock struct{} + +func (storage AdminStorageMock) GetTotalUserCount(ctx *context.Context) (int64, error) { + return 100, nil +} + +func (storage AdminStorageMock) GetActiveUserCount(ctx *context.Context) (int64, error) { + return 75, nil +} + +func (storage AdminStorageMock) GetTotalNoteCount(ctx *context.Context) (int64, error) { + return 999, nil +} diff --git a/internal/mocks/feedback_mock.go b/internal/mocks/feedback_mock.go new file mode 100644 index 0000000..8842175 --- /dev/null +++ b/internal/mocks/feedback_mock.go @@ -0,0 +1,45 @@ +package mocks + +import ( + "context" + + "github.com/capymind/internal/database" +) + +type FeedbackStorageMock struct{} + +func (storage FeedbackStorageMock) GetFeedbackForLastWeek(ctx *context.Context) ([]database.UserFeedback, error) { + var array []database.UserFeedback + + firstName := "John" + lastName := "Doe" + user := database.User{ + ID: "1", + FirstName: &firstName, + LastName: &lastName, + } + feedback1 := database.Feedback{ + Text: "Test feedback", + } + feedback2 := database.Feedback{ + Text: "Test feedback 2", + } + + userFeedback1 := database.UserFeedback{ + User: user, + Feedback: feedback1, + } + userFeedback2 := database.UserFeedback{ + User: user, + Feedback: feedback2, + } + + array = append(array, userFeedback1) + array = append(array, userFeedback2) + + return array, nil +} + +func (storage FeedbackStorageMock) NewFeedback(ctx *context.Context, user database.User, feedback database.Feedback) error { + return nil +} From c767e884a518dda2af0f518c6bf97f8b9fca28ac Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 09:56:50 +0200 Subject: [PATCH 08/18] new mocks --- internal/app/account_test.go | 57 ---------------------------- internal/mocks/filestorage_mock.go | 16 ++++++++ internal/mocks/note_mock.go | 61 ++++++++++++++++++++++++++++++ internal/mocks/user_mock.go | 50 ++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 57 deletions(-) create mode 100644 internal/mocks/filestorage_mock.go create mode 100644 internal/mocks/note_mock.go create mode 100644 internal/mocks/user_mock.go diff --git a/internal/app/account_test.go b/internal/app/account_test.go index 96fb698..41bf63b 100644 --- a/internal/app/account_test.go +++ b/internal/app/account_test.go @@ -1,69 +1,12 @@ package app import ( - "context" "os" "testing" "github.com/capymind/internal/database" ) -type NoteStorageMock struct{} - -func (storage NoteStorageMock) NewNote(ctx *context.Context, user database.User, note database.Note) error { - return nil -} - -func (storage NoteStorageMock) LastNote(ctx *context.Context, userID string) (*database.Note, error) { - note := database.Note{ - Text: "Test note", - } - return ¬e, nil -} - -func (storage NoteStorageMock) GetNotesForLastWeek(ctx *context.Context, userID string) ([]database.Note, error) { - note1 := database.Note{ - Text: "Test note", - } - note2 := database.Note{ - Text: "Test note 2", - } - notes := []database.Note{note1, note2} - return notes, nil -} - -func (storage NoteStorageMock) GetNotes(ctx *context.Context, userID string, count int) ([]database.Note, error) { - note3 := database.Note{ - Text: "Test note 3", - } - note4 := database.Note{ - Text: "Test note 4", - } - notes := []database.Note{note3, note4} - return notes, nil -} - -func (storage NoteStorageMock) GetAllNotes(ctx *context.Context, userID string) ([]database.Note, error) { - note5 := database.Note{ - Text: "Test note 5", - } - note6 := database.Note{ - Text: "Test note 6", - } - notes := []database.Note{note5, note6} - return notes, nil -} - -func (storage NoteStorageMock) NotesCount(ctx *context.Context, userID string) (int64, error) { - return 10, nil -} - -func (storage NoteStorageMock) DeleteAllNotes(ctx *context.Context, userID string) error { - return nil -} - -type UserStorageMock struct{} - func TestCreateZipFile(t *testing.T) { userID := "123" diff --git a/internal/mocks/filestorage_mock.go b/internal/mocks/filestorage_mock.go new file mode 100644 index 0000000..4a4c68e --- /dev/null +++ b/internal/mocks/filestorage_mock.go @@ -0,0 +1,16 @@ +package mocks + +import "time" + +type ValidFileStorageMock struct{} + +func (googleDrive ValidFileStorageMock) Upload(title string, filePath string, expirationDate time.Time) *string { + string := "link" + return &string +} + +type InvalidFileStorageMock struct{} + +func (googleDrive InvalidFileStorageMock) Upload(title string, filePath string, expirationDate time.Time) *string { + return nil +} diff --git a/internal/mocks/note_mock.go b/internal/mocks/note_mock.go new file mode 100644 index 0000000..3d5d61d --- /dev/null +++ b/internal/mocks/note_mock.go @@ -0,0 +1,61 @@ +package mocks + +import ( + "context" + + "github.com/capymind/internal/database" +) + +type NoteStorageMock struct{} + +func (storage NoteStorageMock) NewNote(ctx *context.Context, user database.User, note database.Note) error { + return nil +} + +func (storage NoteStorageMock) LastNote(ctx *context.Context, userID string) (*database.Note, error) { + note := database.Note{ + Text: "Test note", + } + return ¬e, nil +} + +func (storage NoteStorageMock) GetNotesForLastWeek(ctx *context.Context, userID string) ([]database.Note, error) { + note1 := database.Note{ + Text: "Test note", + } + note2 := database.Note{ + Text: "Test note 2", + } + notes := []database.Note{note1, note2} + return notes, nil +} + +func (storage NoteStorageMock) GetNotes(ctx *context.Context, userID string, count int) ([]database.Note, error) { + note3 := database.Note{ + Text: "Test note 3", + } + note4 := database.Note{ + Text: "Test note 4", + } + notes := []database.Note{note3, note4} + return notes, nil +} + +func (storage NoteStorageMock) GetAllNotes(ctx *context.Context, userID string) ([]database.Note, error) { + note5 := database.Note{ + Text: "Test note 5", + } + note6 := database.Note{ + Text: "Test note 6", + } + notes := []database.Note{note5, note6} + return notes, nil +} + +func (storage NoteStorageMock) NotesCount(ctx *context.Context, userID string) (int64, error) { + return 10, nil +} + +func (storage NoteStorageMock) DeleteAllNotes(ctx *context.Context, userID string) error { + return nil +} diff --git a/internal/mocks/user_mock.go b/internal/mocks/user_mock.go new file mode 100644 index 0000000..999ef13 --- /dev/null +++ b/internal/mocks/user_mock.go @@ -0,0 +1,50 @@ +package mocks + +import ( + "context" + + "github.com/capymind/internal/database" +) + +type UserStorageMock struct{} + +func (storage UserStorageMock) GetUser(ctx *context.Context, userID string) (*database.User, error) { + firstName := "John" + lastName := "Doe" + user := database.User{ + ID: "1", + FirstName: &firstName, + LastName: &lastName, + } + return &user, nil +} + +func (storage UserStorageMock) SaveUser(ctx *context.Context, user database.User) error { + return nil +} + +func (storage UserStorageMock) DeleteUser(ctx *context.Context, userID string) error { + return nil +} + +func (storage UserStorageMock) ForEachUser(ctx *context.Context, callback func([]database.User) error) error { + firstName := "John" + lastName := "Doe" + user1 := database.User{ + ID: "1", + FirstName: &firstName, + LastName: &lastName, + } + + firstName = "Jane" + lastName = "Doe" + user2 := database.User{ + ID: "2", + FirstName: &firstName, + LastName: &lastName, + } + + callback([]database.User{user1, user2}) + + return nil +} From 0e2065ad6759074330ac0388eb619bb82258a6db Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 09:57:50 +0200 Subject: [PATCH 09/18] ignore --- internal/mocks/admin_mock.go | 2 ++ internal/mocks/aiservice_mock.go | 2 ++ internal/mocks/feedback_mock.go | 2 ++ internal/mocks/filestorage_mock.go | 2 ++ internal/mocks/note_mock.go | 2 ++ internal/mocks/user_mock.go | 2 ++ 6 files changed, 12 insertions(+) diff --git a/internal/mocks/admin_mock.go b/internal/mocks/admin_mock.go index b2c0dbf..43c8939 100644 --- a/internal/mocks/admin_mock.go +++ b/internal/mocks/admin_mock.go @@ -1,3 +1,5 @@ +//coverage:ignore file + package mocks import "context" diff --git a/internal/mocks/aiservice_mock.go b/internal/mocks/aiservice_mock.go index 85143b3..5ca4f37 100644 --- a/internal/mocks/aiservice_mock.go +++ b/internal/mocks/aiservice_mock.go @@ -1,3 +1,5 @@ +//coverage:ignore file + package mocks import "context" diff --git a/internal/mocks/feedback_mock.go b/internal/mocks/feedback_mock.go index 8842175..d5c35e9 100644 --- a/internal/mocks/feedback_mock.go +++ b/internal/mocks/feedback_mock.go @@ -1,3 +1,5 @@ +//coverage:ignore file + package mocks import ( diff --git a/internal/mocks/filestorage_mock.go b/internal/mocks/filestorage_mock.go index 4a4c68e..04a9c8f 100644 --- a/internal/mocks/filestorage_mock.go +++ b/internal/mocks/filestorage_mock.go @@ -1,3 +1,5 @@ +//coverage:ignore file + package mocks import "time" diff --git a/internal/mocks/note_mock.go b/internal/mocks/note_mock.go index 3d5d61d..3c8a6b2 100644 --- a/internal/mocks/note_mock.go +++ b/internal/mocks/note_mock.go @@ -1,3 +1,5 @@ +//coverage:ignore file + package mocks import ( diff --git a/internal/mocks/user_mock.go b/internal/mocks/user_mock.go index 999ef13..8032983 100644 --- a/internal/mocks/user_mock.go +++ b/internal/mocks/user_mock.go @@ -1,3 +1,5 @@ +//coverage:ignore file + package mocks import ( From 3c5ff23bb955855fa18ef6f4220435ee3ffd2642 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 10:10:06 +0200 Subject: [PATCH 10/18] account tests --- internal/app/account_test.go | 40 ++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/internal/app/account_test.go b/internal/app/account_test.go index 41bf63b..4650382 100644 --- a/internal/app/account_test.go +++ b/internal/app/account_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/capymind/internal/database" + "github.com/capymind/internal/mocks" ) func TestCreateZipFile(t *testing.T) { @@ -35,3 +36,42 @@ func TestCreateZipFile(t *testing.T) { os.Remove(zipFile.Name()) zipFile.Close() } + +func TestDownloadDataHandler(t *testing.T) { + session := createSession(&Job{Command: "/download"}, &database.User{}, nil) + noteStorage := mocks.NoteStorageMock{} + fileStorage := mocks.ValidFileStorageMock{} + + handleDownloadData(session, noteStorage, fileStorage) + + if session.Job.Output[0].TextID != "link" { + t.Error("Expected link, got nil") + } +} + +func TestDeleteAccountHandler(t *testing.T) { + session := createSession(&Job{Command: "/delete"}, &database.User{}, nil) + handleDeleteAccount(session) + + if session.Job.Output[0].TextID != "delete_account_are_you_sure" { + t.Error("Expected delete_account_confirm, got nil") + } + if session.Job.Output[0].Buttons[0].TextID != "delete_account_confirm" { + t.Error("Expected delete_account_are_you_sure, got nil") + } +} + +func TestForceDeleteAccountHandler(t *testing.T) { + session := createSession(&Job{Command: "/force_delete"}, &database.User{}, nil) + userStorage := mocks.UserStorageMock{} + noteStorage := mocks.NoteStorageMock{} + + handleForceDeleteAccount(session, noteStorage, userStorage) + + if session.Job.Output[0].TextID != "delete_account_success" { + t.Error("Expected delete_account_success, got nil") + } + if session.Job.Output[1].TextID != "delete_account_telegram_tip" { + t.Error("Expected delete_account_telegram_tip, got nil") + } +} From 594617670f7d4aa4b8292b8007984f1e1624d677 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 10:20:09 +0200 Subject: [PATCH 11/18] refactoring + tests --- internal/app/admin.go | 11 ++++++---- internal/app/admin_test.go | 41 ++++++++++++++++++++++++++++++++++++++ internal/app/session.go | 6 +++--- 3 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 internal/app/admin_test.go diff --git a/internal/app/admin.go b/internal/app/admin.go index 6298e8a..9ef6e71 100644 --- a/internal/app/admin.go +++ b/internal/app/admin.go @@ -1,22 +1,25 @@ package app -import "github.com/capymind/internal/helpers" +import ( + "github.com/capymind/internal/database" + "github.com/capymind/internal/helpers" +) -func handleTotalUserCount(session *Session) { +func handleTotalUserCount(session *Session, adminStorage database.AdminStorage) { message := helpers.GetTotalUserCount(session.Context, session.Locale(), adminStorage) if message != nil { setOutputText(*message, session) } } -func handleTotalActiveUserCount(session *Session) { +func handleTotalActiveUserCount(session *Session, adminStorage database.AdminStorage) { message := helpers.GetTotalActiveUserCount(session.Context, session.Locale(), adminStorage) if message != nil { setOutputText(*message, session) } } -func handleTotalNoteCount(session *Session) { +func handleTotalNoteCount(session *Session, adminStorage database.AdminStorage) { message := helpers.GetTotalNoteCount(session.Context, session.Locale(), adminStorage) if message != nil { setOutputText(*message, session) diff --git a/internal/app/admin_test.go b/internal/app/admin_test.go new file mode 100644 index 0000000..49a0f4f --- /dev/null +++ b/internal/app/admin_test.go @@ -0,0 +1,41 @@ +package app + +import ( + "testing" + + "github.com/capymind/internal/database" + "github.com/capymind/internal/mocks" +) + +func TestTotalUserCountHandler(t *testing.T) { + session := createSession(&Job{Command: "/total_user_count"}, &database.User{}, nil) + adminStorage := mocks.AdminStorageMock{} + + handleTotalUserCount(session, adminStorage) + + if session.Job.Output[0].TextID != "The total number of users is 100" { + t.Errorf("Expected The total number of users is 100, got %s", session.Job.Output[0].TextID) + } +} + +func TestTotalActiveUserCountHandler(t *testing.T) { + session := createSession(&Job{Command: "/total_active_user_count"}, &database.User{}, nil) + adminStorage := mocks.AdminStorageMock{} + + handleTotalActiveUserCount(session, adminStorage) + + if session.Job.Output[0].TextID != "The total number of active users is 75" { + t.Errorf("Expected The total number of active users is 75, got %s", session.Job.Output[0].TextID) + } +} + +func TestTotalNoteCountHandler(t *testing.T) { + session := createSession(&Job{Command: "/total_note_count"}, &database.User{}, nil) + adminStorage := mocks.AdminStorageMock{} + + handleTotalNoteCount(session, adminStorage) + + if session.Job.Output[0].TextID != "The total number of notes is 999" { + t.Errorf("Expected The total number of notes is 999, got %s", session.Job.Output[0].TextID) + } +} diff --git a/internal/app/session.go b/internal/app/session.go index 8e23edb..b663d7a 100644 --- a/internal/app/session.go +++ b/internal/app/session.go @@ -96,11 +96,11 @@ func handleSession(session *Session) { case ForceDeleteAccount: handleForceDeleteAccount(session, noteStorage, userStorage) case TotalUserCount: - handleTotalUserCount(session) + handleTotalUserCount(session, adminStorage) case TotalActiveUserCount: - handleTotalActiveUserCount(session) + handleTotalActiveUserCount(session, adminStorage) case TotalNoteCount: - handleTotalNoteCount(session) + handleTotalNoteCount(session, adminStorage) case Stats: handleStats(session) case FeedbackLastWeek: From 2dac3f7ddb25ce676d7061a402c36646f06292f9 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 10:27:58 +0200 Subject: [PATCH 12/18] refactoring --- internal/app/analysis.go | 6 ++++-- internal/app/notes.go | 2 +- internal/app/session.go | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/internal/app/analysis.go b/internal/app/analysis.go index 86ee6a3..e71229c 100644 --- a/internal/app/analysis.go +++ b/internal/app/analysis.go @@ -1,14 +1,16 @@ package app import ( + "github.com/capymind/internal/aiservice" "github.com/capymind/internal/analysis" "github.com/capymind/internal/botservice" + "github.com/capymind/internal/database" ) // Handle the analysis command -func handleAnalysis(session *Session) { +func handleAnalysis(session *Session, noteStorage database.NoteStorage, aiService aiservice.AIService) { // Get the user's notes - notes := getNotes(session, 5) + notes := getNotes(session, noteStorage, 5) if len(notes) > 0 { // Prepare the strings for analysis var strings []string diff --git a/internal/app/notes.go b/internal/app/notes.go index 10bb516..23ffe2e 100644 --- a/internal/app/notes.go +++ b/internal/app/notes.go @@ -84,7 +84,7 @@ func saveNote(text string, session *Session) { } // Get the user's notes -func getNotes(session *Session, count int) []database.Note { +func getNotes(session *Session, noteStorage database.NoteStorage, count int) []database.Note { notes, err := noteStorage.GetNotes(session.Context, session.User.ID, count) if err != nil { log.Printf("[Bot] Error getting notes from firestore, %s", err.Error()) diff --git a/internal/app/session.go b/internal/app/session.go index b663d7a..f757bd8 100644 --- a/internal/app/session.go +++ b/internal/app/session.go @@ -70,7 +70,7 @@ func handleSession(session *Session) { case Last: handleLastNote(session) case Analysis: - handleAnalysis(session) + handleAnalysis(session, noteStorage, aiService) case Settings: handleSettings(session) case Language: From b7e2399037605bf7add674457dce30f361e7c573 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 10:35:53 +0200 Subject: [PATCH 13/18] new tests --- internal/app/analysis_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 internal/app/analysis_test.go diff --git a/internal/app/analysis_test.go b/internal/app/analysis_test.go new file mode 100644 index 0000000..bcb703c --- /dev/null +++ b/internal/app/analysis_test.go @@ -0,0 +1,20 @@ +package app + +import ( + "testing" + + "github.com/capymind/internal/database" + "github.com/capymind/internal/mocks" +) + +func TestAnalysisHandler(t *testing.T) { + session := createSession(&Job{Command: "/analysis"}, &database.User{}, nil) + noteStorage := mocks.NoteStorageMock{} + aiService := mocks.ValidAIServiceMock{} + + handleAnalysis(session, noteStorage, aiService) + + if session.Job.Output[0].TextID != "valid response" { + t.Errorf("Expected valid response, got %s", session.Job.Output[0].TextID) + } +} From 5c9ffa9e65eba23cdb03d9401c8b53fdf6c70df4 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 10:42:15 +0200 Subject: [PATCH 14/18] new mock + new tests --- internal/app/analysis_test.go | 24 +++++++++++++++++++ internal/app/messaging.go | 2 ++ internal/mocks/empty_note_mock.go | 39 +++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 internal/mocks/empty_note_mock.go diff --git a/internal/app/analysis_test.go b/internal/app/analysis_test.go index bcb703c..7a56531 100644 --- a/internal/app/analysis_test.go +++ b/internal/app/analysis_test.go @@ -18,3 +18,27 @@ func TestAnalysisHandler(t *testing.T) { t.Errorf("Expected valid response, got %s", session.Job.Output[0].TextID) } } + +func TestAnalysisHandlerNoNotes(t *testing.T) { + session := createSession(&Job{Command: "/analysis"}, &database.User{}, nil) + noteStorage := mocks.EmptyNoteStorageMock{} + aiService := mocks.ValidAIServiceMock{} + + handleAnalysis(session, noteStorage, aiService) + + if session.Job.Output[0].TextID != "no_analysis" { + t.Errorf("Expected no_analysis, got %s", session.Job.Output[0].TextID) + } +} + +func TestAnalysisHandlerNoAIService(t *testing.T) { + session := createSession(&Job{Command: "/analysis"}, &database.User{}, nil) + noteStorage := mocks.NoteStorageMock{} + aiService := mocks.InvalidAIServiceMock{} + + handleAnalysis(session, noteStorage, aiService) + + if session.Job.Output[0].TextID != "no_analysis" { + t.Errorf("Expected no_analysis, got %s", session.Job.Output[0].TextID) + } +} diff --git a/internal/app/messaging.go b/internal/app/messaging.go index 43e3efd..e7f4cc5 100644 --- a/internal/app/messaging.go +++ b/internal/app/messaging.go @@ -46,6 +46,8 @@ func sendJobResult(jobResult botservice.BotResult, session *Session) { } // Send a message to the user (Immediately) +// +//coverage:ignore func sendMessage(textID string, session *Session) { locale := session.Locale() chatID := session.User.ChatID diff --git a/internal/mocks/empty_note_mock.go b/internal/mocks/empty_note_mock.go new file mode 100644 index 0000000..f4c47e1 --- /dev/null +++ b/internal/mocks/empty_note_mock.go @@ -0,0 +1,39 @@ +//coverage:ignore file + +package mocks + +import ( + "context" + + "github.com/capymind/internal/database" +) + +type EmptyNoteStorageMock struct{} + +func (storage EmptyNoteStorageMock) NewNote(ctx *context.Context, user database.User, note database.Note) error { + return nil +} + +func (storage EmptyNoteStorageMock) LastNote(ctx *context.Context, userID string) (*database.Note, error) { + return nil, nil +} + +func (storage EmptyNoteStorageMock) GetNotesForLastWeek(ctx *context.Context, userID string) ([]database.Note, error) { + return []database.Note{}, nil +} + +func (storage EmptyNoteStorageMock) GetNotes(ctx *context.Context, userID string, count int) ([]database.Note, error) { + return []database.Note{}, nil +} + +func (storage EmptyNoteStorageMock) GetAllNotes(ctx *context.Context, userID string) ([]database.Note, error) { + return []database.Note{}, nil +} + +func (storage EmptyNoteStorageMock) NotesCount(ctx *context.Context, userID string) (int64, error) { + return 0, nil +} + +func (storage EmptyNoteStorageMock) DeleteAllNotes(ctx *context.Context, userID string) error { + return nil +} From 6cf85dc9bafbc47116b97446957cbd2ae763a231 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 10:51:04 +0200 Subject: [PATCH 15/18] feedback tests --- internal/app/feedback.go | 7 +++++-- internal/app/feedback_test.go | 25 +++++++++++++++++++++++++ internal/app/session.go | 2 +- 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 internal/app/feedback_test.go diff --git a/internal/app/feedback.go b/internal/app/feedback.go index 8083df8..ad84cef 100644 --- a/internal/app/feedback.go +++ b/internal/app/feedback.go @@ -1,8 +1,11 @@ package app -import "github.com/capymind/internal/helpers" +import ( + "github.com/capymind/internal/database" + "github.com/capymind/internal/helpers" +) -func handleFeedbackLastWeek(session *Session) { +func handleFeedbackLastWeek(session *Session, feedbackStorage database.FeedbackStorage) { array := helpers.PrepareFeedback(session.Context, session.Locale(), feedbackStorage) for _, item := range array { setOutputText(item, session) diff --git a/internal/app/feedback_test.go b/internal/app/feedback_test.go new file mode 100644 index 0000000..c8662dd --- /dev/null +++ b/internal/app/feedback_test.go @@ -0,0 +1,25 @@ +package app + +import ( + "testing" + + "github.com/capymind/internal/database" + "github.com/capymind/internal/mocks" +) + +func TestFeedbackHandler(t *testing.T) { + session := createSession(&Job{Command: "/feedback"}, &database.User{}, nil) + feedbackStorage := mocks.FeedbackStorageMock{} + + handleFeedbackLastWeek(session, feedbackStorage) + + if len(session.Job.Output) != 11 { + t.Errorf("Expected 11 feedback items, got %d", len(session.Job.Output)) + } + if session.Job.Output[6].TextID != "\nTest feedback\n" { + t.Errorf("Expected Test feedback, got %s", session.Job.Output[0].TextID) + } + if session.Job.Output[10].TextID != "\nTest feedback 2\n" { + t.Errorf("Expected Test feedback 2, got %s", session.Job.Output[0].TextID) + } +} diff --git a/internal/app/session.go b/internal/app/session.go index f757bd8..55dac99 100644 --- a/internal/app/session.go +++ b/internal/app/session.go @@ -104,7 +104,7 @@ func handleSession(session *Session) { case Stats: handleStats(session) case FeedbackLastWeek: - handleFeedbackLastWeek(session) + handleFeedbackLastWeek(session, feedbackStorage) case None: // Typing mode if session.User.IsTyping && session.Job.Input != nil { From 8b61ebb3039fe4be4ef806d7731e6bc154c84d81 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 10:52:07 +0200 Subject: [PATCH 16/18] ignore --- internal/app/messaging.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/internal/app/messaging.go b/internal/app/messaging.go index e7f4cc5..6174af5 100644 --- a/internal/app/messaging.go +++ b/internal/app/messaging.go @@ -30,6 +30,8 @@ func setOutputTextWithButtons(textID string, buttons []botservice.BotResultTextB } // Send the output messages +// +//coverage:ignore func sendOutputMessages(session *Session) { if len(session.Job.Output) == 0 { return @@ -41,6 +43,8 @@ func sendOutputMessages(session *Session) { } // Send the output messages +// +//coverage:ignore func sendJobResult(jobResult botservice.BotResult, session *Session) { bot.SendResult(session.User.ChatID, jobResult) } From 584254045f24f22e988b6ddfb5a8e331ca525b65 Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 10:52:57 +0200 Subject: [PATCH 17/18] ignore --- internal/app/vars.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/app/vars.go b/internal/app/vars.go index 7bec174..a732c79 100644 --- a/internal/app/vars.go +++ b/internal/app/vars.go @@ -1,3 +1,5 @@ +//coverage:ignore file + package app import ( From babbcd798fe505e8f8c52196573439cff163071c Mon Sep 17 00:00:00 2001 From: Maksym Bilan <> Date: Mon, 30 Dec 2024 11:08:04 +0200 Subject: [PATCH 18/18] language handler tests --- internal/app/language_test.go | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 internal/app/language_test.go diff --git a/internal/app/language_test.go b/internal/app/language_test.go new file mode 100644 index 0000000..364f471 --- /dev/null +++ b/internal/app/language_test.go @@ -0,0 +1,57 @@ +package app + +import ( + "testing" + + "github.com/capymind/internal/database" +) + +func TestLanguageHandler(t *testing.T) { + session := createSession(&Job{Command: "/language"}, &database.User{}, nil) + handleLanguage(session) + + if session.Job.Output[0].TextID != "language_select" { + t.Errorf("Expected language_select, got %s", session.Job.Output[0].TextID) + } + if session.Job.Output[0].Buttons[0].TextID != "English 🇺🇸" { + t.Errorf("Expected French, got %s", session.Job.Output[0].Buttons[0].TextID) + } + if session.Job.Output[0].Buttons[1].TextID != "Українська 🇺🇦" { + t.Errorf("Expected Українська 🇺🇦, got %s", session.Job.Output[0].Buttons[1].TextID) + } +} + +func TestLanguageHandlerWithParameters(t *testing.T) { + session := createSession(&Job{Command: "/language", Parameters: []string{"uk"}}, &database.User{}, nil) + handleLanguage(session) + + if session.Job.Parameters[0] != "uk" { + t.Errorf("Expected uk, got %s", session.Job.Parameters[0]) + } + if *session.User.Locale != "uk" { + t.Errorf("Expected uk, got %s", *session.User.Locale) + } + + if session.Job.Output[0].TextID != "locale_set" { + t.Errorf("Expected locale_set, got %s", session.Job.Output[0].TextID) + } + if session.Job.Output[1].TextID != "timezone_select" { + t.Errorf("Expected timezone_select, got %d", len(session.Job.Output)) + } +} + +func TestLanguageHandlerWithParametersAndTimezone(t *testing.T) { + time := 123456789 + session := createSession(&Job{Command: "/language", Parameters: []string{"en"}}, &database.User{SecondsFromUTC: &time}, nil) + handleLanguage(session) + + if session.Job.Parameters[0] != "en" { + t.Errorf("Expected en, got %s", session.Job.Parameters[0]) + } + if *session.User.Locale != "en" { + t.Errorf("Expected en, got %s", *session.User.Locale) + } + if session.Job.Output[0].TextID != "locale_set" { + t.Errorf("Expected locale_set, got %s", session.Job.Output[0].TextID) + } +}