haveapi-client 0.26.4 → 0.27.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 990c16577799341bfe013e588b33b15e52c3acf973869a84ba3b051b99de57fd
4
- data.tar.gz: 14d4be7d907a1ef7857f5e7fc56cf39a408958e20aa1d7f0e10f4737d9cc3309
3
+ metadata.gz: a6231f3629c9e015d7e916dc7cf97466b30849db2a1fe86a521f5fd1b99fbb72
4
+ data.tar.gz: 46cb500d05af0f1bdd25f4a2749d7d459ff8460d1477dea59b64e816162dc9e7
5
5
  SHA512:
6
- metadata.gz: 28eefedb8c494cf33f0b81729b34dfcc558affdcb9d3acabf8c58f49b6a0ec9cb55a9f6e8b4c32ad72da42e4f66a78125710aa861284bcc1fbe119f230998306
7
- data.tar.gz: d42f140abba3ffa5851bb68a410061e64e23fd7a7e312d20ed82f36d6a143a1016e496773beb675aaf86248bf33809de994d0a55aba4d1d48324f4f119346325
6
+ metadata.gz: 5afb270a053317c22c6a5748739423690743a02a1b3f8e58d1e045d33b4446bd0d96f5427ffc7c37f6cfbb3266b2cfd8801692d9f3c557843fe586e4a60a9535
7
+ data.tar.gz: e42801e205282f72038c3777d819799be33569e63a9864ef13786e7346785cca469dd6128f9c3241f257d098bd089c9f9b3d8d47473f778019b8c30361833207
data/Gemfile CHANGED
@@ -6,3 +6,7 @@ group :development do
6
6
  gem 'bundler'
7
7
  gem 'rake'
8
8
  end
9
+
10
+ group :test do
11
+ gem 'rspec'
12
+ end
@@ -26,9 +26,9 @@ module HaveAPI::CLI
26
26
  id ||= @id
27
27
 
28
28
  if cancel
29
- puts 'Waiting for the action to cancel (hit Ctrl+C to skip)...'
29
+ warn 'Waiting for the action to cancel (hit Ctrl+C to skip)...'
30
30
  else
31
- puts 'Waiting for the action to complete (hit Ctrl+C to skip)...'
31
+ warn 'Waiting for the action to complete (hit Ctrl+C to skip)...'
32
32
  end
33
33
 
34
34
  last_status = false
@@ -47,11 +47,11 @@ module HaveAPI::CLI
47
47
  end
48
48
  rescue Interrupt
49
49
  @pb && @pb.stop
50
- puts
50
+ warn
51
51
 
52
52
  cancel_action(timeout: timeout) if can_cancel && !cancel && last_status
53
53
 
54
- puts
54
+ warn
55
55
  print_help(id)
56
56
  exit(false)
57
57
  end
@@ -81,7 +81,7 @@ module HaveAPI::CLI
81
81
  end
82
82
 
83
83
  if res.is_a?(HaveAPI::Client::Response) && res.ok?
84
- puts 'Cancelled'
84
+ warn 'Cancelled'
85
85
  exit
86
86
 
87
87
  elsif res
@@ -102,11 +102,11 @@ module HaveAPI::CLI
102
102
  def print_help(id = nil)
103
103
  id ||= @id
104
104
 
105
- puts 'Run'
106
- puts " #{$0} action_state show #{id}"
107
- puts 'or'
108
- puts " #{$0} action_state wait #{id}"
109
- puts "to check the action's progress."
105
+ warn 'Run'
106
+ warn " #{$0} action_state show #{id}"
107
+ warn 'or'
108
+ warn " #{$0} action_state wait #{id}"
109
+ warn "to check the action's progress."
110
110
  end
111
111
 
112
112
  protected
@@ -121,7 +121,8 @@ module HaveAPI::CLI
121
121
  '%t: [%B]'
122
122
  end,
123
123
  starting_at: state.progress.current,
124
- autofinish: false
124
+ autofinish: false,
125
+ output: $stderr
125
126
  )
126
127
 
127
128
  @pb.title = if state.status
@@ -112,7 +112,7 @@ module HaveAPI::CLI
112
112
  @input_params[:meta] = { includes: includes } if includes
113
113
 
114
114
  begin
