adhearsion 2.0.0.rc4 → 2.0.0.rc5
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/CHANGELOG.md +4 -0
- data/adhearsion.gemspec +1 -1
- data/bin/ahn +0 -3
- data/lib/adhearsion.rb +7 -4
- data/lib/adhearsion/call.rb +1 -1
- data/lib/adhearsion/call_controller.rb +1 -0
- data/lib/adhearsion/call_controller/menu_dsl.rb +19 -0
- data/lib/adhearsion/call_controller/menu_dsl/calculated_match.rb +43 -0
- data/lib/adhearsion/call_controller/menu_dsl/calculated_match_collection.rb +45 -0
- data/lib/adhearsion/call_controller/menu_dsl/fixnum_match_calculator.rb +22 -0
- data/lib/adhearsion/call_controller/menu_dsl/match_calculator.rb +40 -0
- data/lib/adhearsion/call_controller/menu_dsl/menu.rb +203 -0
- data/lib/adhearsion/call_controller/menu_dsl/menu_builder.rb +84 -0
- data/lib/adhearsion/call_controller/menu_dsl/range_match_calculator.rb +60 -0
- data/lib/adhearsion/call_controller/menu_dsl/string_match_calculator.rb +25 -0
- data/lib/adhearsion/cli.rb +0 -1
- data/lib/adhearsion/router/route.rb +2 -2
- data/lib/adhearsion/version.rb +1 -1
- data/spec/adhearsion/call_controller/input_spec.rb +1 -1
- data/spec/adhearsion/call_controller/menu_dsl/calculated_match_collection_spec.rb +60 -0
- data/spec/adhearsion/call_controller/menu_dsl/calculated_match_spec.rb +61 -0
- data/spec/adhearsion/call_controller/menu_dsl/fixnum_match_calculator_spec.rb +37 -0
- data/spec/adhearsion/call_controller/menu_dsl/match_calculator_spec.rb +17 -0
- data/spec/adhearsion/call_controller/menu_dsl/menu_builder_spec.rb +151 -0
- data/spec/adhearsion/call_controller/menu_dsl/menu_spec.rb +373 -0
- data/spec/adhearsion/call_controller/menu_dsl/range_match_calculator_spec.rb +32 -0
- data/spec/adhearsion/call_controller/menu_dsl/string_match_calculator_spec.rb +40 -0
- metadata +91 -91
- data/lib/adhearsion/menu_dsl.rb +0 -17
- data/lib/adhearsion/menu_dsl/calculated_match.rb +0 -41
- data/lib/adhearsion/menu_dsl/calculated_match_collection.rb +0 -43
- data/lib/adhearsion/menu_dsl/fixnum_match_calculator.rb +0 -20
- data/lib/adhearsion/menu_dsl/match_calculator.rb +0 -38
- data/lib/adhearsion/menu_dsl/menu.rb +0 -201
- data/lib/adhearsion/menu_dsl/menu_builder.rb +0 -82
- data/lib/adhearsion/menu_dsl/range_match_calculator.rb +0 -58
- data/lib/adhearsion/menu_dsl/string_match_calculator.rb +0 -23
- data/spec/adhearsion/menu_dsl/calculated_match_collection_spec.rb +0 -58
- data/spec/adhearsion/menu_dsl/calculated_match_spec.rb +0 -59
- data/spec/adhearsion/menu_dsl/fixnum_match_calculator_spec.rb +0 -35
- data/spec/adhearsion/menu_dsl/match_calculator_spec.rb +0 -15
- data/spec/adhearsion/menu_dsl/menu_builder_spec.rb +0 -149
- data/spec/adhearsion/menu_dsl/menu_spec.rb +0 -371
- data/spec/adhearsion/menu_dsl/range_match_calculator_spec.rb +0 -30
- data/spec/adhearsion/menu_dsl/string_match_calculator_spec.rb +0 -38
@@ -0,0 +1,84 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Adhearsion
|
4
|
+
class CallController
|
5
|
+
module MenuDSL
|
6
|
+
|
7
|
+
class MenuBuilder
|
8
|
+
|
9
|
+
attr_accessor :patterns, :menu_callbacks
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@patterns = []
|
13
|
+
@menu_callbacks = {}
|
14
|
+
@context = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def build(&block)
|
18
|
+
@context = eval "self", block.binding
|
19
|
+
instance_eval(&block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def match(*args, &block)
|
23
|
+
payload = if block_given?
|
24
|
+
raise ArgumentError, "You cannot specify both a block and a controller name." if args.last.is_a? Class
|
25
|
+
nil
|
26
|
+
else
|
27
|
+
raise ArgumentError, "You need to provide a block or a controller name." unless args.last.is_a? Class
|
28
|
+
args.pop
|
29
|
+
end
|
30
|
+
|
31
|
+
raise ArgumentError, "You cannot call this method without patterns." if args.empty?
|
32
|
+
|
33
|
+
args.each do |pattern|
|
34
|
+
@patterns << MatchCalculator.build_with_pattern(pattern, payload, &block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def weighted_match_calculators
|
39
|
+
@patterns
|
40
|
+
end
|
41
|
+
|
42
|
+
def has_matchers?
|
43
|
+
@patterns.size > 0
|
44
|
+
end
|
45
|
+
|
46
|
+
def execute_hook_for(symbol, input)
|
47
|
+
callback = @menu_callbacks[symbol]
|
48
|
+
return unless callback
|
49
|
+
@context.instance_exec input, &callback
|
50
|
+
end
|
51
|
+
|
52
|
+
def invalid(&block)
|
53
|
+
raise LocalJumpError, "Must supply a block!" unless block_given?
|
54
|
+
@menu_callbacks[:invalid] = block
|
55
|
+
end
|
56
|
+
|
57
|
+
def timeout(&block)
|
58
|
+
raise LocalJumpError, "Must supply a block!" unless block_given?
|
59
|
+
@menu_callbacks[:timeout] = block
|
60
|
+
end
|
61
|
+
|
62
|
+
def failure(&block)
|
63
|
+
raise LocalJumpError, "Must supply a block!" unless block_given?
|
64
|
+
@menu_callbacks[:failure] = block
|
65
|
+
end
|
66
|
+
|
67
|
+
def validator(&block)
|
68
|
+
raise LocalJumpError, "Must supply a block!" unless block_given?
|
69
|
+
@menu_callbacks[:validator] = block
|
70
|
+
end
|
71
|
+
|
72
|
+
def calculate_matches_for(result)
|
73
|
+
CalculatedMatchCollection.new.tap do |collection|
|
74
|
+
weighted_match_calculators.each do |pattern|
|
75
|
+
collection << pattern.match(result)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end # class MenuBuilder
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Adhearsion
|
4
|
+
class CallController
|
5
|
+
module MenuDSL
|
6
|
+
|
7
|
+
class RangeMatchCalculator < MatchCalculator
|
8
|
+
|
9
|
+
def initialize(pattern, match_payload)
|
10
|
+
raise unless pattern.first.kind_of?(Numeric) && pattern.last.kind_of?(Numeric)
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def match(query)
|
15
|
+
numerical_query = coerce_to_numeric query
|
16
|
+
if numerical_query
|
17
|
+
exact_match = pattern.include?(numerical_query) ? query : nil
|
18
|
+
potential_matches = numbers_in_range_like numerical_query
|
19
|
+
potential_matches.reject! { |m| m.to_s == exact_match.to_s } if exact_match
|
20
|
+
|
21
|
+
new_calculated_match :query => query, :exact_matches => exact_match,
|
22
|
+
:potential_matches => potential_matches
|
23
|
+
else
|
24
|
+
CalculatedMatch.failed_match! pattern, query, match_payload
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Returns all numbers in the range (@pattern) that +begin with+ the number given
|
31
|
+
# as the first arguement.
|
32
|
+
#
|
33
|
+
# NOTE: If you're having trouble reading what this method is actually doing. It's
|
34
|
+
# effectively a much more efficient version of this:
|
35
|
+
#
|
36
|
+
# pattern.to_a.select { |x| x.to_s.starts_with? num.to_s }.flatten
|
37
|
+
#
|
38
|
+
# Huge thanks to Dave Troy (http://davetroy.blogspot.com) for this awesomely
|
39
|
+
# efficient code!
|
40
|
+
def numbers_in_range_like(num)
|
41
|
+
return (pattern === 0 ? [0] : nil) if num == 0
|
42
|
+
raise ArgumentError unless num.kind_of?(Numeric)
|
43
|
+
Array.new.tap do |matches|
|
44
|
+
first, last = pattern.first, pattern.last
|
45
|
+
power = 0
|
46
|
+
while num < last
|
47
|
+
ones_count = 10**power - 1
|
48
|
+
range = ([num, first].max..[num + ones_count, last].min).to_a
|
49
|
+
matches.concat range
|
50
|
+
num *= 10
|
51
|
+
power += 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end # class RangeMatchCalculator
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Adhearsion
|
4
|
+
class CallController
|
5
|
+
module MenuDSL
|
6
|
+
|
7
|
+
class StringMatchCalculator < MatchCalculator
|
8
|
+
|
9
|
+
def match(query)
|
10
|
+
args = { :query => query, :exact_matches => nil, :potential_matches => nil }
|
11
|
+
|
12
|
+
if pattern == query.to_s
|
13
|
+
args[:exact_matches] = [pattern]
|
14
|
+
elsif pattern.starts_with? query.to_s
|
15
|
+
args[:potential_matches] = [pattern]
|
16
|
+
end
|
17
|
+
|
18
|
+
new_calculated_match args
|
19
|
+
end
|
20
|
+
|
21
|
+
end # class StringMatchCalculator
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/adhearsion/cli.rb
CHANGED
@@ -29,9 +29,9 @@ module Adhearsion
|
|
29
29
|
target.new call
|
30
30
|
end
|
31
31
|
|
32
|
-
call.execute_controller controller, lambda { |
|
32
|
+
call.execute_controller controller, lambda { |call_actor|
|
33
33
|
begin
|
34
|
-
|
34
|
+
call_actor.hangup
|
35
35
|
rescue Call::Hangup
|
36
36
|
end
|
37
37
|
callback.call if callback
|
data/lib/adhearsion/version.rb
CHANGED
@@ -9,7 +9,7 @@ module Adhearsion
|
|
9
9
|
|
10
10
|
describe "#play_sound_files_for_menu" do
|
11
11
|
let(:options) { Hash.new }
|
12
|
-
let(:menu_instance) {
|
12
|
+
let(:menu_instance) { MenuDSL::Menu.new(options) }
|
13
13
|
let(:sound_file) { "press a button" }
|
14
14
|
let(:sound_files) { [sound_file] }
|
15
15
|
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module Adhearsion
|
6
|
+
class CallController
|
7
|
+
module MenuDSL
|
8
|
+
describe CalculatedMatchCollection do
|
9
|
+
def mock_with_potential_matches(potential_matches)
|
10
|
+
CalculatedMatch.new :potential_matches => potential_matches
|
11
|
+
end
|
12
|
+
|
13
|
+
def mock_with_exact_matches(exact_matches)
|
14
|
+
CalculatedMatch.new :exact_matches => exact_matches
|
15
|
+
end
|
16
|
+
|
17
|
+
def mock_with_potential_and_exact_matches(potential_matches, exact_matches)
|
18
|
+
CalculatedMatch.new :potential_matches => potential_matches,
|
19
|
+
:exact_matches => exact_matches
|
20
|
+
end
|
21
|
+
|
22
|
+
it "the <<() method should collect the potential matches into the actual_potential_matches Array" do
|
23
|
+
mock_matches_array_1 = [:foo, :bar, :qaz],
|
24
|
+
mock_matches_array_2 = [10, 20, 30]
|
25
|
+
mock_matches_1 = mock_with_potential_matches mock_matches_array_1
|
26
|
+
mock_matches_2 = mock_with_potential_matches mock_matches_array_2
|
27
|
+
|
28
|
+
subject << mock_matches_1
|
29
|
+
subject.actual_potential_matches.should be == mock_matches_array_1
|
30
|
+
|
31
|
+
subject << mock_matches_2
|
32
|
+
subject.actual_potential_matches.should be == mock_matches_array_1 + mock_matches_array_2
|
33
|
+
end
|
34
|
+
|
35
|
+
it "the <<() method should collect the exact matches into the actual_exact_matches Array" do
|
36
|
+
mock_matches_array_1 = [:blam, :blargh],
|
37
|
+
mock_matches_array_2 = [5,4,3,2,1]
|
38
|
+
mock_matches_1 = mock_with_exact_matches mock_matches_array_1
|
39
|
+
mock_matches_2 = mock_with_exact_matches mock_matches_array_2
|
40
|
+
|
41
|
+
subject << mock_matches_1
|
42
|
+
subject.actual_exact_matches.should be == mock_matches_array_1
|
43
|
+
|
44
|
+
subject << mock_matches_2
|
45
|
+
subject.actual_exact_matches.should be == mock_matches_array_1 + mock_matches_array_2
|
46
|
+
end
|
47
|
+
|
48
|
+
it "if any exact matches exist, the exact_match?() method should return true" do
|
49
|
+
subject << mock_with_exact_matches([1,2,3])
|
50
|
+
subject.exact_match?.should be true
|
51
|
+
end
|
52
|
+
|
53
|
+
it "if any potential matches exist, the potential_match?() method should return true" do
|
54
|
+
subject << mock_with_potential_matches([1,2,3])
|
55
|
+
subject.potential_match?.should be true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module Adhearsion
|
6
|
+
class CallController
|
7
|
+
module MenuDSL
|
8
|
+
describe CalculatedMatch do
|
9
|
+
it "should make accessible the context name" do
|
10
|
+
CalculatedMatch.new(:match_payload => :foobar).match_payload.should be :foobar
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should make accessible the original pattern" do
|
14
|
+
CalculatedMatch.new(:pattern => :something).pattern.should be :something
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should make accessible the matched query" do
|
18
|
+
CalculatedMatch.new(:query => 123).query.should be 123
|
19
|
+
end
|
20
|
+
|
21
|
+
it "#type_of_match should return :exact, :potential, or nil" do
|
22
|
+
CalculatedMatch.new(:potential_matches => [1]).type_of_match.should be :potential
|
23
|
+
CalculatedMatch.new(:exact_matches => [3,3]).type_of_match.should be :exact
|
24
|
+
CalculatedMatch.new(:exact_matches => [8,3], :potential_matches => [0,9]).type_of_match.should be :exact
|
25
|
+
end
|
26
|
+
|
27
|
+
it "#exact_match? should return true if the match was exact" do
|
28
|
+
CalculatedMatch.new(:exact_matches => [0,3,5]).exact_match?.should be true
|
29
|
+
end
|
30
|
+
|
31
|
+
it "#potential_match? should return true if the match was exact" do
|
32
|
+
CalculatedMatch.new(:potential_matches => [88,99,77]).potential_match?.should be true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "#failed_match? should return false if the match was exact" do
|
36
|
+
CalculatedMatch.new(:potential_matches => [88,99,77]).failed_match?.should be false
|
37
|
+
end
|
38
|
+
|
39
|
+
it "#exact_matches should return an array of exact matches" do
|
40
|
+
CalculatedMatch.new(:exact_matches => [0,3,5]).exact_matches.should be == [0,3,5]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "#potential_matches should return an array of potential matches" do
|
44
|
+
CalculatedMatch.new(:potential_matches => [88,99,77]).potential_matches.should be == [88,99,77]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "::failed_match! should return a match that *really* failed" do
|
48
|
+
failure = CalculatedMatch.failed_match! 10..20, 30, :match_payload_does_not_matter
|
49
|
+
failure.exact_match?.should_not be true
|
50
|
+
failure.potential_match?.should_not be true
|
51
|
+
failure.failed_match?.should be true
|
52
|
+
failure.type_of_match.should be nil
|
53
|
+
|
54
|
+
failure.match_payload.should be :match_payload_does_not_matter
|
55
|
+
failure.pattern.should be == (10..20)
|
56
|
+
failure.query.should be == 30
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module Adhearsion
|
6
|
+
class CallController
|
7
|
+
module MenuDSL
|
8
|
+
describe FixnumMatchCalculator do
|
9
|
+
let(:match_payload) { :main }
|
10
|
+
|
11
|
+
it "a potential match scenario" do
|
12
|
+
calculator = FixnumMatchCalculator.new(444, match_payload)
|
13
|
+
match = calculator.match 4
|
14
|
+
match.potential_match?.should be true
|
15
|
+
match.exact_match?.should_not be true
|
16
|
+
match.potential_matches.should be == [444]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "a multi-digit exact match scenario" do
|
20
|
+
calculator = FixnumMatchCalculator.new(5555, match_payload)
|
21
|
+
calculator.match(5555).exact_match?.should be true
|
22
|
+
end
|
23
|
+
|
24
|
+
it "a single-digit exact match scenario" do
|
25
|
+
calculator = FixnumMatchCalculator.new(1, match_payload)
|
26
|
+
calculator.match(1).exact_match?.should be true
|
27
|
+
end
|
28
|
+
|
29
|
+
it "the context name given to the calculator should be passed on the CalculatedMatch" do
|
30
|
+
match_payload = :icanhascheezburger
|
31
|
+
calculator = FixnumMatchCalculator.new(1337, match_payload)
|
32
|
+
calculator.match(1337).match_payload.should be match_payload
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module Adhearsion
|
6
|
+
class CallController
|
7
|
+
module MenuDSL
|
8
|
+
describe MatchCalculator do
|
9
|
+
describe ".build_with_pattern" do
|
10
|
+
it "should return an appropriate subclass instance based on the pattern's class" do
|
11
|
+
MatchCalculator.build_with_pattern(1..2, :main).should be_an_instance_of RangeMatchCalculator
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module Adhearsion
|
6
|
+
class CallController
|
7
|
+
module MenuDSL
|
8
|
+
|
9
|
+
describe MenuBuilder do
|
10
|
+
subject{ MenuDSL::MenuBuilder.new }
|
11
|
+
|
12
|
+
describe "#build" do
|
13
|
+
it "sets the context and instance_eval's the block" do
|
14
|
+
flexmock(subject).should_receive(:foo).with(:bar)
|
15
|
+
subject.build do
|
16
|
+
foo :bar
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end#build
|
20
|
+
|
21
|
+
describe "#match" do
|
22
|
+
let(:match_block) { Proc.new() {} }
|
23
|
+
|
24
|
+
it "raises an exception if called without a CallController and no block" do
|
25
|
+
expect { subject.match 1 }.to raise_error(ArgumentError)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "raises an exception if given both a payload and a block" do
|
29
|
+
expect { subject.match(1, Object) {} }.to raise_error(ArgumentError)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "raises an exception if given no patterns" do
|
33
|
+
expect { subject.match() {} }.to raise_error(ArgumentError, "You cannot call this method without patterns.")
|
34
|
+
end
|
35
|
+
|
36
|
+
it "creates a pattern based on a payload" do
|
37
|
+
flexmock(MenuDSL::MatchCalculator).should_receive(:build_with_pattern).with("1", Object)
|
38
|
+
subject.match "1", Object
|
39
|
+
end
|
40
|
+
|
41
|
+
it "creates a pattern based on a block" do
|
42
|
+
flexmock(MenuDSL::MatchCalculator).should_receive(:build_with_pattern).with("1", nil, match_block)
|
43
|
+
subject.match("1", &match_block)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "creates multiple patterns if multiple arguments are passed in" do
|
47
|
+
flexmock(MenuDSL::MatchCalculator).should_receive(:build_with_pattern).with(1, Object)
|
48
|
+
flexmock(MenuDSL::MatchCalculator).should_receive(:build_with_pattern).with(2, Object)
|
49
|
+
subject.match(1, 2, Object)
|
50
|
+
end
|
51
|
+
end#match
|
52
|
+
|
53
|
+
describe "#has_matchers?" do
|
54
|
+
context "with no matchers specified" do
|
55
|
+
its(:has_matchers?) { should be false }
|
56
|
+
end
|
57
|
+
|
58
|
+
context "with at least one matcher specified" do
|
59
|
+
before do
|
60
|
+
subject.match(1) {}
|
61
|
+
end
|
62
|
+
|
63
|
+
its(:has_matchers?) { should be true }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#weighted_match_calculators" do
|
68
|
+
let(:expected_pattern) { MenuDSL::MatchCalculator.build_with_pattern("1", Object) }
|
69
|
+
|
70
|
+
it "returns the generated patterns" do
|
71
|
+
flexmock(MenuDSL::MatchCalculator).should_receive(:build_with_pattern).with("1", Object).and_return(expected_pattern)
|
72
|
+
subject.match("1", Object)
|
73
|
+
subject.weighted_match_calculators.should be == [expected_pattern]
|
74
|
+
end
|
75
|
+
end#weighted_match_calculators
|
76
|
+
|
77
|
+
describe "#invalid" do
|
78
|
+
let(:callback) { Proc.new() {} }
|
79
|
+
|
80
|
+
it "raises an error if not passed a block" do
|
81
|
+
expect { subject.invalid }.to raise_error(LocalJumpError)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "sets the invalid callback" do
|
85
|
+
subject.invalid(&callback)
|
86
|
+
subject.menu_callbacks[:invalid].should be == callback
|
87
|
+
end
|
88
|
+
end#invalid
|
89
|
+
|
90
|
+
describe "#timeout" do
|
91
|
+
let(:callback) { Proc.new() {} }
|
92
|
+
|
93
|
+
it "raises an error if not passed a block" do
|
94
|
+
expect { subject.timeout }.to raise_error(LocalJumpError)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "sets the timeout callback" do
|
98
|
+
subject.timeout(&callback)
|
99
|
+
subject.menu_callbacks[:timeout].should be == callback
|
100
|
+
end
|
101
|
+
end#timeout
|
102
|
+
|
103
|
+
describe "#failure" do
|
104
|
+
let(:callback) { Proc.new() {} }
|
105
|
+
|
106
|
+
it "raises an error if not passed a block" do
|
107
|
+
expect { subject.failure }.to raise_error(LocalJumpError)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "sets the failure callback" do
|
111
|
+
subject.failure(&callback)
|
112
|
+
subject.menu_callbacks[:failure].should be == callback
|
113
|
+
end
|
114
|
+
end#failure
|
115
|
+
|
116
|
+
describe "#validator" do
|
117
|
+
let(:callback) { Proc.new() {} }
|
118
|
+
|
119
|
+
it "raises an error if not passed a block" do
|
120
|
+
expect { subject.validator }.to raise_error(LocalJumpError)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "sets the invalid callback" do
|
124
|
+
subject.validator(&callback)
|
125
|
+
subject.menu_callbacks[:validator].should be == callback
|
126
|
+
end
|
127
|
+
end#invalid
|
128
|
+
|
129
|
+
describe "#execute_hook_for" do
|
130
|
+
it "executes the correct hook" do
|
131
|
+
bar = nil
|
132
|
+
subject.invalid do |baz|
|
133
|
+
bar = baz
|
134
|
+
end
|
135
|
+
subject.execute_hook_for(:invalid, "1")
|
136
|
+
bar.should be == "1"
|
137
|
+
end
|
138
|
+
end#execute_hook_for
|
139
|
+
|
140
|
+
describe "#calculate_matches_for" do
|
141
|
+
it "returns a calculated match collection" do
|
142
|
+
subject.match("1", Object)
|
143
|
+
subject.calculate_matches_for("1").should be_a CalculatedMatchCollection
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end# describe MenuBuilder
|
148
|
+
|
149
|
+
end# module MenuDSL
|
150
|
+
end
|
151
|
+
end
|