mithril 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +31 -0
- data/README.md +0 -0
- data/bin/mithril +5 -0
- data/lib/mithril.rb +13 -0
- data/lib/mithril/controllers.rb +7 -0
- data/lib/mithril/controllers/abstract_controller.rb +130 -0
- data/lib/mithril/controllers/mixins.rb +7 -0
- data/lib/mithril/controllers/mixins/actions_base.rb +114 -0
- data/lib/mithril/controllers/mixins/help_actions.rb +46 -0
- data/lib/mithril/controllers/mixins/mixin_with_actions.rb +27 -0
- data/lib/mithril/controllers/proxy_controller.rb +89 -0
- data/lib/mithril/mixin.rb +33 -0
- data/lib/mithril/parsers.rb +7 -0
- data/lib/mithril/parsers/simple_parser.rb +57 -0
- data/lib/mithril/request.rb +11 -0
- data/lib/mithril/version.rb +5 -0
- data/spec/matchers/be_kind_of_spec.rb +50 -0
- data/spec/matchers/construct_spec.rb +49 -0
- data/spec/matchers/respond_to_spec.rb +158 -0
- data/spec/mithril/controllers/_text_controller_helper.rb +81 -0
- data/spec/mithril/controllers/abstract_controller_helper.rb +118 -0
- data/spec/mithril/controllers/abstract_controller_spec.rb +15 -0
- data/spec/mithril/controllers/mixins/actions_base_helper.rb +121 -0
- data/spec/mithril/controllers/mixins/actions_base_spec.rb +18 -0
- data/spec/mithril/controllers/mixins/help_actions_helper.rb +111 -0
- data/spec/mithril/controllers/mixins/help_actions_spec.rb +19 -0
- data/spec/mithril/controllers/mixins/mixin_with_actions_spec.rb +44 -0
- data/spec/mithril/controllers/proxy_controller_helper.rb +111 -0
- data/spec/mithril/controllers/proxy_controller_spec.rb +14 -0
- data/spec/mithril/mixin_helper.rb +54 -0
- data/spec/mithril/mixin_spec.rb +17 -0
- data/spec/mithril/parsers/simple_parser_spec.rb +85 -0
- data/spec/mithril/request_spec.rb +72 -0
- data/spec/mithril_spec.rb +25 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/factories/action_factory.rb +7 -0
- data/spec/support/factories/request_factory.rb +11 -0
- data/spec/support/matchers/be_kind_of.rb +23 -0
- data/spec/support/matchers/construct.rb +49 -0
- data/spec/support/matchers/respond_to.rb +52 -0
- metadata +142 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
# lib/mithril/mixin.rb
|
2
|
+
|
3
|
+
module Mithril
|
4
|
+
# Implements module-based inheritance of both class- and instance-level
|
5
|
+
# methods.
|
6
|
+
module Mixin
|
7
|
+
def mixins
|
8
|
+
@mixins ||= []
|
9
|
+
end # accessor mixins
|
10
|
+
|
11
|
+
def mixins=(ary)
|
12
|
+
@mixins = ary
|
13
|
+
end # mutator mixins
|
14
|
+
|
15
|
+
private
|
16
|
+
# Alternative to Module.extend that also provides inheritance of class-level
|
17
|
+
# methods defined through an (optional) ClassMethods module.
|
18
|
+
def mixin(source_module) # :doc:
|
19
|
+
include source_module
|
20
|
+
|
21
|
+
return unless source_module.respond_to? :mixins
|
22
|
+
|
23
|
+
self.mixins = source_module.mixins.dup || []
|
24
|
+
self.mixins << source_module
|
25
|
+
|
26
|
+
self.mixins.each do |mixin|
|
27
|
+
if mixin.const_defined? :ClassMethods
|
28
|
+
extend mixin::ClassMethods
|
29
|
+
end # if
|
30
|
+
end # each
|
31
|
+
end # method mixin
|
32
|
+
end # module Mixin
|
33
|
+
end # module
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# lib/mithril/parsers/simple_parser.rb
|
2
|
+
|
3
|
+
require 'mithril/parsers'
|
4
|
+
|
5
|
+
module Mithril::Parsers
|
6
|
+
class SimpleParser
|
7
|
+
def initialize(actions)
|
8
|
+
@actions = actions
|
9
|
+
end # method initialize
|
10
|
+
|
11
|
+
# Takes a string input and separates into words, then identifies a matching
|
12
|
+
# action (if any) and remaining arguments. Returns both the command and the
|
13
|
+
# arguments array, so usage can be as follows:
|
14
|
+
#
|
15
|
+
# @example With a "say" command:
|
16
|
+
# command, args = parse_command("say Greetings programs!")
|
17
|
+
# #=> command = :say, args = ["greetings", "programs"]
|
18
|
+
# @example With no "hello" command:
|
19
|
+
# command, args = parse_command("Hello world")
|
20
|
+
# #=> command = nil, args = ["hello", "world"]
|
21
|
+
#
|
22
|
+
# @param [String] text Expects a string composed of one or more words,
|
23
|
+
# separated by whitespace or hyphens.
|
24
|
+
# @return [Array] A two-element array consisting of the command and an
|
25
|
+
# array of the remaining text arguments (if any), or [nil, args] if no
|
26
|
+
# matching action was found.
|
27
|
+
def parse_command(text)
|
28
|
+
words = wordify preprocess_input text
|
29
|
+
|
30
|
+
key = nil
|
31
|
+
args = []
|
32
|
+
|
33
|
+
while 0 < words.count
|
34
|
+
key = words.join('_').intern
|
35
|
+
|
36
|
+
return key, args if @actions.has_action? key
|
37
|
+
|
38
|
+
args.unshift words.pop
|
39
|
+
end # while
|
40
|
+
|
41
|
+
return nil, args
|
42
|
+
end # method parse_command
|
43
|
+
|
44
|
+
private
|
45
|
+
# @!visibility public
|
46
|
+
def preprocess_input(text)
|
47
|
+
text.downcase.
|
48
|
+
gsub(/[\"?!\-',.:\(\)\[\]\;]/, ' ').
|
49
|
+
gsub(/(\s+)/, ' ').strip
|
50
|
+
end # method preprocess_input
|
51
|
+
|
52
|
+
# @!visibility public
|
53
|
+
def wordify(text)
|
54
|
+
text.split(/\s+/)
|
55
|
+
end # method wordify
|
56
|
+
end # class
|
57
|
+
end # module
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# spec/matchers/be_kind_of_spec.rb
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe RSpec::Matchers::BuiltIn::BeAKindOf do
|
6
|
+
let :custom_module do Module.new; end
|
7
|
+
let :custom_class do Class.new.tap { |c| c.send :include, custom_module }; end
|
8
|
+
let :custom_subclass do Class.new custom_class; end
|
9
|
+
|
10
|
+
let :string do "string"; end
|
11
|
+
let :module_instance do Object.new.extend custom_module; end
|
12
|
+
let :class_instance do custom_class.new; end
|
13
|
+
let :subclass_instance do custom_subclass.new; end
|
14
|
+
|
15
|
+
describe "with type" do
|
16
|
+
specify { expect(nil).to be_a NilClass }
|
17
|
+
specify { expect(nil).not_to be_a String }
|
18
|
+
|
19
|
+
specify { expect(string).to be_a String }
|
20
|
+
specify { expect(string).not_to be_a custom_class }
|
21
|
+
|
22
|
+
specify { expect(module_instance).to be_a custom_module }
|
23
|
+
specify { expect(module_instance).not_to be_a custom_class }
|
24
|
+
|
25
|
+
specify { expect(class_instance).to be_a custom_module }
|
26
|
+
specify { expect(class_instance).to be_a custom_class }
|
27
|
+
specify { expect(class_instance).not_to be_a String }
|
28
|
+
|
29
|
+
specify { expect(subclass_instance).to be_a custom_module }
|
30
|
+
specify { expect(subclass_instance).to be_a custom_class }
|
31
|
+
specify { expect(subclass_instance).to be_a custom_subclass }
|
32
|
+
specify { expect(subclass_instance).not_to be_a String }
|
33
|
+
end # describe
|
34
|
+
|
35
|
+
describe "with nil" do
|
36
|
+
specify { expect(nil).to be_a nil }
|
37
|
+
specify { expect(string).not_to be_a nil }
|
38
|
+
end # describe
|
39
|
+
|
40
|
+
describe "with array of types" do
|
41
|
+
specify { expect(nil).to be_a [String, nil] }
|
42
|
+
specify { expect(nil).not_to be_a [custom_class, String] }
|
43
|
+
|
44
|
+
specify { expect(string).to be_a [custom_module, String, nil] }
|
45
|
+
specify { expect(string).not_to be_a [custom_subclass, nil] }
|
46
|
+
|
47
|
+
specify { expect(subclass_instance).to be_a [custom_class, String] }
|
48
|
+
specify { expect(subclass_instance).not_to be_a [nil, String] }
|
49
|
+
end # describe
|
50
|
+
end # describe
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# spec/matchers/construct_spec.rb
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe "construct matcher" do
|
6
|
+
let :class_with_no_arguments do Class.new; end
|
7
|
+
let :class_with_arguments do
|
8
|
+
Class.new do def initialize(a, b, c = nil); end; end
|
9
|
+
end # let
|
10
|
+
let :not_a_class do Object.new; end
|
11
|
+
|
12
|
+
specify { expect(class_with_no_arguments).to construct }
|
13
|
+
specify { expect(class_with_arguments).to construct }
|
14
|
+
specify { expect(not_a_class).not_to construct }
|
15
|
+
|
16
|
+
describe "with a fixed number of arguments" do
|
17
|
+
specify { expect(class_with_no_arguments).to construct.
|
18
|
+
with(0).arguments }
|
19
|
+
specify { expect(class_with_no_arguments).not_to construct.
|
20
|
+
with(1).arguments }
|
21
|
+
|
22
|
+
specify { expect(class_with_arguments).not_to construct.
|
23
|
+
with(1).arguments }
|
24
|
+
specify { expect(class_with_arguments).to construct.
|
25
|
+
with(2).arguments }
|
26
|
+
specify { expect(class_with_arguments).to construct.
|
27
|
+
with(3).arguments }
|
28
|
+
specify { expect(class_with_arguments).not_to construct.
|
29
|
+
with(4).arguments }
|
30
|
+
end # describe
|
31
|
+
|
32
|
+
describe "with a range of arguments" do
|
33
|
+
specify { expect(class_with_no_arguments).to construct.
|
34
|
+
with(0..0).arguments }
|
35
|
+
specify { expect(class_with_no_arguments).not_to construct.
|
36
|
+
with(0..1).arguments }
|
37
|
+
specify { expect(class_with_no_arguments).not_to construct.
|
38
|
+
with(1..2).arguments }
|
39
|
+
|
40
|
+
specify { expect(class_with_arguments).not_to construct.
|
41
|
+
with(1..4).arguments }
|
42
|
+
specify { expect(class_with_arguments).not_to construct.
|
43
|
+
with(1..3).arguments }
|
44
|
+
specify { expect(class_with_arguments).not_to construct.
|
45
|
+
with(2..4).arguments }
|
46
|
+
specify { expect(class_with_arguments).to construct.
|
47
|
+
with(2..3).arguments }
|
48
|
+
end # describe
|
49
|
+
end # describe
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# spec/matchers/respond_to_spec.rb
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe RSpec::Matchers::BuiltIn::RespondTo do
|
6
|
+
let :described_class do
|
7
|
+
Class.new do
|
8
|
+
def method_with_no_arguments; end
|
9
|
+
|
10
|
+
def method_with_required_arguments(a, b, c); end
|
11
|
+
|
12
|
+
def method_with_optional_arguments(a, b, c = nil, d = nil); end
|
13
|
+
|
14
|
+
def method_with_variadic_arguments(a, b, c, *rest); end
|
15
|
+
|
16
|
+
def method_with_mixed_arguments(a, b, c = nil, d = nil, *rest); end
|
17
|
+
|
18
|
+
def method_with_yield; yield; end
|
19
|
+
|
20
|
+
def method_with_block_argument(&block); end
|
21
|
+
|
22
|
+
def method_with_block_and_mixed_arguments(a, b = nil, *rest, &block); end
|
23
|
+
end # class
|
24
|
+
end # let
|
25
|
+
let :instance do described_class.new; end
|
26
|
+
|
27
|
+
specify { expect(instance).to respond_to :method_with_no_arguments }
|
28
|
+
specify { expect(instance).to respond_to :method_with_required_arguments }
|
29
|
+
specify { expect(instance).to respond_to :method_with_optional_arguments }
|
30
|
+
specify { expect(instance).to respond_to :method_with_variadic_arguments }
|
31
|
+
specify { expect(instance).to respond_to :method_with_yield }
|
32
|
+
specify { expect(instance).to respond_to :method_with_mixed_arguments }
|
33
|
+
specify { expect(instance).to respond_to :method_with_block_argument }
|
34
|
+
|
35
|
+
specify { expect(instance).not_to respond_to :not_a_method }
|
36
|
+
|
37
|
+
describe "with a fixed number of arguments" do
|
38
|
+
specify { expect(instance).to respond_to(:method_with_no_arguments).
|
39
|
+
with(0).arguments }
|
40
|
+
specify { expect(instance).not_to respond_to(:method_with_no_arguments).
|
41
|
+
with(1).arguments }
|
42
|
+
|
43
|
+
specify { expect(instance).not_to respond_to(:method_with_required_arguments).
|
44
|
+
with(2).arguments }
|
45
|
+
specify { expect(instance).to respond_to(:method_with_required_arguments).
|
46
|
+
with(3).arguments }
|
47
|
+
specify { expect(instance).not_to respond_to(:method_with_required_arguments).
|
48
|
+
with(4).arguments }
|
49
|
+
|
50
|
+
specify { expect(instance).not_to respond_to(:method_with_optional_arguments).
|
51
|
+
with(1).arguments }
|
52
|
+
specify { expect(instance).to respond_to(:method_with_optional_arguments).
|
53
|
+
with(2).arguments }
|
54
|
+
specify { expect(instance).to respond_to(:method_with_optional_arguments).
|
55
|
+
with(3).arguments }
|
56
|
+
specify { expect(instance).to respond_to(:method_with_optional_arguments).
|
57
|
+
with(4).arguments }
|
58
|
+
specify { expect(instance).not_to respond_to(:method_with_optional_arguments).
|
59
|
+
with(5).arguments }
|
60
|
+
|
61
|
+
specify { expect(instance).not_to respond_to(:method_with_variadic_arguments).
|
62
|
+
with(2).arguments }
|
63
|
+
specify { expect(instance).to respond_to(:method_with_variadic_arguments).
|
64
|
+
with(3).arguments }
|
65
|
+
specify { expect(instance).to respond_to(:method_with_variadic_arguments).
|
66
|
+
with(4).arguments }
|
67
|
+
specify { expect(instance).to respond_to(:method_with_variadic_arguments).
|
68
|
+
with(9001).arguments } # IT'S OVER NINE THOUSAND!
|
69
|
+
|
70
|
+
specify { expect(instance).not_to respond_to(:method_with_mixed_arguments).
|
71
|
+
with(1).arguments }
|
72
|
+
specify { expect(instance).to respond_to(:method_with_mixed_arguments).
|
73
|
+
with(2).arguments }
|
74
|
+
specify { expect(instance).to respond_to(:method_with_mixed_arguments).
|
75
|
+
with(3).arguments }
|
76
|
+
specify { expect(instance).to respond_to(:method_with_mixed_arguments).
|
77
|
+
with(4).arguments }
|
78
|
+
specify { expect(instance).to respond_to(:method_with_mixed_arguments).
|
79
|
+
with(5).arguments }
|
80
|
+
specify { expect(instance).to respond_to(:method_with_mixed_arguments).
|
81
|
+
with(9001).arguments } # WHAT?! NINE THOUSAND!
|
82
|
+
end # describe
|
83
|
+
|
84
|
+
describe "with a range of arguments" do
|
85
|
+
specify { expect(instance).to respond_to(:method_with_no_arguments).
|
86
|
+
with(0..0).arguments }
|
87
|
+
specify { expect(instance).not_to respond_to(:method_with_no_arguments).
|
88
|
+
with(0..1).arguments }
|
89
|
+
|
90
|
+
specify { expect(instance).not_to respond_to(:method_with_required_arguments).
|
91
|
+
with(0..3).arguments }
|
92
|
+
specify { expect(instance).not_to respond_to(:method_with_required_arguments).
|
93
|
+
with(2..3).arguments }
|
94
|
+
specify { expect(instance).not_to respond_to(:method_with_required_arguments).
|
95
|
+
with(3..4).arguments }
|
96
|
+
specify { expect(instance).to respond_to(:method_with_required_arguments).
|
97
|
+
with(3..3).arguments }
|
98
|
+
|
99
|
+
specify { expect(instance).not_to respond_to(:method_with_optional_arguments).
|
100
|
+
with(0..4).arguments }
|
101
|
+
specify { expect(instance).not_to respond_to(:method_with_optional_arguments).
|
102
|
+
with(2..5).arguments }
|
103
|
+
specify { expect(instance).to respond_to(:method_with_optional_arguments).
|
104
|
+
with(2..2).arguments }
|
105
|
+
specify { expect(instance).to respond_to(:method_with_optional_arguments).
|
106
|
+
with(2..3).arguments }
|
107
|
+
specify { expect(instance).to respond_to(:method_with_optional_arguments).
|
108
|
+
with(2..4).arguments }
|
109
|
+
specify { expect(instance).to respond_to(:method_with_optional_arguments).
|
110
|
+
with(3..4).arguments }
|
111
|
+
specify { expect(instance).to respond_to(:method_with_optional_arguments).
|
112
|
+
with(4..4).arguments }
|
113
|
+
|
114
|
+
specify { expect(instance).not_to respond_to(:method_with_variadic_arguments).
|
115
|
+
with(0..4).arguments }
|
116
|
+
specify { expect(instance).not_to respond_to(:method_with_variadic_arguments).
|
117
|
+
with(2..4).arguments }
|
118
|
+
specify { expect(instance).to respond_to(:method_with_variadic_arguments).
|
119
|
+
with(3..4).arguments }
|
120
|
+
specify { expect(instance).to respond_to(:method_with_variadic_arguments).
|
121
|
+
with(5..9).arguments }
|
122
|
+
specify { expect(instance).to respond_to(:method_with_variadic_arguments).
|
123
|
+
with(3..9001).arguments } # VEGETA, WHAT DOES...NEVER MIND, JOKE'S OVER
|
124
|
+
|
125
|
+
specify { expect(instance).not_to respond_to(:method_with_mixed_arguments).
|
126
|
+
with(0..5).arguments }
|
127
|
+
specify { expect(instance).not_to respond_to(:method_with_mixed_arguments).
|
128
|
+
with(1..5).arguments }
|
129
|
+
specify { expect(instance).to respond_to(:method_with_mixed_arguments).
|
130
|
+
with(2..5).arguments }
|
131
|
+
specify { expect(instance).to respond_to(:method_with_mixed_arguments).
|
132
|
+
with(3..5).arguments }
|
133
|
+
specify { expect(instance).to respond_to(:method_with_mixed_arguments).
|
134
|
+
with(4..5).arguments }
|
135
|
+
specify { expect(instance).to respond_to(:method_with_mixed_arguments).
|
136
|
+
with(5..5).arguments }
|
137
|
+
specify { expect(instance).to respond_to(:method_with_mixed_arguments).
|
138
|
+
with(2..9001).arguments } # THERE'S NO WAY THAT CAN BE RIGHT. CAN IT?!?
|
139
|
+
end # describe
|
140
|
+
|
141
|
+
describe "with a block" do
|
142
|
+
specify { expect(instance).not_to respond_to(:method_with_no_arguments).
|
143
|
+
with.a_block }
|
144
|
+
|
145
|
+
specify { expect(instance).not_to respond_to(:method_with_yield).
|
146
|
+
with.a_block }
|
147
|
+
|
148
|
+
specify { expect(instance).to respond_to(:method_with_block_argument).
|
149
|
+
with.a_block }
|
150
|
+
specify { expect(instance).to respond_to(:method_with_block_argument).
|
151
|
+
with(0).arguments.and.a_block }
|
152
|
+
|
153
|
+
specify { expect(instance).to respond_to(:method_with_block_and_mixed_arguments).
|
154
|
+
with.a_block }
|
155
|
+
specify { expect(instance).to respond_to(:method_with_block_and_mixed_arguments).
|
156
|
+
with(2..9001).arguments.and.a_block } # FINE, FINE. KILLJOYS.
|
157
|
+
end # describe
|
158
|
+
end # describe
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# spec/controllers/text_controller_helper.rb
|
2
|
+
|
3
|
+
require 'mithril/controllers/abstract_controller_helper'
|
4
|
+
|
5
|
+
shared_examples_for "Mithril::Controllers::_TextController" do
|
6
|
+
it_behaves_like Mithril::Controllers::AbstractController
|
7
|
+
|
8
|
+
let :input do "text input"; end
|
9
|
+
|
10
|
+
describe :parser do
|
11
|
+
specify { expect(instance.parser).to be_a Mithril::Parsers::SimpleParser }
|
12
|
+
end # describe
|
13
|
+
|
14
|
+
describe :parse_command do
|
15
|
+
specify { expect(instance.parse_command input).to be_a Array }
|
16
|
+
|
17
|
+
specify "returns nil" do
|
18
|
+
command, args = instance.parse_command input
|
19
|
+
expect(command).to be nil
|
20
|
+
end # specify
|
21
|
+
end # describe
|
22
|
+
|
23
|
+
describe :command_missing do
|
24
|
+
specify "returns the text with a helpful message" do
|
25
|
+
output = instance.command_missing input
|
26
|
+
expect(output).to match /don't know how/
|
27
|
+
expect(output).to match /#{input}/
|
28
|
+
end # specify
|
29
|
+
end # describe
|
30
|
+
|
31
|
+
describe :invoke_command do
|
32
|
+
specify "returns the text with a helpful message" do
|
33
|
+
output = instance.invoke_command input
|
34
|
+
expect(output).to match /don't know how/
|
35
|
+
expect(output).to match /#{input}/
|
36
|
+
end # specify
|
37
|
+
end # describe
|
38
|
+
|
39
|
+
context "with actions defined" do
|
40
|
+
let :command do FactoryGirl.generate :action_key; end
|
41
|
+
let :arguments do %w(arguments for command); end
|
42
|
+
|
43
|
+
before :each do
|
44
|
+
described_class.define_action command do |session, args| args.join(' '); end
|
45
|
+
end # before each
|
46
|
+
|
47
|
+
specify { expect(instance.can_invoke? command.to_s).to be true }
|
48
|
+
|
49
|
+
describe :invoke_command do
|
50
|
+
let :text do "#{command} #{arguments.join(' ')}"; end
|
51
|
+
|
52
|
+
specify "invokes matching action" do
|
53
|
+
instance.should_receive(:invoke_action).with(command, arguments).and_call_original
|
54
|
+
instance.should_receive(:"action_#{command}").with(request.session, arguments).and_call_original
|
55
|
+
instance.invoke_command text
|
56
|
+
end # specify
|
57
|
+
|
58
|
+
specify { expect(instance.invoke_command text).to eq arguments.join(' ') }
|
59
|
+
|
60
|
+
context "with a non-matching command" do
|
61
|
+
let :non_matching do FactoryGirl.generate :action_key; end
|
62
|
+
|
63
|
+
specify { expect(instance.invoke_command non_matching.to_s).to match /don't know how/i }
|
64
|
+
end # context
|
65
|
+
end # describe
|
66
|
+
end # context
|
67
|
+
|
68
|
+
describe "empty actions" do
|
69
|
+
def self.input
|
70
|
+
chars, words = [*"a".."z", *"0".."9"], [""] * 5
|
71
|
+
5.times do |i|
|
72
|
+
word = ""
|
73
|
+
(6 + rand(10)).times do word << chars[rand(36)]; end
|
74
|
+
words[i] = word
|
75
|
+
end # times
|
76
|
+
words.join " "
|
77
|
+
end # helper input
|
78
|
+
|
79
|
+
it_behaves_like "Mithril::Controllers::AbstractController#empty_actions", input
|
80
|
+
end # describe
|
81
|
+
end # describe
|