package application import ( "context" "fmt" "testing" "git.defalsify.org/vise.git/resource" "git.grassecon.net/grassrootseconomics/sarafu-api/models" "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" dataserviceapi "github.com/grassrootseconomics/ussd-data-service/pkg/api" ) func TestManageVouchers(t *testing.T) { sessionId := "session123" publicKey := "0X13242618721" ctx, userStore := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) _, logdb := InitializeTestLogdbStore(t) logDb := store.LogDb{ Db: logdb, } fm, err := NewFlagManager(flagsPath) if err != nil { t.Fatal(err) } flag_no_active_voucher, err := fm.GetFlag("flag_no_active_voucher") if err != nil { t.Fatal(err) } flag_api_error, err := fm.GetFlag("flag_api_call_error") if err != nil { t.Fatal(err) } err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_PUBLIC_KEY, []byte(publicKey)) if err != nil { t.Fatal(err) } tests := []struct { name string vouchersResp []dataserviceapi.TokenHoldings storedActiveVoucher string expectedVoucherSymbols []byte expectedUpdatedAddress []byte expectedResult resource.Result }{ { name: "No vouchers available", vouchersResp: []dataserviceapi.TokenHoldings{}, expectedVoucherSymbols: []byte(""), expectedUpdatedAddress: []byte(""), expectedResult: resource.Result{ FlagSet: []uint32{flag_no_active_voucher}, FlagReset: []uint32{flag_api_error}, }, }, { name: "Set default voucher when no active voucher is set", vouchersResp: []dataserviceapi.TokenHoldings{ { TokenAddress: "0x123", TokenSymbol: "TOKEN1", TokenDecimals: "18", Balance: "100", }, }, expectedVoucherSymbols: []byte("1:TOKEN1"), expectedUpdatedAddress: []byte("0x123"), expectedResult: resource.Result{ FlagReset: []uint32{flag_api_error, flag_no_active_voucher}, }, }, { name: "Check and update active voucher balance", vouchersResp: []dataserviceapi.TokenHoldings{ {TokenAddress: "0xd4c288865Ce", TokenSymbol: "SRF", TokenDecimals: "6", Balance: "100"}, {TokenAddress: "0x41c188d63Qa", TokenSymbol: "MILO", TokenDecimals: "4", Balance: "200"}, }, storedActiveVoucher: "SRF", expectedVoucherSymbols: []byte("1:SRF\n2:MILO"), expectedUpdatedAddress: []byte("0xd4c288865Ce"), expectedResult: resource.Result{ FlagReset: []uint32{flag_api_error, flag_no_active_voucher}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mockAccountService := new(mocks.MockAccountService) h := &MenuHandlers{ userdataStore: userStore, accountService: mockAccountService, flagManager: fm, logDb: logDb, } mockAccountService.On("FetchVouchers", string(publicKey)).Return(tt.vouchersResp, nil) // Store active voucher if needed if tt.storedActiveVoucher != "" { err := userStore.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_SYM, []byte(tt.storedActiveVoucher)) if err != nil { t.Fatal(err) } err = userStore.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_ADDRESS, []byte("0x41c188D45rfg6ds")) if err != nil { t.Fatal(err) } } res, err := h.ManageVouchers(ctx, "manage_vouchers", []byte("")) assert.NoError(t, err) assert.Equal(t, tt.expectedResult, res) if tt.storedActiveVoucher != "" { // Validate stored voucher symbols voucherData, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_VOUCHER_SYMBOLS) assert.NoError(t, err) assert.Equal(t, tt.expectedVoucherSymbols, voucherData) // Validate stored active contract address updatedAddress, err := userStore.ReadEntry(ctx, sessionId, storedb.DATA_ACTIVE_ADDRESS) assert.NoError(t, err) assert.Equal(t, tt.expectedUpdatedAddress, updatedAddress) mockAccountService.AssertExpectations(t) } }) } } func TestGetVoucherList(t *testing.T) { sessionId := "session123" ctx, store := InitializeTestStore(t) ctx = context.WithValue(ctx, "SessionId", sessionId) // Initialize MenuHandlers h := &MenuHandlers{ userdataStore: store, ReplaceSeparatorFunc: mockReplaceSeparator, } mockSymbols := []byte("1:SRF\n2:MILO") mockBalances := []byte("1:10.099999\n2:40.7") // Put voucher symnols and balances data to the store err := store.WriteEntry(ctx, sessionId, storedb.DATA_VOUCHER_SYMBOLS, mockSymbols) if err != nil { t.Fatal(err) } err = store.WriteEntry(ctx, sessionId, storedb.DATA_VOUCHER_BALANCES, mockBalances) if err != nil { t.Fatal(err) } expectedList := []byte("1: SRF 10.09\n2: MILO 40.70") res, err := h.GetVoucherList(ctx, "", []byte("")) assert.NoError(t, err) assert.Equal(t, res.Content, string(expectedList)) } func TestViewVoucher(t *testing.T) { fm, err := NewFlagManager(flagsPath) if err != nil { t.Logf(err.Error()) } ctx, store := InitializeTestStore(t) sessionId := "session123" ctx = context.WithValue(ctx, "SessionId", sessionId) h := &MenuHandlers{ userdataStore: store, flagManager: fm, } // Define mock voucher data mockData := map[storedb.DataTyp][]byte{ storedb.DATA_VOUCHER_SYMBOLS: []byte("1:SRF\n2:MILO"), storedb.DATA_VOUCHER_BALANCES: []byte("1:100\n2:200"), storedb.DATA_VOUCHER_DECIMALS: []byte("1:6\n2:4"), storedb.DATA_VOUCHER_ADDRESSES: []byte("1:0xd4c288865Ce\n2:0x41c188d63Qa"), } // Put the data for key, value := range mockData { err := store.WriteEntry(ctx, sessionId, key, []byte(value)) if err != nil { t.Fatal(err) } } res, err := h.ViewVoucher(ctx, "view_voucher", []byte("1")) assert.NoError(t, err) assert.Equal(t, res.Content, "Symbol: SRF\nBalance: 100") } func TestSetVoucher(t *testing.T) { ctx, store := InitializeTestStore(t) sessionId := "session123" ctx = context.WithValue(ctx, "SessionId", sessionId) h := &MenuHandlers{ userdataStore: store, } // Define the temporary voucher data tempData := &dataserviceapi.TokenHoldings{ TokenSymbol: "SRF", Balance: "200", TokenDecimals: "6", TokenAddress: "0xd4c288865Ce0985a481Eef3be02443dF5E2e4Ea9", } expectedData := fmt.Sprintf("%s,%s,%s,%s", tempData.TokenSymbol, tempData.Balance, tempData.TokenDecimals, tempData.TokenAddress) // store the expectedData if err := store.WriteEntry(ctx, sessionId, storedb.DATA_TEMPORARY_VALUE, []byte(expectedData)); err != nil { t.Fatal(err) } res, err := h.SetVoucher(ctx, "set_voucher", []byte("")) assert.NoError(t, err) assert.Equal(t, string(tempData.TokenSymbol), res.Content) } func TestGetVoucherDetails(t *testing.T) { ctx, store := InitializeTestStore(t) fm, err := NewFlagManager(flagsPath) if err != nil { t.Logf(err.Error()) } flag_api_error, _ := fm.GetFlag("flag_api_call_error") mockAccountService := new(mocks.MockAccountService) sessionId := "session123" ctx = context.WithValue(ctx, "SessionId", sessionId) expectedResult := resource.Result{} tokA_AAddress := "0x0000000000000000000000000000000000000000" h := &MenuHandlers{ userdataStore: store, flagManager: fm, accountService: mockAccountService, } err = store.WriteEntry(ctx, sessionId, storedb.DATA_ACTIVE_ADDRESS, []byte(tokA_AAddress)) if err != nil { t.Fatal(err) } tokenDetails := &models.VoucherDataResult{ TokenName: "Token A", TokenSymbol: "TOKA", TokenLocation: "Kilifi,Kenya", TokenCommodity: "Farming", } expectedResult.Content = fmt.Sprintf( "Name: %s\nSymbol: %s\nCommodity: %s\nLocation: %s", tokenDetails.TokenName, tokenDetails.TokenSymbol, tokenDetails.TokenCommodity, tokenDetails.TokenLocation, ) mockAccountService.On("VoucherData", string(tokA_AAddress)).Return(tokenDetails, nil) res, err := h.GetVoucherDetails(ctx, "SessionId", []byte("")) expectedResult.FlagReset = append(expectedResult.FlagReset, flag_api_error) assert.NoError(t, err) assert.Equal(t, expectedResult, res) }