turnip 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -1
- data/README.md +47 -0
- data/examples/backtick_steps.rb +4 -0
- data/examples/interpolation.feature +9 -0
- data/examples/steps.rb +12 -0
- data/examples/with_backticks.feature +5 -0
- data/lib/turnip/placeholder.rb +2 -2
- data/lib/turnip/step_definition.rb +4 -0
- data/lib/turnip/table.rb +20 -11
- data/lib/turnip/version.rb +1 -1
- data/spec/integration_spec.rb +1 -1
- data/spec/step_definition_spec.rb +6 -0
- data/spec/table_spec.rb +27 -8
- metadata +26 -10
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -246,6 +246,25 @@ Feature: Red Dragons are deadly
|
|
246
246
|
Then the knight is dead
|
247
247
|
```
|
248
248
|
|
249
|
+
### Calling steps from other steps
|
250
|
+
You can also call steps from other steps. This is done by just calling `step
|
251
|
+
"name_of_the_step"`, so for instance if you have:
|
252
|
+
|
253
|
+
``` ruby
|
254
|
+
step "a random step" do
|
255
|
+
@value = 1
|
256
|
+
end
|
257
|
+
|
258
|
+
step "calling a step" do
|
259
|
+
step "a random step"
|
260
|
+
@value += 1
|
261
|
+
end
|
262
|
+
```
|
263
|
+
|
264
|
+
Now if you use the step `calling a step` in any Scenario, then the value of
|
265
|
+
`@value` will be 2 afterwards as it first executes the code defined for the step
|
266
|
+
`a random step`. You can think of it as a simple method call.
|
267
|
+
|
249
268
|
### Auto-included steps
|
250
269
|
By default, Turnip will automatically make available any steps defined in
|
251
270
|
a `steps_for` block with the same name as the feature file being run. For
|
@@ -263,6 +282,7 @@ steps_for :user_signup do
|
|
263
282
|
end
|
264
283
|
|
265
284
|
step "I should see a welcome message" do
|
285
|
+
...
|
266
286
|
end
|
267
287
|
end
|
268
288
|
```
|
@@ -328,6 +348,32 @@ end
|
|
328
348
|
These regular expressions must not use anchors, e.g. `^` or `$`. They may not
|
329
349
|
contain named capture groups, e.g. `(?<color>blue|green)`.
|
330
350
|
|
351
|
+
## Table Steps
|
352
|
+
Turnip also supports steps that take a table as a parameter similar to Cucumber:
|
353
|
+
|
354
|
+
``` cucumber
|
355
|
+
Scenario: This is a feature with a table
|
356
|
+
Given there are the following monsters:
|
357
|
+
| Name | Hitpoints |
|
358
|
+
| Blaaarg | 23 |
|
359
|
+
| Moorg | 12 |
|
360
|
+
Then "Blaaarg" should have 23 hitpoints
|
361
|
+
And "Moorg" should have 12 hitpoints
|
362
|
+
```
|
363
|
+
The table is a `Turnip::Table` object which works in much the same way as Cucumber's
|
364
|
+
`Cucumber::Ast::Table` obects.
|
365
|
+
|
366
|
+
E.g. converting the `Turnip::Table` to an array of hashes:
|
367
|
+
|
368
|
+
``` ruby
|
369
|
+
step "there are the following monsters:" do |table|
|
370
|
+
@monsters = {}
|
371
|
+
table.hashes.each do |hash|
|
372
|
+
@monsters[hash['Name']] = hash['Hitpoints'].to_i
|
373
|
+
end
|
374
|
+
end
|
375
|
+
```
|
376
|
+
|
331
377
|
## Using with Capybara
|
332
378
|
|
333
379
|
Just require `turnip/capybara` in your `spec_helper`. You can now use the
|
@@ -360,3 +406,4 @@ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
360
406
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
361
407
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
362
408
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
409
|
+
|
@@ -3,10 +3,19 @@ Feature: A simple feature
|
|
3
3
|
Given there is a monster called "John Smith"
|
4
4
|
Then it should be called "John Smith"
|
5
5
|
|
6
|
+
Scenario: Interpolation with empty quotes
|
7
|
+
Given there is a monster called "John Smith"
|
8
|
+
When I change its name to ""
|
9
|
+
Then it should be nameless
|
10
|
+
|
6
11
|
Scenario: Interpolation without quotes
|
7
12
|
Given there is a monster called John
|
8
13
|
Then it should be called "John"
|
9
14
|
|
15
|
+
Scenario: Interpolation with mixed quotes
|
16
|
+
Given there is a monster called "O'Flannahan"
|
17
|
+
Then it should be called "O'Flannahan"
|
18
|
+
|
10
19
|
Scenario: Interpolation with customer regexp
|
11
20
|
Given there are 3 monkeys with blue hair
|
12
21
|
Then there should be 3 monkeys with blue hair
|
data/examples/steps.rb
CHANGED
@@ -32,6 +32,18 @@ step 'it should be called "John"' do
|
|
32
32
|
@monster_name.should == "John"
|
33
33
|
end
|
34
34
|
|
35
|
+
step 'it should be called "O\'Flannahan"' do
|
36
|
+
@monster_name.should == "O'Flannahan"
|
37
|
+
end
|
38
|
+
|
39
|
+
step "I change its name to :empty_string" do |empty_string|
|
40
|
+
@monster_name = empty_string
|
41
|
+
end
|
42
|
+
|
43
|
+
step "it should be nameless" do
|
44
|
+
@monster_name.should == ""
|
45
|
+
end
|
46
|
+
|
35
47
|
step "there is a monster with :count hitpoints" do |count|
|
36
48
|
@monster = count
|
37
49
|
end
|
data/lib/turnip/placeholder.rb
CHANGED
@@ -27,8 +27,8 @@ module Turnip
|
|
27
27
|
|
28
28
|
def default
|
29
29
|
@default ||= new(:default) do
|
30
|
-
match %r((?:["'
|
31
|
-
first or second
|
30
|
+
match %r((?:"([^"]*)"|'([^']*)'|([a-zA-Z0-9_-]+))) do |first, second, third|
|
31
|
+
first or second or third
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -54,9 +54,13 @@ module Turnip
|
|
54
54
|
OPTIONAL_WORD_REGEXP = /(\\\s)?\\\(([^)]+)\\\)(\\\s)?/
|
55
55
|
PLACEHOLDER_REGEXP = /:([\w]+)/
|
56
56
|
ALTERNATIVE_WORD_REGEXP = /(\w+)((\/\w+)+)/
|
57
|
+
COMMAND_REGEXP = /`([^`]+)`/
|
57
58
|
|
58
59
|
def compile_regexp
|
59
60
|
regexp = Regexp.escape(expression)
|
61
|
+
regexp.gsub!(COMMAND_REGEXP) do |_|
|
62
|
+
"(?:[`]([^`]+)[`])"
|
63
|
+
end
|
60
64
|
regexp.gsub!(OPTIONAL_WORD_REGEXP) do |_|
|
61
65
|
[$1, $2, $3].compact.map { |m| "(#{m})?" }.join
|
62
66
|
end
|
data/lib/turnip/table.rb
CHANGED
@@ -10,31 +10,40 @@ module Turnip
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def headers
|
13
|
-
|
13
|
+
raw.first
|
14
14
|
end
|
15
15
|
|
16
16
|
def rows
|
17
|
-
|
17
|
+
raw.drop(1)
|
18
18
|
end
|
19
19
|
|
20
20
|
def hashes
|
21
21
|
rows.map { |row| Hash[headers.zip(row)] }
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def rows_hash
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
raise WidthMismatch.new(2, width) unless width == 2
|
26
|
+
transpose.hashes.first
|
27
|
+
end
|
28
|
+
|
29
|
+
def transpose
|
30
|
+
self.class.new(raw.transpose)
|
28
31
|
end
|
29
32
|
|
30
33
|
def each
|
31
|
-
|
34
|
+
raw.each { |row| yield(row) }
|
32
35
|
end
|
33
|
-
|
36
|
+
|
34
37
|
private
|
35
|
-
|
36
|
-
def
|
37
|
-
|
38
|
+
|
39
|
+
def width
|
40
|
+
raw[0].size
|
41
|
+
end
|
42
|
+
|
43
|
+
class WidthMismatch < StandardError
|
44
|
+
def initialize(expected, actual)
|
45
|
+
super("Expected the table to be #{expected} columns wide, got #{actual}")
|
46
|
+
end
|
38
47
|
end
|
39
48
|
end
|
40
49
|
end
|
data/lib/turnip/version.rb
CHANGED
data/spec/integration_spec.rb
CHANGED
@@ -67,6 +67,12 @@ describe Turnip::StepDefinition do
|
|
67
67
|
step.should match('there is a monster named "Hairy"')
|
68
68
|
end
|
69
69
|
|
70
|
+
it "matches backticked placeholders" do
|
71
|
+
step = Turnip::StepDefinition.new("I run `:cmd`") {}
|
72
|
+
step.should match("I run `echo foo`")
|
73
|
+
step.should match(%q{I run `echo "foo 'bar' baz"`})
|
74
|
+
end
|
75
|
+
|
70
76
|
it "matches alternative words" do
|
71
77
|
step = Turnip::StepDefinition.new("there is/are monsters") {}
|
72
78
|
step.should match("there are monsters")
|
data/spec/table_spec.rb
CHANGED
@@ -1,54 +1,73 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Turnip::Table do
|
4
|
+
let(:table) { described_class.new( raw ) }
|
5
|
+
let(:raw) { [['foo', 'bar'], ['quox', '42']] }
|
6
|
+
|
4
7
|
describe '#raw' do
|
5
8
|
it 'returns the raw table' do
|
6
|
-
table = Turnip::Table.new([['foo', 'bar'], ['quox', '42']])
|
7
9
|
table.raw.should == [['foo', 'bar'], ['quox', '42']]
|
8
10
|
end
|
9
11
|
end
|
10
12
|
|
11
13
|
describe '#to_a' do
|
12
14
|
it 'returns the raw table' do
|
13
|
-
table = Turnip::Table.new([['foo', 'bar'], ['quox', '42']])
|
14
15
|
table.to_a.should == [['foo', 'bar'], ['quox', '42']]
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
18
19
|
describe '#headers' do
|
19
20
|
it 'returns the first row' do
|
20
|
-
table = Turnip::Table.new([['foo', 'bar'], ['quox', '42']])
|
21
21
|
table.headers.should == ['foo', 'bar']
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
describe '#rows' do
|
26
|
+
let(:raw) { [['foo', 'bar'], ['moo', '55'], ['quox', '42']] }
|
26
27
|
it 'returns the rows beyond the first' do
|
27
|
-
table = Turnip::Table.new([['foo', 'bar'], ['moo', '55'], ['quox', '42']])
|
28
28
|
table.rows.should == [['moo', '55'], ['quox', '42']]
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
describe '#hashes' do
|
33
|
+
let(:raw) { [['foo', 'bar'], ['moo', '55'], ['quox', '42']] }
|
33
34
|
it 'returns a list of hashes based on the headers' do
|
34
|
-
table = Turnip::Table.new([['foo', 'bar'], ['moo', '55'], ['quox', '42']])
|
35
35
|
table.hashes.should == [
|
36
36
|
{'foo' => 'moo', 'bar' => '55'},
|
37
37
|
{'foo' => 'quox', 'bar' => '42'}
|
38
38
|
]
|
39
39
|
end
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
|
+
describe '#transpose' do
|
43
|
+
context "when table is 2 columns wide" do
|
44
|
+
|
45
|
+
let(:raw) { [["Name", "Dave"], ["Age", "99"], ["Height", "6ft"]] }
|
46
|
+
it 'transposes the raw table' do
|
47
|
+
table.transpose.hashes.should == [{ "Name" => "Dave", "Age" => "99", "Height" => "6ft" }]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
42
52
|
describe '#rows_hash' do
|
53
|
+
let(:raw) { [['foo', 'moo'], ['bar', '55']] }
|
43
54
|
it 'converts this table into a Hash where the first column is used as keys and the second column is used as values' do
|
44
|
-
table = Turnip::Table.new([['foo', 'moo'], ['bar', '55']])
|
45
55
|
table.rows_hash.should == {'foo' => 'moo', 'bar' => '55'}
|
46
56
|
end
|
57
|
+
|
58
|
+
context "when table is greater than 2 columns wide" do
|
59
|
+
|
60
|
+
let(:raw) { [["a", "b", "c"], ["1", "2", "3"]] }
|
61
|
+
|
62
|
+
it 'raises an error' do
|
63
|
+
expect { table.rows_hash }.to raise_error Turnip::Table::WidthMismatch
|
64
|
+
end
|
65
|
+
end
|
47
66
|
end
|
48
67
|
|
49
68
|
describe '#map' do
|
69
|
+
let(:raw) { [['moo', '55'], ['quox', '42']] }
|
50
70
|
it 'iterates over the raw table' do
|
51
|
-
table = Turnip::Table.new([['moo', '55'], ['quox', '42']])
|
52
71
|
table.map(&:first).should == ['moo', 'quox']
|
53
72
|
end
|
54
73
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: turnip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-04-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '2.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: gherkin
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: '2.5'
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '2.5'
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: rake
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
@@ -43,7 +53,12 @@ dependencies:
|
|
43
53
|
version: '0'
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
47
62
|
description: Provides the ability to define steps and run Gherkin files from with
|
48
63
|
RSpec
|
49
64
|
email:
|
@@ -63,6 +78,7 @@ files:
|
|
63
78
|
- examples/autoload_steps.feature
|
64
79
|
- examples/autoload_steps.rb
|
65
80
|
- examples/backgrounds.feature
|
81
|
+
- examples/backtick_steps.rb
|
66
82
|
- examples/dragon_steps.rb
|
67
83
|
- examples/evil_steps.rb
|
68
84
|
- examples/interpolation.feature
|
@@ -81,6 +97,7 @@ files:
|
|
81
97
|
- examples/steps_for_super.feature
|
82
98
|
- examples/table.feature
|
83
99
|
- examples/tags.feature
|
100
|
+
- examples/with_backticks.feature
|
84
101
|
- examples/with_comments.feature
|
85
102
|
- lib/turnip.rb
|
86
103
|
- lib/turnip/builder.rb
|
@@ -132,7 +149,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
149
|
version: '0'
|
133
150
|
requirements: []
|
134
151
|
rubyforge_project: turnip
|
135
|
-
rubygems_version: 1.8.
|
152
|
+
rubygems_version: 1.8.22
|
136
153
|
signing_key:
|
137
154
|
specification_version: 3
|
138
155
|
summary: Gherkin extension for RSpec
|
@@ -150,4 +167,3 @@ test_files:
|
|
150
167
|
- spec/step_loader_spec.rb
|
151
168
|
- spec/step_module_spec.rb
|
152
169
|
- spec/table_spec.rb
|
153
|
-
has_rdoc:
|