menu-voucherlist #101
| @ -17,6 +17,7 @@ import ( | |||||||
| 	"git.defalsify.org/vise.git/resource" | 	"git.defalsify.org/vise.git/resource" | ||||||
| 
 | 
 | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/handlers" | 	"git.grassecon.net/urdt/ussd/internal/handlers" | ||||||
|  | 	"git.grassecon.net/urdt/ussd/internal/handlers/server" | ||||||
| 	httpserver "git.grassecon.net/urdt/ussd/internal/http" | 	httpserver "git.grassecon.net/urdt/ussd/internal/http" | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/storage" | 	"git.grassecon.net/urdt/ussd/internal/storage" | ||||||
| ) | ) | ||||||
| @ -127,7 +128,8 @@ func main() { | |||||||
| 		os.Exit(1) | 		os.Exit(1) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	hl, err := lhs.GetHandler() | 	accountService := server.AccountService{} | ||||||
|  | 	hl, err := lhs.GetHandler(&accountService) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | 		fmt.Fprintf(os.Stderr, err.Error()) | ||||||
| 		os.Exit(1) | 		os.Exit(1) | ||||||
|  | |||||||
| @ -14,6 +14,7 @@ import ( | |||||||
| 	"git.defalsify.org/vise.git/resource" | 	"git.defalsify.org/vise.git/resource" | ||||||
| 
 | 
 | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/handlers" | 	"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/storage" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -94,8 +95,9 @@ func main() { | |||||||
| 
 | 
 | ||||||
| 	lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) | 	lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) | ||||||
| 	lhs.SetDataStore(&userdataStore) | 	lhs.SetDataStore(&userdataStore) | ||||||
|  | 	accountService := server.AccountService{} | ||||||
| 
 | 
 | ||||||
| 	hl, err := lhs.GetHandler() | 	hl, err := lhs.GetHandler(&accountService) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | 		fmt.Fprintf(os.Stderr, err.Error()) | ||||||
| 		os.Exit(1) | 		os.Exit(1) | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ import ( | |||||||
| 	"git.defalsify.org/vise.git/resource" | 	"git.defalsify.org/vise.git/resource" | ||||||
| 
 | 
 | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/handlers" | 	"git.grassecon.net/urdt/ussd/internal/handlers" | ||||||
|  | 	"git.grassecon.net/urdt/ussd/internal/handlers/server" | ||||||
| 	httpserver "git.grassecon.net/urdt/ussd/internal/http" | 	httpserver "git.grassecon.net/urdt/ussd/internal/http" | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/storage" | 	"git.grassecon.net/urdt/ussd/internal/storage" | ||||||
| ) | ) | ||||||
| @ -87,8 +88,8 @@ func main() { | |||||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | 		fmt.Fprintf(os.Stderr, err.Error()) | ||||||
| 		os.Exit(1) | 		os.Exit(1) | ||||||
| 	} | 	} | ||||||
| 
 | 	accountService := server.AccountService{} | ||||||
