spinach 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -28,6 +28,22 @@ module Spinach
28
28
  run_hook(hook, *args, &block)
29
29
  end
30
30
  end
31
+
32
+ # Adds a new around_hook to this class. Every hook defines two methods
33
+ # used to add new callbacks and to run them around a given block of code
34
+ # passing a bunch of parameters and invoking them in the order they were
35
+ # defined.
36
+ #
37
+ # @example
38
+ # class
39
+ def around_hook(hook)
40
+ define_method hook do |&block|
41
+ add_hook(hook, &block)
42
+ end
43
+ define_method "run_#{hook}" do |*args, &block|
44
+ run_around_hook(hook, *args, &block)
45
+ end
46
+ end
31
47
  end
32
48
 
33
49
  module InstanceMethods
@@ -45,6 +61,32 @@ module Spinach
45
61
  self.hooks = {}
46
62
  end
47
63
 
64
+ # Runs around hooks in a way that ensure the scenario block is executed
65
+ # only once
66
+ #
67
+ # @param [String] name
68
+ # the around hook's name
69
+ #
70
+ # @param [] args
71
+ # the list of arguments to pass to other around filters
72
+ #
73
+ # @param [Proc] block
74
+ # the block containing the scenario action to be executed
75
+ def run_around_hook(name, *args, &block)
76
+ raise ArgumentError.new("block is mandatory") unless block
77
+ if callbacks = hooks[name.to_sym]
78
+ callbacks.reverse.inject(block) do |blk, callback|
79
+ proc do
80
+ callback.call *args do
81
+ blk.call
82
+ end
83
+ end
84
+ end.call
85
+ else
86
+ yield
87
+ end
88
+ end
89
+
48
90
  # Runs a particular hook given a set of arguments
49
91
  #
50
92
  # @param [String] name
data/lib/spinach/hooks.rb CHANGED
@@ -62,7 +62,7 @@ module Spinach
62
62
  # # feature_data is a hash of the parsed scenario data
63
63
  # block.call
64
64
  # end
65
- hook :around_scenario
65
+ around_hook :around_scenario
66
66
 
67
67
  # Runs after every scenario
68
68
  #
@@ -74,7 +74,7 @@ module Spinach
74
74
 
75
75
  def run_scenario?(scenario, current_scenario_index)
76
76
  match_line(current_scenario_index) &&
77
- TagsMatcher.match(feature_tags | scenario.tags)
77
+ TagsMatcher.match((feature_tags << scenario.tags).flatten.compact)
78
78
  end
79
79
 
80
80
  def match_line(current_scenario_index)
@@ -27,15 +27,17 @@ module Spinach
27
27
  end
28
28
 
29
29
  def match_tag_group(tag_group, tags)
30
- tag_group.any? do |tag|
31
- tag_matched = tags.include?(tag.delete(NEGATION_SIGN))
32
-
33
- if tag_negated?(tag)
34
- !tag_matched
35
- else
36
- tag_matched
37
- end
38
- end
30
+ matched_tags = tag_group.select { |tag| !tag_negated?(tag) }
31
+
32
+ matched = matched_tags.any? { |tag| tags.include?(tag) }
33
+
34
+ return true if matched
35
+
36
+ negated_tags = tag_group.select { |tag| tag_negated? tag }
37
+ negated = negated_tags.any? {|tag| !tags.include?(tag.delete(NEGATION_SIGN))}
38
+
39
+ return true if negated && tag_group.count == 1
40
+ false
39
41
  end
40
42
 
41
43
  def tag_negated?(tag)
@@ -1,4 +1,4 @@
1
1
  module Spinach
2
2
  # Spinach version.
3
- VERSION = "0.5.1"
3
+ VERSION = "0.5.2"
4
4
  end
@@ -12,6 +12,11 @@ describe Spinach::Hookable do
12
12
  subject.class.hook :before_save
13
13
  subject.must_respond_to :before_save
14
14
  end
15
+
16
+ it "defines a new around hook" do
17
+ subject.class.around_hook :around_save
18
+ subject.must_respond_to :around_save
19
+ end
15
20
  end
16
21
 
17
22
  describe "hooking mechanism" do
@@ -30,6 +35,17 @@ describe Spinach::Hookable do
30
35
  subject.run_hook(:before_save)
31
36
  arbitrary_variable.must_equal true
32
37
  end
