cucumber-blinkbox 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Y2MyODE2NDZjYTE4Y2VhNjNhN2VmNmM4MDhkY2EzMmU0MTIyYzNiNQ==
5
+ data.tar.gz: !binary |-
6
+ NmNkZGExNjNkNTcyYWJlZmUxZTVlMjM2YTdiZTVmNzZlYTIwNjQzMQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZDI5MTIwZGJlOTQ2NzkyZDU5YzczYzFhNDczYWJiNjU1M2I0MjM4NzNkYjc4
10
+ ZjkyNGU1MTIwZjM1OTVmNTM0YjA3NjMzOTIzZjIzNzNiNTY5Y2NiOGMyMDEy
11
+ Mzg2MmE1MTgwOWVmNjZjZmMzMTYyNGQxZmY4NWE2MDQyNGJlOWU=
12
+ data.tar.gz: !binary |-
13
+ YjU4ZGI4YzhkYjZmMDlhNmMxM2YwNTdhYmQzNDRjZjJhZTk2MTMxNDVhYjI4
14
+ OTY5MWI3ZjM5YjQ1MTFhYzViYzNlYmQ4M2E3NWVhYWNmMTIzZTE2Y2Y3MGYy
15
+ ZGY5ZThjMzBlYWJjOGI2MjI2M2NkY2IyMDQ3ODgzYTdmMDRkMzU=
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.3
@@ -0,0 +1,6 @@
1
+ require "cucumber/blinkbox/environment"
2
+ require "cucumber/blinkbox/data_dependencies"
3
+ require "cucumber/blinkbox/subjects"
4
+ require "cucumber/blinkbox/requests"
5
+ require "cucumber/blinkbox/responses"
6
+ require "cucumber/blinkbox/response_validation"
@@ -0,0 +1,31 @@
1
+ module KnowsAboutDataDependencies
2
+ ::TEST_CONFIG ||= {}
3
+
4
+ def self.extended(base)
5
+ base.instance_eval do
6
+ path = TEST_CONFIG["data.yml"] || "config/data.yml"
7
+ raise "The data dependencies file does not exist at #{path}" unless File.exist?(path)
8
+ @data_dependencies = YAML.load_file(path)
9
+ end
10
+ end
11
+
12
+ def data_for_a(object, which: nil, but_isnt: nil, instances: nil)
13
+ raise ArgumentError, "Please specify a condition using `which:`" if which.nil?
14
+ data = @data_dependencies[object.to_s][which] rescue nil
15
+
16
+ if data.respond_to? :sample
17
+ data.delete_if { |item| item == but_isnt } if but_isnt
18
+ if instances
19
+ pending "Test error: There are not enough examples defined for a #{object} which #{which}" unless data.size >= instances
20
+ data = data.sample(instances)
21
+ else
22
+ data = data.sample
23
+ end
24
+ end
25
+
26
+ pending "Test error: There is no data dependency defined for a #{object} which #{which}" unless data
27
+ data
28
+ end
29
+ end
30
+
31
+ World(KnowsAboutDataDependencies)
@@ -0,0 +1,35 @@
1
+ module KnowsAboutTheEnvironment
2
+ ::TEST_CONFIG ||= {}
3
+
4
+ class EnvStruct
5
+ def initialize(env)
6
+ @env = env
7
+ end
8
+ def [](key)
9
+ value = @env[key.to_s]
10
+ value.is_a?(Hash) ? EnvStruct.new(value) : value
11
+ end
12
+ def method_missing(name, *args)
13
+ key = name.to_s.tr("_", " ").downcase
14
+ self[key]
15
+ end
16
+ def inspect
17
+ @env.inspect
18
+ end
19
+ end
20
+
21
+ def self.extended(base)
22
+ base.instance_eval do
23
+ path = TEST_CONFIG["environments.yml"] || "config/environments.yml"
24
+ raise "The environments file does not exist at #{path}" unless File.exist?(path)
25
+ env = YAML.load_file(path)[TEST_CONFIG["server"].downcase]
26
+ raise "Environment '#{TEST_CONFIG["server"]}' is not defined in environments.yml" if env.nil?
27
+ @test_env = EnvStruct.new(env)
28
+ end
29
+ end
30
+
31
+ def test_env
32
+ @test_env
33
+ end
34
+ end
35
+ World(KnowsAboutTheEnvironment)
@@ -0,0 +1,124 @@
1
+ require 'cucumber/formatter/html'
2
+
3
+ module Cucumber
4
+ module Blinkbox
5
+ module Formatter
6
+ class Html < Cucumber::Formatter::Html
7
+
8
+ def timestamp
9
+ Time.now.strftime("%b %e %H:%M:%S")
10
+ end
11
+
12
+ def append_timestamp_to(name)
13
+ "#{name} [#{timestamp}]"
14
+ end
15
+
16
+ def prefix_with_timestamp(name)
17
+ "#{timestamp} #{name}"
18
+ end
19
+
20
+ #override inline JS in the default html formatter to always show cucumber tags regardless expand/collapse state of the scenarios
21
+ #also make all scenarios collapsed on page load
22
+ def inline_js_content
23
+ <<-EOF
24
+
25
+ SCENARIOS = "h3[id^='scenario_'],h3[id^=background_]";
26
+
27
+ $(document).ready(function() {
28
+ $(SCENARIOS).css('cursor', 'pointer');
29
+ $(SCENARIOS).click(function() {
30
+ $(this).siblings().toggle(250, function(){
31
+ $(this).siblings(".tag").show();
32
+ $(this).siblings(".examples").show();
33
+ $(this).siblings(".examples").children().show();
34
+ });
35
+ });
36
+
37
+ $("#collapser").css('cursor', 'pointer');
38
+ $("#collapser").click(function() {
39
+ $(SCENARIOS).siblings().hide();
40
+ $(SCENARIOS).siblings(".tag").show();
41
+ });
42
+
43
+ $("#expander").css('cursor', 'pointer');
44
+ $("#expander").click(function() {
45
+ $(SCENARIOS).siblings().show();
46
+ });
47
+
48
+ $(SCENARIOS).siblings().hide();
49
+ $(SCENARIOS).siblings(".tag").show();
50
+ })
51
+
52
+ function moveProgressBar(percentDone) {
53
+ $("cucumber-header").css('width', percentDone +"%");
54
+ }
55
+ function makeRed(element_id) {
56
+ $('#'+element_id).css('background', '#C40D0D');
57
+ $('#'+element_id).css('color', '#FFFFFF');
58
+ }
59
+ function makeYellow(element_id) {
60
+ $('#'+element_id).css('background', '#FAF834');
61
+ $('#'+element_id).css('color', '#000000');
62
+ }
63
+
64
+ EOF
65
+ end
66
+
67
+ #log scenario name so that console log is more readable
68
+ #also track the position in the all logs array from which out for current scenario starts
69
+ def scenario_name(keyword, name, file_colon_line, source_indent)
70
+ name = append_timestamp_to(name)
71
+ super(keyword, name, file_colon_line, source_indent)
72
+ end
73
+
74
+ def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
75
+ name = super
76
+ append_timestamp_to(name)
77
+ end
78
+
79
+ def build_step(keyword, step_match, status)
80
+ super
81
+ @builder.div(:class => 'step_file') do |div|
82
+ @builder.span do
83
+ @builder << append_timestamp_to("")
84
+ end
85
+ end
86
+ end
87
+
88
+ #override to set color of pending exceptions backtraces to Yellow instead of Red (and thus not make the whole scenario Red)
89
+ def after_table_row(table_row)
90
+ return if @hide_this_step
91
+ print_table_row_messages
92
+ @builder << '</tr>'
93
+ if table_row.exception
94
+ if table_row.exception.instance_of?(Cucumber::Pending)
95
+ @builder.tr do
96
+ @builder.td(:colspan => @col_index.to_s, :class => 'pending') do
97
+ @builder.pre do |pre|
98
+ pre << h(format_exception(table_row.exception))
99
+ end
100
+ end
101
+ end
102
+ set_scenario_color_pending
103
+ else
104
+ @builder.tr do
105
+ @builder.td(:colspan => @col_index.to_s, :class => 'failed') do
106
+ @builder.pre do |pre|
107
+ pre << h(format_exception(table_row.exception))
108
+ end
109
+ end
110
+ end
111
+ set_scenario_color_failed
112
+ end
113
+ end
114
+ if @outline_row
115
+ @outline_row += 1
116
+ end
117
+ @step_number += 1
118
+ move_progress
119
+ end
120
+
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,92 @@
1
+ module KnowsAboutApiRequests
2
+ CONTENT_TYPE = "application/vnd.blinkboxbooks.data.v1+json"
3
+
4
+ def http_client
5
+ @http ||= HTTPClient.new(TEST_CONFIG["proxy"])
6
+ # Ensure we're using the system SSL certs, as per other libraries (like HTTParty)
7
+ @http.ssl_config.set_trust_ca(OpenSSL::X509::DEFAULT_CERT_FILE)
8
+ @http.debug_dev = STDOUT if TEST_CONFIG["debug"]
9
+ #@http.reset_all
10
+ @http
11
+ end
12
+
13
+ def query
14
+ @query ||= {}
15
+ end
16
+
17
+ def request_headers(header = {})
18
+ @request_headers ||= {
19
+ "Accept" => CONTENT_TYPE
20
+ }
21
+ if @access_token
22
+ @request_headers["Authorization"] = "Bearer #{@access_token}"
23
+ else
24
+ @request_headers.delete("Authorization")
25
+ end
26
+ @request_headers.merge!(header)
27
+ @request_headers
28
+ end
29
+
30
+ def set_query_param(name, value)
31
+ if value.respond_to?(:each)
32
+ value.each { |v| set_query_param(name, v) }
33
+ else
34
+ name = name.camel_case
35
+ value = is_enum_param(name) ? value.snake_case(:upper) : value
36
+ current_value = query[name]
37
+
38
+ if current_value.nil?
39
+ query[name] = value
40
+ elsif current_value.is_a?(Array)
41
+ query[name] << value
42
+ else
43
+ query[name] = [current_value, value]
44
+ end
45
+ end
46
+ end
47
+
48
+ def qualified_uri(server, path)
49
+ uri = test_env.servers[server.to_sym]
50
+ raise "Test Error: #{server} doesn't appear to be defined in the environments.yml" if uri.nil?
51
+ File.join(uri.to_s, path)
52
+ end
53
+
54
+ # request methods
55
+
56
+ def http_get(server, path, header = {})
57
+ uri = qualified_uri(server, path)
58
+ params = query if query.count > 0
59
+ @response = http_client.get(uri, query: params, header: request_headers(header), follow_redirect: true)
60
+ end
61
+
62
+ def http_post(server, path, body = {}, header = {})
63
+ uri = qualified_uri(server, path)
64
+ @response = http_client.post(uri, body: format_body(body), header: request_headers({"Content-Type" => CONTENT_TYPE}.merge(header)))
65
+ end
66
+
67
+ def http_put(server, path, body = {}, header = {})
68
+ uri = qualified_uri(server, path)
69
+ @response = http_client.put(uri, body: format_body(body), header: request_headers({"Content-Type" => CONTENT_TYPE}.merge(header)))
70
+ end
71
+
72
+ def http_delete(server, path, header = {})
73
+ uri = qualified_uri(server, path)
74
+ params = query if query.count > 0
75
+ @response = http_client.delete(uri, query: params, header: request_headers(header))
76
+ end
77
+
78
+ private
79
+
80
+ def format_body(body)
81
+ body.is_a?(Hash) ? JSON.dump(body) : body
82
+ end
83
+
84
+ # So that we don't have to put enum parameters in the Gherkin in SCREAMING_SNAKE_CASE this heuristic identifies
85
+ # enum parameters so that we can transform them, meaning an enum value like PURCHASE_DATE can be written in the
86
+ # Gherkin as "purchase date" but still be sent correctly. This heuristic will need updating over time.
87
+ def is_enum_param(name)
88
+ ["bookmarkType", "order", "role"].include?(name)
89
+ end
90
+ end
91
+
92
+ World(KnowsAboutApiRequests)
@@ -0,0 +1,135 @@
1
+ # encoding: utf-8
2
+ module KnowsAboutResponseValidation
3
+ INFINITY = 1.0 / 0.0
4
+
5
+ # Parses a string into a data if that's the specified date type. This is needed for interpreting JSON markup as
6
+ # it doesn't have dates as a first-class concept so they should appear as specifically formatted strings.
7
+ def parse_and_validate_date_if_necessary(value, type)
8
+ # note: cannot use 'case type' as that expands to === which checks for instances of rather than type equality
9
+ if type == Date
10
+ expect(value).to match(/^\d{4}-\d{2}-\d{2}$/)
11
+ Date.strptime(value, "%Y-%m-%d")
12
+ elsif type == DateTime
13
+ expect(value).to match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/)
14
+ DateTime.strptime(value, "%Y-%m-%dT%H:%M:%SZ")
15
+ else
16
+ value
17
+ end
18
+ end
19
+
20
+ def validate_attribute(data, name, options = {})
21
+ type = options[:type]
22
+ type = type.constantize if type.respond_to?(:constantize) # allows it to be passed in as a string or a constant
23
+ expected_value = options[:is] || options[:value]
24
+ expected_value = expected_value.to_type(type) if expected_value.is_a?(String) && !type.nil?
25
+ expected_content = options[:contains]
26
+
27
+ value = parse_and_validate_date_if_necessary(data.deep_key(name), type)
28
+
29
+ begin
30
+ expect(value).to_not be_nil
31
+ expect(value).to be_a_kind_of(type) unless type.nil?
32
+ expect(value).to eq(expected_value) unless expected_value.nil?
33
+ expect(value).to match(/#{Regexp.escape(expected_content)}/) unless expected_content.nil?
34
+ yield value if block_given?
35
+ rescue => e
36
+ message = "'#{name}' is invalid:\n#{e.message}"
37
+ send((options[:warn_only] ? "puts" : "raise").to_sym, message)
38
+ end
39
+ end
40
+
41
+ def validate_entity(data, type, options = {})
42
+ warn_only = options[:warn_only] || []
43
+ validate_attribute(data, "type", type: String, warn_only: warn_only.include?(:type)) { |value| expect(value).to eq("urn:blinkboxbooks:schema:#{type}") }
44
+ validate_attribute(data, "guid", type: String, warn_only: warn_only.include?(:guid)) { |value| expect(value).to start_with "urn:blinkboxbooks:id:#{type}:#{data["id"]}" }
45
+ end
46
+
47
+ def validate_link(data)
48
+ validate_attribute(data, "rel", type: String) { |value| expect(value).to start_with "urn:blinkboxbooks:schema:" }
49
+ validate_attribute(data, "href", type: String) { |value| expect(value).to_not be_empty } if data["href"]
50
+ validate_attribute(data, "title", type: String) { |value| expect(value).to_not be_empty } if data["title"]
51
+ validate_attribute(data, "text", type: String) { |value| expect(value).to_not be_empty } if data["text"]
52
+ end
53
+
54
+ def validate_links(data, *expected)
55
+ validate_attribute(data, "links", type: Array)
56
+ data["links"].each { |link_data| validate_link(link_data) }
57
+ expected.each do |link_info|
58
+ rel = link_info[:rel] || link_info[:relationship]
59
+ rel = "urn:blinkboxbooks:schema:" << rel.tr(" ", "").downcase unless rel.start_with?("urn:")
60
+ count = data["links"].select { |link| link["rel"] == rel }.count
61
+ min = link_info[:min].to_i
62
+ max = %w{∞ *}.include?(link_info[:max]) ? INFINITY : link_info[:min].to_i
63
+ raise "Wrong number of #{rel} links: Expected #{min..max}, Actual: #{count}" unless count >= min && count <= max
64
+ end
65
+ end
66
+
67
+ # Validates a list of items is in the standardised blinkbox books format.
68
+ #
69
+ # @param options [Hash] Options for the validation.
70
+ # @option options [String] :item_type The (singular, snake cased) name of the items in the list, and the validation method (`validate_item_type`) that will be used to test them.
71
+ # @option options [String] :list_type The (signular, snake cased) name of the list type to be validated. Corresponds to the schema urn of `urn:blinkboxbooks:schema:listtypelist` and will look for the method `validate_list_of_list_type`.
72
+ # @option options [Integer] :min_count The minimum number of items there must be.
73
+ # @option options [Integer] :max_count The maximum number of items there can be.
74
+ # @option options [Integer] :count The exact number of items there must be. (Is overridden by min_ and max_count)
75
+ # @option options [Integer] :offset The offset expected for the data (used for ensuring the `offset` value is correct)
76
+ # @option options [Array<Symbol>] :warn_only Ask the validator to be lenient while testing the specified attributes (NB. Use snake_case)
77
+ def validate_list(data, options = {})
78
+ list_type = options[:list_type]
79
+ item_type = options[:item_type]
80
+ min_count = options[:min_count] || options[:count] || 0
81
+ max_count = options[:max_count] || options[:count] || 1000000
82
+ offset = options[:offset] || 0
83
+ warn_only = options[:warn_only] || []
84
+
85
+ # TODO: Should this be :list:#{list_type} rather than the list type before list?
86
+ expected_type = "urn:blinkboxbooks:schema:#{(list_type || "").tr("_", "")}list"
87
+ validate_attribute(data, "type", type: String, warn_only: warn_only.include?(:type)) { |value| expect(value).to eq(expected_type) }
88
+ validate_attribute(data, "count", type: Integer, warn_only: warn_only.include?(:count)) { |value| expect(min_count..max_count).to cover(value) }
89
+ validate_attribute(data, "offset", type: Integer, warn_only: warn_only.include?(:offset)) { |value| expect(value).to eq(offset) }
90
+ validate_attribute(data, "numberOfResults", type: Integer, warn_only: warn_only.include?(:number_of_results)) { |value| expect(value).to be >= data["count"] }
91
+ validate_attribute(data, "items", type: Array, warn_only: warn_only.include?(:empty_items))
92
+
93
+ unless list_type.nil?
94
+ further_validation = "validate_list_of_#{list_type}".to_sym
95
+ send(further_validation, data) if respond_to?(further_validation)
96
+ end
97
+
98
+ if data["items"] || min_count > 0
99
+ validate_attribute(data, "items", type: Array) do |value|
100
+ if min_count == max_count
101
+ expect(value.count).to eq(min_count)
102
+ else
103
+ expect(value.count).to be_between(min_count, max_count)
104
+ end
105
+ end
106
+ unless item_type.nil?
107
+ item_validation_method = "validate_#{item_type}".to_sym
108
+ data["items"].each { |item| self.send(item_validation_method, item) }
109
+ end
110
+ end
111
+ end
112
+
113
+ def validate_list_order(data, attribute_name, descending: false)
114
+ attribute_values = data["items"].map.with_index do |item, index|
115
+ value = item[attribute_name]
116
+ expect(value).to_not be_nil, "'#{attribute_name}' is nil in item at index #{index}"
117
+ if attribute_name =~ /date$/i
118
+ DateTime.parse(value)
119
+ else
120
+ value
121
+ end
122
+ end
123
+ expected_values = attribute_values.sort do |a, b|
124
+ if a.respond_to?(:upcase)
125
+ a.upcase <=> b.upcase # ordering of values should be case-insensitive
126
+ else
127
+ a <=> b
128
+ end
129
+ end
130
+ expected_values.reverse! if descending
131
+ expect(attribute_values).to eq(expected_values)
132
+ end
133
+ end
134
+
135
+ World(KnowsAboutResponseValidation)
@@ -0,0 +1,17 @@
1
+ require "http_capture"
2
+
3
+ module KnowsAboutApiResponses
4
+ # Parses response data that is expected to be in JSON format.
5
+ #
6
+ # @return [Hash] The response data.
7
+ def parse_response_data
8
+ expect(HttpCapture::RESPONSES.last["Content-Type"]).to match(%r{^application/vnd.blinkboxbooks.data.v1\+json;?})
9
+ begin
10
+ @response_data = JSON.load(HttpCapture::RESPONSES.last.body)
11
+ rescue => e
12
+ raise "The response is not valid JSON: #{e.message}"
13
+ end
14
+ end
15
+ end
16
+
17
+ World(KnowsAboutApiResponses)
@@ -0,0 +1,28 @@
1
+ # This module allows steps to set the subject of a scenario simply.
2
+ #
3
+ # subject(:book, {"isbn" => "9780111222333"})
4
+ # subject(:contributor, {"guid" => "abc123"})
5
+ #
6
+ # p subject(:book)
7
+ # # => {"isbn" => "9780111222333"}
8
+ #
9
+ # It's really just a readable wrapper for a hash with some test specific exceptions and things
10
+ module KnowsAboutGrammaticalSubjects
11
+ SUBJECTS = {}
12
+ USING_SETTER = :you_will_never_accidentally_pass_this
13
+
14
+ def subject(type, details = USING_SETTER)
15
+ if details == USING_SETTER
16
+ raise "Test error: A #{type} subject hasn't been defined in this scenario yet." unless SUBJECTS[type]
17
+ return SUBJECTS[type]
18
+ else
19
+ SUBJECTS[type] = details
20
+ end
21
+ end
22
+ end
23
+
24
+ World(KnowsAboutGrammaticalSubjects)
25
+
26
+ Before do
27
+ KnowsAboutGrammaticalSubjects::SUBJECTS.clear
28
+ end
@@ -0,0 +1,56 @@
1
+ require_relative "../../spec_helper"
2
+ require 'rspec'
3
+ require 'cucumber/blinkbox/requests'
4
+
5
+ # needed for String#camel_case
6
+ # (ought this be required by cucumber/blinkbox/requests ?)
7
+ require 'cucumber/helpers'
8
+
9
+ # needed for String#camelize
10
+ # (ought this be required by cucumber/helpers ?)
11
+ require 'active_support/core_ext/string'
12
+
13
+ describe "requests" do
14
+
15
+ describe "setting query parameters" do
16
+
17
+ before :each do
18
+ @request = Object.new
19
+ @request.extend(KnowsAboutApiRequests)
20
+ end
21
+
22
+ it "accepts a single value" do
23
+ @request.set_query_param("foo", 1)
24
+ @request.query["foo"].should eq(1)
25
+ end
26
+
27
+ it "accepts an array of values" do
28
+ @request.set_query_param("foo", [1, 2])
29
+ @request.query["foo"].should eq([1, 2])
30
+ end
31
+
32
+ it "accepts multiple single values" do
33
+ @request.set_query_param("foo", 1)
34
+ @request.set_query_param("foo", 2)
35
+ @request.query["foo"].should eq([1, 2])
36
+ end
37
+
38
+ it "appends arrays to existing arrays" do
39
+ @request.set_query_param("foo", [1, 2])
40
+ @request.set_query_param("foo", [3, 4])
41
+ @request.query["foo"].should eq([1, 2, 3, 4])
42
+ end
43
+
44
+ it "appends single values to existing arrays" do
45
+ @request.set_query_param("foo", [1, 2])
46
+ @request.set_query_param("foo", 3)
47
+ @request.query["foo"].should eq([1, 2, 3])
48
+ end
49
+
50
+ it "appends arrays to existing values" do
51
+ @request.set_query_param("foo", 1)
52
+ @request.set_query_param("foo", [2, 3])
53
+ @request.query["foo"].should eq([1, 2, 3])
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,6 @@
1
+ $:<<File.join(File.dirname(__FILE__), "..", "lib")
2
+
3
+ # Modules under test register themselves with Cucumber by passing themselves to
4
+ # World(m) Since Cucumber doesn't exist in test scope, however, we need to
5
+ # create a noop World
6
+ def World(m) end
metadata ADDED
@@ -0,0 +1,169 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cucumber-blinkbox
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.3
5
+ platform: ruby
6
+ authors:
7
+ - blinkbox books
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: cucumber
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: httpclient
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: http_capture
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '1.3'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '2.99'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '2.99'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: cucumber-helpers
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: blinkbox books specific cucumber test helpers
126
+ email:
127
+ - jphastings@blinkbox.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - VERSION
133
+ - lib/cucumber/blinkbox.rb
134
+ - lib/cucumber/blinkbox/data_dependencies.rb
135
+ - lib/cucumber/blinkbox/environment.rb
136
+ - lib/cucumber/blinkbox/formatter/html.rb
137
+ - lib/cucumber/blinkbox/requests.rb
138
+ - lib/cucumber/blinkbox/response_validation.rb
139
+ - lib/cucumber/blinkbox/responses.rb
140
+ - lib/cucumber/blinkbox/subjects.rb
141
+ - spec/cucumber/blinkbox/requests_spec.rb
142
+ - spec/spec_helper.rb
143
+ homepage: http://blinkboxbooks.github.io/
144
+ licenses:
145
+ - MIT
146
+ metadata: {}
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ! '>='
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ! '>='
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 2.4.5
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: blinkbox books specific cucumber test helpers
167
+ test_files:
168
+ - spec/cucumber/blinkbox/requests_spec.rb
169
+ - spec/spec_helper.rb