| 	hl, err := lhs.GetHandler() | 	hl, err := lhs.GetHandler(&accountService) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | 		fmt.Fprintf(os.Stderr, err.Error()) | ||||||
| 		os.Exit(1) | 		os.Exit(1) | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ import ( | |||||||
| 	"git.defalsify.org/vise.git/logging" | 	"git.defalsify.org/vise.git/logging" | ||||||
| 	"git.defalsify.org/vise.git/resource" | 	"git.defalsify.org/vise.git/resource" | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/handlers" | 	"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/storage" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -85,7 +86,8 @@ func main() { | |||||||
| 		os.Exit(1) | 		os.Exit(1) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	hl, err := lhs.GetHandler() | 	accountService := server.AccountService{} | ||||||
|  | 	hl, err := lhs.GetHandler(&accountService) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		fmt.Fprintf(os.Stderr, err.Error()) | 		fmt.Fprintf(os.Stderr, err.Error()) | ||||||
| 		os.Exit(1) | 		os.Exit(1) | ||||||
|  | |||||||
							
								
								
									
										111
									
								
								driver/groupdriver.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								driver/groupdriver.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,111 @@ | |||||||
|  | package driver | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"encoding/json" | ||||||
|  | 	"log" | ||||||
|  | 	"os" | ||||||
|  | 	"regexp" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type Step struct { | ||||||
|  | 	Input           string `json:"input"` | ||||||
|  | 	ExpectedContent string `json:"expectedContent"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (s *Step) MatchesExpectedContent(content []byte) (bool, error) { | ||||||
|  | 	pattern := regexp.QuoteMeta(s.ExpectedContent) | ||||||
|  | 	re, err := regexp.Compile(pattern) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return false, err | ||||||
|  | 	} | ||||||
|  | 	if re.Match([]byte(content)) { | ||||||
|  | 		return true, nil | ||||||
|  | 	} | ||||||
|  | 	return false, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Group represents a group of steps
 | ||||||
|  | type Group struct { | ||||||
|  | 	Name  string `json:"name"` | ||||||
|  | 	Steps []Step `json:"steps"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type TestCase struct { | ||||||
|  | 	Name            string | ||||||
|  | 	Input           string | ||||||
|  | 	ExpectedContent string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (s *TestCase) MatchesExpectedContent(content []byte) (bool, error) { | ||||||
|  | 	pattern := regexp.QuoteMeta(s.ExpectedContent) | ||||||
|  | 	re, err := regexp.Compile(pattern) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return false, err | ||||||
|  | 	} | ||||||
|  | 	// Check if the content matches the regex pattern
 | ||||||
|  | 	if re.Match(content) { | ||||||
|  | 		return true, nil | ||||||
|  | 	} | ||||||
|  | 	return false, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DataGroup represents the overall structure of the JSON.
 | ||||||
|  | type DataGroup struct { | ||||||
|  | 	Groups []Group `json:"groups"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type Session struct { | ||||||
|  | 	Name   string  `json:"name"` | ||||||
|  | 	Groups []Group `json:"groups"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func ReadData() []Session { | ||||||
|  | 	data, err := os.ReadFile("test_setup.json") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to read file: %v", err) | ||||||
|  | 	} | ||||||
|  | 	// Unmarshal JSON data
 | ||||||
|  | 	var sessions []Session | ||||||
|  | 	err = json.Unmarshal(data, &sessions) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to unmarshal JSON: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return sessions | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func FilterGroupsByName(groups []Group, name string) []Group { | ||||||
|  | 	var filteredGroups []Group | ||||||
|  | 	for _, group := range groups { | ||||||
|  | 		if group.Name == name { | ||||||
|  | 			filteredGroups = append(filteredGroups, group) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return filteredGroups | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func LoadTestGroups(filePath string) (DataGroup, error) { | ||||||
|  | 	var sessionsData DataGroup | ||||||
|  | 	data, err := os.ReadFile(filePath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return sessionsData, err | ||||||
|  | 	} | ||||||
|  | 	err = json.Unmarshal(data, &sessionsData) | ||||||
|  | 	return sessionsData, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func CreateTestCases(group DataGroup) []TestCase { | ||||||
|  | 	var tests []TestCase | ||||||
|  | 	for _, group := range group.Groups { | ||||||
|  | 		for _, step := range group.Steps { | ||||||
|  | 			// Create a test case for each group
 | ||||||
|  | 			tests = append(tests, TestCase{ | ||||||
|  | 				Name:            group.Name, | ||||||
|  | 				Input:           step.Input, | ||||||
|  | 				ExpectedContent: step.ExpectedContent, | ||||||
|  | 			}) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return tests | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							| @ -15,6 +15,7 @@ require ( | |||||||
| 	github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c // indirect | 	github.com/barbashov/iso639-3 v0.0.0-20211020172741-1f4ffb2d8d1c // indirect | ||||||
| 	github.com/davecgh/go-spew v1.1.1 // indirect | 	github.com/davecgh/go-spew v1.1.1 // indirect | ||||||
| 	github.com/fxamacker/cbor/v2 v2.4.0 // indirect | 	github.com/fxamacker/cbor/v2 v2.4.0 // indirect | ||||||
|  | 	github.com/gofrs/uuid v4.4.0+incompatible | ||||||
| 	github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 // indirect | 	github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 // indirect | ||||||
| 	github.com/hexops/gotextdiff v1.0.3 // indirect | 	github.com/hexops/gotextdiff v1.0.3 // indirect | ||||||
| 	github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a // indirect | 	github.com/mattn/kinako v0.0.0-20170717041458-332c0a7e205a // indirect | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							| @ -16,6 +16,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c | |||||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||||
| github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= | github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88= | ||||||
| github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= | github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= | ||||||
|  | github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= | ||||||
|  | github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | ||||||
| github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo= | github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4 h1:U4kkNYryi/qfbBF8gh7Vsbuz+cVmhf5kt6pE9bYYyLo= | ||||||
| github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y= | github.com/graygnuorg/go-gdbm v0.0.0-20220711140707-71387d66dce4/go.mod h1:zpZDgZFzeq9s0MIeB1P50NIEWDFFHSFBohI/NbaTD/Y= | ||||||
| github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= | github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ import ( | |||||||
| 	"git.defalsify.org/vise.git/engine" | 	"git.defalsify.org/vise.git/engine" | ||||||
| 	"git.defalsify.org/vise.git/persist" | 	"git.defalsify.org/vise.git/persist" | ||||||
| 	"git.defalsify.org/vise.git/resource" | 	"git.defalsify.org/vise.git/resource" | ||||||
|  | 	"git.grassecon.net/urdt/ussd/internal/handlers/server" | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/handlers/ussd" | 	"git.grassecon.net/urdt/ussd/internal/handlers/ussd" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -52,8 +53,8 @@ func (ls *LocalHandlerService) SetDataStore(db *db.Db) { | |||||||
| 	ls.UserdataStore = db | 	ls.UserdataStore = db | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ls *LocalHandlerService) GetHandler() (*ussd.Handlers, error) { | func (ls *LocalHandlerService) GetHandler(accountService server.AccountServiceInterface) (*ussd.Handlers, error) { | ||||||
| 	ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore) | 	ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore,accountService) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ import ( | |||||||
| 	"io" | 	"io" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"git.grassecon.net/urdt/ussd/config" | 	"git.grassecon.net/urdt/ussd/config" | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/models" | 	"git.grassecon.net/urdt/ussd/internal/models" | ||||||
| @ -20,6 +21,9 @@ type AccountServiceInterface interface { | |||||||
| type AccountService struct { | type AccountService struct { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type TestAccountService struct { | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // CheckAccountStatus retrieves the status of an account transaction based on the provided tracking ID.
 | // CheckAccountStatus retrieves the status of an account transaction based on the provided tracking ID.
 | ||||||
| //
 | //
 | ||||||
| // Parameters:
 | // Parameters:
 | ||||||
| @ -111,3 +115,58 @@ func (as *AccountService) FetchVouchers(publicKey string) (*models.VoucherHoldin | |||||||
| 	} | 	} | ||||||
| 	return &holdings, nil | 	return &holdings, nil | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (tas *TestAccountService) CreateAccount() (*models.AccountResponse, error) { | ||||||
|  | 	return &models.AccountResponse{ | ||||||
|  | 		Ok: true, | ||||||
|  | 		Result: struct { | ||||||
|  | 			CustodialId json.Number `json:"custodialId"` | ||||||
|  | 			PublicKey   string      `json:"publicKey"` | ||||||
|  | 			TrackingId  string      `json:"trackingId"` | ||||||
|  | 		}{ | ||||||
|  | 			CustodialId: json.Number("182"), | ||||||
|  | 			PublicKey:   "0x48ADca309b5085852207FAaf2816eD72B52F527C", | ||||||
|  | 			TrackingId:  "28ebe84d-b925-472c-87ae-bbdfa1fb97be", | ||||||
|  | 		}, | ||||||
|  | 	}, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (tas *TestAccountService) CheckBalance(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(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 | ||||||
|  | } | ||||||
|  | |||||||
| @ -63,7 +63,7 @@ type Handlers struct { | |||||||
| 	accountService server.AccountServiceInterface | 	accountService server.AccountServiceInterface | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db) (*Handlers, error) { | func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db, accountService server.AccountServiceInterface) (*Handlers, error) { | ||||||
| 	if userdataStore == nil { | 	if userdataStore == nil { | ||||||
| 		return nil, fmt.Errorf("cannot create handler with nil userdata store") | 		return nil, fmt.Errorf("cannot create handler with nil userdata store") | ||||||
| 	} | 	} | ||||||
| @ -73,7 +73,7 @@ func NewHandlers(appFlags *asm.FlagParser, userdataStore db.Db) (*Handlers, erro | |||||||
| 	h := &Handlers{ | 	h := &Handlers{ | ||||||
| 		userdataStore:  userDb, | 		userdataStore:  userDb, | ||||||
| 		flagManager:    appFlags, | 		flagManager:    appFlags, | ||||||
| 		accountService: &server.AccountService{}, | 		accountService: accountService, | ||||||
| 	} | 	} | ||||||
| 	return h, nil | 	return h, nil | ||||||
| } | } | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ import ( | |||||||
| 	"git.defalsify.org/vise.git/persist" | 	"git.defalsify.org/vise.git/persist" | ||||||
| 	"git.defalsify.org/vise.git/resource" | 	"git.defalsify.org/vise.git/resource" | ||||||
| 	"git.defalsify.org/vise.git/state" | 	"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/mocks" | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/models" | 	"git.grassecon.net/urdt/ussd/internal/models" | ||||||
| 	"git.grassecon.net/urdt/ussd/internal/utils" | 	"git.grassecon.net/urdt/ussd/internal/utils" | ||||||
| @ -28,22 +29,15 @@ var ( | |||||||
| 	flagsPath = path.Join(baseDir, "services", "registration", "pp.csv") | 	flagsPath = path.Join(baseDir, "services", "registration", "pp.csv") | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type Transaction struct { |  | ||||||
| 	CreatedAt     time.Time   `json:"createdAt"` |  | ||||||
| 	Status        string      `json:"status"` |  | ||||||
| 	TransferValue json.Number `json:"transferValue"` |  | ||||||
| 	TxHash        string      `json:"txHash"` |  | ||||||
| 	TxType        string      `json:"txType"` |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestNewHandlers(t *testing.T) { | func TestNewHandlers(t *testing.T) { | ||||||
| 	fm, err := NewFlagManager(flagsPath) | 	fm, err := NewFlagManager(flagsPath) | ||||||
|  | 	accountService := server.TestAccountService{} | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Logf(err.Error()) | 		t.Logf(err.Error()) | ||||||
| 	} | 	} | ||||||
| 	t.Run("Valid UserDataStore", func(t *testing.T) { | 	t.Run("Valid UserDataStore", func(t *testing.T) { | ||||||
| 		mockStore := &mocks.MockUserDataStore{} | 		mockStore := &mocks.MockUserDataStore{} | ||||||
| 		handlers, err := NewHandlers(fm.parser, mockStore) | 		handlers, err := NewHandlers(fm.parser, mockStore, &accountService) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			t.Fatalf("expected no error, got %v", err) | 			t.Fatalf("expected no error, got %v", err) | ||||||
| 		} | 		} | ||||||
| @ -59,7 +53,7 @@ func TestNewHandlers(t *testing.T) { | |||||||
| 	t.Run("Nil UserDataStore", func(t *testing.T) { | 	t.Run("Nil UserDataStore", func(t *testing.T) { | ||||||
| 		appFlags := &asm.FlagParser{} | 		appFlags := &asm.FlagParser{} | ||||||
| 
 | 
 | ||||||
| 		handlers, err := NewHandlers(appFlags, nil) | 		handlers, err := NewHandlers(appFlags, nil, &accountService) | ||||||
| 
 | 
 | ||||||
| 		if err == nil { | 		if err == nil { | ||||||
| 			t.Fatal("expected an error, got none") | 			t.Fatal("expected an error, got none") | ||||||
| @ -1061,7 +1055,7 @@ func TestCheckAccountStatus(t *testing.T) { | |||||||
| 						TxType        string      "json:\"txType\"" | 						TxType        string      "json:\"txType\"" | ||||||
| 					} | 					} | ||||||
| 				}{ | 				}{ | ||||||
| 					Transaction: Transaction{ | 					Transaction: models.Transaction{ | ||||||
| 						CreatedAt:     time.Now(), | 						CreatedAt:     time.Now(), | ||||||
| 						Status:        "SUCCESS", | 						Status:        "SUCCESS", | ||||||
| 						TransferValue: json.Number("0.5"), | 						TransferValue: json.Number("0.5"), | ||||||
| @ -1099,7 +1093,7 @@ func TestCheckAccountStatus(t *testing.T) { | |||||||
| 						TxType        string      "json:\"txType\"" | 						TxType        string      "json:\"txType\"" | ||||||
| 					} | 					} | ||||||
| 				}{ | 				}{ | ||||||
| 					Transaction: Transaction{ | 					Transaction: models.Transaction{ | ||||||
| 						CreatedAt:     time.Now(), | 						CreatedAt:     time.Now(), | ||||||
| 						Status:        "IN_NETWORK", | 						Status:        "IN_NETWORK", | ||||||
| 						TransferValue: json.Number("0.5"), | 						TransferValue: json.Number("0.5"), | ||||||
|  | |||||||
| @ -5,6 +5,13 @@ import ( | |||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | type Transaction struct { | ||||||
|  | 	CreatedAt     time.Time   `json:"createdAt"` | ||||||
|  | 	Status        string      `json:"status"` | ||||||
|  | 	TransferValue json.Number `json:"transferValue"` | ||||||
|  | 	TxHash        string      `json:"txHash"` | ||||||
|  | 	TxType        string      `json:"txType"` | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| type TrackStatusResponse struct { | type TrackStatusResponse struct { | ||||||
| 	Ok     bool `json:"ok"` | 	Ok     bool `json:"ok"` | ||||||
| @ -17,4 +24,4 @@ type TrackStatusResponse struct { | |||||||
| 			TxType        string      `json:"txType"` | 			TxType        string      `json:"txType"` | ||||||
| 		} | 		} | ||||||
| 	} `json:"result"` | 	} `json:"result"` | ||||||
| } | } | ||||||
|  | |||||||
| @ -109,6 +109,7 @@ func(tdb *ThreadGdbmDb) Get(ctx context.Context, key []byte) ([]byte, error) { | |||||||
| func(tdb *ThreadGdbmDb) Close() error { | func(tdb *ThreadGdbmDb) Close() error { | ||||||
| 	tdb.reserve() | 	tdb.reserve() | ||||||
| 	close(dbC[tdb.connStr]) | 	close(dbC[tdb.connStr]) | ||||||
|  | 	delete(dbC, tdb.connStr) | ||||||
| 	err := tdb.db.Close() | 	err := tdb.db.Close() | ||||||
| 	tdb.db = nil | 	tdb.db = nil | ||||||
| 	return err | 	return err | ||||||
|  | |||||||
							
								
								
									
										121
									
								
								internal/testutil/TestEngine.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								internal/testutil/TestEngine.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | |||||||
|  | package testutil | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"path" | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
|  | 	"git.defalsify.org/vise.git/engine" | ||||||
|  | 	"git.defalsify.org/vise.git/logging" | ||||||
|  | 	"git.defalsify.org/vise.git/resource" | ||||||
|  | 	"git.grassecon.net/urdt/ussd/internal/handlers" | ||||||
|  | 	"git.grassecon.net/urdt/ussd/internal/handlers/server" | ||||||
|  | 	"git.grassecon.net/urdt/ussd/internal/storage" | ||||||
|  | 	testdataloader "github.com/peteole/testdata-loader" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	baseDir   = testdataloader.GetBasePath() | ||||||
|  | 	logg      = logging.NewVanilla() | ||||||
|  | 	scriptDir = path.Join(baseDir, "services", "registration") | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestEngine(sessionId string) (engine.Engine, func(), chan bool) { | ||||||
|  | 	ctx := context.Background() | ||||||
|  | 	ctx = context.WithValue(ctx, "SessionId", sessionId) | ||||||
|  | 	pfp := path.Join(scriptDir, "pp.csv") | ||||||
|  | 
 | ||||||
|  | 	var eventChannel = make(chan bool) | ||||||
|  | 
 | ||||||
|  | 	cfg := engine.Config{ | ||||||
|  | 		Root:       "root", | ||||||
|  | 		SessionId:  sessionId, | ||||||
|  | 		OutputSize: uint32(160), | ||||||
|  | 		FlagCount:  uint32(128), | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	dbDir := ".test_state" | ||||||
|  | 	resourceDir := scriptDir | ||||||
|  | 	menuStorageService := storage.NewMenuStorageService(dbDir, resourceDir) | ||||||
|  | 
 | ||||||
|  | 	err := menuStorageService.EnsureDbDir() | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Fprintf(os.Stderr, err.Error()) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	rs, err := menuStorageService.GetResource(ctx) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Fprintf(os.Stderr, err.Error()) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pe, err := menuStorageService.GetPersister(ctx) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Fprintf(os.Stderr, err.Error()) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	userDataStore, err := menuStorageService.GetUserdataDb(ctx) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Fprintf(os.Stderr, err.Error()) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	dbResource, ok := rs.(*resource.DbResource) | ||||||
|  | 	if !ok { | ||||||
|  | 		fmt.Fprintf(os.Stderr, err.Error()) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) | ||||||
|  | 	lhs.SetDataStore(&userDataStore) | ||||||
|  | 	lhs.SetPersister(pe) | ||||||
|  | 
 | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Fprintf(os.Stderr, err.Error()) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if AccountService == nil { | ||||||
|  | 		AccountService = &server.AccountService{} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch AccountService.(type) { | ||||||
|  | 	case *server.TestAccountService: | ||||||
|  | 		go func() { | ||||||
|  | 			eventChannel <- false | ||||||
|  | 		}() | ||||||
|  | 	case *server.AccountService: | ||||||
|  | 		go func() { | ||||||
|  | 			time.Sleep(5 * time.Second) // Wait for 5 seconds
 | ||||||
|  | 			eventChannel <- true | ||||||
|  | 		}() | ||||||
|  | 	default: | ||||||
|  | 		panic("Unknown account service type") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	hl, err := lhs.GetHandler(AccountService) | ||||||
|  | 	if err != nil { | ||||||
|  | 		fmt.Fprintf(os.Stderr, err.Error()) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	en := lhs.GetEngine() | ||||||
|  | 	en = en.WithFirst(hl.Init) | ||||||
|  | 	cleanFn := func() { | ||||||
|  | 		err := en.Finish() | ||||||
|  | 		if err != nil { | ||||||
|  | 			logg.Errorf(err.Error()) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err = menuStorageService.Close() | ||||||
|  | 		if err != nil { | ||||||
|  | 			logg.Errorf(err.Error()) | ||||||
|  | 		} | ||||||
|  | 		logg.Infof("testengine storage closed") | ||||||
|  | 	} | ||||||
|  | 	return en, cleanFn, eventChannel | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								internal/testutil/offlinetest.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								internal/testutil/offlinetest.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | // +build !online
 | ||||||
|  | 
 | ||||||
|  | package testutil | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"git.grassecon.net/urdt/ussd/internal/handlers/server" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	AccountService server.AccountServiceInterface = &server.TestAccountService{} | ||||||
|  | ) | ||||||
							
								
								
									
										9
									
								
								internal/testutil/onlinetest.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								internal/testutil/onlinetest.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | // +build online
 | ||||||
|  | 
 | ||||||
|  | package testutil | ||||||
|  | 
 | ||||||
|  | import "git.grassecon.net/urdt/ussd/internal/handlers/server" | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	AccountService server.AccountServiceInterface | ||||||
|  | ) | ||||||
							
								
								
									
										460
									
								
								menutraversal_test/group_test.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										460
									
								
								menutraversal_test/group_test.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,460 @@ | |||||||
|  | { | ||||||
|  |     "groups": [ | ||||||
|  |         { | ||||||
|  |             "name": "my_account_change_pin", | ||||||
|  |             "steps": [ | ||||||
|  |                 { | ||||||
|  |                     "input": "", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "5", | ||||||
|  |                     "expectedContent": "PIN Management\n1:Change PIN\n2:Reset other's PIN\n3:Guard my PIN\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "Enter your old PIN\n\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "Enter a new four number PIN:\n\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "Confirm your new PIN:\n\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "Your PIN change request has been successful\n\n0:Back\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "menu_my_account_language_change", | ||||||
|  |             "steps": [ | ||||||
|  |                 { | ||||||
|  |                     "input": "", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "2", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1235", | ||||||
|  |                     "expectedContent": "Incorrect pin\n1:retry\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "Select language:\n0:english\n1:kiswahili" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "Your language change request was successful.\n0:Back\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "menu_my_account_check_my_balance", | ||||||
|  |             "steps": [ | ||||||
|  |                 { | ||||||
|  |                     "input": "", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "Balances:\n1:My balance\n2:Community balance\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1235", | ||||||
|  |                     "expectedContent": "Incorrect pin\n1:retry\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "Your balance is 0.003 CELO\n0:Back\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                      "expectedContent": "Balances:\n1:My balance\n2:Community balance\n0:Back" | ||||||
|  |                      | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "menu_my_account_check_community_balance", | ||||||
|  |             "steps": [ | ||||||
|  |                 { | ||||||
|  |                     "input": "", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "Balances:\n1:My balance\n2:Community balance\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "2", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1235", | ||||||
|  |                     "expectedContent": "Incorrect pin\n1:retry\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "Your community balance is 0.003 CELO\n0:Back\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                      "expectedContent": "Balances:\n1:My balance\n2:Community balance\n0:Back" | ||||||
|  |                      | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "menu_my_account_edit_firstname", | ||||||
|  |             "steps": [ | ||||||
|  |                 { | ||||||
|  |                     "input": "", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "Enter your first names:\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "foo", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "Profile updated successfully\n\n0:Back\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "menu_my_account_edit_familyname", | ||||||
|  |             "steps": [ | ||||||
|  |                 { | ||||||
|  |                     "input": "", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "2", | ||||||
|  |                     "expectedContent": "Enter family name:\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "bar", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "Profile updated successfully\n\n0:Back\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 } | ||||||
|  |                 | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "menu_my_account_edit_gender", | ||||||
|  |             "steps": [ | ||||||
|  |                 { | ||||||
|  |                     "input": "", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "Select gender: \n1:Male\n2:Female\n3:Unspecified\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "Profile updated successfully\n\n0:Back\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "menu_my_account_edit_yob", | ||||||
|  |             "steps": [ | ||||||
|  |                 { | ||||||
|  |                     "input": "", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "4", | ||||||
|  |                     "expectedContent": "Enter your year of birth\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1945", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "Profile updated successfully\n\n0:Back\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "menu_my_account_edit_location", | ||||||
|  |             "steps": [ | ||||||
|  |                 { | ||||||
|  |                     "input": "", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "5", | ||||||
|  |                     "expectedContent": "Enter your location:\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "Kilifi", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "Profile updated successfully\n\n0:Back\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "menu_my_account_edit_offerings", | ||||||
|  |             "steps": [ | ||||||
|  |                 { | ||||||
|  |                     "input": "", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "6", | ||||||
|  |                     "expectedContent": "Enter the services or goods you offer: \n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "Bananas", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "Profile updated successfully\n\n0:Back\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "menu_my_account_view_profile", | ||||||
|  |             "steps": [ | ||||||
|  |                 { | ||||||
|  |                     "input": "", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "3", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "7", | ||||||
|  |                     "expectedContent": "Please enter your PIN:" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "1234", | ||||||
|  |                     "expectedContent": "My profile:\nName: foo bar\nGender: male\nAge: 79\nLocation: Kilifi\nYou provide: Bananas\n\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My profile\n1:Edit name\n2:Edit family name\n3:Edit gender\n4:Edit year of birth\n5:Edit location\n6:Edit offerings\n7:View profile\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "input": "0", | ||||||
|  |                     "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         } | ||||||
|  |     ] | ||||||
|  | } | ||||||
|  |        | ||||||
|  |          | ||||||
|  |         | ||||||
|  |          | ||||||
|  |      | ||||||
|  | 
 | ||||||
							
								
								
									
										278
									
								
								menutraversal_test/menu_traversal_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										278
									
								
								menutraversal_test/menu_traversal_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,278 @@ | |||||||
|  | package menutraversaltest | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"context" | ||||||
|  | 	"log" | ||||||
|  | 	"math/rand" | ||||||
|  | 	"os" | ||||||
|  | 	"regexp" | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"git.grassecon.net/urdt/ussd/driver" | ||||||
|  | 	"git.grassecon.net/urdt/ussd/internal/testutil" | ||||||
|  | 	"github.com/gofrs/uuid" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	testData      = driver.ReadData() | ||||||
|  | 	testStore     = ".test_state" | ||||||
|  | 	groupTestFile = "group_test.json" | ||||||
|  | 	sessionID     string | ||||||
|  | 	src           = rand.NewSource(42) | ||||||
|  | 	g             = rand.New(src) | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func GenerateSessionId() string { | ||||||
|  | 	uu := uuid.NewGenWithOptions(uuid.WithRandomReader(g)) | ||||||
|  | 	v, err := uu.NewV4() | ||||||
|  | 	if err != nil { | ||||||
|  | 		panic(err) | ||||||
|  | 	} | ||||||
|  | 	return v.String() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Extract the public key from the engine response
 | ||||||
|  | func extractPublicKey(response []byte) string { | ||||||
|  | 	// Regex pattern to match the public key starting with 0x and 40 characters
 | ||||||
|  | 	re := regexp.MustCompile(`0x[a-fA-F0-9]{40}`) | ||||||
|  | 	match := re.Find(response) | ||||||
|  | 	if match != nil { | ||||||
|  | 		return string(match) | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestMain(m *testing.M) { | ||||||
|  | 	sessionID = GenerateSessionId() | ||||||
|  | 	defer func() { | ||||||
|  | 		if err := os.RemoveAll(testStore); err != nil { | ||||||
|  | 			log.Fatalf("Failed to delete state store %s: %v", testStore, err) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 	m.Run() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestAccountCreationSuccessful(t *testing.T) { | ||||||
|  | 	en, fn, eventChannel := testutil.TestEngine(sessionID) | ||||||
|  | 	defer fn() | ||||||
|  | 	ctx := context.Background() | ||||||
|  | 	sessions := testData | ||||||
|  | 	for _, session := range sessions { | ||||||
|  | 		groups := driver.FilterGroupsByName(session.Groups, "account_creation_successful") | ||||||
|  | 		for _, group := range groups { | ||||||
|  | 			for _, step := range group.Steps { | ||||||
|  | 				cont, err := en.Exec(ctx, []byte(step.Input)) | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Fatalf("Test case '%s' failed at input '%s': %v", group.Name, step.Input, err) | ||||||
|  | 				} | ||||||
|  | 				if !cont { | ||||||
|  | 					break | ||||||
|  | 				} | ||||||
|  | 				w := bytes.NewBuffer(nil) | ||||||
|  | 				_, err = en.Flush(ctx, w) | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Fatalf("Test case '%s' failed during Flush: %v", group.Name, err) | ||||||
|  | 				} | ||||||
|  | 				b := w.Bytes() | ||||||
|  | 				match, err := step.MatchesExpectedContent(b) | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Fatalf("Error compiling regex for step '%s': %v", step.Input, err) | ||||||
|  | 				} | ||||||
|  | 				if !match { | ||||||
|  | 					t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", step.ExpectedContent, b) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	<-eventChannel | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestAccountRegistrationRejectTerms(t *testing.T) { | ||||||
|  | 	// Generate a new UUID for this edge case test
 | ||||||
|  | 	uu := uuid.NewGenWithOptions(uuid.WithRandomReader(g)) | ||||||
|  | 	v, err := uu.NewV4() | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fail() | ||||||
|  | 	} | ||||||
|  | 	edgeCaseSessionID := v.String() | ||||||
|  | 	en, fn, _ := testutil.TestEngine(edgeCaseSessionID) | ||||||
|  | 	defer fn() | ||||||
|  | 	ctx := context.Background() | ||||||
|  | 	sessions := testData | ||||||
|  | 	for _, session := range sessions { | ||||||
|  | 		groups := driver.FilterGroupsByName(session.Groups, "account_creation_reject_terms") | ||||||
|  | 		for _, group := range groups { | ||||||
|  | 			for _, step := range group.Steps { | ||||||
|  | 				cont, err := en.Exec(ctx, []byte(step.Input)) | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Fatalf("Test case '%s' failed at input '%s': %v", group.Name, step.Input, err) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 				if !cont { | ||||||
|  | 					break | ||||||
|  | 				} | ||||||
|  | 				w := bytes.NewBuffer(nil) | ||||||
|  | 				if _, err := en.Flush(ctx, w); err != nil { | ||||||
|  | 					t.Fatalf("Test case '%s' failed during Flush: %v", group.Name, err) | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				b := w.Bytes() | ||||||
|  | 				match, err := step.MatchesExpectedContent(b) | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Fatalf("Error compiling regex for step '%s': %v", step.Input, err) | ||||||
|  | 				} | ||||||
|  | 				if !match { | ||||||
|  | 					t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", step.ExpectedContent, b) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestMainMenuHelp(t *testing.T) { | ||||||
|  | 	en, fn, _ := testutil.TestEngine(sessionID) | ||||||
|  | 	defer fn() | ||||||
|  | 	ctx := context.Background() | ||||||
|  | 	sessions := testData | ||||||
|  | 	for _, session := range sessions { | ||||||
|  | 		groups := driver.FilterGroupsByName(session.Groups, "main_menu_help") | ||||||
|  | 		for _, group := range groups { | ||||||
|  | 			for _, step := range group.Steps { | ||||||
|  | 				cont, err := en.Exec(ctx, []byte(step.Input)) | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Fatalf("Test case '%s' failed at input '%s': %v", group.Name, step.Input, err) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 				if !cont { | ||||||
|  | 					break | ||||||
|  | 				} | ||||||
|  | 				w := bytes.NewBuffer(nil) | ||||||
|  | 				if _, err := en.Flush(ctx, w); err != nil { | ||||||
|  | 					t.Fatalf("Test case '%s' failed during Flush: %v", group.Name, err) | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				b := w.Bytes() | ||||||
|  | 				match, err := step.MatchesExpectedContent(b) | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Fatalf("Error compiling regex for step '%s': %v", step.Input, err) | ||||||
|  | 				} | ||||||
|  | 				if !match { | ||||||
|  | 					t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", step.ExpectedContent, b) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestMainMenuQuit(t *testing.T) { | ||||||
|  | 	en, fn, _ := testutil.TestEngine(sessionID) | ||||||
|  | 	defer fn() | ||||||
|  | 	ctx := context.Background() | ||||||
|  | 	sessions := testData | ||||||
|  | 	for _, session := range sessions { | ||||||
|  | 		groups := driver.FilterGroupsByName(session.Groups, "main_menu_quit") | ||||||
|  | 		for _, group := range groups { | ||||||
|  | 			for _, step := range group.Steps { | ||||||
|  | 				cont, err := en.Exec(ctx, []byte(step.Input)) | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Fatalf("Test case '%s' failed at input '%s': %v", group.Name, step.Input, err) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 				if !cont { | ||||||
|  | 					break | ||||||
|  | 				} | ||||||
|  | 				w := bytes.NewBuffer(nil) | ||||||
|  | 				if _, err := en.Flush(ctx, w); err != nil { | ||||||
|  | 					t.Fatalf("Test case '%s' failed during Flush: %v", group.Name, err) | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				b := w.Bytes() | ||||||
|  | 				match, err := step.MatchesExpectedContent(b) | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Fatalf("Error compiling regex for step '%s': %v", step.Input, err) | ||||||
|  | 				} | ||||||
|  | 				if !match { | ||||||
|  | 					t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", step.ExpectedContent, b) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestMyAccount_MyAddress(t *testing.T) { | ||||||
|  | 	en, fn, _ := testutil.TestEngine(sessionID) | ||||||
|  | 	defer fn() | ||||||
|  | 	ctx := context.Background() | ||||||
|  | 	sessions := testData | ||||||
|  | 	for _, session := range sessions { | ||||||
|  | 		groups := driver.FilterGroupsByName(session.Groups, "menu_my_account_my_address") | ||||||
|  | 		for _, group := range groups { | ||||||
|  | 			for index, step := range group.Steps { | ||||||
|  | 				t.Logf("step %v with input %v", index, step.Input) | ||||||
|  | 				cont, err := en.Exec(ctx, []byte(step.Input)) | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Errorf("Test case '%s' failed at input '%s': %v", group.Name, step.Input, err) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 				if !cont { | ||||||
|  | 					break | ||||||
|  | 				} | ||||||
|  | 				w := bytes.NewBuffer(nil) | ||||||
|  | 				if _, err := en.Flush(ctx, w); err != nil { | ||||||
|  | 					t.Errorf("Test case '%s' failed during Flush: %v", group.Name, err) | ||||||
|  | 				} | ||||||
|  | 				b := w.Bytes() | ||||||
|  | 
 | ||||||
|  | 				publicKey := extractPublicKey(b) | ||||||
|  | 				expectedContent := bytes.Replace([]byte(step.ExpectedContent), []byte("{public_key}"), []byte(publicKey), -1) | ||||||
|  | 				step.ExpectedContent = string(expectedContent) | ||||||
|  | 				match, err := step.MatchesExpectedContent(b) | ||||||
|  | 				if err != nil { | ||||||
|  | 					t.Fatalf("Error compiling regex for step '%s': %v", step.Input, err) | ||||||
|  | 				} | ||||||
|  | 				if !match { | ||||||
|  | 					t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", expectedContent, b) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestGroups(t *testing.T) { | ||||||
|  | 	groups, err := driver.LoadTestGroups(groupTestFile) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to load test groups: %v", err) | ||||||
|  | 	} | ||||||
|  | 	en, fn, _ := testutil.TestEngine(sessionID) | ||||||
|  | 	defer fn() | ||||||
|  | 	ctx := context.Background() | ||||||
|  | 	// Create test cases from loaded groups
 | ||||||
|  | 	tests := driver.CreateTestCases(groups) | ||||||
|  | 	for _, tt := range tests { | ||||||
|  | 		t.Run(tt.Name, func(t *testing.T) { | ||||||
|  | 			cont, err := en.Exec(ctx, []byte(tt.Input)) | ||||||
|  | 			if err != nil { | ||||||
|  | 				t.Errorf("Test case '%s' failed at input '%s': %v", tt.Name, tt.Input, err) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			if !cont { | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			w := bytes.NewBuffer(nil) | ||||||
|  | 			if _, err := en.Flush(ctx, w); err != nil { | ||||||
|  | 				t.Errorf("Test case '%s' failed during Flush: %v", tt.Name, err) | ||||||
|  | 			} | ||||||
|  | 			b := w.Bytes() | ||||||
|  | 			match, err := tt.MatchesExpectedContent(b) | ||||||
|  | 			if err != nil { | ||||||
|  | 				t.Fatalf("Error compiling regex for step '%s': %v", tt.Input, err) | ||||||
|  | 			} | ||||||
|  | 			if !match { | ||||||
|  | 				t.Fatalf("expected:\n\t%s\ngot:\n\t%s\n", tt.ExpectedContent, b) | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										153
									
								
								menutraversal_test/test_setup.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								menutraversal_test/test_setup.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,153 @@ | |||||||
|  | [ | ||||||
|  |     { | ||||||
|  |         "name": "session one", | ||||||
|  |         "groups": [ | ||||||
|  |             { | ||||||
|  |                 "name": "account_creation_successful", | ||||||
|  |                 "steps": [ | ||||||
|  |                     { | ||||||
|  |                         "input": "", | ||||||
|  |                         "expectedContent": "Welcome to Sarafu Network\nPlease select a language\n0:english\n1:kiswahili" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "0", | ||||||
|  |                         "expectedContent": "Do you agree to terms and conditions?\n0:yes\n1:no" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "0", | ||||||
|  |                         "expectedContent": "Please enter a new four number PIN for your account:\n0:Exit" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "1234", | ||||||
|  |                         "expectedContent": "Enter your four number PIN again:" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "1111", | ||||||
|  |                         "expectedContent": "The PIN is not a match. Try again\n1:retry\n9:Quit" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "1", | ||||||
|  |                         "expectedContent": "Enter your four number PIN again:" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "1234", | ||||||
|  |                         "expectedContent": "Your account is being created...Thank you for using Sarafu. Goodbye!" | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 "name": "account_creation_reject_terms", | ||||||
|  |                 "steps": [ | ||||||
|  |                     { | ||||||
|  |                         "input": "", | ||||||
|  |                         "expectedContent": "Welcome to Sarafu Network\nPlease select a language\n0:english\n1:kiswahili" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "0", | ||||||
|  |                         "expectedContent": "Do you agree to terms and conditions?\n0:yes\n1:no" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "1", | ||||||
|  |                         "expectedContent": "Thank you for using Sarafu. Goodbye!" | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 "name": "send_with_invalid_inputs", | ||||||
|  |                 "steps": [ | ||||||
|  |                     { | ||||||
|  |                         "input": "", | ||||||
|  |                         "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "1", | ||||||
|  |                         "expectedContent": "Enter recipient's phone number:\n0:Back" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "000", | ||||||
|  |                         "expectedContent": "000 is not registered or invalid, please try again:\n1:retry\n9:Quit" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "1", | ||||||
|  |                         "expectedContent": "Enter recipient's phone number:\n0:Back" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "065656", | ||||||
|  |                         "expectedContent": "Maximum amount: 0.003 CELO\nEnter amount:\n0:Back" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "0.1", | ||||||
|  |                         "expectedContent": "Amount 0.1 is invalid, please try again:\n1:retry\n9:Quit" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "1", | ||||||
|  |                         "expectedContent": "Maximum amount: 0.003 CELO\nEnter amount:\n0:Back" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "0.001", | ||||||
|  |                         "expectedContent": "065656 will receive 0.001 from {public_key}\nPlease enter your PIN to confirm:\n0:Back\n9:Quit" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "1222", | ||||||
|  |                         "expectedContent": "Incorrect pin\n1:retry\n9:Quit" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "1", | ||||||
|  |                         "expectedContent": "065656 will receive 0.001 from {public_key}\nPlease enter your PIN to confirm:\n0:Back\n9:Quit" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "1234", | ||||||
|  |                         "expectedContent": "Your request has been sent. 065656 will receive 0.001 from {public_key}." | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 "name": "main_menu_help", | ||||||
|  |                 "steps": [ | ||||||
|  |                     { | ||||||
|  |                         "input": "", | ||||||
|  |                         "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "4", | ||||||
|  |                         "expectedContent": "For more help,please call: 0757628885" | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 "name": "main_menu_quit", | ||||||
|  |                 "steps": [ | ||||||
|  |                     { | ||||||
|  |                         "input": "", | ||||||
|  |                         "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "9", | ||||||
|  |                         "expectedContent": "Thank you for using Sarafu. Goodbye!" | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |                 "name": "menu_my_account_my_address", | ||||||
|  |                 "steps": [ | ||||||
|  |                     { | ||||||
|  |                         "input": "", | ||||||
|  |                         "expectedContent": "Balance: 0.003 CELO\n\n1:Send\n2:My Vouchers\n3:My Account\n4:Help\n9:Quit" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "3", | ||||||
|  |                         "expectedContent": "My Account\n1:Profile\n2:Change language\n3:Check balances\n4:Check statement\n5:PIN options\n6:My Address\n0:Back" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "6", | ||||||
|  |                         "expectedContent": "Address: {public_key}\n9:Quit" | ||||||
|  |                     }, | ||||||
|  |                     { | ||||||
|  |                         "input": "9", | ||||||
|  |                         "expectedContent": "Thank you for using Sarafu. Goodbye!" | ||||||
|  |                     } | ||||||
|  |                 ] | ||||||
|  |             } | ||||||
|  |         ] | ||||||
|  |     } | ||||||
|  | ] | ||||||
| @ -1,4 +1,5 @@ | |||||||
| LOAD reset_account_authorized 16 | LOAD reset_account_authorized 16 | ||||||
|  | RELOAD reset_account_authorized | ||||||
| LOAD reset_allow_update 0 | LOAD reset_allow_update 0 | ||||||
| RELOAD reset_allow_update | RELOAD reset_allow_update | ||||||
| MOUT edit_name 1 | MOUT edit_name 1 | ||||||
|  | |||||||
| @ -1 +1 @@ | |||||||
| Enter a new four number pin | Enter a new four number PIN: | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user