38
+
39
+ it "allows to run around hook" do
40
+ arbitrary_variable = false
41
+ subject.add_hook(:around_save) do |&block|
42
+ arbitrary_variable = true
43
+ block.call
44
+ end
45
+ subject.run_around_hook(:around_save) do
46
+ end
47
+ arbitrary_variable.must_equal true
48
+ end
33
49
  end
34
50
 
35
51
  describe "with params" do
@@ -49,6 +65,18 @@ describe Spinach::Hookable do
49
65
  array.must_equal [1, 2]
50
66
  end
51
67
 
68
+ it "allows to run an around hook" do
69
+ array = []
70
+ subject.add_hook(:around_save) do |var1, var2, &block|
71
+ array << var1
72
+ array << var2
73
+ block.call
74
+ end
75
+ subject.run_around_hook(:around_save, 1, 2) do
76
+ end
77
+ array.must_equal [1, 2]
78
+ end
79
+
52
80
  it "yields to hook block even if nothing is hooked" do
53
81
  called = false
54
82
  subject.run_hook(:before_save) do
@@ -56,11 +84,77 @@ describe Spinach::Hookable do
56
84
  end
57
85
  called.must_equal true
58
86
  end
87
+
88
+ it "yields to around hook block even if nothing is hooked" do
89
+ called = false
90
+ subject.run_hook(:around_save) do
91
+ called = true
92
+ end
93
+ called.must_equal true
94
+ end
95
+ end
96
+
97
+ describe "order" do
98
+ it "runs hooks in registration order" do
99
+ save = sequence("save")
100
+ object = mock("object")
101
+ object.expects(:before_first).in_sequence(save)
102
+ object.expects(:before_second).in_sequence(save)
103
+
104
+ subject.add_hook(:before_save) do
105
+ object.before_first
106
+ end
107
+ subject.add_hook(:before_save) do
108
+ object.before_second
109
+ end
110
+ subject.run_hook(:before_save)
111
+ end
112
+
113
+ it "runs around hooks in registration order" do
114
+ save = sequence("save")
115
+ object = mock("object")
116
+ object.expects(:before_first).in_sequence(save)
117
+ object.expects(:before_second).in_sequence(save)
118
+ object.expects(:after_second).in_sequence(save)
119
+ object.expects(:after_first).in_sequence(save)
120
+
121
+ subject.add_hook(:around_save) do |&block|
122
+ object.before_first
123
+ block.call
124
+ object.after_first
125
+ end
126
+ subject.add_hook(:around_save) do |&block|
127
+ object.before_second
128
+ block.call
129
+ object.after_second
130
+ end
131
+
132
+ subject.run_around_hook(:around_save) {}
133
+ end
134
+ end
135
+
136
+ it "requires a block when running around hook" do
137
+ subject.add_hook(:around_save) do
138
+ end
139
+ lambda {
140
+ subject.run_around_hook(:around_save)
141
+ }.must_raise ArgumentError
142
+ end
143
+
144
+ it "runs around hook block only once" do
145
+ object = mock("object")
146
+ object.expects(:save).once
147
+ subject.add_hook(:around_save){|&block| block.call}
148
+ subject.add_hook(:around_save){|&block| block.call}
149
+ subject.run_around_hook(:around_save){ object.save }
59
150
  end
60
151
 
61
152
  describe "#reset_hooks" do
62
153
  it "resets the hooks to a pristine state" do
63
154
  subject.add_hook(:before_save)
155
+ (subject.hooks.empty?).must_equal false
156
+ subject.reset
157
+ (subject.hooks.empty?).must_equal true
64
158
  end
65
159
  end
66
160
  end
@@ -6,9 +6,23 @@ describe Spinach::Hooks do
6
6
  end
7
7
 
8
8
  describe "hooks" do
9
- %w{before_run after_run before_feature after_feature on_undefined_feature
10
- before_scenario around_scenario after_scenario before_step after_step on_successful_step
11
- on_failed_step on_error_step on_undefined_step on_skipped_step}.each do |callback|
9
+ %w{
10
+ before_run
11
+ after_run
12
+ before_feature
13
+ after_feature
14
+ on_undefined_feature
15
+ before_scenario
16
+ after_scenario
17
+ before_step
18
+ after_step
19
+ on_successful_step
20
+ on_failed_step
21
+ on_error_step
22
+ on_undefined_step
23
+ on_skipped_step
24
+ on_pending_step
25
+ }.each do |callback|
12
26
  describe "#{callback}" do
13
27
  it "responds to #{callback}" do
