Co-authored-by: Gabriel Radureau <arcodange@gmail.com> Co-committed-by: Gabriel Radureau <arcodange@gmail.com>
103 lines
2.5 KiB
Go
103 lines
2.5 KiB
Go
package steps
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"sync"
|
|
)
|
|
|
|
// ScenarioState holds per-scenario state for step definitions
|
|
// This prevents state pollution between scenarios running in the same test process
|
|
type ScenarioState struct {
|
|
LastToken string
|
|
FirstToken string
|
|
LastUserID uint
|
|
LastSecret string
|
|
LastError string
|
|
MagicLinkEmail string
|
|
MagicLinkToken string
|
|
// Add more fields as needed for other step types
|
|
}
|
|
|
|
// scenarioStateManager manages per-scenario state isolation
|
|
type scenarioStateManager struct {
|
|
mu sync.RWMutex
|
|
states map[string]*ScenarioState
|
|
}
|
|
|
|
var globalStateManager *scenarioStateManager
|
|
var once sync.Once
|
|
|
|
// GetScenarioStateManager returns the singleton scenario state manager
|
|
func GetScenarioStateManager() *scenarioStateManager {
|
|
once.Do(func() {
|
|
globalStateManager = &scenarioStateManager{
|
|
states: make(map[string]*ScenarioState),
|
|
}
|
|
})
|
|
return globalStateManager
|
|
}
|
|
|
|
// scenarioKey generates a unique key for a scenario
|
|
func scenarioKey(scenario string) string {
|
|
// Use SHA256 hash to create a consistent, bounded-length key
|
|
hash := sha256.Sum256([]byte(scenario))
|
|
return hex.EncodeToString(hash[:])
|
|
}
|
|
|
|
// GetState returns the state for a given scenario, creating it if necessary
|
|
func (sm *scenarioStateManager) GetState(scenario string) *ScenarioState {
|
|
sm.mu.RLock()
|
|
key := scenarioKey(scenario)
|
|
state, exists := sm.states[key]
|
|
sm.mu.RUnlock()
|
|
|
|
if exists {
|
|
return state
|
|
}
|
|
|
|
sm.mu.Lock()
|
|
defer sm.mu.Unlock()
|
|
|
|
// Double-check after acquiring write lock
|
|
if state, exists = sm.states[key]; exists {
|
|
return state
|
|
}
|
|
|
|
state = &ScenarioState{}
|
|
sm.states[key] = state
|
|
return state
|
|
}
|
|
|
|
// ClearState removes the state for a given scenario
|
|
func (sm *scenarioStateManager) ClearState(scenario string) {
|
|
sm.mu.Lock()
|
|
defer sm.mu.Unlock()
|
|
key := scenarioKey(scenario)
|
|
delete(sm.states, key)
|
|
}
|
|
|
|
// ClearAllStates removes all scenario states
|
|
func (sm *scenarioStateManager) ClearAllStates() {
|
|
sm.mu.Lock()
|
|
defer sm.mu.Unlock()
|
|
sm.states = make(map[string]*ScenarioState)
|
|
}
|
|
|
|
// Package-level convenience functions
|
|
|
|
// GetScenarioState returns the state for the current scenario
|
|
func GetScenarioState(scenario string) *ScenarioState {
|
|
return GetScenarioStateManager().GetState(scenario)
|
|
}
|
|
|
|
// ClearScenarioState removes the state for the current scenario
|
|
func ClearScenarioState(scenario string) {
|
|
GetScenarioStateManager().ClearState(scenario)
|
|
}
|
|
|
|
// ClearAllScenarioStates removes all scenario states
|
|
func ClearAllScenarioStates() {
|
|
GetScenarioStateManager().ClearAllStates()
|
|
}
|