forked from urdt/ussd
Merge remote-tracking branch 'refs/remotes/origin/wip-account-creation' into wip-account-creation
This commit is contained in:
commit
edcbf9979d
@ -29,9 +29,21 @@ type FSData struct {
|
||||
St *state.State
|
||||
}
|
||||
|
||||
type AccountCreator interface {
|
||||
CreateAccount() (*models.AccountResponse, error)
|
||||
}
|
||||
|
||||
// ServerAccountCreator implements AccountCreator using the server package
|
||||
type ServerAccountCreator struct{}
|
||||
|
||||
func (s *ServerAccountCreator) CreateAccount() (*models.AccountResponse, error) {
|
||||
return server.CreateAccount()
|
||||
}
|
||||
|
||||
type Handlers struct {
|
||||
fs *FSData
|
||||
//accountFileHandler *utils.AccountFileHandler
|
||||
accountCreator AccountCreator
|
||||
accountFileHandler utils.AccountFileHandlerInterface
|
||||
accountService server.AccountServiceInterface
|
||||
}
|
||||
@ -43,6 +55,7 @@ func NewHandlers(path string, st *state.State) *Handlers {
|
||||
St: st,
|
||||
},
|
||||
accountFileHandler: utils.NewAccountFileHandler(path + "_data"),
|
||||
accountCreator: &ServerAccountCreator{},
|
||||
accountService: &server.AccountService{},
|
||||
}
|
||||
}
|
||||
|
@ -1,53 +1,281 @@
|
||||
package ussd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"git.grassecon.net/urdt/ussd/internal/handlers/ussd/mocks"
|
||||
"git.defalsify.org/vise.git/resource"
|
||||
"git.grassecon.net/urdt/ussd/internal/models"
|
||||
"github.com/alecthomas/assert/v2"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"git.grassecon.net/urdt/ussd/internal/utils"
|
||||
)
|
||||
|
||||
func TestCreateAccount_Success(t *testing.T) {
|
||||
mockAccountFileHandler := new(mocks.MockAccountFileHandler)
|
||||
mockCreateAccountService := new(mocks.MockAccountService)
|
||||
// MockAccountCreator implements AccountCreator for testing
|
||||
type MockAccountCreator struct {
|
||||
mockResponse *models.AccountResponse
|
||||
mockError error
|
||||
}
|
||||
|
||||
mockAccountFileHandler.On("EnsureFileExists").Return(nil)
|
||||
func (m *MockAccountCreator) CreateAccount() (*models.AccountResponse, error) {
|
||||
return m.mockResponse, m.mockError
|
||||
}
|
||||
|
||||
// Mock that no account data exists
|
||||
mockAccountFileHandler.On("ReadAccountData").Return(nil, nil)
|
||||
func TestCreateAccount(t *testing.T) {
|
||||
// Setup
|
||||
tempDir, err := os.MkdirTemp("", "test_create_account")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir) // Clean up after the test run
|
||||
|
||||
// Define expected account response after api call
|
||||
expectedAccountResp := &models.AccountResponse{
|
||||
Ok: true,
|
||||
Result: struct {
|
||||
CustodialId json.Number `json:"custodialId"`
|
||||
PublicKey string `json:"publicKey"`
|
||||
TrackingId string `json:"trackingId"`
|
||||
}{
|
||||
CustodialId: "12",
|
||||
PublicKey: "some-public-key",
|
||||
TrackingId: "some-tracking-id",
|
||||
sessionID := "07xxxxxxxx"
|
||||
|
||||
// Set up the data file path using the session ID
|
||||
accountFilePath := filepath.Join(tempDir, sessionID+"_data")
|
||||
|
||||
// Initialize account file handler
|
||||
accountFileHandler := utils.NewAccountFileHandler(accountFilePath)
|
||||
|
||||
// Create a mock account creator
|
||||
mockAccountCreator := &MockAccountCreator{
|
||||
mockResponse: &models.AccountResponse{
|
||||
Ok: true,
|
||||
Result: struct {
|
||||
CustodialId json.Number `json:"custodialId"`
|
||||
PublicKey string `json:"publicKey"`
|
||||
TrackingId string `json:"trackingId"`
|
||||
}{
|
||||
CustodialId: "test-custodial-id",
|
||||
PublicKey: "test-public-key",
|
||||
TrackingId: "test-tracking-id",
|
||||
},
|
||||
},
|
||||
}
|
||||
mockCreateAccountService.On("CreateAccount").Return(expectedAccountResp, nil)
|
||||
|
||||
// Mock WriteAccountData to not error
|
||||
mockAccountFileHandler.On("WriteAccountData", mock.Anything).Return(nil)
|
||||
|
||||
handlers := &Handlers{
|
||||
accountService: mockCreateAccountService,
|
||||
// Initialize Handlers with mock account creator
|
||||
h := &Handlers{
|
||||
accountFileHandler: accountFileHandler,
|
||||
accountCreator: mockAccountCreator,
|
||||
}
|
||||
|
||||
|
||||
actualResponse, err := handlers.accountService.CreateAccount()
|
||||
tests := []struct {
|
||||
name string
|
||||
existingData map[string]string
|
||||
expectedResult resource.Result
|
||||
expectedData map[string]string
|
||||
}{
|
||||
{
|
||||
name: "New account creation",
|
||||
existingData: nil,
|
||||
expectedResult: resource.Result{
|
||||
FlagSet: []uint32{models.USERFLAG_ACCOUNT_CREATED},
|
||||
},
|
||||
expectedData: map[string]string{
|
||||
"TrackingId": "test-tracking-id",
|
||||
"PublicKey": "test-public-key",
|
||||
"CustodialId": "test-custodial-id",
|
||||
"Status": "PENDING",
|
||||
"Gender": "Not provided",
|
||||
"YOB": "Not provided",
|
||||
"Location": "Not provided",
|
||||
"Offerings": "Not provided",
|
||||
"FirstName": "Not provided",
|
||||
"FamilyName": "Not provided",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Existing account",
|
||||
existingData: map[string]string{
|
||||
"TrackingId": "test-tracking-id",
|
||||
"PublicKey": "test-public-key",
|
||||
"CustodialId": "test-custodial-id",
|
||||
"Status": "PENDING",
|
||||
"Gender": "Not provided",
|
||||
"YOB": "Not provided",
|
||||
"Location": "Not provided",
|
||||
"Offerings": "Not provided",
|
||||
"FirstName": "Not provided",
|
||||
"FamilyName": "Not provided",
|
||||
},
|
||||
expectedResult: resource.Result{
|
||||
FlagSet: []uint32{models.USERFLAG_ACCOUNT_CREATED},
|
||||
},
|
||||
expectedData: map[string]string{
|
||||
"TrackingId": "test-tracking-id",
|
||||
"PublicKey": "test-public-key",
|
||||
"CustodialId": "test-custodial-id",
|
||||
"Status": "PENDING",
|
||||
"Gender": "Not provided",
|
||||
"YOB": "Not provided",
|
||||
"Location": "Not provided",
|
||||
"Offerings": "Not provided",
|
||||
"FirstName": "Not provided",
|
||||
"FamilyName": "Not provided",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Assert results
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t,expectedAccountResp.Ok,true)
|
||||
assert.Equal(t,expectedAccountResp,actualResponse)
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Set up the data file path using the session ID
|
||||
accountFilePath := filepath.Join(tempDir, sessionID+"_data")
|
||||
|
||||
// Setup existing data if any
|
||||
if tt.existingData != nil {
|
||||
data, _ := json.Marshal(tt.existingData)
|
||||
err := os.WriteFile(accountFilePath, data, 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to write existing data: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Call the function
|
||||
result, err := h.CreateAccount(context.Background(), "", nil)
|
||||
|
||||
// Check for errors
|
||||
if err != nil {
|
||||
t.Fatalf("CreateAccount returned an error: %v", err)
|
||||
}
|
||||
|
||||
// Check the result
|
||||
if len(result.FlagSet) != len(tt.expectedResult.FlagSet) {
|
||||
t.Errorf("Expected %d flags, got %d", len(tt.expectedResult.FlagSet), len(result.FlagSet))
|
||||
}
|
||||
for i, flag := range tt.expectedResult.FlagSet {
|
||||
if result.FlagSet[i] != flag {
|
||||
t.Errorf("Expected flag %d, got %d", flag, result.FlagSet[i])
|
||||
}
|
||||
}
|
||||
|
||||
// Check the stored data
|
||||
data, err := os.ReadFile(accountFilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read account data file: %v", err)
|
||||
}
|
||||
|
||||
var storedData map[string]string
|
||||
err = json.Unmarshal(data, &storedData)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to unmarshal stored data: %v", err)
|
||||
}
|
||||
|
||||
for key, expectedValue := range tt.expectedData {
|
||||
if storedValue, ok := storedData[key]; !ok || storedValue != expectedValue {
|
||||
t.Errorf("Expected %s to be %s, got %s", key, expectedValue, storedValue)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSavePin(t *testing.T) {
|
||||
// Setup
|
||||
tempDir, err := os.MkdirTemp("", "test_save_pin")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
sessionID := "07xxxxxxxx"
|
||||
|
||||
// Set up the data file path using the session ID
|
||||
accountFilePath := filepath.Join(tempDir, sessionID+"_data")
|
||||
initialAccountData := map[string]string{
|
||||
"TrackingId": "test-tracking-id",
|
||||
"PublicKey": "test-public-key",
|
||||
}
|
||||
data, _ := json.Marshal(initialAccountData)
|
||||
err = os.WriteFile(accountFilePath, data, 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to write initial account data: %v", err)
|
||||
}
|
||||
|
||||
// Create a new AccountFileHandler and set it in the Handlers struct
|
||||
accountFileHandler := utils.NewAccountFileHandler(accountFilePath)
|
||||
h := &Handlers{
|
||||
accountFileHandler: accountFileHandler,
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input []byte
|
||||
expectedFlags []uint32
|
||||
expectedData map[string]string
|
||||
expectedErrors bool
|
||||
}{
|
||||
{
|
||||
name: "Valid PIN",
|
||||
input: []byte("1234"),
|
||||
expectedFlags: []uint32{},
|
||||
expectedData: map[string]string{
|
||||
"TrackingId": "test-tracking-id",
|
||||
"PublicKey": "test-public-key",
|
||||
"AccountPIN": "1234",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Invalid PIN - non-numeric",
|
||||
input: []byte("12ab"),
|
||||
expectedFlags: []uint32{models.USERFLAG_INCORRECTPIN},
|
||||
expectedData: initialAccountData, // No changes expected
|
||||
expectedErrors: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid PIN - less than 4 digits",
|
||||
input: []byte("123"),
|
||||
expectedFlags: []uint32{models.USERFLAG_INCORRECTPIN},
|
||||
expectedData: initialAccountData, // No changes expected
|
||||
expectedErrors: false,
|
||||
},
|
||||
{
|
||||
name: "Invalid PIN - more than 4 digits",
|
||||
input: []byte("12345"),
|
||||
expectedFlags: []uint32{models.USERFLAG_INCORRECTPIN},
|
||||
expectedData: initialAccountData, // No changes expected
|
||||
expectedErrors: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Ensure the file exists before running the test
|
||||
err := accountFileHandler.EnsureFileExists()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to ensure account file exists: %v", err)
|
||||
}
|
||||
|
||||
result, err := h.SavePin(context.Background(), "", tt.input)
|
||||
if err != nil && !tt.expectedErrors {
|
||||
t.Fatalf("SavePin returned an unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if len(result.FlagSet) != len(tt.expectedFlags) {
|
||||
t.Errorf("Expected %d flags, got %d", len(tt.expectedFlags), len(result.FlagSet))
|
||||
}
|
||||
for i, flag := range tt.expectedFlags {
|
||||
if result.FlagSet[i] != flag {
|
||||
t.Errorf("Expected flag %d, got %d", flag, result.FlagSet[i])
|
||||
}
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(accountFilePath)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read account data file: %v", err)
|
||||
}
|
||||
|
||||
var storedData map[string]string
|
||||
err = json.Unmarshal(data, &storedData)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to unmarshal stored data: %v", err)
|
||||
}
|
||||
|
||||
for key, expectedValue := range tt.expectedData {
|
||||
if storedValue, ok := storedData[key]; !ok || storedValue != expectedValue {
|
||||
t.Errorf("Expected %s to be %s, got %s", key, expectedValue, storedValue)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user