Compare commits

...

9 Commits

7 changed files with 236 additions and 2 deletions

2
go.mod
View File

@ -1,3 +1,5 @@
module git.grassecon.net/urdt/ussd
go 1.22.6
require github.com/stretchr/testify v1.9.0 // indirect

2
go.sum Normal file
View File

@ -0,0 +1,2 @@
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=

View File

@ -0,0 +1,86 @@
package server
import (
"encoding/json"
"io"
"net/http"
"git.grassecon.net/urdt/ussd/config"
"git.grassecon.net/urdt/ussd/internal/models"
)
type AccountServiceInterface interface {
CheckBalance(publicKey string) (string, error)
CreateAccount() (*models.AccountResponse, error)
CheckAccountStatus(trackingId string) (string, error)
}
type AccountService struct {
}
func (as *AccountService) CheckAccountStatus(trackingId string) (string, error) {
resp, err := http.Get(config.TrackStatusURL + trackingId)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
var trackResp models.TrackStatusResponse
err = json.Unmarshal(body, &trackResp)
if err != nil {
return "", err
}
status := trackResp.Result.Transaction.Status
return status, nil
}
func (as *AccountService) CheckBalance(publicKey string) (string, error) {
resp, err := http.Get(config.BalanceURL + publicKey)
if err != nil {
return "0.0", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "0.0", err
}
var balanceResp models.BalanceResponse
err = json.Unmarshal(body, &balanceResp)
if err != nil {
return "0.0", err
}
balance := balanceResp.Result.Balance
return balance, nil
}
func (as *AccountService) CreateAccount() (*models.AccountResponse, error) {
resp, err := http.Post(config.CreateAccountURL, "application/json", nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var accountResp models.AccountResponse
err = json.Unmarshal(body, &accountResp)
if err != nil {
return nil, err
}
return &accountResp, nil
}

View File

@ -42,8 +42,9 @@ func (s *ServerAccountCreator) CreateAccount() (*models.AccountResponse, error)
type Handlers struct {
fs *FSData
accountFileHandler *utils.AccountFileHandler
accountCreator AccountCreator
accountFileHandler utils.AccountFileHandlerInterface
accountService server.AccountServiceInterface
}
func NewHandlers(path string, st *state.State) *Handlers {
@ -54,6 +55,7 @@ func NewHandlers(path string, st *state.State) *Handlers {
},
accountFileHandler: utils.NewAccountFileHandler(path + "_data"),
accountCreator: &ServerAccountCreator{},
accountService: &server.AccountService{},
}
}
@ -94,7 +96,7 @@ func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte)
return res, err
}
accountResp, err := h.accountCreator.CreateAccount()
accountResp, err := h.accountService.CreateAccount()
if err != nil {
res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_CREATION_FAILED)
return res, err

View File

@ -8,8 +8,11 @@ import (
"testing"
"git.defalsify.org/vise.git/resource"
"git.grassecon.net/urdt/ussd/internal/handlers/ussd/mocks"
"git.grassecon.net/urdt/ussd/internal/models"
"git.grassecon.net/urdt/ussd/internal/utils"
"github.com/alecthomas/assert/v2"
"github.com/stretchr/testify/mock"
)
// MockAccountCreator implements AccountCreator for testing
@ -170,6 +173,51 @@ func TestCreateAccount(t *testing.T) {
}
}
func TestCreateAccount_Success(t *testing.T) {
mockAccountFileHandler := new(mocks.MockAccountFileHandler)
mockCreateAccountService := new(mocks.MockAccountService)
mockAccountFileHandler.On("EnsureFileExists").Return(nil)
// Mock that no account data exists
mockAccountFileHandler.On("ReadAccountData").Return(nil, nil)
// Define expected account response after api call
expectedAccountResp := &models.AccountResponse{
Ok: true,
Result: struct {
CustodialId json.Number `json:"custodialId"`
PublicKey string `json:"publicKey"`
TrackingId string `json:"trackingId"`
}{
CustodialId: "12",
PublicKey: "some-public-key",
TrackingId: "some-tracking-id",
},
}
mockCreateAccountService.On("CreateAccount").Return(expectedAccountResp, nil)
// Mock WriteAccountData to not error
mockAccountFileHandler.On("WriteAccountData", mock.Anything).Return(nil)
handlers := &Handlers{
accountService: mockCreateAccountService,
}
actualResponse, err := handlers.accountService.CreateAccount()
// Assert results
assert.NoError(t, err)
assert.Equal(t,expectedAccountResp.Ok,true)
assert.Equal(t,expectedAccountResp,actualResponse)
}
func TestSavePin(t *testing.T) {
// Setup
tempDir, err := os.MkdirTemp("", "test_save_pin")

View File

@ -0,0 +1,44 @@
package mocks
import (
"git.grassecon.net/urdt/ussd/internal/models"
"github.com/stretchr/testify/mock"
)
type MockAccountFileHandler struct {
mock.Mock
}
func (m *MockAccountFileHandler) EnsureFileExists() error {
args := m.Called()
return args.Error(0)
}
func (m *MockAccountFileHandler) ReadAccountData() (map[string]string, error) {
args := m.Called()
return args.Get(0).(map[string]string), args.Error(1)
}
func (m *MockAccountFileHandler) WriteAccountData(data map[string]string) error {
args := m.Called(data)
return args.Error(0)
}
type MockAccountService struct {
mock.Mock
}
func (m *MockAccountService) CreateAccount() (*models.AccountResponse, error) {
args := m.Called()
return args.Get(0).(*models.AccountResponse), args.Error(1)
}
func (m *MockAccountService) CheckAccountStatus(TrackingId string) (string, error) {
args := m.Called()
return args.Get(0).(string), args.Error(1)
}
func (m *MockAccountService) CheckBalance(PublicKey string) (string, error) {
args := m.Called()
return args.Get(0).(string), args.Error(1)
}

View File

@ -0,0 +1,50 @@
package utils
import (
"encoding/json"
"os"
)
type AccountFileHandlerInterface interface {
EnsureFileExists() error
ReadAccountData() (map[string]string, error)
WriteAccountData(data map[string]string) error
}
type AccountFileHandler2 struct {
FilePath string
}
// Implement the methods required by AccountFileHandlerInterface.
func (afh *AccountFileHandler2) EnsureFileExists() error {
f, err := os.OpenFile(afh.FilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
return f.Close()
}
func (afh *AccountFileHandler2) ReadAccountData() (map[string]string, error) {
jsonData, err := os.ReadFile(afh.FilePath)
if err != nil {
return nil, err
}
var accountData map[string]string
err = json.Unmarshal(jsonData, &accountData)
if err != nil {
return nil, err
}
return accountData, nil
}
func (afh *AccountFileHandler2) WriteAccountData(data map[string]string) error {
jsonData, err := json.Marshal(data)
if err != nil {
return err
}
return os.WriteFile(afh.FilePath, jsonData, 0644)
}