14
28
  subject.must_respond_to callback
@@ -27,6 +41,24 @@ describe Spinach::Hooks do
27
41
  end
28
42
  end
29
43
 
44
+ describe "around_scenario" do
45
+ it "responds to around_scenario" do
46
+ subject.must_respond_to :around_scenario
47
+ end
48
+
49
+ it "executes the hook with params" do
50
+ array = []
51
+ block = Proc.new do |arg1, arg2|
52
+ array << arg1
53
+ array << arg2
54
+ end
55
+ subject.send(:around_scenario, &block)
56
+ subject.send("run_around_scenario", 1, 2) do
57
+ end
58
+ array.must_equal [1, 2]
59
+ end
60
+ end
61
+
30
62
  describe "#on_tag" do
31
63
  let(:scenario) do
32
64
  stub(tags: ['javascript', 'capture'])
@@ -113,27 +113,46 @@ describe Spinach::Runner::FeatureRunner do
113
113
 
114
114
  describe "when running for specific tags configured" do
115
115
 
116
- before do
117
- @feature = stub('feature', name: 'Feature', tags: ["feature_tag"])
118
- Spinach.stubs(:find_step_definitions).returns(true)
119
- @scenario = stub(line: 4, tags: ["scenario_tag"])
120
- @feature.stubs(:scenarios).returns [@scenario]
121
- end
116
+ describe "with feature" do
117
+ before do
118
+ @feature = stub('feature', name: 'Feature', tags: ["feature_tag"])
119
+ Spinach.stubs(:find_step_definitions).returns(true)
120
+ @scenario = stub(line: 4, tags: [])
121
+ @feature.stubs(:scenarios).returns [@scenario]
122
+ end
122
123
 
123
- it "runs matching scenario" do
124
- Spinach::TagsMatcher.expects(:match).with(["feature_tag", "scenario_tag"]).returns true
125
- Spinach::Runner::ScenarioRunner.expects(:new).with(@scenario).returns stub(run: true)
124
+ it "runs matching feature" do
125
+ Spinach::TagsMatcher.expects(:match).with(["feature_tag"]).returns true
126
+ Spinach::Runner::ScenarioRunner.expects(:new).with(@scenario).returns stub(run: true)
126
127
 
127
- @runner = Spinach::Runner::FeatureRunner.new(@feature)
128
- @runner.run
128
+ @runner = Spinach::Runner::FeatureRunner.new(@feature)
129
+ @runner.run
130
+ end
129
131
  end
130
132
 
131
- it "skips scenarios that do not match" do
132
- Spinach::TagsMatcher.expects(:match).with(["feature_tag", "scenario_tag"]).returns false
133
- Spinach::Runner::ScenarioRunner.expects(:new).never
133
+ describe "with scenario" do
134
+ before do
135
+ @feature = stub('feature', name: 'Feature', tags: ["feature_tag"])
136
+ Spinach.stubs(:find_step_definitions).returns(true)
137
+ @scenario = stub(line: 4, tags: ["scenario_tag"])
138
+ @feature.stubs(:scenarios).returns [@scenario]
139
+ end
134
140
 
135
- @runner = Spinach::Runner::FeatureRunner.new(@feature)
136
- @runner.run
141
+ it "runs matching scenario" do
142
+ Spinach::TagsMatcher.expects(:match).with(["feature_tag", "scenario_tag"]).returns true
143
+ Spinach::Runner::ScenarioRunner.expects(:new).with(@scenario).returns stub(run: true)
144
+
145
+ @runner = Spinach::Runner::FeatureRunner.new(@feature)
146
+ @runner.run
147
+ end
148
+
149
+ it "skips scenarios that do not match" do
150
+ Spinach::TagsMatcher.expects(:match).with(["feature_tag", "scenario_tag"]).returns false
151
+ Spinach::Runner::ScenarioRunner.expects(:new).never
152
+
153
+ @runner = Spinach::Runner::FeatureRunner.new(@feature)
154
+ @runner.run
155
+ end
137
156
  end
138
157
  end
139
158
  end
@@ -45,6 +45,27 @@ describe Spinach::TagsMatcher do
45
45
  end
46
46
  end
47
47
 
