cucumber-rest-bdd 0.6.0 → 0.6.1

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.
@@ -2,101 +2,107 @@ require 'cucumber-api/response'
2
2
  require 'cucumber-api/steps'
3
3
 
4
4
  ParameterType(
5
- name: 'item_type',
6
- regexp: /([\w\s]+)/,
7
- transformer: -> (s) { s },
8
- use_for_snippets: false
5
+ name: 'item_type',
6
+ regexp: /([\w\s]+)/,
7
+ transformer: ->(s) { s },
8
+ use_for_snippets: false
9
9
  )
10
10
 
11
- Then("the request is/was successful") do
12
- raise %/Expected Successful response code 2xx but was #{@response.code}/ if @response.code < 200 || @response.code >= 300
11
+ Then('the request is/was successful') do
12
+ if @response.code < 200 || @response.code >= 300
13
+ raise %(Expected Successful response code 2xx but was #{@response.code})
14
+ end
13
15
  end
14
16
 
15
- Then("the request is/was redirected") do
16
- raise %/Expected redirected response code 3xx but was #{@response.code}/ if @response.code < 300 || @response.code >= 400
17
+ Then('the request is/was redirected') do
18
+ if @response.code < 300 || @response.code >= 400
19
+ raise %(Expected redirected response code 3xx but was #{@response.code})
20
+ end
17
21
  end
18
22
 
19
- Then("the request fail(s/ed)") do
20
- raise %/Expected failed response code 4xx\/5xx but was #{@response.code}/ if @response.code < 400 || @response.code >= 600
23
+ Then('the request fail(s/ed)') do
24
+ if @response.code < 400 || @response.code >= 600
25
+ raise %(Expected failed response code 4xx\/5xx but was #{@response.code})
26
+ end
21
27
  end
22
28
 
23
- Then("the request is/was successful and a/the resource is/was created") do
24
- steps %Q{Then the response status should be "201"}
29
+ Then('the request is/was successful and a/the resource is/was created') do
30
+ steps %(Then the response status should be "201")
25
31
  end
26
32
 
27
- Then("(the request is/was successful and )a/the {item_type} is/was created") do | item_type |
28
- steps %Q{Then the response status should be "201"}
33
+ Then('(the request is/was successful and )a/the {item_type} is/was created') do |_item_type|
34
+ steps %(Then the response status should be "201")
29
35
  end
30
36
 
31
- Then("the request is/was successfully accepted") do
32
- steps %Q{Then the response status should be "202"}
37
+ Then('the request is/was successfully accepted') do
38
+ steps %(Then the response status should be "202")
33
39
  end
34
40
 
35
- Then("the request is/was successful and (an )empty/blank/no response body is/was returned") do
36
- steps %Q{Then the response status should be "204"}
37
- raise %/Expected the request body to be empty/ if !@response.body.empty?
41
+ Then('the request is/was successful and (an )empty/blank/no response body is/was returned') do
42
+ steps %(Then the response status should be "204")
43
+ raise %(Expected the request body to be empty) unless @response.body.empty?
38
44
  end
39
45
 
40
- Then("the request fail(s/ed) because (the )it/resource is/was invalid") do
41
- steps %Q{Then the response status should be "400"}
46
+ Then('the request fail(s/ed) because (the )it/resource is/was invalid') do
47
+ steps %(Then the response status should be "400")
42
48
  end
43
49
 
44
- Then("the request fail(s/ed) because (the ){item_type} is/was invalid") do | item_type |
45
- steps %Q{Then the response status should be "400"}
50
+ Then('the request fail(s/ed) because (the ){item_type} is/was invalid') do |_item_type|
51
+ steps %(Then the response status should be "400")
46
52
  end
47
53
 
48
- Then("the request fail(s/ed) because (the )it/resource is/was/am/are unauthorised/unauthorized") do
49
- steps %Q{Then the response status should be "401"}
54
+ Then('the request fail(s/ed) because (the )it/resource is/was/am/are unauthorised/unauthorized') do
55
+ steps %(Then the response status should be "401")
50
56
  end
51
57
 
52
- Then("the request fail(s/ed) because (the ){item_type} is/was/am/are unauthorised/unauthorized") do | item_type |
53
- steps %Q{Then the response status should be "401"}
58
+ Then('the request fail(s/ed) because (the ){item_type} is/was/am/are unauthorised/unauthorized') do |_item_type|
59
+ steps %(Then the response status should be "401")
54
60
  end
55
61
 
56
- Then("the request fail(s/ed) because (the )it/resource is/was forbidden") do
57
- steps %Q{Then the response status should be "403"}
62
+ Then('the request fail(s/ed) because (the )it/resource is/was forbidden') do
63
+ steps %(Then the response status should be "403")
58
64
  end
59
65
 
60
- Then("the request fail(s/ed) because (the ){item_type} is/was forbidden") do | item_type |
61
- steps %Q{Then the response status should be "403"}
66
+ Then('the request fail(s/ed) because (the ){item_type} is/was forbidden') do |_item_type|
67
+ steps %(Then the response status should be "403")
62
68
  end
63
69
 
64
- Then("the request fail(s/ed) because (the )it/resource is/was not found") do
65
- steps %Q{Then the response status should be "404"}
70
+ Then('the request fail(s/ed) because (the )it/resource is/was not found') do
71
+ steps %(Then the response status should be "404")
66
72
  end
67
73
 
68
- Then("the request fail(s/ed) because (the ){item_type} is/was not found") do | item_type |
69
- steps %Q{Then the response status should be "404"}
74
+ Then('the request fail(s/ed) because (the ){item_type} is/was not found') do |_item_type|
75
+ steps %(Then the response status should be "404")
70
76
  end
71
77
 
72
- Then("the request fail(s/ed) because (the )it/resource is/was not allowed") do
73
- steps %Q{Then the response status should be "405"}
78
+ Then('the request fail(s/ed) because (the )it/resource is/was not allowed') do
79
+ steps %(Then the response status should be "405")
74
80
  end
75
81
 
76
- Then("the request fail(s/ed) because (the ){item_type} is/was not allowed") do | item_type |
77
- steps %Q{Then the response status should be "405"}
82
+ Then('the request fail(s/ed) because (the ){item_type} is/was not allowed') do |_item_type|
83
+ steps %(Then the response status should be "405")
78
84
  end
79
85
 
80
- Then("the request fail(s/ed) because there is/was/has a conflict") do
81
- steps %Q{Then the response status should be "409"}
86
+ Then('the request fail(s/ed) because there is/was/has a conflict') do
87
+ steps %(Then the response status should be "409")
82
88
  end
83
89
 
84
- Then("the request fail(s/ed) because there is/was/has a conflict with {item_type}") do | item_type |
85
- steps %Q{Then the response status should be "409"}
90
+ Then('the request fail(s/ed) because there is/was/has a conflict with {item_type}') do |_item_type|
91
+ steps %(Then the response status should be "409")
86
92
  end
87
93
 
88
- Then("the request fail(s/ed) because (the )it/resource is/was/has gone") do
89
- steps %Q{Then the response status should be "410"}
94
+ Then('the request fail(s/ed) because (the )it/resource is/was/has gone') do
95
+ steps %(Then the response status should be "410")
90
96
  end
91
97
 
92
- Then("the request fail(s/ed) because (the ){item_type} is/was/has gone") do | item_type |
93
- steps %Q{Then the response status should be "410"}
98
+ Then('the request fail(s/ed) because (the ){item_type} is/was/has gone') do |_item_type|
99
+ steps %(Then the response status should be "410")
94
100
  end
95
101
 
96
- Then("the request fail(s/ed) because (the )it/resource is/was not implemented") do
97
- steps %Q{Then the response status should be "501"}
102
+ Then('the request fail(s/ed) because (the )it/resource is/was not implemented') do
103
+ steps %(Then the response status should be "501")
98
104
  end
99
105
 
100
- Then("the request fail(s/ed) because (the ){item_type} is/was not implemented") do | item_type |
101
- steps %Q{Then the response status should be "501"}
106
+ Then('the request fail(s/ed) because (the ){item_type} is/was not implemented') do |_item_type|
107
+ steps %(Then the response status should be "501")
102
108
  end
@@ -1,188 +1,197 @@
1
1
  require 'active_support/inflector'
2
2
 
3
- HAVE_ALTERNATION = "has/have/having/contain/contains/containing/with"
4
- RESOURCE_NAME_SYNONYM = '\w+\b(?:\s+\w+\b)*?|`[^`]*`'
5
- FIELD_NAME_SYNONYM = '\w+\b(?:(?:\s+:)?\s+\w+\b)*?|`[^`]*`'
6
- MAXIMAL_FIELD_NAME_SYNONYM = '\w+\b(?:(?:\s+:)?\s+\w+\b)*|`[^`]*`'
3
+ HAVE_ALTERNATION = 'has/have/having/contain/contains/containing/with'.freeze
4
+ RESOURCE_NAME_SYNONYM = '\w+\b(?:\s+\w+\b)*?|`[^`]*`'.freeze
5
+ FIELD_NAME_SYNONYM = '\w+\b(?:(?:\s+:)?\s+\w+\b)*?|`[^`]*`'.freeze
6
+ MAXIMAL_FIELD_NAME_SYNONYM = '\w+\b(?:(?:\s+:)?\s+\w+\b)*|`[^`]*`'.freeze
7
7
 
8
8
  ParameterType(
9
- name: 'resource_name',
10
- regexp: /#{RESOURCE_NAME_SYNONYM}/,
11
- transformer: -> (s) { get_resource(s) },
12
- use_for_snippets: false
9
+ name: 'resource_name',
10
+ regexp: /#{RESOURCE_NAME_SYNONYM}/,
11
+ transformer: ->(s) { get_resource(s) },
12
+ use_for_snippets: false
13
13
  )
14
14
 
15
15
  ParameterType(
16
- name: 'field_name',
17
- regexp: /#{FIELD_NAME_SYNONYM}/,
18
- transformer: -> (s) { ResponseField.new(s) },
19
- use_for_snippets: false
16
+ name: 'field_name',
17
+ regexp: /#{FIELD_NAME_SYNONYM}/,
18
+ transformer: ->(s) { ResponseField.new(s) },
19
+ use_for_snippets: false
20
20
  )
21
21
 
22
+ # Add Boolean module to handle types
22
23
  module Boolean; end
24
+ # True
23
25
  class TrueClass; include Boolean; end
26
+ # False
24
27
  class FalseClass; include Boolean; end
25
28
 
29
+ # Add Enum module to handle types
26
30
  module Enum; end
31
+ # Enum is a type of string
27
32
  class String; include Enum; end
28
33
 
34
+ # Handle parsing a field from a response
29
35
  class ResponseField
30
- def initialize(names)
31
- @fields = get_fields(names)
32
- end
33
-
34
- def to_json_path()
35
- return "#{get_root_data_key()}#{@fields.join('.')}"
36
- end
37
-
38
- def get_value(response, type)
39
- return response.get_as_type to_json_path(), parse_type(type)
40
- end
41
-
42
- def validate_value(response, value, regex)
43
- raise %/Expected #{json_path} value '#{value}' to match regex: #{regex}\n#{response.to_json_s}/ if (regex =~ value).nil?
44
- end
36
+ def initialize(names)
37
+ @fields = split_fields(names)
38
+ end
39
+
40
+ def to_json_path
41
+ "#{root_data_key}#{@fields.join('.')}"
42
+ end
43
+
44
+ def get_value(response, type)
45
+ response.get_as_type to_json_path, parse_type(type)
46
+ end
47
+
48
+ def validate_value(response, value, regex)
49
+ raise "Expected #{json_path} value '#{value}' to match regex: #{regex}\n#{response.to_json_s}" \
50
+ if (regex =~ value).nil?
51
+ end
45
52
  end
46
53
 
47
54
  def parse_type(type)
48
- replacements = {
49
- /^numeric$/i => 'numeric',
50
- /^int$/i => 'numeric',
51
- /^long$/i => 'numeric',
52
- /^number$/i => 'numeric',
53
- /^decimal$/i => 'numeric',
54
- /^double$/i => 'numeric',
55
- /^bool$/i => 'boolean',
56
- /^null$/i => 'nil_class',
57
- /^nil$/i => 'nil_class',
58
- /^string$/i => 'string',
59
- /^text$/i => 'string'
60
- }
61
- type.tr(' ', '_')
62
- replacements.each { |k,v| type.gsub!(k, v) }
63
- type
55
+ replacements = {
56
+ /^numeric$/i => 'numeric',
57
+ /^int$/i => 'numeric',
58
+ /^long$/i => 'numeric',
59
+ /^number$/i => 'numeric',
60
+ /^decimal$/i => 'numeric',
61
+ /^double$/i => 'numeric',
62
+ /^bool$/i => 'boolean',
63
+ /^null$/i => 'nil_class',
64
+ /^nil$/i => 'nil_class',
65
+ /^string$/i => 'string',
66
+ /^text$/i => 'string'
67
+ }
68
+ type.tr(' ', '_')
69
+ replacements.each { |k, v| type.gsub!(k, v) }
70
+ type
64
71
  end
65
72
 
66
73
  def string_to_type(value, type)
67
- replacements = {
68
- /^numeric$/i => 'integer',
69
- /^int$/i => 'integer',
70
- /^long$/i => 'integer',
71
- /^number$/i => 'integer',
72
- /^decimal$/i => 'float',
73
- /^double$/i => 'float',
74
- /^bool$/i => 'boolean',
75
- /^null$/i => 'nil_class',
76
- /^nil$/i => 'nil_class',
77
- /^string$/i => 'string',
78
- /^text$/i => 'string'
79
- }
80
- type.tr(' ', '_')
81
- replacements.each { |k,v| type.gsub!(k, v) }
82
- type = type.camelize.constantize
83
- # cannot use 'case type' which checks for instances of a type rather than type equality
84
- if type == Boolean then !(value =~ /true|yes/i).nil?
85
- elsif type == Enum then value.upcase.tr(" ", "_")
86
- elsif type == Float then value.to_f
87
- elsif type == Integer then value.to_i
88
- elsif type == NilClass then nil
89
- else value
90
- end
74
+ replacements = {
75
+ /^numeric$/i => 'integer',
76
+ /^int$/i => 'integer',
77
+ /^long$/i => 'integer',
78
+ /^number$/i => 'integer',
79
+ /^decimal$/i => 'float',
80
+ /^double$/i => 'float',
81
+ /^bool$/i => 'boolean',
82
+ /^null$/i => 'nil_class',
83
+ /^nil$/i => 'nil_class',
84
+ /^string$/i => 'string',
85
+ /^text$/i => 'string'
86
+ }
87
+ type.tr(' ', '_')
88
+ replacements.each { |k, v| type.gsub!(k, v) }
89
+ type = type.camelize.constantize
90
+ # cannot use 'case type' which checks for instances of a type rather than type equality
91
+ if type == Boolean then !(value =~ /true|yes/i).nil?
92
+ elsif type == Enum then value.upcase.tr(' ', '_')
93
+ elsif type == Float then value.to_f
94
+ elsif type == Integer then value.to_i
95
+ elsif type == NilClass then nil
96
+ else value
97
+ end
91
98
  end
92
99
 
93
100
  def get_resource(name)
94
- if name[0] == '`' && name[-1] == '`'
95
- name = name[1..-2]
96
- else
97
- name = name.parameterize
98
- name = (ENV.has_key?('resource_single') && ENV['resource_single'] == 'true') ? name.singularize : name.pluralize
99
- end
100
- return name
101
+ if name[0] == '`' && name[-1] == '`'
102
+ name = name[1..-2]
103
+ else
104
+ name = name.parameterize
105
+ name = ENV.key?('resource_single') && ENV['resource_single'] == 'true' ? name.singularize : name.pluralize
106
+ end
107
+ name
101
108
  end
102
109
 
103
- def get_root_data_key()
104
- return ENV.has_key?('data_key') && !ENV['data_key'].empty? ? "$.#{ENV['data_key']}." : "$."
110
+ def root_data_key
111
+ ENV.key?('data_key') && !ENV['data_key'].empty? ? "$.#{ENV['data_key']}." : '$.'
105
112
  end
106
113
 
107
- def get_json_path(names)
108
- return "#{get_root_data_key()}#{get_fields(names).join('.')}"
114
+ def json_path(names)
115
+ "#{root_data_key}#{split_fields(names).join('.')}"
109
116
  end
110
117
 
111
- def get_fields(names)
112
- return names.split(':').map { |n| get_field(n.strip) }
118
+ def split_fields(names)
119
+ names.split(':').map { |n| parse_field(n.strip) }
113
120
  end
114
121
 
115
- def get_field(name)
116
- if name[0] == '`' && name[-1] == '`'
117
- name = name[1..-2]
118
- elsif name[0] != '[' || name[-1] != ']'
119
- separator = ENV.has_key?('field_separator') ? ENV['field_separator'] : '_'
120
- name = name.parameterize(separator: separator)
121
- name = name.camelize(:lower) if (ENV.has_key?('field_camel') && ENV['field_camel'] == 'true')
122
- end
123
- return name
122
+ def parse_field(name)
123
+ if name[0] == '`' && name[-1] == '`'
124
+ name = name[1..-2]
125
+ elsif name[0] != '[' || name[-1] != ']'
126
+ separator = ENV.key?('field_separator') ? ENV['field_separator'] : '_'
127
+ name = name.parameterize(separator: separator)
128
+ name = name.camelize(:lower) if ENV.key?('field_camel') && ENV['field_camel'] == 'true'
129
+ end
130
+ name
124
131
  end
125
132
 
126
- def get_list_field(name)
127
- if name[0] == '`' && name[-1] == '`'
128
- name = name[1..-2]
129
- elsif name[0] != '[' || name[-1] != ']'
130
- separator = ENV.has_key?('field_separator') ? ENV['field_separator'] : '_'
131
- name = name.parameterize(separator: separator)
132
- name = name.pluralize
133
- name = name.camelize(:lower) if (ENV.has_key?('field_camel') && ENV['field_camel'] == 'true')
134
- end
135
- return name
133
+ def parse_list_field(name)
134
+ if name[0] == '`' && name[-1] == '`'
135
+ name = name[1..-2]
136
+ elsif name[0] != '[' || name[-1] != ']'
137
+ separator = ENV.key?('field_separator') ? ENV['field_separator'] : '_'
138
+ name = name.parameterize(separator: separator)
139
+ name = name.pluralize
140
+ name = name.camelize(:lower) if ENV.key?('field_camel') && ENV['field_camel'] == 'true'
141
+ end
142
+ name
136
143
  end
137
144
 
138
- def get_attributes(hashes)
139
- attributes = hashes.each_with_object({}) do |row, hash|
140
- name, value, type = row["attribute"], row["value"], row["type"]
141
- value = resolve_functions(value)
142
- value = resolve(value)
143
- value.gsub!(/\\n/, "\n")
144
- names = get_fields(name)
145
- new_hash = names.reverse.inject(string_to_type(value, type)) { |a, n| add_to_hash(a, n) }
146
- hash.deep_merge!(new_hash) { |key, old, new| new.kind_of?(Array) ? merge_arrays(old, new) : new }
147
- end
145
+ def parse_attributes(hashes)
146
+ hashes.each_with_object({}) do |row, hash|
147
+ name = row['attribute']
148
+ value = row['value']
149
+ type = row['type']
150
+ value = resolve_functions(value)
151
+ value = resolve(value)
152
+ value.gsub!(/\\n/, "\n")
153
+ names = split_fields(name)
154
+ new_hash = names.reverse.inject(string_to_type(value, type)) { |a, n| add_to_hash(a, n) }
155
+ hash.deep_merge!(new_hash) { |_, old, new| new.is_a?(Array) ? merge_arrays(old, new) : new }
156
+ end
148
157
  end
149
158
 
150
159
  def resolve_functions(value)
151
- value.gsub!(/\[([a-zA-Z0-9_]+)\]/) do |s|
152
- s.gsub!(/[\[\]]/, '')
153
- case s.downcase
154
- when "datetime"
155
- Time.now.strftime("%Y%m%d%H%M%S")
156
- else
157
- raise 'Unrecognised function ' + s + '?'
158
- end
160
+ value.gsub!(/\[([a-zA-Z0-9_]+)\]/) do |s|
161
+ s.gsub!(/[\[\]]/, '')
162
+ case s.downcase
163
+ when 'datetime'
164
+ Time.now.strftime('%Y%m%d%H%M%S')
165
+ else
166
+ raise 'Unrecognised function ' + s + '?'
159
167
  end
160
- value
168
+ end
169
+ value
161
170
  end
162
171
 
163
- def add_to_hash(a, n)
164
- result = nil
165
- if (n[0] == '[' && n[-1] == ']') then
166
- array = Array.new(n[1..-2].to_i() + 1)
167
- array[n[1..-2].to_i()] = a
168
- result = array
169
- end
170
- result != nil ? result : { n => a };
172
+ def add_to_hash(hash, node)
173
+ result = nil
174
+ if node[0] == '[' && node[-1] == ']'
175
+ array = Array.new(node[1..-2].to_i + 1)
176
+ array[node[1..-2].to_i] = hash
177
+ result = array
178
+ end
179
+ !result.nil? ? result : { node => hash }
171
180
  end
172
181
 
173
- def merge_arrays(a, b)
174
- new_length = [a.length, b.length].max
175
- new_array = Array.new(new_length)
176
- new_length.times do |n|
177
- if b[n].nil? then
178
- new_array[n] = a[n]
179
- else
180
- if a[n].nil? then
181
- new_array[n] = b[n]
182
- else
183
- new_array[n] = a[n].merge(b[n])
184
- end
185
- end
186
- end
187
- return new_array
182
+ def merge_arrays(first, second)
183
+ new_length = [first.length, second.length].max
184
+ new_array = Array.new(new_length)
185
+ new_length.times do |n|
186
+ new_array[n] = if second[n].nil?
187
+ first[n]
188
+ else
189
+ new_array[n] = if first[n].nil?
190
+ second[n]
191
+ else
192
+ first[n].merge(second[n])
193
+ end
194
+ end
195
+ end
196
+ new_array
188
197
  end