spinach 0.5.1 → 0.5.2

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.
@@ -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