From f22f86a2fb85d989f10548d9dda0e0c7f1b976ad Mon Sep 17 00:00:00 2001 From: alfred-mk Date: Thu, 3 Jul 2025 17:02:36 +0300 Subject: [PATCH] move PIN tests to pin_test.go --- handlers/application/menuhandler_test.go | 277 --------------------- handlers/application/pin_test.go | 293 +++++++++++++++++++++++ 2 files changed, 293 insertions(+), 277 deletions(-) create mode 100644 handlers/application/pin_test.go diff --git a/handlers/application/menuhandler_test.go b/handlers/application/menuhandler_test.go index 6161f41..83c23ce 100644 --- a/handlers/application/menuhandler_test.go +++ b/handlers/application/menuhandler_test.go @@ -621,67 +621,6 @@ func TestSaveGender(t *testing.T) { } } -func TestSaveTemporaryPin(t *testing.T) { - sessionId := "session123" - - ctx, userdatastore := InitializeTestStore(t) - ctx = context.WithValue(ctx, "SessionId", sessionId) - - _, logdb := InitializeTestLogdbStore(t) - logDb := store.LogDb{ - Db: logdb, - } - - fm, err := NewFlagManager(flagsPath) - if err != nil { - log.Fatal(err) - } - - flag_invalid_pin, _ := fm.GetFlag("flag_invalid_pin") - - // Create the MenuHandlers instance with the mock flag manager - h := &MenuHandlers{ - flagManager: fm, - userdataStore: userdatastore, - logDb: logDb, - } - - // Define test cases - tests := []struct { - name string - input []byte - expectedResult resource.Result - }{ - { - name: "Valid Pin entry", - input: []byte("1234"), - expectedResult: resource.Result{ - FlagReset: []uint32{flag_invalid_pin}, - }, - }, - { - name: "Invalid Pin entry", - input: []byte("12343"), - expectedResult: resource.Result{ - FlagSet: []uint32{flag_invalid_pin}, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Call the method - res, err := h.SaveTemporaryPin(ctx, "save_pin", tt.input) - - if err != nil { - t.Error(err) - } - // Assert that the Result FlagSet has the required flags after language switch - assert.Equal(t, res, tt.expectedResult, "Result should match expected result") - }) - } -} - func TestCheckIdentifier(t *testing.T) { sessionId := "session123" ctx, userdatastore := InitializeTestStore(t) @@ -2001,65 +1940,6 @@ func TestGetProfile(t *testing.T) { } } -func TestConfirmPinChange(t *testing.T) { - sessionId := "session123" - - mockState := state.NewState(16) - ctx, store := InitializeTestStore(t) - ctx = context.WithValue(ctx, "SessionId", sessionId) - - fm, _ := NewFlagManager(flagsPath) - flag_pin_mismatch, _ := fm.GetFlag("flag_pin_mismatch") - flag_account_pin_reset, _ := fm.GetFlag("flag_account_pin_reset") - - mockAccountService := new(mocks.MockAccountService) - h := &MenuHandlers{ - userdataStore: store, - flagManager: fm, - accountService: mockAccountService, - st: mockState, - } - - tests := []struct { - name string - input []byte - temporarypin string - expectedResult resource.Result - }{ - { - name: "Test with correct pin confirmation", - input: []byte("1234"), - temporarypin: "1234", - expectedResult: resource.Result{ - FlagReset: []uint32{flag_pin_mismatch, flag_account_pin_reset}, - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Hash the PIN - hashedPIN, err := pin.HashPIN(tt.temporarypin) - if err != nil { - logg.ErrorCtxf(ctx, "failed to hash temporaryPin", "error", err) - t.Fatal(err) - } - - // Set up the expected behavior of the mock - err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(hashedPIN)) - if err != nil { - t.Fatal(err) - } - - //Call the function under test - res, _ := h.ConfirmPinChange(ctx, "confirm_pin_change", tt.input) - - //Assert that the result set to content is what was expected - assert.Equal(t, res, tt.expectedResult, "Result should contain flags set according to user input") - - }) - } -} - func TestFetchCommunityBalance(t *testing.T) { // Define test data @@ -2371,56 +2251,6 @@ func TestGetVoucherDetails(t *testing.T) { assert.Equal(t, expectedResult, res) } -func TestCountIncorrectPINAttempts(t *testing.T) { - ctx, store := InitializeTestStore(t) - sessionId := "session123" - ctx = context.WithValue(ctx, "SessionId", sessionId) - attempts := uint8(2) - - h := &MenuHandlers{ - userdataStore: store, - } - err := store.WriteEntry(ctx, sessionId, storedb.DATA_INCORRECT_PIN_ATTEMPTS, []byte(strconv.Itoa(int(attempts)))) - if err != nil { - t.Logf(err.Error()) - } - err = h.incrementIncorrectPINAttempts(ctx, sessionId) - if err != nil { - t.Logf(err.Error()) - } - - attemptsAfterCount, err := store.ReadEntry(ctx, sessionId, storedb.DATA_INCORRECT_PIN_ATTEMPTS) - if err != nil { - t.Logf(err.Error()) - } - pinAttemptsValue, _ := strconv.ParseUint(string(attemptsAfterCount), 0, 64) - pinAttemptsCount := uint8(pinAttemptsValue) - expectedAttempts := attempts + 1 - assert.Equal(t, pinAttemptsCount, expectedAttempts) -} - -func TestResetIncorrectPINAttempts(t *testing.T) { - ctx, store := InitializeTestStore(t) - sessionId := "session123" - ctx = context.WithValue(ctx, "SessionId", sessionId) - - err := store.WriteEntry(ctx, sessionId, storedb.DATA_INCORRECT_PIN_ATTEMPTS, []byte(string("2"))) - if err != nil { - t.Logf(err.Error()) - } - - h := &MenuHandlers{ - userdataStore: store, - } - h.resetIncorrectPINAttempts(ctx, sessionId) - incorrectAttempts, err := store.ReadEntry(ctx, sessionId, storedb.DATA_INCORRECT_PIN_ATTEMPTS) - - if err != nil { - t.Logf(err.Error()) - } - assert.Equal(t, "0", string(incorrectAttempts)) -} - func TestPersistLanguageCode(t *testing.T) { ctx, store := InitializeTestStore(t) @@ -2955,80 +2785,6 @@ func TestShowBlockedAccount(t *testing.T) { } } -func TestValidateBlockedNumber(t *testing.T) { - sessionId := "session123" - validNumber := "+254712345678" - invalidNumber := "12343" // Invalid phone number - unregisteredNumber := "+254734567890" // Valid but unregistered number - publicKey := "0X13242618721" - mockState := state.NewState(128) - - ctx, userStore := InitializeTestStore(t) - ctx = context.WithValue(ctx, "SessionId", sessionId) - - fm, err := NewFlagManager(flagsPath) - if err != nil { - t.Fatal(err) - } - flag_unregistered_number, _ := fm.GetFlag("flag_unregistered_number") - - h := &MenuHandlers{ - userdataStore: userStore, - st: mockState, - flagManager: fm, - } - - err = userStore.WriteEntry(ctx, validNumber, storedb.DATA_PUBLIC_KEY, []byte(publicKey)) - if err != nil { - t.Fatal(err) - } - - tests := []struct { - name string - input []byte - expectedResult resource.Result - }{ - { - name: "Valid and registered number", - input: []byte(validNumber), - expectedResult: resource.Result{}, - }, - { - name: "Invalid Phone Number", - input: []byte(invalidNumber), - expectedResult: resource.Result{ - FlagSet: []uint32{flag_unregistered_number}, - }, - }, - { - name: "Unregistered Phone Number", - input: []byte(unregisteredNumber), - expectedResult: resource.Result{ - FlagSet: []uint32{flag_unregistered_number}, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - res, err := h.ValidateBlockedNumber(ctx, "validate_blocked_number", tt.input) - - assert.NoError(t, err) - - assert.Equal(t, tt.expectedResult, res) - - if tt.name == "Valid and registered number" { - blockedNumber, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_BLOCKED_NUMBER) - if err != nil { - t.Fatal(err) - } - - assert.Equal(t, validNumber, string(blockedNumber)) - } - }) - } -} - func TestGetCurrentProfileInfo(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) @@ -3152,39 +2908,6 @@ func TestGetCurrentProfileInfo(t *testing.T) { } } -func TestResetOthersPin(t *testing.T) { - sessionId := "session123" - blockedNumber := "+254712345678" - testPin := "1234" - - ctx, userStore := InitializeTestStore(t) - ctx = context.WithValue(ctx, "SessionId", sessionId) - - hashedPIN, err := pin.HashPIN(testPin) - if err != nil { - logg.ErrorCtxf(ctx, "failed to hash testPin", "error", err) - t.Fatal(err) - } - - h := &MenuHandlers{ - userdataStore: userStore, - } - - // Write initial data to the store - err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_BLOCKED_NUMBER, []byte(blockedNumber)) - if err != nil { - t.Fatal(err) - } - err = userStore.WriteEntry(ctx, blockedNumber, storedb.DATA_TEMPORARY_VALUE, []byte(hashedPIN)) - if err != nil { - t.Fatal(err) - } - - _, err = h.ResetOthersPin(ctx, "reset_others_pin", []byte("")) - - assert.NoError(t, err) -} - func TestResetUnregisteredNumber(t *testing.T) { ctx := context.Background() diff --git a/handlers/application/pin_test.go b/handlers/application/pin_test.go new file mode 100644 index 0000000..4079aa9 --- /dev/null +++ b/handlers/application/pin_test.go @@ -0,0 +1,293 @@ +package application + +import ( + "context" + "log" + "strconv" + "testing" + + "git.defalsify.org/vise.git/resource" + "git.defalsify.org/vise.git/state" + "git.grassecon.net/grassrootseconomics/common/pin" + "git.grassecon.net/grassrootseconomics/sarafu-api/testutil/mocks" + "git.grassecon.net/grassrootseconomics/sarafu-vise/store" + storedb "git.grassecon.net/grassrootseconomics/sarafu-vise/store/db" + "github.com/alecthomas/assert/v2" +) + +func TestCountIncorrectPINAttempts(t *testing.T) { + ctx, store := InitializeTestStore(t) + sessionId := "session123" + ctx = context.WithValue(ctx, "SessionId", sessionId) + attempts := uint8(2) + + h := &MenuHandlers{ + userdataStore: store, + } + err := store.WriteEntry(ctx, sessionId, storedb.DATA_INCORRECT_PIN_ATTEMPTS, []byte(strconv.Itoa(int(attempts)))) + if err != nil { + t.Logf(err.Error()) + } + err = h.incrementIncorrectPINAttempts(ctx, sessionId) + if err != nil { + t.Logf(err.Error()) + } + + attemptsAfterCount, err := store.ReadEntry(ctx, sessionId, storedb.DATA_INCORRECT_PIN_ATTEMPTS) + if err != nil { + t.Logf(err.Error()) + } + pinAttemptsValue, _ := strconv.ParseUint(string(attemptsAfterCount), 0, 64) + pinAttemptsCount := uint8(pinAttemptsValue) + expectedAttempts := attempts + 1 + assert.Equal(t, pinAttemptsCount, expectedAttempts) +} + +func TestResetIncorrectPINAttempts(t *testing.T) { + ctx, store := InitializeTestStore(t) + sessionId := "session123" + ctx = context.WithValue(ctx, "SessionId", sessionId) + + err := store.WriteEntry(ctx, sessionId, storedb.DATA_INCORRECT_PIN_ATTEMPTS, []byte(string("2"))) + if err != nil { + t.Logf(err.Error()) + } + + h := &MenuHandlers{ + userdataStore: store, + } + h.resetIncorrectPINAttempts(ctx, sessionId) + incorrectAttempts, err := store.ReadEntry(ctx, sessionId, storedb.DATA_INCORRECT_PIN_ATTEMPTS) + + if err != nil { + t.Logf(err.Error()) + } + assert.Equal(t, "0", string(incorrectAttempts)) +} + +func TestSaveTemporaryPin(t *testing.T) { + sessionId := "session123" + + ctx, userdatastore := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + _, logdb := InitializeTestLogdbStore(t) + logDb := store.LogDb{ + Db: logdb, + } + + fm, err := NewFlagManager(flagsPath) + if err != nil { + log.Fatal(err) + } + + flag_invalid_pin, _ := fm.GetFlag("flag_invalid_pin") + + // Create the MenuHandlers instance with the mock flag manager + h := &MenuHandlers{ + flagManager: fm, + userdataStore: userdatastore, + logDb: logDb, + } + + // Define test cases + tests := []struct { + name string + input []byte + expectedResult resource.Result + }{ + { + name: "Valid Pin entry", + input: []byte("1234"), + expectedResult: resource.Result{ + FlagReset: []uint32{flag_invalid_pin}, + }, + }, + { + name: "Invalid Pin entry", + input: []byte("12343"), + expectedResult: resource.Result{ + FlagSet: []uint32{flag_invalid_pin}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Call the method + res, err := h.SaveTemporaryPin(ctx, "save_pin", tt.input) + + if err != nil { + t.Error(err) + } + // Assert that the Result FlagSet has the required flags after language switch + assert.Equal(t, res, tt.expectedResult, "Result should match expected result") + }) + } +} + +func TestConfirmPinChange(t *testing.T) { + sessionId := "session123" + + mockState := state.NewState(16) + ctx, store := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, _ := NewFlagManager(flagsPath) + flag_pin_mismatch, _ := fm.GetFlag("flag_pin_mismatch") + flag_account_pin_reset, _ := fm.GetFlag("flag_account_pin_reset") + + mockAccountService := new(mocks.MockAccountService) + h := &MenuHandlers{ + userdataStore: store, + flagManager: fm, + accountService: mockAccountService, + st: mockState, + } + + tests := []struct { + name string + input []byte + temporarypin string + expectedResult resource.Result + }{ + { + name: "Test with correct pin confirmation", + input: []byte("1234"), + temporarypin: "1234", + expectedResult: resource.Result{ + FlagReset: []uint32{flag_pin_mismatch, flag_account_pin_reset}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Hash the PIN + hashedPIN, err := pin.HashPIN(tt.temporarypin) + if err != nil { + logg.ErrorCtxf(ctx, "failed to hash temporaryPin", "error", err) + t.Fatal(err) + } + + // Set up the expected behavior of the mock + err = store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(hashedPIN)) + if err != nil { + t.Fatal(err) + } + + //Call the function under test + res, _ := h.ConfirmPinChange(ctx, "confirm_pin_change", tt.input) + + //Assert that the result set to content is what was expected + assert.Equal(t, res, tt.expectedResult, "Result should contain flags set according to user input") + + }) + } +} + +func TestValidateBlockedNumber(t *testing.T) { + sessionId := "session123" + validNumber := "+254712345678" + invalidNumber := "12343" // Invalid phone number + unregisteredNumber := "+254734567890" // Valid but unregistered number + publicKey := "0X13242618721" + mockState := state.NewState(128) + + ctx, userStore := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + fm, err := NewFlagManager(flagsPath) + if err != nil { + t.Fatal(err) + } + flag_unregistered_number, _ := fm.GetFlag("flag_unregistered_number") + + h := &MenuHandlers{ + userdataStore: userStore, + st: mockState, + flagManager: fm, + } + + err = userStore.WriteEntry(ctx, validNumber, storedb.DATA_PUBLIC_KEY, []byte(publicKey)) + if err != nil { + t.Fatal(err) + } + + tests := []struct { + name string + input []byte + expectedResult resource.Result + }{ + { + name: "Valid and registered number", + input: []byte(validNumber), + expectedResult: resource.Result{}, + }, + { + name: "Invalid Phone Number", + input: []byte(invalidNumber), + expectedResult: resource.Result{ + FlagSet: []uint32{flag_unregistered_number}, + }, + }, + { + name: "Unregistered Phone Number", + input: []byte(unregisteredNumber), + expectedResult: resource.Result{ + FlagSet: []uint32{flag_unregistered_number}, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res, err := h.ValidateBlockedNumber(ctx, "validate_blocked_number", tt.input) + + assert.NoError(t, err) + + assert.Equal(t, tt.expectedResult, res) + + if tt.name == "Valid and registered number" { + blockedNumber, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_BLOCKED_NUMBER) + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, validNumber, string(blockedNumber)) + } + }) + } +} + +func TestResetOthersPin(t *testing.T) { + sessionId := "session123" + blockedNumber := "+254712345678" + testPin := "1234" + + ctx, userStore := InitializeTestStore(t) + ctx = context.WithValue(ctx, "SessionId", sessionId) + + hashedPIN, err := pin.HashPIN(testPin) + if err != nil { + logg.ErrorCtxf(ctx, "failed to hash testPin", "error", err) + t.Fatal(err) + } + + h := &MenuHandlers{ + userdataStore: userStore, + } + + // Write initial data to the store + err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_BLOCKED_NUMBER, []byte(blockedNumber)) + if err != nil { + t.Fatal(err) + } + err = userStore.WriteEntry(ctx, blockedNumber, storedb.DATA_TEMPORARY_VALUE, []byte(hashedPIN)) + if err != nil { + t.Fatal(err) + } + + _, err = h.ResetOthersPin(ctx, "reset_others_pin", []byte("")) + + assert.NoError(t, err) +}