48
+ describe 'when matching against a single negated tag and an added tag' do
49
+
50
+ before { @config.tags = [['~wip', 'added']] }
51
+
52
+ it "returns false for the same tag" do
53
+ subject.match(['wip']).must_equal false
54
+ end
55
+
56
+ it "returns true for the added tag" do
57
+ subject.match(['added']).must_equal true
58
+ end
59
+
60
+ it "returns false for a different tag" do
61
+ subject.match(['important']).must_equal false
62
+ end
63
+
64
+ it "returns false when no tags are present" do
65
+ subject.match([]).must_equal false
66
+ end
67
+ end
68
+
48
69
  describe "when matching against ANDed tags" do
49
70
 
50
71
  before { @config.tags = [['wip'], ['important']] }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spinach
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -12,11 +12,11 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2012-06-02 00:00:00.000000000 Z
15
+ date: 2012-06-18 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: gherkin-ruby
19
- requirement: !ruby/object:Gem::Requirement
19
+ requirement: &2153592980 !ruby/object:Gem::Requirement
20
20
  none: false
21
21
  requirements:
22
22
  - - ~>
@@ -24,15 +24,10 @@ dependencies:
24
24
  version: 0.2.0
25
25
  type: :runtime
26
26
  prerelease: false
27
- version_requirements: !ruby/object:Gem::Requirement
28
- none: false
29
- requirements:
30
- - - ~>
31
- - !ruby/object:Gem::Version
32
- version: 0.2.0
27
+ version_requirements: *2153592980
33
28
  - !ruby/object:Gem::Dependency
34
29
  name: colorize
35
- requirement: !ruby/object:Gem::Requirement
30
+ requirement: &2153592500 !ruby/object:Gem::Requirement
36
31
  none: false
37
32
  requirements:
38
33
  - - ! '>='
@@ -40,15 +35,10 @@ dependencies:
40
35
  version: '0'
41
36
  type: :runtime
42
37
  prerelease: false
43
- version_requirements: !ruby/object:Gem::Requirement
44
- none: false
45
- requirements:
46
- - - ! '>='
47
- - !ruby/object:Gem::Version
48
- version: '0'
38
+ version_requirements: *2153592500
49
39
  - !ruby/object:Gem::Dependency
50
40
  name: rake
51
- requirement: !ruby/object:Gem::Requirement
41
+ requirement: &2153591980 !ruby/object:Gem::Requirement
52
42
  none: false
53
43
  requirements:
54
44
  - - ! '>='
@@ -56,15 +46,10 @@ dependencies:
56
46
  version: '0'
57
47
  type: :development
58
48
  prerelease: false
59
- version_requirements: !ruby/object:Gem::Requirement
60
- none: false
61
- requirements:
62
- - - ! '>='
63
- - !ruby/object:Gem::Version
64
- version: '0'
49
+ version_requirements: *2153591980
65
50
  - !ruby/object:Gem::Dependency
66
51
  name: mocha
67
- requirement: !ruby/object:Gem::Requirement
52
+ requirement: &2153591360 !ruby/object:Gem::Requirement
68
53
  none: false
69
54
  requirements:
70
55
  - - ! '>='
@@ -72,15 +57,10 @@ dependencies:
72
57
  version: '0'
73
58
  type: :development
74
59
  prerelease: false
75
- version_requirements: !ruby/object:Gem::Requirement
76
- none: false
77
- requirements:
78
- - - ! '>='
79
- - !ruby/object:Gem::Version
80
- version: '0'
60
+ version_requirements: *2153591360
81
61
  - !ruby/object:Gem::Dependency
82
62
  name: sinatra
83
- requirement: !ruby/object:Gem::Requirement
63
+ requirement: &2153590420 !ruby/object:Gem::Requirement
84
64
  none: false
85
65
  requirements:
86
66
  - - ! '>='
@@ -88,15 +68,10 @@ dependencies:
88
68
  version: '0'
89
69
  type: :development
90
70
  prerelease: false
91
- version_requirements: !ruby/object:Gem::Requirement
92
- none: false
93
- requirements:
94
- - - ! '>='
95
- - !ruby/object:Gem::Version
96
- version: '0'
71
+ version_requirements: *2153590420
97
72
  - !ruby/object:Gem::Dependency
98
73
  name: capybara
99
- requirement: !ruby/object:Gem::Requirement
74
+ requirement: &2153589600 !ruby/object:Gem::Requirement
100
75
  none: false
101
76
  requirements:
102
77
  - - ! '>='
@@ -104,15 +79,10 @@ dependencies:
104
79
  version: '0'
105
80
  type: :development
106
81
  prerelease: false
