cucumber-rest-bdd 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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