115
- ret = action.execute(@input_params, raw: @opts[:raw])
115
+ ret = action.execute(@input_params)
116
116
  rescue HaveAPI::Client::ValidationError => e
117
117
  format_errors(action, 'input parameters not valid', e.errors)
118
118
  exit(false)
@@ -508,7 +508,7 @@ module HaveAPI::CLI
508
508
 
509
509
  def format_output(action, response, out = $>)
510
510
  if @opts[:raw]
511
- puts JSON.generate(response)
511
+ puts JSON.pretty_generate(response)
512
512
  return
513
513
  end
514
514
 
@@ -16,7 +16,7 @@ module HaveAPI::Client
16
16
  "#<#{self.class.name} @name=#{@name}>"
17
17
  end
18
18
 
19
- def execute(data, raw: false)
19
+ def execute(data)
20
20
  params_arg = {}
21
21
 
22
22
  if input
@@ -29,7 +29,7 @@ module HaveAPI::Client
29
29
  params_arg = params.to_api
30
30
  end
31
31
 
32
- ret = @api.call(self, params_arg, raw: raw)
32
+ ret = @api.call(self, params_arg)
33
33
  reset
34
34
  ret
35
35
  end
@@ -117,7 +117,7 @@ module HaveAPI::Client
117
117
  end
118
118
  end
119
119
 
120
- def call(action, params = {}, raw: false)
120
+ def call(action, params = {})
121
121
  args = []
122
122
  input_namespace = action.input && action.namespace(:input)
123
123
  meta = nil
@@ -164,11 +164,7 @@ module HaveAPI::Client
164
164
  end
165
165
 
166
166
  if response[:status]
167
- if raw
168
- ok(JSON.pretty_generate(response[:response]))
169
- else
170
- ok(response[:response])
171
- end
167
+ ok(response[:response])
172
168
 
173
169
  else
174
170
  error(response[:message], response[:errors])
@@ -5,7 +5,11 @@ module HaveAPI::Client
5
5
  attr_reader :response
6
6
 
7
7
  def initialize(response)
8
- super("#{response.action.name} failed: #{response.message}")
8
+ if response.respond_to?(:action)
9
+ super("#{response.action.name} failed: #{response.message}")
10
+ else
11
+ super(response.to_s)
12
+ end
9
13
 
10
14
  @response = response
11
15
  end
@@ -18,6 +18,8 @@ module HaveAPI::Client
18
18
  protected
19
19
 
20
20
  def coerce(v)
21
+ return nil if v.nil?
22
+
21
23
  if !v.is_a?(::Integer) && /\A\d+\z/ !~ v
22
24
  @errors << 'not a valid resource id'
23
25
  nil
@@ -2,20 +2,6 @@ require 'date'
2
2
 
3
3
  module HaveAPI::Client
4
4
  class Parameters::Typed
5
- module Boolean
6
- def self.to_b(str)
7
- return true if str === true
8
- return false if str === false
9
-
10
- if str.respond_to?(:=~)
11
- return true if str =~ /^(true|t|yes|y|1)$/i
12
- return false if str =~ /^(false|f|no|n|0)$/i
13
- end
14
-
15
- false
16
- end
17
- end
18
-
19
5
  attr_reader :errors, :value
20
6
 
21
7
  def initialize(params, desc, value)
@@ -26,6 +12,8 @@ module HaveAPI::Client
26
12
  end
27
13
 
28
14
  def valid?
15
+ return false unless @errors.empty?
16
+
29
17
  ret = Validator.validate(@desc[:validators], @value, @params)
30
18
 
31
19
  @errors.concat(ret) unless ret === true
@@ -44,39 +32,146 @@ module HaveAPI::Client
44
32
  protected
45
33
 
46
34
  def coerce(raw)
35
+ return nil if raw.nil?
36
+
47
37
  type = @desc[:type]
48
38
 
