cucumber-helpers 0.0.6
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.
- checksums.yaml +15 -0
- data/CHANGELOG.md +39 -0
- data/README.md +71 -0
- data/VERSION +1 -0
- data/lib/cucumber/helpers.rb +7 -0
- data/lib/cucumber/helpers/core_ext.rb +128 -0
- data/lib/cucumber/helpers/table.rb +56 -0
- metadata +110 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZGJmNTZhZGNlNGNjZDNlOThiYWI3MzQzZWFkYzkzYzUzNzFkMTE5NA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MDVkOTJhZDgwM2FkZTBmNGM0ZDU2N2Q3YTdkMTRkOWIyMWFjN2IyYg==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NDU5YjM2OWVlNzkwNzE1MWZiMzJhMDY0ZDgzZWRjN2ZjZTkyMTM0NjIwNzk1
|
10
|
+
ZjQwZjAzOTNkZDg5YmYzYzMzNDkzNzdkYTY1ZWUyYzNiM2NkYjVmNzk0Zjlm
|
11
|
+
NjA1ZGVhMTZkY2UxMDg4OTI4ZGM0ZmU3ZTI4YjUzZTdhZWZhNmU=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YzViYjBkNmVlMWY0NzI3MTIyYjg3MTA2M2UzZjRmMTcwYmExOWE5NDEwMzA1
|
14
|
+
NDJiY2UzNjkzZTYyNTliNGFiZGU4MDc1MTk3MzVhNjc1NzBhMjkzYjc3OGIx
|
15
|
+
OWFiNjM3ZjAwODVjMmNlYWU3NGFhODNkMGFlYWRjZTkxZjQzN2Y=
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 0.0.6 ([#8](https://git.mobcastdev.com/TEST/cucumber-helpers/pull/8) 2014-08-05 13:59:05)
|
4
|
+
|
5
|
+
Fix contantize
|
6
|
+
|
7
|
+
### Bug fix
|
8
|
+
|
9
|
+
- Fixes an issue with the constantization of types which are "List of <whatever>".
|
10
|
+
|
11
|
+
## 0.0.5 ([#7](https://git.mobcastdev.com/TEST/cucumber-helpers/pull/7) 2014-06-30 17:17:06)
|
12
|
+
|
13
|
+
Move to artifactory
|
14
|
+
|
15
|
+
### Improvement
|
16
|
+
|
17
|
+
- Move to artifactory.
|
18
|
+
|
19
|
+
## 0.0.4 (2014-02-24 10:59)
|
20
|
+
|
21
|
+
### New Features
|
22
|
+
|
23
|
+
* `Cucumber::Ast::Table`'s `.attribute_hash` will now return a hash with values set to the class type specified if no value column is given in the table.
|
24
|
+
|
25
|
+
## 0.0.3 (2014-01-20 17:09)
|
26
|
+
|
27
|
+
### New Features
|
28
|
+
|
29
|
+
* Added can now specify array types with `List of <type>s`, for example `List of Integers` or `List of Strings`.
|
30
|
+
|
31
|
+
## 0.0.2 (2014-01-20 11:14)
|
32
|
+
|
33
|
+
### Bug fixes
|
34
|
+
|
35
|
+
* Ensure the build will run on systems without git (ie. the build box!)
|
36
|
+
|
37
|
+
## 0.0.1
|
38
|
+
|
39
|
+
Initial release
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Cucumber::Helpers
|
2
|
+
|
3
|
+
A collection of helpers for cucumber tests we use at blinkbox books.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'cucumber-helpers'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install cucumber-helpers
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
### Typed object initialisation with Tables
|
22
|
+
|
23
|
+
Occasionally you'll want to create an object with specific attributes, or test that the attributes that are present are of a particular data type. In Gherkin there is no defined way to specify the type of a named object, because Gherkin is a business language.
|
24
|
+
|
25
|
+
This helper provides a mechanism to define attributes in a business-friendly manner and step helpers to convert them to the key names your code uses.
|
26
|
+
|
27
|
+
#### Examples
|
28
|
+
|
29
|
+
Let's say you have the following gherkin:
|
30
|
+
|
31
|
+
```gherkin
|
32
|
+
Given that a user exists with the following attributes:
|
33
|
+
| attribute | type | value | description |
|
34
|
+
| First Name | String | Sherlock | The user's first name |
|
35
|
+
| Last Name | String | Holmes | The user's last name |
|
36
|
+
| Date of Birth | Date | 1999-12-31 | The user's birth date |
|
37
|
+
| Address: First Line | String | 221B Baker Street | The first line of the user's address |
|
38
|
+
| Address: Second Line | String | London | The second line of the user's address |
|
39
|
+
| Address: Postcode | String | NW1 6XE | The user's postcode |
|
40
|
+
| Number of Pipes | Number | 12 | The number of pipes the user owns |
|
41
|
+
```
|
42
|
+
|
43
|
+
And the following step definition:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
# TBC
|
47
|
+
```
|
48
|
+
|
49
|
+
The default attribute mapper will generate a hash (`attribute_hash`) that looks like this:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
{
|
53
|
+
"first_name" => "Sherlock",
|
54
|
+
"last_name" => "Holmes",
|
55
|
+
"date_of_birth" => #<Date: 1999-12-31 ((2451544j,0s,0n),+0s,2299161j)>,
|
56
|
+
"address" => {
|
57
|
+
"first_line" => "221B Baker Street",
|
58
|
+
"second_line" => "London",
|
59
|
+
"postcode" => "NW1 6XE"
|
60
|
+
},
|
61
|
+
"number_of_pipes" => 12
|
62
|
+
}
|
63
|
+
```
|
64
|
+
|
65
|
+
## Contributing
|
66
|
+
|
67
|
+
1. Fork it
|
68
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
69
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
70
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
71
|
+
5. Create new Pull Request
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.6
|
@@ -0,0 +1,128 @@
|
|
1
|
+
class Hash
|
2
|
+
def deep_key(deep_key)
|
3
|
+
sub_obj = self
|
4
|
+
deep_key.split('.').each do |k|
|
5
|
+
if k.match(/^(.+)\[(\d+)\]$/)
|
6
|
+
sub_obj = sub_obj[$1][$2.to_i]
|
7
|
+
else
|
8
|
+
sub_obj = sub_obj[k]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
sub_obj
|
12
|
+
rescue
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def deep_delete(deep_key)
|
17
|
+
path_keys = deep_key.split('.')
|
18
|
+
final_key = path_keys.pop
|
19
|
+
|
20
|
+
sub_obj = self
|
21
|
+
path_keys.each do |k|
|
22
|
+
if k.match(/^(.+)\[(\d+)\]$/)
|
23
|
+
sub_obj = sub_obj[$1][$2.to_i]
|
24
|
+
else
|
25
|
+
sub_obj = sub_obj[k]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
sub_obj.delete(final_key)
|
30
|
+
end
|
31
|
+
|
32
|
+
def deep_set(deep_key, value)
|
33
|
+
path_keys = deep_key.split('.')
|
34
|
+
final_key = path_keys.pop
|
35
|
+
|
36
|
+
sub_obj = self
|
37
|
+
path_keys.each do |k|
|
38
|
+
if k.match(/^(.+)\[(\d+)\]$/)
|
39
|
+
sub_obj = sub_obj[$1][$2.to_i]
|
40
|
+
else
|
41
|
+
sub_obj[k] ||= {}
|
42
|
+
sub_obj = sub_obj[k]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if final_key.match(/^(.+)\[(\d+)\]$/)
|
47
|
+
sub_obj[$1][$2.to_i] = value
|
48
|
+
else
|
49
|
+
sub_obj[final_key] = value
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Collapses any nested hashes, converting the keys to delimited strings.
|
54
|
+
#
|
55
|
+
# For example, the hash `{ "address" => { "line1" => ..., "line2" => ... } }` will be converted to
|
56
|
+
# `{ "address.line1" => ..., "address.line2" => ... }`. The keys produced are compatible with the
|
57
|
+
# `deep_*` functions on hash, so this can provide a convenient way to iterate through values of a
|
58
|
+
# hash.
|
59
|
+
#
|
60
|
+
# Note that this function is lossy - if two nested hashes would result in the same keys then only
|
61
|
+
# one will be preserved.
|
62
|
+
def flat_hash(separator = ".")
|
63
|
+
each_with_object({}) do |(k, v), result|
|
64
|
+
if v.is_a?(Hash)
|
65
|
+
v.flat_hash(separator).each do |k2, v2|
|
66
|
+
result["#{k}#{separator}#{k2}"] = v2
|
67
|
+
end
|
68
|
+
else
|
69
|
+
result[k] = v
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Integer
|
76
|
+
def digits
|
77
|
+
self.to_s.chars.map(&:to_i)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# This is a bit of a hack to allow you to say "type: Boolean" as a validation
|
82
|
+
module Boolean; end
|
83
|
+
class TrueClass; include Boolean; end
|
84
|
+
class FalseClass; include Boolean; end
|
85
|
+
|
86
|
+
# This is a bit of a hack to allow you to say "type: Enum" as a validation
|
87
|
+
module Enum; end
|
88
|
+
class String; include Enum; end
|
89
|
+
|
90
|
+
class String
|
91
|
+
# Converts a string to camelCase.
|
92
|
+
def camel_case
|
93
|
+
s = self
|
94
|
+
s = s.snake_case unless /^[a-z0-9]+$/i =~ s
|
95
|
+
s = s.downcase if s == s.upcase # stop "CVV" -> "cVV" when it should be "cvv"
|
96
|
+
s.camelize(:lower)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Converts a string to snake_case or SNAKE_CASE.
|
100
|
+
def snake_case(casing = :lower)
|
101
|
+
s = self.tr(" ", "_")
|
102
|
+
case casing
|
103
|
+
when :lower then s.downcase
|
104
|
+
when :upper then s.upcase
|
105
|
+
else raise ArgumentError, "unsupported casing"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Converts a string to the specified primitive type. Useful because all Gherkin values are treated as strings.
|
110
|
+
def to_type(type)
|
111
|
+
# note: cannot use 'case type' as that expands to === which checks for instances of rather than type equality
|
112
|
+
if type == Boolean
|
113
|
+
self == "true"
|
114
|
+
elsif type == Date
|
115
|
+
Date.parse(self)
|
116
|
+
elsif type == DateTime
|
117
|
+
DateTime.parse(self)
|
118
|
+
elsif type == Enum
|
119
|
+
self.snake_case(:upper)
|
120
|
+
elsif type == Float
|
121
|
+
self.to_f
|
122
|
+
elsif type == Integer
|
123
|
+
self.to_i
|
124
|
+
else
|
125
|
+
self
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "active_support/inflector"
|
2
|
+
|
3
|
+
class Cucumber::Ast::Table
|
4
|
+
# Converts a table of attributes to a hash.
|
5
|
+
#
|
6
|
+
# The table must have the following columns:
|
7
|
+
#
|
8
|
+
# attribute::
|
9
|
+
# The name of the attribute. You can use natural language here and the parameter name will be
|
10
|
+
# inferred, for example "Cardholder Name" will be converted to "cardholderName". You can also
|
11
|
+
# specify nested objects using a `:` separator, for example "Address: Line 1" will be converted
|
12
|
+
# to an attribute like `{ "address": { "line1": ... } }`.
|
13
|
+
#
|
14
|
+
# value::
|
15
|
+
# If provided this defines value of the attribute, cast according to the `type` specified. If
|
16
|
+
# not provided the value of the corresponding hash key will be the class constant of the `type`
|
17
|
+
# specified, or an array containing the class constant in the case of a 'List of' type.
|
18
|
+
#
|
19
|
+
# type::
|
20
|
+
# The type of the attribute. This is used both as documentation of the type of the attribute
|
21
|
+
# which is useful in itself, but also to control how the parameter is formatted in the JSON.
|
22
|
+
# As well as built-in types, you can use the special type "Enum" which will represent the value
|
23
|
+
# as a string, but convert it to the appropriate case, e.g. a value of "Sales Rank" will be
|
24
|
+
# formatted as "SALES_RANK" inkeeping with enumeration conventions.
|
25
|
+
#
|
26
|
+
# If the `type` is given as "List of <Type>", the `value` is assumed to be a comma delimited
|
27
|
+
# list of items of the "<Type>" specified and is emitted as an array of typecast objects.
|
28
|
+
# White space either side of commas is stripped.
|
29
|
+
#
|
30
|
+
# Any other columns in the table will be ignored, so you can have other columns in the table for
|
31
|
+
# different purposes, e.g. "description" is a fairly useful column purely for documentation.
|
32
|
+
def attribute_hash(casing: :camel_case)
|
33
|
+
class_only = !raw.first.include?('value')
|
34
|
+
hashes.each_with_object({}) do |row, hash|
|
35
|
+
name = row["attribute"].gsub(/: /, ".").send(casing)
|
36
|
+
hash.deep_set(name, value_from_row(row, class_only))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def value_from_row(row, class_only)
|
43
|
+
list_of = row["type"].match(/^List of (?<type>.*)$/)
|
44
|
+
type = (list_of ? list_of[:type].singularize : row["type"]).constantize
|
45
|
+
|
46
|
+
return type if class_only
|
47
|
+
|
48
|
+
if list_of
|
49
|
+
row["value"].split(/\s*,\s*/).collect do |subvalue|
|
50
|
+
subvalue.to_type(type)
|
51
|
+
end
|
52
|
+
else
|
53
|
+
row["value"].to_type(type)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cucumber-helpers
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.6
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Greg Beech
|
8
|
+
- JP Hastings-Spital
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-01-29 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '4.0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '4.0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: bundler
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1.3'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.3'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ~>
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '2.99'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '2.99'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rake
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
description: Helpers for step definitions in cucumber.
|
71
|
+
email:
|
72
|
+
- greg@blinkbox.com
|
73
|
+
- jphastings@blinkbox.com
|
74
|
+
executables: []
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files:
|
77
|
+
- README.md
|
78
|
+
- CHANGELOG.md
|
79
|
+
files:
|
80
|
+
- CHANGELOG.md
|
81
|
+
- README.md
|
82
|
+
- VERSION
|
83
|
+
- lib/cucumber/helpers.rb
|
84
|
+
- lib/cucumber/helpers/core_ext.rb
|
85
|
+
- lib/cucumber/helpers/table.rb
|
86
|
+
homepage: https://blinkboxbooks.github.io/
|
87
|
+
licenses:
|
88
|
+
- MIT
|
89
|
+
metadata: {}
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
requirements: []
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 2.4.5
|
107
|
+
signing_key:
|
108
|
+
specification_version: 4
|
109
|
+
summary: Helpers for cucumber.
|
110
|
+
test_files: []
|