funktional 1.0.0
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/MIT-LICENSE +20 -0
- data/Manifest +60 -0
- data/README.rdoc +292 -0
- data/Rakefile +36 -0
- data/funktional.gemspec +31 -0
- data/lib/funktional/assertion.rb +9 -0
- data/lib/funktional/assigned_assertion.rb +43 -0
- data/lib/funktional/attribute_test_helper.rb +27 -0
- data/lib/funktional/context/assigned_should_block.rb +32 -0
- data/lib/funktional/context/collector.rb +21 -0
- data/lib/funktional/context/count_should_block.rb +21 -0
- data/lib/funktional/context/delegating_should_block.rb +30 -0
- data/lib/funktional/context/element_should_block.rb +29 -0
- data/lib/funktional/context/flashed_should_block.rb +17 -0
- data/lib/funktional/context/should_block.rb +60 -0
- data/lib/funktional/context/should_create_block.rb +17 -0
- data/lib/funktional/context/should_delete_block.rb +17 -0
- data/lib/funktional/context/should_not_block.rb +20 -0
- data/lib/funktional/context/should_not_create_block.rb +17 -0
- data/lib/funktional/context/should_not_delete_block.rb +17 -0
- data/lib/funktional/context/should_not_send_email_block.rb +18 -0
- data/lib/funktional/context/stack_recorder.rb +35 -0
- data/lib/funktional/context.rb +126 -0
- data/lib/funktional/email_assertion.rb +50 -0
- data/lib/funktional/flashed_assertion.rb +12 -0
- data/lib/funktional/model_assertions.rb +108 -0
- data/lib/funktional/random_characters.rb +11 -0
- data/lib/funktional/recursive_assertion.rb +23 -0
- data/lib/funktional/route_checker.rb +49 -0
- data/lib/funktional/setup.rb +11 -0
- data/lib/funktional/test_class_methods.rb +28 -0
- data/lib/funktional/test_instance_methods.rb +131 -0
- data/lib/funktional.rb +42 -0
- data/tasks/should_b_tasks.rake +4 -0
- data/test/fixtures/posts.yml +4 -0
- data/test/fixtures/users.yml +9 -0
- data/test/functional/users_controller_test.rb +59 -0
- data/test/test-app/app/controllers/application_controller.rb +10 -0
- data/test/test-app/app/controllers/users_controller.rb +33 -0
- data/test/test-app/app/helpers/application_helper.rb +3 -0
- data/test/test-app/app/models/post.rb +3 -0
- data/test/test-app/app/models/user.rb +7 -0
- data/test/test-app/app/views/users/edit.html.erb +0 -0
- data/test/test-app/app/views/users/index.html.erb +0 -0
- data/test/test-app/app/views/users/new.html.erb +0 -0
- data/test/test-app/config/boot.rb +110 -0
- data/test/test-app/config/database.yml +4 -0
- data/test/test-app/config/environment.rb +12 -0
- data/test/test-app/config/environments/test.rb +0 -0
- data/test/test-app/config/initializers/funktional.rb +8 -0
- data/test/test-app/config/initializers/new_rails_defaults.rb +21 -0
- data/test/test-app/config/routes.rb +5 -0
- data/test/test-app/db/migrate/001_create_users.rb +18 -0
- data/test/test-app/db/migrate/002_create_posts.rb +13 -0
- data/test/test-app/public/404.html +30 -0
- data/test/test-app/public/422.html +30 -0
- data/test/test-app/public/500.html +30 -0
- data/test/test-app/script/console +3 -0
- data/test/test-app/script/generate +3 -0
- data/test/test_helper.rb +26 -0
- data/test/unit/user_test.rb +12 -0
- metadata +159 -0
@@ -0,0 +1,60 @@
|
|
1
|
+
module Funktional
|
2
|
+
class ShouldBlock
|
3
|
+
|
4
|
+
def self.build(options, context, &blk)
|
5
|
+
return self.new(name = options, context, &blk) if options.is_a? String
|
6
|
+
|
7
|
+
options = {:render_404 => 'public/404'} if options == :render_404
|
8
|
+
|
9
|
+
case options.keys.first
|
10
|
+
when :create
|
11
|
+
ShouldCreateBlock.new(options[:create], context)
|
12
|
+
when :delete
|
13
|
+
ShouldDeleteBlock.new(options[:delete], context)
|
14
|
+
else
|
15
|
+
DelegatingShouldBlock.new(options, context, &blk)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(should_name, context, &blk)
|
20
|
+
raise 'block required' unless block_given?
|
21
|
+
@should_name, @blk, @context = should_name, blk, context
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_test
|
25
|
+
context, blk, before = @context, @blk, @before
|
26
|
+
|
27
|
+
@context.test_unit_class.send(:define_method, build_test_name) do
|
28
|
+
begin
|
29
|
+
context.run_parent_setup_blocks(self)
|
30
|
+
before.bind(self).call if before
|
31
|
+
|
32
|
+
context.run_current_setup_blocks(self)
|
33
|
+
blk.bind(self).call
|
34
|
+
ensure
|
35
|
+
context.run_all_teardown_blocks(self)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def test_and_line_no
|
43
|
+
stack_frame = caller.grep(/bind/).last
|
44
|
+
stack_frame.split(':in ').first
|
45
|
+
end
|
46
|
+
|
47
|
+
def build_test_name
|
48
|
+
test_name = test_name_parts.flatten.join(' ')
|
49
|
+
|
50
|
+
if @context.test_unit_class.instance_methods.include?(test_name)
|
51
|
+
warn " * WARNING: '#{test_name}' is already defined"
|
52
|
+
end
|
53
|
+
return test_name.to_sym
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_name_parts
|
57
|
+
["test:", @context.full_name, "should", "#{@should_name}."]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Funktional
|
2
|
+
class ShouldCreateBlock < ShouldBlock
|
3
|
+
|
4
|
+
def initialize(klass, context)
|
5
|
+
@context = context
|
6
|
+
@should_name = "create a #{klass}"
|
7
|
+
|
8
|
+
@before = lambda { @before_setup_count = klass.count }
|
9
|
+
where = test_and_line_no
|
10
|
+
|
11
|
+
@blk = lambda do
|
12
|
+
expected_count = @before_setup_count + 1
|
13
|
+
assert_equal expected_count, klass.count, "New [#{klass}] was not created. #{where}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Funktional
|
2
|
+
class ShouldDeleteBlock < ShouldBlock
|
3
|
+
|
4
|
+
def initialize(klass, context)
|
5
|
+
@context = context
|
6
|
+
@should_name = "delete a #{klass}"
|
7
|
+
|
8
|
+
@before = lambda { @before_setup_count = klass.count }
|
9
|
+
where = test_and_line_no
|
10
|
+
|
11
|
+
@blk = lambda do
|
12
|
+
expected_count = @before_setup_count - 1
|
13
|
+
assert_equal expected_count, klass.count, "New [#{klass}] was not deleted. #{where}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Funktional
|
2
|
+
class ShouldNotBlock
|
3
|
+
|
4
|
+
def self.build(options, context, &blk)
|
5
|
+
|
6
|
+
if options.is_a? Symbol and options.eql? :send_email
|
7
|
+
return ShouldNotSendEmailBlock.new(context)
|
8
|
+
end
|
9
|
+
|
10
|
+
case options.keys.first
|
11
|
+
when :create
|
12
|
+
ShouldNotCreateBlock.new(options[:create], context)
|
13
|
+
when :delete
|
14
|
+
ShouldNotDeleteBlock.new(options[:delete], context)
|
15
|
+
else
|
16
|
+
raise "Unknown assertion [should_not #{options.inspect}]"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Funktional
|
2
|
+
class ShouldNotCreateBlock < ShouldBlock
|
3
|
+
|
4
|
+
def initialize(klass, context)
|
5
|
+
@context = context
|
6
|
+
@should_name = "not create a #{klass}"
|
7
|
+
|
8
|
+
@before = lambda { @before_setup_count = klass.count }
|
9
|
+
where = test_and_line_no
|
10
|
+
|
11
|
+
@blk = lambda do
|
12
|
+
expected_count = @before_setup_count
|
13
|
+
assert_equal expected_count, klass.count, "New [#{klass}] was created. #{where}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Funktional
|
2
|
+
class ShouldNotDeleteBlock < ShouldBlock
|
3
|
+
|
4
|
+
def initialize(klass, context)
|
5
|
+
@context = context
|
6
|
+
@should_name = "not delete a #{klass}"
|
7
|
+
|
8
|
+
@before = lambda { @before_setup_count = klass.count }
|
9
|
+
where = test_and_line_no
|
10
|
+
|
11
|
+
@blk = lambda do
|
12
|
+
expected_count = @before_setup_count
|
13
|
+
assert_equal expected_count, klass.count, "New [#{klass}] was deleted. #{where}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Funktional
|
2
|
+
class ShouldNotSendEmailBlock < ShouldBlock
|
3
|
+
|
4
|
+
def initialize(context)
|
5
|
+
@context = context
|
6
|
+
@should_name = "not send an email"
|
7
|
+
|
8
|
+
@before = lambda { @before_setup_count = ActionMailer::Base.deliveries.size }
|
9
|
+
where = test_and_line_no
|
10
|
+
|
11
|
+
@blk = lambda do
|
12
|
+
expected_count = @before_setup_count
|
13
|
+
current = ActionMailer::Base.deliveries.size
|
14
|
+
assert_equal expected_count, current, "New [Email] was sent."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Funktional
|
2
|
+
class BlankSlate
|
3
|
+
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
|
4
|
+
end
|
5
|
+
|
6
|
+
class StackRecorder < BlankSlate
|
7
|
+
attr_reader :__target
|
8
|
+
|
9
|
+
def initialize(target)
|
10
|
+
@__target = target
|
11
|
+
@__methods = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def __meth(index)
|
15
|
+
@__methods[index]
|
16
|
+
end
|
17
|
+
|
18
|
+
def __each_called
|
19
|
+
@__methods.each { |meth| yield [meth[:name], meth[:args], meth[:block]] }
|
20
|
+
end
|
21
|
+
|
22
|
+
def __last_value
|
23
|
+
@__methods.last[:args].first
|
24
|
+
end
|
25
|
+
|
26
|
+
def method_missing(method_name, *args, &block)
|
27
|
+
@__methods << {
|
28
|
+
:name => method_name,
|
29
|
+
:args => args,
|
30
|
+
:block => block
|
31
|
+
}
|
32
|
+
return self
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# borrowing heavily from shoulda contexts.
|
2
|
+
|
3
|
+
module Funktional
|
4
|
+
class Context
|
5
|
+
|
6
|
+
attr_accessor :name
|
7
|
+
attr_accessor :parent
|
8
|
+
attr_accessor :sub_contexts
|
9
|
+
attr_accessor :setup_blocks
|
10
|
+
attr_accessor :teardown_blocks
|
11
|
+
attr_accessor :should_blocks
|
12
|
+
|
13
|
+
def initialize(name, parent, &blk)
|
14
|
+
Funktional.add_context(self)
|
15
|
+
self.name = name
|
16
|
+
self.parent = parent
|
17
|
+
self.setup_blocks = []
|
18
|
+
self.teardown_blocks = []
|
19
|
+
self.should_blocks = []
|
20
|
+
self.sub_contexts = []
|
21
|
+
|
22
|
+
merge_block(&blk)
|
23
|
+
Funktional.remove_context
|
24
|
+
end
|
25
|
+
|
26
|
+
def merge_block(&blk)
|
27
|
+
blk.bind(self).call
|
28
|
+
end
|
29
|
+
|
30
|
+
def context(name, &blk)
|
31
|
+
self.sub_contexts << Context.new(name, self, &blk)
|
32
|
+
end
|
33
|
+
|
34
|
+
def setup(&blk)
|
35
|
+
self.setup_blocks << blk
|
36
|
+
end
|
37
|
+
|
38
|
+
alias :before :setup
|
39
|
+
|
40
|
+
def teardown(&blk)
|
41
|
+
self.teardown_blocks << blk
|
42
|
+
end
|
43
|
+
|
44
|
+
alias :after :teardown
|
45
|
+
|
46
|
+
def should(options, &blk)
|
47
|
+
self.should_blocks << ShouldBlock.build(options, self, &blk)
|
48
|
+
end
|
49
|
+
|
50
|
+
def should_not(options, &blk)
|
51
|
+
self.should_blocks << ShouldNotBlock.build(options, self, &blk)
|
52
|
+
end
|
53
|
+
|
54
|
+
def element(selector)
|
55
|
+
recorder = StackRecorder.new(selector)
|
56
|
+
self.should_blocks << ElementShouldBlock.new(recorder, self)
|
57
|
+
|
58
|
+
return recorder
|
59
|
+
end
|
60
|
+
|
61
|
+
def count(selector)
|
62
|
+
recorder = StackRecorder.new(selector)
|
63
|
+
self.should_blocks << CountShouldBlock.new(recorder, self)
|
64
|
+
|
65
|
+
return recorder
|
66
|
+
end
|
67
|
+
|
68
|
+
def assigned(target)
|
69
|
+
recorder = StackRecorder.new(target)
|
70
|
+
self.should_blocks << AssignedShouldBlock.new(recorder, self)
|
71
|
+
|
72
|
+
return recorder
|
73
|
+
end
|
74
|
+
|
75
|
+
def flashed(kind)
|
76
|
+
recorder = StackRecorder.new(kind)
|
77
|
+
self.should_blocks << FlashedShouldBlock.new(recorder, self)
|
78
|
+
|
79
|
+
return recorder
|
80
|
+
end
|
81
|
+
|
82
|
+
def full_name
|
83
|
+
parent_name = parent.full_name if sub_context?
|
84
|
+
return [parent_name, name].join(" ").strip
|
85
|
+
end
|
86
|
+
|
87
|
+
def sub_context?
|
88
|
+
parent.is_a?(self.class)
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_unit_class
|
92
|
+
sub_context? ? parent.test_unit_class : parent
|
93
|
+
end
|
94
|
+
|
95
|
+
def run_all_setup_blocks(binding)
|
96
|
+
run_parent_setup_blocks(binding)
|
97
|
+
run_current_setup_blocks(binding)
|
98
|
+
end
|
99
|
+
|
100
|
+
def run_parent_setup_blocks(binding)
|
101
|
+
self.parent.run_all_setup_blocks(binding) if sub_context?
|
102
|
+
end
|
103
|
+
|
104
|
+
def run_current_setup_blocks(binding)
|
105
|
+
setup_blocks.each do |setup_block|
|
106
|
+
setup_block.bind(binding).call
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def run_all_teardown_blocks(binding)
|
111
|
+
teardown_blocks.reverse.each do |teardown_block|
|
112
|
+
teardown_block.bind(binding).call
|
113
|
+
end
|
114
|
+
self.parent.run_all_teardown_blocks(binding) if sub_context?
|
115
|
+
end
|
116
|
+
|
117
|
+
def build
|
118
|
+
self.should_blocks.map(&:to_test)
|
119
|
+
sub_contexts.each { |context| context.build }
|
120
|
+
end
|
121
|
+
|
122
|
+
def method_missing(method, *args, &blk)
|
123
|
+
test_unit_class.send(method, *args, &blk)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Funktional
|
2
|
+
class EmailAssertion < Funktional::Assertion
|
3
|
+
def initialize(expectations)
|
4
|
+
if ActionMailer::Base.deliveries.size < 1
|
5
|
+
flunk 'No emails have been sent'
|
6
|
+
end
|
7
|
+
|
8
|
+
email = ActionMailer::Base.deliveries.last
|
9
|
+
|
10
|
+
expectations.each_key do |key|
|
11
|
+
case key
|
12
|
+
when :from
|
13
|
+
then check_from(expectations[:from], email.from)
|
14
|
+
when :to
|
15
|
+
then check_to(expectations[:to], email.to)
|
16
|
+
when :subject
|
17
|
+
then assert_equal expectations[:subject], email.subject
|
18
|
+
when :containing
|
19
|
+
then check_containing(expectations[:containing], email.body)
|
20
|
+
else
|
21
|
+
flunk "Assertion key: [#{key}] not recognised"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def check_from(expected_from, email_from)
|
27
|
+
if email_from.nil?
|
28
|
+
flunk 'email is missing a [from]'
|
29
|
+
end
|
30
|
+
assert_equal expected_from, email_from[0]
|
31
|
+
end
|
32
|
+
|
33
|
+
def check_to(expected_to, email_to)
|
34
|
+
if email_to.nil?
|
35
|
+
flunk 'email is missing a [to]'
|
36
|
+
end
|
37
|
+
assert_equal expected_to, email_to[0]
|
38
|
+
end
|
39
|
+
|
40
|
+
def check_containing(should_contain, body)
|
41
|
+
if should_contain.is_a? Array
|
42
|
+
should_contain.each do |should_i|
|
43
|
+
assert_match /#{Regexp.escape(should_i)}/, body
|
44
|
+
end
|
45
|
+
else
|
46
|
+
assert_match /#{Regexp.escape(should_contain)}/, body
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Funktional
|
2
|
+
class FlashedAssertion < Funktional::Assertion
|
3
|
+
def initialize(symbol)
|
4
|
+
@symbol = symbol
|
5
|
+
end
|
6
|
+
|
7
|
+
def should_be(expected_value)
|
8
|
+
assert_not_nil flash[@symbol], "Flash is empty [#{expected_value}] expected."
|
9
|
+
assert_equal expected_value, flash[@symbol]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Funktional
|
2
|
+
module ModelAssertions
|
3
|
+
def should_require_a(field, expected_error_message = nil)
|
4
|
+
check_test_instance!
|
5
|
+
must_be_valid_before_test!
|
6
|
+
|
7
|
+
assign_nil_to(field, expected_error_message) do
|
8
|
+
assert_invalid("'#{self.class.name}' should require a '#{field}'")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
alias :should_require_an :should_require_a
|
13
|
+
|
14
|
+
def should_not_require_a(field)
|
15
|
+
check_test_instance!
|
16
|
+
|
17
|
+
assign_nil_to(field) do
|
18
|
+
assert_valid
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
alias :should_not_require_an :should_not_require_a
|
23
|
+
|
24
|
+
def should_have_invalid(field, expected_error_message = nil)
|
25
|
+
check_test_instance!
|
26
|
+
|
27
|
+
assert_invalid("'#{self.class.name}' should have invalid '#{field}'")
|
28
|
+
assert_message(field, expected_error_message) if expected_error_message
|
29
|
+
end
|
30
|
+
|
31
|
+
def should_mass_assign(*fields)
|
32
|
+
check_test_instance!
|
33
|
+
fields.each do |field|
|
34
|
+
Funktional.test_instance.assert self.class.accessible_attributes.include?(field.to_s)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def should_not_mass_assign(*fields)
|
39
|
+
check_test_instance!
|
40
|
+
accessible_attrib = self.class.accessible_attributes.to_a
|
41
|
+
protected_attrib = self.class.protected_attributes.to_a
|
42
|
+
fields = fields.map(&:to_s)
|
43
|
+
|
44
|
+
if accessible_attrib.any?
|
45
|
+
common_fields = (accessible_attrib & fields)
|
46
|
+
@test.assert((common_fields.size == 0), "#{common_fields.inspect} marked accessible")
|
47
|
+
elsif protected_attrib.any?
|
48
|
+
common_fields = (protected_attrib & fields)
|
49
|
+
difference = (fields - protected_attrib)
|
50
|
+
@test.assert((common_fields.size == fields.size), "#{difference.inspect} not protected")
|
51
|
+
else
|
52
|
+
@test.flunk "#{fields.inspect} not protected"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def should_protect(*fields)
|
57
|
+
check_test_instance!
|
58
|
+
fields.each do |field|
|
59
|
+
Funktional.test_instance.assert self.class.protected_attributes.include?(field.to_s)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def should_respond_to(method)
|
64
|
+
Funktional.test_instance.assert_respond_to self, method
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def assign_nil_to(field, expected_error_message = nil)
|
70
|
+
saved_existing_value = self.send field
|
71
|
+
self.send "#{field}=", nil
|
72
|
+
|
73
|
+
yield
|
74
|
+
|
75
|
+
assert_message(field, expected_error_message) if expected_error_message
|
76
|
+
self.send "#{field}=", saved_existing_value
|
77
|
+
|
78
|
+
# clear errors
|
79
|
+
self.valid?
|
80
|
+
end
|
81
|
+
|
82
|
+
def assert_invalid(message)
|
83
|
+
Funktional.test_instance.assert self.invalid?, message
|
84
|
+
end
|
85
|
+
|
86
|
+
def assert_valid
|
87
|
+
Funktional.test_instance.assert self.valid?
|
88
|
+
end
|
89
|
+
|
90
|
+
def assert_message(field, expected_error_message)
|
91
|
+
Funktional.test_instance.assert_equal(expected_error_message, self.errors[field])
|
92
|
+
end
|
93
|
+
|
94
|
+
def must_be_valid_before_test!
|
95
|
+
if self.invalid?
|
96
|
+
error = "Funktional requires a valid instance of #{self.class.name}"
|
97
|
+
Funktional.test_instance.flunk error
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def check_test_instance!
|
102
|
+
if Funktional.test_instance.nil?
|
103
|
+
raise Funktional::Setup::Error, 'Did you forget to (setup :funktional) in test/test_helper?'
|
104
|
+
end
|
105
|
+
@test = Funktional.test_instance
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Funktional
|
2
|
+
class RecursiveAssertion < Funktional::Assertion
|
3
|
+
def initialize(assigned, method)
|
4
|
+
@test = Funktional.test_instance
|
5
|
+
@assigned = assigned
|
6
|
+
@method = method
|
7
|
+
|
8
|
+
@test.assert_respond_to @assigned, @method
|
9
|
+
end
|
10
|
+
|
11
|
+
def should_be(expected_value)
|
12
|
+
value = @assigned.send @method
|
13
|
+
@test.assert_equal expected_value, value
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
|
18
|
+
def method_missing(method, *args)
|
19
|
+
@assigned = @assigned.send @method
|
20
|
+
RecursiveAssertion.new(@assigned, method)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Funktional
|
2
|
+
|
3
|
+
class RouteChecker
|
4
|
+
instance_methods.each do |method|
|
5
|
+
undef_method(method) unless %w(__send__ __id__ instance_eval).include?(method)
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :__path_and_method, :__controller_action_etc
|
9
|
+
|
10
|
+
def self.build(params, &blk)
|
11
|
+
checker = self.new(params)
|
12
|
+
|
13
|
+
checker.instance_eval(&blk)
|
14
|
+
return checker
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(params)
|
18
|
+
@__path_and_method = __get_path_and_method(params)
|
19
|
+
@__controller_action_etc = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def __test_name
|
23
|
+
path = @__path_and_method[:path]
|
24
|
+
method = @__path_and_method[:method]
|
25
|
+
|
26
|
+
"route '#{path}' :method '#{method}' to #{@__controller_action_etc.inspect}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def method_missing(method_name, value)
|
30
|
+
@__controller_action_etc[method_name] = value
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def __get_path_and_method(params)
|
36
|
+
if params.is_a? Hash
|
37
|
+
{
|
38
|
+
:path => params[:route],
|
39
|
+
:method => params[:method].to_sym
|
40
|
+
}
|
41
|
+
else
|
42
|
+
{
|
43
|
+
:path => params,
|
44
|
+
:method => :get
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Funktional
|
2
|
+
|
3
|
+
module TestClassMethods
|
4
|
+
def context(name, &blk)
|
5
|
+
if Funktional.current_context
|
6
|
+
Funktional.current_context.context(name, &blk)
|
7
|
+
else
|
8
|
+
context = Funktional::Context.new(name, self, &blk)
|
9
|
+
context.build
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def should(name, &blk)
|
14
|
+
if Funktional.current_context
|
15
|
+
raise 'block required' unless block_given?
|
16
|
+
Funktional.current_context.should(name, &blk)
|
17
|
+
else
|
18
|
+
context_name = self.name.gsub(/Test/, "")
|
19
|
+
|
20
|
+
context = Funktional::Context.new(context_name, self) do
|
21
|
+
raise 'block required' unless block_given?
|
22
|
+
should(name, &blk)
|
23
|
+
end
|
24
|
+
context.build
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|