-
Notifications
You must be signed in to change notification settings - Fork 1
/
scenario.go
124 lines (101 loc) · 2.43 KB
/
scenario.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package dispatcher
import (
"errors"
"fmt"
)
// Scenario handle URIs accross the application
type Scenario struct {
currentStep *Step
runError error
startFunc func()
endFunc func()
steps []*Step
}
// Play runs a scenario through all its steps
func (s *Scenario) Play(event *Event) {
if s.startFunc != nil {
s.startFunc()
}
var currentStep, nextStep *Step
var runError error
currentStep = s.CurrentStep()
// No initial Step set
if currentStep == nil {
s.runError = errors.New("No initial step provided")
return
}
for {
runError = currentStep.Run(event)
if runError != nil {
s.runError = runError
return
}
// Going to next step
nextStep = s.NextStep()
if nextStep != nil {
// Updating step
s.SetCurrentStep(nextStep)
currentStep = nextStep
} else {
// No next step, breaking out
if s.endFunc != nil {
s.endFunc()
}
return
}
}
}
// OnStart defines a callback to run when the scenario starts
func (s *Scenario) OnStart(callback func()) *Scenario {
s.startFunc = callback
return s
}
// OnEnd defines a callback to run when the scenario ends
func (s *Scenario) OnEnd(callback func()) *Scenario {
s.endFunc = callback
return s
}
// SetInitialStep defines the first step for the scenario
func (s *Scenario) SetInitialStep(step string) error {
foundStep := s.findStepByName(step)
if foundStep == nil {
return fmt.Errorf("Undefined initial step %s", step)
}
s.SetCurrentStep(foundStep)
return nil
}
// SetCurrentStep updates the scenario current step
func (s *Scenario) SetCurrentStep(step *Step) {
s.currentStep = step
}
// CurrentStep returns the current scenario step
func (s *Scenario) CurrentStep() *Step {
return s.currentStep
}
// RunError return a run error if any
func (s *Scenario) RunError() error {
return s.runError
}
// From defines a step with the given name for the current scenario
func (s *Scenario) From(name string) *Step {
newStep := &Step{from: name}
s.steps = append(s.steps, newStep)
return newStep
}
// NextStep returns next step to run, based on the current step next info
func (s *Scenario) NextStep() *Step {
nextStepName := s.currentStep.Next()
if nextStepName != "" {
return s.findStepByName(nextStepName)
}
return nil
}
// findStepByName returns a step if it exists
func (s *Scenario) findStepByName(name string) *Step {
for stepIndex, step := range s.steps {
if step.From() == name {
return s.steps[stepIndex]
}
}
return nil
}