diff --git a/go.mod b/go.mod index 7112503..0b30354 100644 --- a/go.mod +++ b/go.mod @@ -7,19 +7,17 @@ toolchain go1.23.2 require ( git.defalsify.org/vise.git v0.2.1-0.20241017112704-307fa6fcdc6b github.com/alecthomas/assert/v2 v2.2.2 + github.com/grassrootseconomics/eth-custodial v1.3.0-beta github.com/peteole/testdata-loader v0.3.0 gopkg.in/leonelquinteros/gotext.v1 v1.3.1 - ) -require github.com/joho/godotenv v1.5.1 - require ( - github.com/grassrootseconomics/eth-custodial v1.3.0-beta github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx/v5 v5.7.1 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/joho/godotenv v1.5.1 github.com/kr/text v0.2.0 // indirect github.com/rogpeppe/go-internal v1.13.1 // indirect golang.org/x/crypto v0.27.0 // indirect @@ -42,7 +40,4 @@ require ( github.com/stretchr/testify v1.9.0 github.com/x448/float16 v0.8.4 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - ) - - diff --git a/internal/handlers/server/accountservice.go b/internal/handlers/server/accountservice.go index 3e2f91d..890d1db 100644 --- a/internal/handlers/server/accountservice.go +++ b/internal/handlers/server/accountservice.go @@ -8,7 +8,6 @@ import ( "io" "net/http" "os" - "time" "git.grassecon.net/urdt/ussd/config" "git.grassecon.net/urdt/ussd/internal/models" @@ -31,9 +30,6 @@ type AccountServiceInterface interface { type AccountService struct { } -type TestAccountService struct { -} - // Parameters: // - trackingId: A unique identifier for the account.This should be obtained from a previous call to // CreateAccount or a similar function that returns an AccountResponse. The `trackingId` field in the @@ -187,88 +183,3 @@ func (as *AccountService) FetchVouchers(ctx context.Context, publicKey string) ( } return &holdings, nil } - -func (tas *TestAccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) { - return &api.OKResponse{ - Ok: true, - Description: "Account creation request received successfully", - Result: map[string]any{"publicKey": "0x48ADca309b5085852207FAaf2816eD72B52F527C", "trackingId": "28ebe84d-b925-472c-87ae-bbdfa1fb97be"}, - }, nil - -} - -func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) { - balanceResponse := &models.BalanceResponse{ - Ok: true, - Result: struct { - Balance string `json:"balance"` - Nonce json.Number `json:"nonce"` - }{ - Balance: "0.003 CELO", - Nonce: json.Number("0"), - }, - } - return balanceResponse, nil -} - -func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) { - return &api.OKResponse{ - Ok: true, - Description: "Account creation succeeded", - Result: map[string]any{ - "active": true, - }, - }, nil -} - -func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) { - trackResponse := &models.TrackStatusResponse{ - Ok: true, - Result: struct { - Transaction struct { - CreatedAt time.Time "json:\"createdAt\"" - Status string "json:\"status\"" - TransferValue json.Number "json:\"transferValue\"" - TxHash string "json:\"txHash\"" - TxType string "json:\"txType\"" - } - }{ - Transaction: models.Transaction{ - CreatedAt: time.Now(), - Status: "SUCCESS", - TransferValue: json.Number("0.5"), - TxHash: "0x123abc456def", - TxType: "transfer", - }, - }, - } - return trackResponse, nil -} - -func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey string) (*models.VoucherHoldingResponse, error) { - return &models.VoucherHoldingResponse{ - Ok: true, - Result: struct { - Holdings []struct { - ContractAddress string `json:"contractAddress"` - TokenSymbol string `json:"tokenSymbol"` - TokenDecimals string `json:"tokenDecimals"` - Balance string `json:"balance"` - } `json:"holdings"` - }{ - Holdings: []struct { - ContractAddress string `json:"contractAddress"` - TokenSymbol string `json:"tokenSymbol"` - TokenDecimals string `json:"tokenDecimals"` - Balance string `json:"balance"` - }{ - { - ContractAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee", - TokenSymbol: "SRF", - TokenDecimals: "6", - Balance: "2745987", - }, - }, - }, - }, nil -} diff --git a/internal/handlers/ussd/menuhandler.go b/internal/handlers/ussd/menuhandler.go index d397eff..d395a8b 100644 --- a/internal/handlers/ussd/menuhandler.go +++ b/internal/handlers/ussd/menuhandler.go @@ -27,12 +27,12 @@ import ( ) var ( - logg = logging.NewVanilla().WithDomain("ussdmenuhandler") - scriptDir = path.Join("services", "registration") - translationDir = path.Join(scriptDir, "locale") - PINChangePrivilege byte = 1 - okResponse *api.OKResponse - errResponse *api.ErrResponse + logg = logging.NewVanilla().WithDomain("ussdmenuhandler") + scriptDir = path.Join("services", "registration") + translationDir = path.Join(scriptDir, "locale") + okResponse *api.OKResponse + errResponse *api.ErrResponse + backOption = []byte("0") ) // FlagManager handles centralized flag management @@ -354,6 +354,9 @@ func (h *Handlers) SaveFirstname(ctx context.Context, sym string, input []byte) return res, fmt.Errorf("missing session") } if len(input) > 0 { + if bytes.Equal(input, backOption) { + return res, nil + } firstName := string(input) store := h.userdataStore err = store.WriteEntry(ctx, sessionId, utils.DATA_FIRST_NAME, []byte(firstName)) @@ -373,8 +376,10 @@ func (h *Handlers) SaveFamilyname(ctx context.Context, sym string, input []byte) if !ok { return res, fmt.Errorf("missing session") } - if len(input) > 0 { + if bytes.Equal(input, backOption) { + return res, nil + } familyName := string(input) store := h.userdataStore err = store.WriteEntry(ctx, sessionId, utils.DATA_FAMILY_NAME, []byte(familyName)) @@ -417,8 +422,10 @@ func (h *Handlers) SaveLocation(ctx context.Context, sym string, input []byte) ( if !ok { return res, fmt.Errorf("missing session") } - if len(input) > 0 { + if bytes.Equal(input, backOption) { + return res, nil + } location := string(input) store := h.userdataStore err = store.WriteEntry(ctx, sessionId, utils.DATA_LOCATION, []byte(location)) @@ -439,6 +446,9 @@ func (h *Handlers) SaveGender(ctx context.Context, sym string, input []byte) (re if !ok { return res, fmt.Errorf("missing session") } + if bytes.Equal(input, backOption) { + return res, nil + } gender := strings.Split(symbol, "_")[1] store := h.userdataStore err = store.WriteEntry(ctx, sessionId, utils.DATA_GENDER, []byte(gender)) diff --git a/internal/handlers/ussd/menuhandler_test.go b/internal/handlers/ussd/menuhandler_test.go index 9bcee63..28d25e8 100644 --- a/internal/handlers/ussd/menuhandler_test.go +++ b/internal/handlers/ussd/menuhandler_test.go @@ -15,9 +15,10 @@ import ( "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" - "git.grassecon.net/urdt/ussd/internal/handlers/server" - "git.grassecon.net/urdt/ussd/internal/mocks" "git.grassecon.net/urdt/ussd/internal/models" + "git.grassecon.net/urdt/ussd/internal/testutil/mocks" + "git.grassecon.net/urdt/ussd/internal/testutil/testservice" + "git.grassecon.net/urdt/ussd/internal/utils" "github.com/alecthomas/assert/v2" "github.com/grassrootseconomics/eth-custodial/pkg/api" @@ -32,7 +33,7 @@ var ( func TestNewHandlers(t *testing.T) { fm, err := NewFlagManager(flagsPath) - accountService := server.TestAccountService{} + accountService := testservice.TestAccountService{} if err != nil { t.Logf(err.Error()) } diff --git a/internal/http/http_test.go b/internal/http/http_test.go index 8f6f312..14bb90a 100644 --- a/internal/http/http_test.go +++ b/internal/http/http_test.go @@ -13,7 +13,7 @@ import ( "git.defalsify.org/vise.git/engine" "git.grassecon.net/urdt/ussd/internal/handlers" - "git.grassecon.net/urdt/ussd/internal/mocks/httpmocks" + "git.grassecon.net/urdt/ussd/internal/testutil/mocks/httpmocks" ) // invalidRequestType is a custom type to test invalid request scenarios diff --git a/internal/testutil/TestEngine.go b/internal/testutil/TestEngine.go index 75ac817..bd6bc7f 100644 --- a/internal/testutil/TestEngine.go +++ b/internal/testutil/TestEngine.go @@ -13,6 +13,8 @@ import ( "git.grassecon.net/urdt/ussd/internal/handlers" "git.grassecon.net/urdt/ussd/internal/handlers/server" "git.grassecon.net/urdt/ussd/internal/storage" + "git.grassecon.net/urdt/ussd/internal/testutil/testservice" + "git.grassecon.net/urdt/ussd/internal/testutil/testtag" testdataloader "github.com/peteole/testdata-loader" ) @@ -80,12 +82,12 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool) { os.Exit(1) } - if AccountService == nil { - AccountService = &server.AccountService{} + if testtag.AccountService == nil { + testtag.AccountService = &server.AccountService{} } - switch AccountService.(type) { - case *server.TestAccountService: + switch testtag.AccountService.(type) { + case *testservice.TestAccountService: go func() { eventChannel <- false }() @@ -98,7 +100,7 @@ func TestEngine(sessionId string) (engine.Engine, func(), chan bool) { panic("Unknown account service type") } - hl, err := lhs.GetHandler(AccountService) + hl, err := lhs.GetHandler(testtag.AccountService) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) diff --git a/driver/groupdriver.go b/internal/testutil/driver/groupdriver.go similarity index 100% rename from driver/groupdriver.go rename to internal/testutil/driver/groupdriver.go diff --git a/internal/mocks/dbmock.go b/internal/testutil/mocks/dbmock.go similarity index 100% rename from internal/mocks/dbmock.go rename to internal/testutil/mocks/dbmock.go diff --git a/internal/mocks/httpmocks/enginemock.go b/internal/testutil/mocks/httpmocks/enginemock.go similarity index 100% rename from internal/mocks/httpmocks/enginemock.go rename to internal/testutil/mocks/httpmocks/enginemock.go diff --git a/internal/mocks/httpmocks/requesthandlermock.go b/internal/testutil/mocks/httpmocks/requesthandlermock.go similarity index 100% rename from internal/mocks/httpmocks/requesthandlermock.go rename to internal/testutil/mocks/httpmocks/requesthandlermock.go diff --git a/internal/mocks/httpmocks/requestparsermock.go b/internal/testutil/mocks/httpmocks/requestparsermock.go similarity index 100% rename from internal/mocks/httpmocks/requestparsermock.go rename to internal/testutil/mocks/httpmocks/requestparsermock.go diff --git a/internal/mocks/httpmocks/writermock.go b/internal/testutil/mocks/httpmocks/writermock.go similarity index 100% rename from internal/mocks/httpmocks/writermock.go rename to internal/testutil/mocks/httpmocks/writermock.go diff --git a/internal/mocks/servicemock.go b/internal/testutil/mocks/servicemock.go similarity index 100% rename from internal/mocks/servicemock.go rename to internal/testutil/mocks/servicemock.go diff --git a/internal/mocks/userdbmock.go b/internal/testutil/mocks/userdbmock.go similarity index 100% rename from internal/mocks/userdbmock.go rename to internal/testutil/mocks/userdbmock.go diff --git a/internal/testutil/offlinetest.go b/internal/testutil/offlinetest.go deleted file mode 100644 index 476ade3..0000000 --- a/internal/testutil/offlinetest.go +++ /dev/null @@ -1,11 +0,0 @@ -// +build !online - -package testutil - -import ( - "git.grassecon.net/urdt/ussd/internal/handlers/server" -) - -var ( - AccountService server.AccountServiceInterface = &server.TestAccountService{} -) diff --git a/internal/testutil/testservice/TestAccountService.go b/internal/testutil/testservice/TestAccountService.go new file mode 100644 index 0000000..6332345 --- /dev/null +++ b/internal/testutil/testservice/TestAccountService.go @@ -0,0 +1,101 @@ +package testservice + +import ( + "context" + "encoding/json" + "time" + + "git.grassecon.net/urdt/ussd/internal/models" + "github.com/grassrootseconomics/eth-custodial/pkg/api" +) + +type TestAccountService struct { +} + +func (tas *TestAccountService) CreateAccount(ctx context.Context) (*api.OKResponse, error) { + return &api.OKResponse{ + Ok: true, + Description: "Account creation succeeded", + Result: map[string]any{ + "trackingId": "075ccc86-f6ef-4d33-97d5-e91cfb37aa0d", + "publicKey": "0x623EFAFa8868df4B934dd12a8B26CB3Dd75A7AdD", + }, + }, nil +} + +func (tas *TestAccountService) CheckBalance(ctx context.Context, publicKey string) (*models.BalanceResponse, error) { + balanceResponse := &models.BalanceResponse{ + Ok: true, + Result: struct { + Balance string `json:"balance"` + Nonce json.Number `json:"nonce"` + }{ + Balance: "0.003 CELO", + Nonce: json.Number("0"), + }, + } + + return balanceResponse, nil +} + +func (tas *TestAccountService) CheckAccountStatus(ctx context.Context, trackingId string) (*models.TrackStatusResponse, error) { + trackResponse := &models.TrackStatusResponse{ + Ok: true, + Result: struct { + Transaction struct { + CreatedAt time.Time "json:\"createdAt\"" + Status string "json:\"status\"" + TransferValue json.Number "json:\"transferValue\"" + TxHash string "json:\"txHash\"" + TxType string "json:\"txType\"" + } + }{ + Transaction: models.Transaction{ + CreatedAt: time.Now(), + Status: "SUCCESS", + TransferValue: json.Number("0.5"), + TxHash: "0x123abc456def", + TxType: "transfer", + }, + }, + } + return trackResponse, nil +} + +func (tas *TestAccountService) TrackAccountStatus(ctx context.Context, publicKey string) (*api.OKResponse, error) { + return &api.OKResponse{ + Ok: true, + Description: "Account creation succeeded", + Result: map[string]any{ + "active": true, + }, + }, nil +} + +func (tas *TestAccountService) FetchVouchers(ctx context.Context, publicKey string) (*models.VoucherHoldingResponse, error) { + return &models.VoucherHoldingResponse{ + Ok: true, + Result: struct { + Holdings []struct { + ContractAddress string `json:"contractAddress"` + TokenSymbol string `json:"tokenSymbol"` + TokenDecimals string `json:"tokenDecimals"` + Balance string `json:"balance"` + } `json:"holdings"` + }{ + Holdings: []struct { + ContractAddress string `json:"contractAddress"` + TokenSymbol string `json:"tokenSymbol"` + TokenDecimals string `json:"tokenDecimals"` + Balance string `json:"balance"` + }{ + { + ContractAddress: "0x6CC75A06ac72eB4Db2eE22F781F5D100d8ec03ee", + TokenSymbol: "SRF", + TokenDecimals: "6", + Balance: "2745987", + }, + }, + }, + }, nil +} diff --git a/internal/testutil/testtag/offlinetest.go b/internal/testutil/testtag/offlinetest.go new file mode 100644 index 0000000..70e2e80 --- /dev/null +++ b/internal/testutil/testtag/offlinetest.go @@ -0,0 +1,12 @@ +// +build !online + +package testtag + +import ( + "git.grassecon.net/urdt/ussd/internal/handlers/server" + accountservice "git.grassecon.net/urdt/ussd/internal/testutil/testservice" +) + +var ( + AccountService server.AccountServiceInterface = &accountservice.TestAccountService{} +) diff --git a/internal/testutil/onlinetest.go b/internal/testutil/testtag/onlinetest.go similarity index 88% rename from internal/testutil/onlinetest.go rename to internal/testutil/testtag/onlinetest.go index ddb5cf0..92cbb14 100644 --- a/internal/testutil/onlinetest.go +++ b/internal/testutil/testtag/onlinetest.go @@ -1,6 +1,6 @@ // +build online -package testutil +package testtag import "git.grassecon.net/urdt/ussd/internal/handlers/server" diff --git a/menutraversal_test/menu_traversal_test.go b/menutraversal_test/menu_traversal_test.go index 900ebcc..d79b771 100644 --- a/menutraversal_test/menu_traversal_test.go +++ b/menutraversal_test/menu_traversal_test.go @@ -9,8 +9,8 @@ import ( "regexp" "testing" - "git.grassecon.net/urdt/ussd/driver" "git.grassecon.net/urdt/ussd/internal/testutil" + "git.grassecon.net/urdt/ussd/internal/testutil/driver" "github.com/gofrs/uuid" ) diff --git a/services/registration/enter_location.vis b/services/registration/enter_location.vis index fdd29ce..c8da2dd 100644 --- a/services/registration/enter_location.vis +++ b/services/registration/enter_location.vis @@ -1,8 +1,8 @@ CATCH incorrect_pin flag_incorrect_pin 1 CATCH profile_update_success flag_allow_update 1 -LOAD save_location 0 MOUT back 0 HALT +LOAD save_location 0 RELOAD save_location INCMP _ 0 INCMP pin_entry * diff --git a/services/registration/enter_name.vis b/services/registration/enter_name.vis index 563577e..799b2a1 100644 --- a/services/registration/enter_name.vis +++ b/services/registration/enter_name.vis @@ -1,12 +1,8 @@ CATCH incorrect_pin flag_incorrect_pin 1 CATCH profile_update_success flag_allow_update 1 -LOAD save_firstname 0 -RELOAD save_firstname MOUT back 0 HALT +LOAD save_firstname 0 RELOAD save_firstname INCMP _ 0 INCMP pin_entry * - - -