49
- if type == 'Integer'
50
- raw.to_i
39
+ case type
40
+ when 'Integer'
41
+ coerce_integer(raw)
42
+ when 'Float'
43
+ coerce_float(raw)
44
+ when 'Boolean'
45
+ coerce_boolean(raw)
46
+ when 'Datetime'
47
+ coerce_datetime(raw)
48
+ when 'String', 'Text'
49
+ coerce_string(raw)
50
+ else
51
+ raw
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def coerce_integer(raw)
58
+ case raw
59
+ when ::Integer
60
+ raw
61
+
62
+ when ::Float
63
+ return raw.to_i if raw.finite? && raw == raw.to_i
64
+
65
+ invalid_integer
66
+
67
+ when ::String
68
+ s = raw.strip
69
+ return invalid_integer if s.empty?
70
+ return invalid_integer unless s.match?(/\A[+-]?\d+\z/)
51
71
 
52
- elsif type == 'Float'
53
- raw.to_f
72
+ Integer(s, 10)
54
73
 
55
- elsif type == 'Boolean'
56
- Boolean.to_b(raw)
74
+ else
75
+ invalid_integer
76
+ end
77
+ rescue ArgumentError
78
+ invalid_integer
79
+ end
57
80
 
58
- elsif type == 'Datetime'
59
- if raw.is_a?(::Time)
60
- raw
81
+ def coerce_float(raw)
82
+ if raw.is_a?(::Numeric)
83
+ value = raw.to_f
84
+ return value if value.finite?
61
85
 
62
- elsif raw.is_a?(::Date) || raw.is_a?(::DateTime)
63
- raw.to_time
86
+ @errors << 'not a valid float'
87
+ nil
64
88
 
65
- else
66
- begin
67
- DateTime.iso8601(raw).to_time
68
- rescue ArgumentError
69
- @errors << 'not in ISO 8601 format'
70
- nil
71
- end
72
- end
89
+ elsif raw.is_a?(::String)
90
+ s = raw.strip
91
+ return invalid_float if s.empty?
73
92
 
74
- elsif %w[String Text].include?(type)
75
- raw.to_s
93
+ value = Float(s)
94
+ return value if value.finite?
95
+
96
+ invalid_float
76
97
 
77
98
  else
99
+ invalid_float
100
+ end
101
+ rescue ArgumentError
102
+ invalid_float
103
+ end
104
+
105
+ def coerce_boolean(raw)
106
+ return raw if [true, false].include?(raw)
107
+
108
+ if raw.is_a?(::Integer)
109
+ return true if raw == 1
110
+ return false if raw == 0
111
+
112
+ return invalid_boolean
113
+ end
114
+
115
+ if raw.is_a?(::String)
116
+ s = raw.strip.downcase
117
+ return invalid_boolean if s.empty?
118
+
119
+ return true if %w[true t yes y 1].include?(s)
120
+ return false if %w[false f no n 0].include?(s)
121
+ end
122
+
123
+ invalid_boolean
124
+ end
125
+
126
+ def coerce_datetime(raw)
127
+ case raw
128
+ when ::Time
78
129
  raw
130
+
131
+ when ::Date, ::DateTime
132
+ raw.to_time
133
+
134
+ when ::String
135
+ return invalid_datetime if raw.strip.empty?
136
+
137
+ DateTime.iso8601(raw).to_time
138
+
139
+ else
140
+ invalid_datetime
79
141
  end
142
+ rescue ArgumentError
143
+ invalid_datetime
144
+ end
145
+
146
+ def coerce_string(raw)
147
+ return invalid_string if raw.is_a?(::Array) || raw.is_a?(::Hash)
148
+
149
+ raw.to_s
150
+ end
151
+
152
+ def invalid_integer
153
+ @errors << 'not a valid integer'
154
+ nil
155
+ end
156
+
157
+ def invalid_float
158
+ @errors << 'not a valid float'
159
+ nil
160
+ end
161
+
162
+ def invalid_boolean
163
+ @errors << 'not a valid boolean'
164
+ nil
165
+ end
166
+
167
+ def invalid_datetime
168
+ @errors << 'not in ISO 8601 format'
169
+ nil
170
+ end
171
+
172
+ def invalid_string
173
+ @errors << 'not a valid string'
174
+ nil
80
175
  end
81
176
  end
82
177
  end
@@ -29,9 +29,12 @@ module HaveAPI::Client
29
29
  @action.input_params.each do |name, p|
30
30
  next if p[:validators].nil?
31
31
 
32
- if p[:validators][:presence] && @params[name].nil?
33
- error(name, 'required parameter missing')
32
+ presence_validator =
33
+ p[:validators][:presence] || p[:validators][:present] || p[:validators][:required]
34
34
 