107
- version_requirements: !ruby/object:Gem::Requirement
108
- none: false
109
- requirements:
110
- - - ! '>='
111
- - !ruby/object:Gem::Version
112
- version: '0'
82
+ version_requirements: *2153589600
113
83
  - !ruby/object:Gem::Dependency
114
84
  name: pry
115
- requirement: !ruby/object:Gem::Requirement
85
+ requirement: &2153589180 !ruby/object:Gem::Requirement
116
86
  none: false
117
87
  requirements:
118
88
  - - ! '>='
@@ -120,15 +90,10 @@ dependencies:
120
90
  version: '0'
121
91
  type: :development
122
92
  prerelease: false
123
- version_requirements: !ruby/object:Gem::Requirement
124
- none: false
125
- requirements:
126
- - - ! '>='
127
- - !ruby/object:Gem::Version
128
- version: '0'
93
+ version_requirements: *2153589180
129
94
  - !ruby/object:Gem::Dependency
130
95
  name: simplecov
131
- requirement: !ruby/object:Gem::Requirement
96
+ requirement: &2153721260 !ruby/object:Gem::Requirement
132
97
  none: false
133
98
  requirements:
134
99
  - - ! '>='
@@ -136,15 +101,10 @@ dependencies:
136
101
  version: '0'
137
102
  type: :development
138
103
  prerelease: false
139
- version_requirements: !ruby/object:Gem::Requirement
140
- none: false
141
- requirements:
142
- - - ! '>='
143
- - !ruby/object:Gem::Version
144
- version: '0'
104
+ version_requirements: *2153721260
145
105
  - !ruby/object:Gem::Dependency
146
106
  name: rspec
147
- requirement: !ruby/object:Gem::Requirement
107
+ requirement: &2153720800 !ruby/object:Gem::Requirement
148
108
  none: false
149
109
  requirements:
150
110
  - - ! '>='
@@ -152,15 +112,10 @@ dependencies:
152
112
  version: '0'
153
113
  type: :development
154
114
  prerelease: false
155
- version_requirements: !ruby/object:Gem::Requirement
156
- none: false
157
- requirements:
158
- - - ! '>='
159
- - !ruby/object:Gem::Version
160
- version: '0'
115
+ version_requirements: *2153720800
161
116
  - !ruby/object:Gem::Dependency
162
117
  name: minitest
163
- requirement: !ruby/object:Gem::Requirement
118
+ requirement: &2153720380 !ruby/object:Gem::Requirement
164
119
  none: false
165
120
  requirements:
166
121
  - - ! '>='
@@ -168,15 +123,10 @@ dependencies:
168
123
  version: '0'
169
124
  type: :development
170
125
  prerelease: false
171
- version_requirements: !ruby/object:Gem::Requirement
172
- none: false
173
- requirements:
174
- - - ! '>='
175
- - !ruby/object:Gem::Version
176
- version: '0'
126
+ version_requirements: *2153720380
177
127
  - !ruby/object:Gem::Dependency
178
128
  name: turn
179
- requirement: !ruby/object:Gem::Requirement
129
+ requirement: &2153719960 !ruby/object:Gem::Requirement
180
130
  none: false
181
131
  requirements:
182
132
  - - ! '>='
@@ -184,12 +134,7 @@ dependencies:
184
134
  version: '0'
185
135
  type: :development
186
136
  prerelease: false
187
- version_requirements: !ruby/object:Gem::Requirement
188
- none: false
189
- requirements:
190
- - - ! '>='
191
- - !ruby/object:Gem::Version
192
- version: '0'
137
+ version_requirements: *2153719960
193
138
  description: Spinach is a BDD framework on top of gherkin
194
139
  email:
195
140
  - info@codegram.com
@@ -306,15 +251,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
306
251
  - - ! '>='
307
252
  - !ruby/object:Gem::Version
308
253
  version: '0'
254
+ segments:
255
+ - 0
256
+ hash: 264819993730994742
309
257
  required_rubygems_version: !ruby/object:Gem::Requirement
310
258
  none: false
311
259
  requirements:
312
260
  - - ! '>='
313
261
  - !ruby/object:Gem::Version
314
262
  version: '0'
263
+ segments:
264
+ - 0
265
+ hash: 264819993730994742
315
266
  requirements: []
316
267
  rubyforge_project:
317
- rubygems_version: 1.8.21
268
+ rubygems_version: 1.8.15
318
269
  signing_key:
319
270
  specification_version: 3
320
271
  summary: Spinach is a BDD framework on top of gherkin