Added tests for CreateAccount and SavePin
This commit is contained in:
		
							parent
							
								
									b344720fdc
								
							
						
					
					
						commit
						802c3f92df
					
				@ -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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewHandlers(path string, st *state.State) *Handlers {
 | 
			
		||||
@ -41,6 +53,7 @@ func NewHandlers(path string, st *state.State) *Handlers {
 | 
			
		||||
			St:   st,
 | 
			
		||||
		},
 | 
			
		||||
		accountFileHandler: utils.NewAccountFileHandler(path + "_data"),
 | 
			
		||||
		accountCreator:     &ServerAccountCreator{},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -81,7 +94,7 @@ func (h *Handlers) CreateAccount(ctx context.Context, sym string, input []byte)
 | 
			
		||||
		return res, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	accountResp, err := server.CreateAccount()
 | 
			
		||||
	accountResp, err := h.accountCreator.CreateAccount()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		res.FlagSet = append(res.FlagSet, models.USERFLAG_ACCOUNT_CREATION_FAILED)
 | 
			
		||||
		return res, err
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,281 @@
 | 
			
		||||
package ussd
 | 
			
		||||
 | 
			
		||||
import "testing"
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"git.defalsify.org/vise.git/resource"
 | 
			
		||||
	"git.grassecon.net/urdt/ussd/internal/models"
 | 
			
		||||
	"git.grassecon.net/urdt/ussd/internal/utils"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MockAccountCreator implements AccountCreator for testing
 | 
			
		||||
type MockAccountCreator struct {
 | 
			
		||||
	mockResponse *models.AccountResponse
 | 
			
		||||
	mockError    error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *MockAccountCreator) CreateAccount() (*models.AccountResponse, error) {
 | 
			
		||||
	return m.mockResponse, m.mockError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
func CreateAccountTest(t *testing.T){
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
	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",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Initialize Handlers with mock account creator
 | 
			
		||||
	h := &Handlers{
 | 
			
		||||
		accountFileHandler: accountFileHandler,
 | 
			
		||||
		accountCreator:     mockAccountCreator,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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