35
+ if presence_validator && @params[name].nil?
36
+ error(name, 'required parameter missing')
37
+ next
35
38
  elsif @params[name].nil?
36
39
  next
37
40
  end
@@ -1,6 +1,6 @@
1
1
  module HaveAPI
2
2
  module Client
3
3
  PROTOCOL_VERSION = '2.0'.freeze
4
- VERSION = '0.26.4'.freeze
4
+ VERSION = '0.27.0'.freeze
5
5
  end
6
6
  end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe HaveAPI::Client::Client do
6
+ let(:base_url) { TEST_SERVER.base_url }
7
+
8
+ it 'exposes versions and compatibility' do
9
+ client = described_class.new(base_url)
10
+
11
+ versions = client.versions
12
+ expect(versions[:default]).to eq('1.0')
13
+ expect(versions[:versions]).to include('1.0')
14
+ expect(client.compatible?).to(
15
+ satisfy { |value| [:compatible, :imperfect, false].include?(value) }
16
+ )
17
+ end
18
+
19
+ it 'filters docs until authenticated' do
20
+ unauthenticated = described_class.new(base_url)
21
+ unauthenticated.setup
22
+
23
+ expect { unauthenticated.project }.to raise_error(NoMethodError)
24
+
25
+ authenticated = described_class.new(base_url)
26
+ authenticated.authenticate(:basic, user: 'user', password: 'pass')
27
+
28
+ expect { authenticated.project }.not_to raise_error
29
+ expect(authenticated.project).to be_a(HaveAPI::Client::Resource)
30
+ end
31
+
32
+ it 'supports CRUD flow for projects' do
33
+ client = described_class.new(base_url)
34
+ client.authenticate(:basic, user: 'user', password: 'pass')
35
+
36
+ projects = client.project.list
37
+ expect(projects).to be_a(Array)
38
+ expect(projects.size).to be >= 2
39
+
40
+ project = client.project.find(projects.first.id)
41
+ expect(project.id).to eq(projects.first.id)
42
+
43
+ created = client.project.create(name: 'Gamma')
44
+ expect(created.id).to be_a(Integer)
45
+ expect(created.name).to eq('Gamma')
46
+ end
47
+
48
+ it 'handles nested task resources' do
49
+ client = described_class.new(base_url)
50
+ client.authenticate(:basic, user: 'user', password: 'pass')
51
+
52
+ project = client.project.list.first
53
+ tasks = client.project.task.list(project.id)
54
+ expect(tasks).to be_a(Array)
55
+
56
+ task = client.project(project.id).task.create(label: 'Do it')
57
+ expect(task.id).to be_a(Integer)
58
+ expect(task.label).to eq('Do it')
59
+ end
60
+
61
+ it 'raises validation error on missing required params' do
62
+ client = described_class.new(base_url)
63
+ client.authenticate(:basic, user: 'user', password: 'pass')
64
+
65
+ expect { client.project.create({}) }
66
+ .to raise_error(HaveAPI::Client::ValidationError)
67
+ end
68
+
69
+ it 'supports blocking actions and action state polling' do
70
+ client = described_class.new(base_url)
71
+ client.authenticate(:basic, user: 'user', password: 'pass')
72
+
73
+ project = client.project.create(name: 'Blocky')
74
+ task = client.project(project.id).task.create(label: 'Run me')
75
+
76
+ response = client.project.task.run(project.id, task.id, meta: { block: false })
77
+ expect(response.meta[:action_state_id]).to be_a(Integer)
78
+
79
+ result = response.wait_for_completion(interval: 0.05, update_in: 0.05, timeout: 2)
80
+ expect(result).to be(true)
81
+ end
82
+
83
+ it 'surfaces HaveAPI errors as ActionFailed' do
84
+ client = described_class.new(base_url)
85
+
86
+ expect { client.test.fail }
87
+ .to raise_error(HaveAPI::Client::ActionFailed) do |err|
88
+ expect(err.response.message).to eq('forced failure')
89
+ expect(err.response.errors).to include(:base)
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe HaveAPI::Client::Client do
6
+ let(:client) { described_class.new(TEST_SERVER.base_url) }
7
+ let(:valid_params) do
8
+ {
9
+ i: 1,
10
+ f: 1.0,
11
+ b: true,
12
+ dt: '2020-01-01T00:00:00Z',
13
+ s: 'x',
14
+ t: 'y'
15
+ }
16
+ end
17
+
18
+ it 'coerces valid typed inputs' do
19
+ res = client.test.echo(
20
+ i: ' 42 ',
21
+ f: 5,
22
+ b: 'yes',
23
+ dt: '2020-01-01T00:00:00Z',
24
+ s: 123,
25
+ t: false
26
+ )
27
+
28
+ expect(res).to be_a(HaveAPI::Client::Response)
29
+ expect(res[:i]).to eq(42)
30
+ expect(res[:f]).to eq(5.0)
31
+ expect(res[:b]).to be(true)
32
+ expect(res[:dt]).to match(/\A2020-01-01T00:00:00(?:Z|\+00:00)\z/)
33
+ expect(res[:s]).to eq('123')
34
+ expect(res[:t]).to eq('false')
35
+ end
36
+
37
+ it 'accepts exponent float strings' do
38
+ res = client.test.echo(
39
+ i: 1,
40
+ f: '1e3',
41
+ b: true,
42
+ dt: '2020-01-01',
43
+ s: 'ok',
44
+ t: 'ok'
45
+ )
46
+
47
+ expect(res[:f]).to eq(1000.0)
48
+ end
49
+
50
+ it 'rejects invalid integer strings' do
51
+ expect { client.test.echo(valid_params.merge(i: 'abc')) }
52
+ .to raise_error(HaveAPI::Client::ValidationError) do |err|
53
+ expect(err.errors).to include(:i)
54
+ expect(err.errors[:i]).to include(a_string_matching(/not a valid integer/))
55
+ end
56
+ end
57
+
58
+ it 'rejects non-integral floats for integers' do
59
+ expect { client.test.echo(valid_params.merge(i: 12.3)) }
60
+ .to raise_error(HaveAPI::Client::ValidationError) do |err|
61
+ expect(err.errors).to include(:i)
62
+ expect(err.errors[:i]).to include(a_string_matching(/not a valid integer/))
63
+ end
64
+ end
65
+
66
+ it 'rejects invalid floats' do
67
+ expect { client.test.echo(valid_params.merge(f: 'abc')) }
68
+ .to raise_error(HaveAPI::Client::ValidationError) do |err|
69
+ expect(err.errors).to include(:f)
70
+ expect(err.errors[:f]).to include(a_string_matching(/not a valid float/))
71
+ end
72
+ end
73
+
74
+ it 'rejects invalid boolean strings' do
75
+ expect { client.test.echo(valid_params.merge(b: 'maybe')) }
76
+ .to raise_error(HaveAPI::Client::ValidationError) do |err|
77
+ expect(err.errors).to include(:b)
78
+ expect(err.errors[:b]).to include(a_string_matching(/not a valid boolean/))
79
+ end
80
+ end
81
+
82
+ it 'rejects invalid boolean integers' do
83
+ expect { client.test.echo(valid_params.merge(b: 2)) }
84
+ .to raise_error(HaveAPI::Client::ValidationError) do |err|
85
+ expect(err.errors).to include(:b)
86
+ expect(err.errors[:b]).to include(a_string_matching(/not a valid boolean/))
87
+ end
88
+ end
89
+
90
+ it 'rejects invalid datetimes' do
91
+ expect { client.test.echo(valid_params.merge(dt: 'yesterday')) }
92
+ .to raise_error(HaveAPI::Client::ValidationError) do |err|
93
+ expect(err.errors).to include(:dt)
94
+ expect(err.errors[:dt]).to include(a_string_matching(/ISO 8601/))
95
+ end
96
+ end
97
+
98
+ it 'rejects arrays for string params' do
99
+ expect { client.test.echo(valid_params.merge(s: [1, 2])) }
100
+ .to raise_error(HaveAPI::Client::ValidationError) do |err|
101
+ expect(err.errors).to include(:s)
102
+ expect(err.errors[:s]).to include(a_string_matching(/not a valid string/))
103
+ end
104
+ end
105
+
106
+ it 'rejects hashes for text params' do
107
+ expect { client.test.echo(valid_params.merge(t: { a: 1 })) }
108
+ .to raise_error(HaveAPI::Client::ValidationError) do |err|
109
+ expect(err.errors).to include(:t)
110
+ expect(err.errors[:t]).to include(a_string_matching(/not a valid string/))
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'haveapi/client'
5
+
6
+ require_relative 'support/test_server'
7
+
8
+ TEST_SERVER = ClientTestServer.new
9
+
10
+ RSpec.configure do |config|
11
+ config.order = :random
12
+
13
+ config.before(:suite) do
14
+ TEST_SERVER.start
15
+ end
16
+
17
+ config.after(:suite) do
18
+ TEST_SERVER.stop!
19
+ end
20
+
21
+ config.before do
22
+ TEST_SERVER.reset!
23
+ end
24
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+ require 'net/http'
5
+ require 'timeout'
6
+ require 'uri'
7
+
8
+ class ClientTestServer
9
+ READY_PREFIX = 'HAVEAPI_TEST_SERVER_READY'
10
+
11
+ attr_reader :base_url
12
+
13
+ def initialize
14
+ @root = File.expand_path('../../../..', __dir__)
15
+ @server_script = File.join(@root, 'servers', 'ruby', 'test_support', 'client_test_server.rb')
16
+ @gemfile = File.join(@root, 'servers', 'ruby', 'Gemfile')
17
+ @cwd = File.join(@root, 'clients', 'ruby')
18
+ end
19
+
20
+ def start
21
+ return if @wait_thr
22
+
23
+ env = { 'BUNDLE_GEMFILE' => @gemfile }
24
+ cmd = ['bundle', 'exec', 'ruby', @server_script, '--port', '0']
25
+ @stdin, @stdout, @wait_thr = Open3.popen2e(env, *cmd, chdir: @cwd)
26
+
27
+ read_ready!
28
+ wait_for_health!
29
+ end
30
+
31
+ def reset!
32
+ ensure_started!
33
+
34
+ uri = URI.join(@base_url, '/__reset')
35
+ req = Net::HTTP::Post.new(uri)
36
+ req['Content-Type'] = 'application/json'
37
+ res = Net::HTTP.start(uri.host, uri.port) { |http| http.request(req) }
38
+
39
+ return if res.is_a?(Net::HTTPSuccess)
40
+
41
+ raise "reset failed: #{res.code} #{res.body}"
42
+ end
43
+
44
+ def stop!
45
+ return unless @wait_thr
46
+
47
+ Process.kill('TERM', @wait_thr.pid)
48
+ @wait_thr.value
49
+ rescue Errno::ESRCH
50
+ nil
51
+ ensure
52
+ @stdin&.close
53
+ @stdout&.close
54
+ @wait_thr = nil
55
+ end
56
+
57
+ private
58
+
59
+ def ensure_started!
60
+ start unless @wait_thr
61
+ end
62
+
63
+ def read_ready!
64
+ Timeout.timeout(10) do
65
+ while (line = @stdout.gets)
66
+ next unless line.include?(READY_PREFIX)
67
+
68
+ @base_url = line.split.last&.strip
69
+ break
70
+ end
71
+ end
72
+
73
+ raise 'server did not start' unless @base_url
74
+ rescue Timeout::Error
75
+ raise 'server did not start in time'
76
+ end
77
+
78
+ def wait_for_health!
79
+ Timeout.timeout(5) do
80
+ loop do
81
+ begin
82
+ uri = URI.join(@base_url, '/__health')
83
+ res = Net::HTTP.get_response(uri)
84
+ return if res.is_a?(Net::HTTPSuccess)
85
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, IOError
86
+ # retry
87
+ end
88
+
89
+ sleep 0.05
90
+ end
91
+ end
92
+ rescue Timeout::Error
93
+ raise 'server did not become healthy in time'
94
+ end
95
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haveapi-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.26.4
4
+ version: 0.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Skokan
@@ -151,6 +151,10 @@ files:
151
151
  - lib/haveapi/client/version.rb
152
152
  - lib/restclient_ext/resource.rb
153
153
  - shell.nix
154
+ - spec/integration/client_spec.rb
155
+ - spec/integration/typed_input_spec.rb
156
+ - spec/spec_helper.rb
157
+ - spec/support/test_server.rb
154
158
  homepage: ''
155
159
  licenses:
156
160
  - MIT