hat-trick 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/Changelog +17 -3
- data/README.md +44 -19
- data/app/assets/javascripts/hat-trick.js.coffee +214 -123
- data/lib/hat-trick.rb +0 -2
- data/lib/hat_trick/config.rb +10 -11
- data/lib/hat_trick/controller_helpers.rb +18 -4
- data/lib/hat_trick/controller_hooks.rb +37 -23
- data/lib/hat_trick/dsl.rb +144 -50
- data/lib/hat_trick/engine.rb +6 -0
- data/lib/hat_trick/form_helper.rb +1 -1
- data/lib/hat_trick/model_methods.rb +14 -3
- data/lib/hat_trick/step.rb +24 -11
- data/lib/hat_trick/step_definition.rb +162 -36
- data/lib/hat_trick/version.rb +1 -1
- data/lib/hat_trick/wizard.rb +105 -46
- data/lib/hat_trick/wizard_definition.rb +18 -9
- data/lib/hat_trick/wizard_steps.rb +12 -3
- data/spec/lib/hat_trick/dsl_spec.rb +11 -10
- data/spec/lib/hat_trick/step_definition_spec.rb +106 -0
- data/spec/lib/hat_trick/wizard_definition_spec.rb +18 -9
- data/spec/lib/hat_trick/wizard_spec.rb +22 -17
- data/spec/spec_helper.rb +6 -0
- data/vendor/assets/javascripts/array.filter.js +22 -0
- data/vendor/assets/javascripts/history.html4.js +658 -0
- data/vendor/assets/javascripts/history.js +1991 -0
- data/vendor/assets/javascripts/jquery.form.wizard.js +162 -145
- data/vendor/assets/javascripts/jquery.history.js +77 -1
- data/vendor/assets/javascripts/json.js +480 -0
- metadata +10 -4
@@ -1,8 +1,10 @@
|
|
1
1
|
module HatTrick
|
2
2
|
class StepDefinition
|
3
3
|
attr_reader :callbacks, :include_data_key
|
4
|
-
attr_accessor :name, :fieldset, :
|
5
|
-
attr_writer :skipped
|
4
|
+
attr_accessor :name, :fieldset, :wizard
|
5
|
+
attr_writer :skipped, :first
|
6
|
+
|
7
|
+
delegate :config, :to => :wizard
|
6
8
|
|
7
9
|
def initialize(args={})
|
8
10
|
args.each_pair do |k,v|
|
@@ -12,15 +14,53 @@ module HatTrick
|
|
12
14
|
end
|
13
15
|
end
|
14
16
|
@callbacks = {}
|
15
|
-
@buttons =
|
16
|
-
|
17
|
+
@buttons = [
|
18
|
+
{ next: default_button(:next) },
|
19
|
+
{ back: default_button(:back) }
|
20
|
+
]
|
21
|
+
@skipped ||= false
|
22
|
+
@last ||= false
|
23
|
+
@first ||= false
|
24
|
+
end
|
25
|
+
|
26
|
+
def buttons
|
27
|
+
# We should check for a new translation every time because the user may
|
28
|
+
# have changed their desired localization.
|
29
|
+
@buttons.map do |b|
|
30
|
+
button_type = b.keys.first
|
31
|
+
if b[button_type][:default]
|
32
|
+
b[button_type][:label] = button_label(button_type)
|
33
|
+
end
|
34
|
+
b
|
35
|
+
end
|
17
36
|
end
|
18
37
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
38
|
+
def next_button
|
39
|
+
get_button(:next)
|
40
|
+
end
|
41
|
+
|
42
|
+
def back_button
|
43
|
+
get_button(:back)
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_button(type)
|
47
|
+
button = buttons.detect { |b| b.keys.first == type.to_sym }
|
48
|
+
button[type.to_sym] unless button.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
def default_button(type)
|
52
|
+
{ :label => button_label(type), :default => true }
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_button(button)
|
56
|
+
@buttons.delete_if do |b|
|
57
|
+
b.keys.first == button.keys.first && b[b.keys.first][:default]
|
58
|
+
end
|
59
|
+
@buttons << button
|
60
|
+
end
|
61
|
+
|
62
|
+
def delete_button(type)
|
63
|
+
@buttons.delete_if { |b| b.keys.first == type }
|
24
64
|
end
|
25
65
|
|
26
66
|
def name=(name)
|
@@ -35,14 +75,27 @@ module HatTrick
|
|
35
75
|
@fieldset or name
|
36
76
|
end
|
37
77
|
|
38
|
-
def repeat?
|
39
|
-
!repeat_of.nil?
|
40
|
-
end
|
41
|
-
|
42
78
|
def skipped?
|
43
79
|
@skipped
|
44
80
|
end
|
45
81
|
|
82
|
+
def last=(_last)
|
83
|
+
@last = _last
|
84
|
+
if @last
|
85
|
+
@buttons.delete_if { |b| b.keys.include?(:next) }
|
86
|
+
else
|
87
|
+
@buttons << { :next => default_next_button }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def last?
|
92
|
+
@last
|
93
|
+
end
|
94
|
+
|
95
|
+
def first?
|
96
|
+
@first
|
97
|
+
end
|
98
|
+
|
46
99
|
def to_s
|
47
100
|
str = "<HatTrick::Step:0x%08x :#{name}" % (object_id * 2)
|
48
101
|
str += " fieldset: #{fieldset}" if fieldset != name
|
@@ -54,19 +107,12 @@ module HatTrick
|
|
54
107
|
name.to_sym
|
55
108
|
end
|
56
109
|
|
57
|
-
def
|
58
|
-
|
59
|
-
json[:repeatOf] = repeat_of.as_json if repeat?
|
60
|
-
json[:buttons] = buttons unless buttons.empty?
|
61
|
-
json
|
62
|
-
end
|
63
|
-
|
64
|
-
def before_callback=(blk)
|
65
|
-
callbacks[:before] = blk
|
110
|
+
def before_callback=(block)
|
111
|
+
callbacks[:before] = block
|
66
112
|
end
|
67
113
|
|
68
|
-
def after_callback=(
|
69
|
-
callbacks[:after] =
|
114
|
+
def after_callback=(block)
|
115
|
+
callbacks[:after] = block
|
70
116
|
end
|
71
117
|
|
72
118
|
def include_data=(hash)
|
@@ -74,31 +120,111 @@ module HatTrick
|
|
74
120
|
@include_data_key = hash.keys.first
|
75
121
|
end
|
76
122
|
|
123
|
+
def step_contents_callback=(block)
|
124
|
+
callbacks[:step_contents] = block
|
125
|
+
end
|
126
|
+
|
127
|
+
def step_contents(context, model)
|
128
|
+
contents = run_step_contents_callback(context, model)
|
129
|
+
{
|
130
|
+
:hatTrickStepContents => {
|
131
|
+
name.to_s.camelize(:lower).to_sym => contents
|
132
|
+
}
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
136
|
+
def include_data(context, model)
|
137
|
+
inc_data = run_include_data_callback(context, model)
|
138
|
+
return {} unless inc_data.respond_to?(:as_json)
|
139
|
+
key = include_data_key.to_s.camelize(:lower)
|
140
|
+
{ key => camelize_hash_keys(inc_data) }
|
141
|
+
end
|
142
|
+
|
143
|
+
def before_callbacks
|
144
|
+
before_callbacks = [callbacks[:before]]
|
145
|
+
if wizard.before_callback_for_all_steps
|
146
|
+
before_callbacks << wizard.before_callback_for_all_steps
|
147
|
+
end
|
148
|
+
before_callbacks
|
149
|
+
end
|
150
|
+
|
77
151
|
def run_before_callback(context, model)
|
78
|
-
|
152
|
+
Rails.logger.info "Running before callback for #{name}"
|
153
|
+
run_callbacks(before_callbacks, context, model)
|
79
154
|
end
|
80
155
|
|
81
156
|
def run_include_data_callback(context, model)
|
82
|
-
|
157
|
+
run_callbacks([callbacks[:include_data]], context, model)
|
158
|
+
end
|
159
|
+
|
160
|
+
def run_step_contents_callback(context, model)
|
161
|
+
run_callbacks([callbacks[:step_contents]], context, model)
|
162
|
+
end
|
163
|
+
|
164
|
+
def after_callbacks
|
165
|
+
after_callbacks = [callbacks[:after]]
|
166
|
+
if wizard.after_callback_for_all_steps
|
167
|
+
after_callbacks << wizard.after_callback_for_all_steps
|
168
|
+
end
|
169
|
+
after_callbacks
|
83
170
|
end
|
84
171
|
|
85
172
|
def run_after_callback(context, model)
|
86
|
-
|
173
|
+
run_callbacks(after_callbacks, context, model)
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def button_label(type)
|
179
|
+
config.send("#{type}_button_label") or
|
180
|
+
if i18n_key = config.send("#{type}_button_label_i18n_key")
|
181
|
+
I18n.t i18n_key
|
182
|
+
end or
|
183
|
+
default_button_label(type)
|
87
184
|
end
|
88
185
|
|
89
|
-
|
186
|
+
def default_button_label(type)
|
187
|
+
translate_button_label(type)
|
188
|
+
end
|
90
189
|
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
190
|
+
def translate_button_label(type)
|
191
|
+
default_label = type.to_s.humanize
|
192
|
+
begin
|
193
|
+
label = I18n.t("wizard.buttons.#{type}", :default => default_label)
|
194
|
+
rescue NameError
|
195
|
+
label = default_label
|
196
|
+
end
|
197
|
+
label
|
198
|
+
end
|
199
|
+
|
200
|
+
def run_callbacks(callbacks, context, model)
|
201
|
+
result = nil
|
202
|
+
callbacks.each do |callback|
|
203
|
+
if callback && callback.is_a?(Proc)
|
204
|
+
if callback.arity > 0
|
205
|
+
unless model.nil? || model.is_a?(ActiveModel::Errors)
|
206
|
+
result = context.instance_exec model, &callback
|
207
|
+
end
|
208
|
+
else
|
209
|
+
result = context.instance_eval &callback
|
97
210
|
end
|
98
|
-
else
|
99
|
-
context.instance_eval &callback
|
100
211
|
end
|
101
212
|
end
|
213
|
+
|
214
|
+
# return the last result; mainly for include_data
|
215
|
+
result
|
216
|
+
end
|
217
|
+
|
218
|
+
def camelize_hash_keys(_hash)
|
219
|
+
hash = {}
|
220
|
+
if _hash.respond_to?(:each)
|
221
|
+
_hash.each do |k,v|
|
222
|
+
hash[k.to_s.camelize(:lower)] = v
|
223
|
+
end
|
224
|
+
else
|
225
|
+
hash = _hash
|
226
|
+
end
|
227
|
+
hash
|
102
228
|
end
|
103
229
|
end
|
104
230
|
end
|
data/lib/hat_trick/version.rb
CHANGED
data/lib/hat_trick/wizard.rb
CHANGED
@@ -6,12 +6,15 @@ module HatTrick
|
|
6
6
|
class Wizard
|
7
7
|
include WizardSteps
|
8
8
|
|
9
|
-
attr_accessor :controller, :model
|
9
|
+
attr_accessor :controller, :model, :external_redirect_url
|
10
10
|
attr_reader :current_step, :wizard_def, :steps
|
11
11
|
|
12
|
+
delegate :config, :to => :wizard_def
|
13
|
+
|
12
14
|
def initialize(wizard_def)
|
13
15
|
@wizard_def = wizard_def
|
14
16
|
@steps = @wizard_def.steps.map { |s| HatTrick::Step.new(s, self) }
|
17
|
+
@current_step = first_step
|
15
18
|
end
|
16
19
|
|
17
20
|
def controller=(new_controller)
|
@@ -20,15 +23,12 @@ module HatTrick
|
|
20
23
|
|
21
24
|
def model=(new_model)
|
22
25
|
@model = new_model
|
23
|
-
unless @model.class.included_modules.include?(HatTrick::ModelMethods)
|
24
|
-
@model.class.send(:include, HatTrick::ModelMethods)
|
25
|
-
end
|
26
26
|
end
|
27
27
|
|
28
28
|
def current_step=(_step)
|
29
29
|
raise "Don't set current_step to nil" if _step.nil?
|
30
30
|
step = find_step(_step)
|
31
|
-
raise "#{
|
31
|
+
raise StepNotFound, "#{_step} is not a member of this wizard" unless step
|
32
32
|
@current_step = step
|
33
33
|
end
|
34
34
|
|
@@ -72,7 +72,7 @@ module HatTrick
|
|
72
72
|
def next_step
|
73
73
|
step = find_next_step
|
74
74
|
while step.skipped? do
|
75
|
-
step =
|
75
|
+
step = step_after(step)
|
76
76
|
end
|
77
77
|
step
|
78
78
|
end
|
@@ -91,11 +91,64 @@ module HatTrick
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def start
|
94
|
-
|
94
|
+
reset_step_session_data
|
95
95
|
self.current_step ||= first_step
|
96
96
|
run_before_callback
|
97
97
|
end
|
98
98
|
|
99
|
+
def steps_before_current
|
100
|
+
steps_before(current_step)
|
101
|
+
end
|
102
|
+
|
103
|
+
def steps_after_current
|
104
|
+
steps_after(current_step)
|
105
|
+
end
|
106
|
+
|
107
|
+
def visited_steps
|
108
|
+
session["hat-trick.visited_steps"] ||= []
|
109
|
+
end
|
110
|
+
|
111
|
+
def skipped_steps
|
112
|
+
session["hat-trick.skipped_steps"] ||= []
|
113
|
+
end
|
114
|
+
|
115
|
+
def percent_complete(step=current_step)
|
116
|
+
percent = (steps_before_current.count.to_f / total_step_count) * 100
|
117
|
+
if percent > 100.0
|
118
|
+
100
|
119
|
+
elsif percent <= 0
|
120
|
+
0
|
121
|
+
elsif percent < 5.0
|
122
|
+
5
|
123
|
+
else
|
124
|
+
percent
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def steps_remaining=(count)
|
129
|
+
self.override_step_count = steps_before_current.count + count
|
130
|
+
end
|
131
|
+
|
132
|
+
def steps_remaining
|
133
|
+
total_step_count - steps_before_current.count
|
134
|
+
end
|
135
|
+
|
136
|
+
def override_step_count=(count)
|
137
|
+
if count.nil?
|
138
|
+
session.delete('hat-trick.override_step_count')
|
139
|
+
else
|
140
|
+
session['hat-trick.override_step_count'] = count
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def override_step_count
|
145
|
+
session['hat-trick.override_step_count']
|
146
|
+
end
|
147
|
+
|
148
|
+
def total_step_count
|
149
|
+
override_step_count or steps.count
|
150
|
+
end
|
151
|
+
|
99
152
|
def run_before_callback(step=current_step)
|
100
153
|
step.run_before_callback(controller, model)
|
101
154
|
end
|
@@ -104,13 +157,29 @@ module HatTrick
|
|
104
157
|
step.run_after_callback(controller, model)
|
105
158
|
end
|
106
159
|
|
160
|
+
def redirect_to_step(step)
|
161
|
+
redirect_from = current_step.fieldset
|
162
|
+
self.current_step = step
|
163
|
+
current_step.redirect_from = redirect_from
|
164
|
+
end
|
165
|
+
|
107
166
|
def advance_step(next_step_name=nil)
|
108
167
|
# clean up current step
|
109
|
-
current_step.
|
168
|
+
current_step.mark_as_visited
|
169
|
+
before_callback_next_step = current_step.next_step
|
110
170
|
run_after_callback
|
171
|
+
after_callback_next_step = current_step.next_step
|
111
172
|
|
112
|
-
#
|
113
|
-
|
173
|
+
# return if any redirects were requested
|
174
|
+
return if external_redirect_url.present?
|
175
|
+
|
176
|
+
# if after callback changed the next step, go to that one
|
177
|
+
requested_next_step = if after_callback_next_step != before_callback_next_step
|
178
|
+
after_callback_next_step
|
179
|
+
else
|
180
|
+
# use argument, if there was one
|
181
|
+
find_step(next_step_name) unless next_step_name.nil?
|
182
|
+
end
|
114
183
|
|
115
184
|
# finish if we're on the last step
|
116
185
|
if current_step == last_step && !requested_next_step
|
@@ -122,72 +191,62 @@ module HatTrick
|
|
122
191
|
run_before_callback
|
123
192
|
# if the step was explicitly requested, we ignore #skipped?
|
124
193
|
else
|
125
|
-
Rails.logger.info "Advancing to step: #{next_step}"
|
126
194
|
self.current_step = next_step
|
127
195
|
run_before_callback
|
128
196
|
# Running the before callback may have marked current_step as skipped
|
129
197
|
while current_step.skipped?
|
130
198
|
self.current_step = next_step
|
131
199
|
run_before_callback
|
200
|
+
# make sure we don't loop forever
|
201
|
+
break if current_step == last_step
|
132
202
|
end
|
203
|
+
Rails.logger.info "Advancing to step: #{current_step}"
|
133
204
|
end
|
134
205
|
end
|
135
206
|
end
|
136
207
|
|
137
208
|
def include_data
|
209
|
+
include_data_for_step(current_step)
|
210
|
+
end
|
211
|
+
|
212
|
+
def include_data_for_step(step)
|
138
213
|
return {} if model.nil?
|
139
|
-
inc_data =
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
next if step_data.nil? || !step_data.respond_to?(:as_json)
|
144
|
-
step_key = step.include_data_key.to_s.camelize(:lower)
|
145
|
-
begin
|
146
|
-
inc_data[step_key] = camelize_hash_keys(step_data)
|
147
|
-
rescue NoMethodError => e
|
148
|
-
Rails.logger.error "Unable to serialize data for step #{step}: #{e}"
|
149
|
-
end
|
150
|
-
end
|
214
|
+
inc_data = step.include_data(controller, model)
|
215
|
+
contents = step.step_contents(controller, model)
|
216
|
+
inc_data.merge! contents
|
217
|
+
inc_data.delete_if { |k,v| v.nil? }
|
151
218
|
inc_data
|
152
219
|
end
|
153
220
|
|
154
221
|
def alias_action_methods
|
155
222
|
action_methods = controller.action_methods.reject do |m|
|
156
|
-
/^render/ =~ m.to_s
|
157
|
-
|
223
|
+
/^render/ =~ m.to_s or
|
224
|
+
m.to_s.include?('!') or
|
225
|
+
controller.respond_to?("#{m}_without_hat_trick", :include_private)
|
158
226
|
end
|
159
227
|
HatTrick::ControllerHooks.def_action_method_aliases(action_methods)
|
160
|
-
action_methods.each do |
|
161
|
-
|
162
|
-
controller.class.send(:
|
228
|
+
action_methods.each do |m|
|
229
|
+
Rails.logger.info "Aliasing #{m}"
|
230
|
+
controller.class.send(:alias_method_chain, m, :hat_trick)
|
231
|
+
controller.class.send(:private, "#{m}_without_hat_trick")
|
163
232
|
end
|
164
233
|
end
|
165
234
|
|
166
235
|
private
|
167
236
|
|
237
|
+
def reset_step_session_data
|
238
|
+
# TODO: Move this into a StepCollection class (maybe subclass Set)
|
239
|
+
visited_steps = []
|
240
|
+
skipped_steps = []
|
241
|
+
end
|
242
|
+
|
168
243
|
def fake_session
|
244
|
+
Rails.logger.warn "Using a fake session object!"
|
169
245
|
@fake_session ||= {}
|
170
246
|
end
|
171
247
|
|
172
248
|
def find_next_step
|
173
|
-
find_step(current_step.next_step)
|
174
|
-
end
|
175
|
-
|
176
|
-
def find_step_after(step)
|
177
|
-
next_path_step = step_after step
|
178
|
-
next_path_step or find_next_active_step(step)
|
179
|
-
end
|
180
|
-
|
181
|
-
def camelize_hash_keys(_hash)
|
182
|
-
hash = {}
|
183
|
-
if _hash.respond_to?(:each)
|
184
|
-
_hash.each do |k,v|
|
185
|
-
hash[k.to_s.camelize(:lower)] = v
|
186
|
-
end
|
187
|
-
else
|
188
|
-
hash = _hash
|
189
|
-
end
|
190
|
-
hash
|
249
|
+
find_step(current_step.next_step) || step_after(current_step)
|
191
250
|
end
|
192
251
|
end
|
193
252
|
end
|
@@ -6,19 +6,28 @@ module HatTrick
|
|
6
6
|
class WizardDefinition
|
7
7
|
include WizardSteps
|
8
8
|
|
9
|
-
|
9
|
+
attr_reader :config
|
10
|
+
attr_accessor :before_callback_for_all_steps, :after_callback_for_all_steps
|
10
11
|
|
11
|
-
def initialize
|
12
|
+
def initialize(config)
|
13
|
+
@config = config
|
12
14
|
@steps = []
|
13
15
|
end
|
14
16
|
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
def make_wizard_for(controller)
|
18
|
+
Rails.logger.info "Making new wizard instance"
|
19
|
+
wizard = HatTrick::Wizard.new(self)
|
20
|
+
wizard.controller = controller
|
21
|
+
wizard.alias_action_methods
|
22
|
+
wizard
|
23
|
+
end
|
24
|
+
|
25
|
+
def configured_create_url
|
26
|
+
config.create_url
|
27
|
+
end
|
28
|
+
|
29
|
+
def configured_update_url
|
30
|
+
config.update_url
|
22
31
|
end
|
23
32
|
end
|
24
33
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
module HatTrick
|
2
|
+
class StepNotFound < StandardError; end
|
3
|
+
|
2
4
|
module WizardSteps
|
3
5
|
include Enumerable
|
4
6
|
attr_reader :steps
|
@@ -26,9 +28,11 @@ module HatTrick
|
|
26
28
|
def steps_after(_step)
|
27
29
|
step = find_step(_step)
|
28
30
|
return [] unless step
|
31
|
+
return [] if step.last? && !step.skipped?
|
29
32
|
step_index = steps.index(step)
|
30
33
|
max_index = steps.count - 1
|
31
|
-
|
34
|
+
return [] if step_index >= max_index
|
35
|
+
after_index = step_index + 1
|
32
36
|
steps[after_index .. -1]
|
33
37
|
end
|
34
38
|
|
@@ -40,7 +44,8 @@ module HatTrick
|
|
40
44
|
step = find_step(_step)
|
41
45
|
return [] unless step
|
42
46
|
step_index = steps.index(step)
|
43
|
-
|
47
|
+
return [] if step_index <= 0
|
48
|
+
before_index = step_index - 1
|
44
49
|
steps[0 .. before_index]
|
45
50
|
end
|
46
51
|
|
@@ -48,10 +53,14 @@ module HatTrick
|
|
48
53
|
if step.is_a?(HatTrick::Step) || step.is_a?(HatTrick::StepDefinition)
|
49
54
|
new_step = step
|
50
55
|
else
|
51
|
-
step_args = args.merge(:name => step)
|
56
|
+
step_args = args.merge(:name => step, :wizard => self)
|
52
57
|
new_step = HatTrick::StepDefinition.new(step_args)
|
53
58
|
end
|
54
59
|
|
60
|
+
if steps.count == 0
|
61
|
+
new_step.first = true
|
62
|
+
end
|
63
|
+
|
55
64
|
steps << new_step
|
56
65
|
|
57
66
|
new_step
|
@@ -1,26 +1,27 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
# will automatically get HatTrick::DSL included
|
4
|
-
class FakeController < ActionController::Base; end
|
5
|
-
|
6
3
|
describe HatTrick::DSL do
|
7
|
-
|
4
|
+
subject(:controller) {
|
5
|
+
Class.new.send(:include, HatTrick::DSL).tap do |c|
|
6
|
+
c.stubs(:before_filter)
|
7
|
+
c.any_instance.stubs(:render)
|
8
|
+
end
|
9
|
+
}
|
8
10
|
|
9
|
-
# save some typing
|
10
|
-
def dsl(&block)
|
11
|
-
controller_class.instance_eval &block
|
12
|
-
end
|
13
|
-
|
14
11
|
describe HatTrick::DSL::ClassMethods do
|
15
12
|
describe "#step" do
|
16
13
|
it "should call Wizard#add_step" do
|
17
14
|
HatTrick::WizardDefinition.any_instance.expects(:add_step).with(:foo, {})
|
18
|
-
|
15
|
+
controller.instance_eval do
|
19
16
|
wizard do
|
20
17
|
step :foo
|
21
18
|
end
|
22
19
|
end
|
23
20
|
end
|
21
|
+
|
22
|
+
it "raises an error if called outside a wizard block" do
|
23
|
+
expect { controller.step :foo }.to raise_error
|
24
|
+
end
|
24
25
|
end
|
25
26
|
end
|
26
27
|
end
|