scalingo 3.0.0.beta.2 → 3.1.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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/publish.yml +28 -0
  3. data/.github/workflows/ruby.yml +45 -0
  4. data/.rubocop.yml +16 -0
  5. data/CHANGELOG.md +24 -0
  6. data/README.md +25 -20
  7. data/lib/scalingo/api/client.rb +38 -10
  8. data/lib/scalingo/api/endpoint.rb +12 -2
  9. data/lib/scalingo/api/response.rb +11 -2
  10. data/lib/scalingo/auth/keys.rb +4 -4
  11. data/lib/scalingo/auth/scm_integrations.rb +4 -4
  12. data/lib/scalingo/auth/tokens.rb +6 -6
  13. data/lib/scalingo/auth/two_factor_auth.rb +4 -4
  14. data/lib/scalingo/auth/user.rb +15 -2
  15. data/lib/scalingo/bearer_token.rb +15 -0
  16. data/lib/scalingo/billing/profile.rb +3 -3
  17. data/lib/scalingo/client.rb +26 -113
  18. data/lib/scalingo/configuration.rb +8 -36
  19. data/lib/scalingo/core_client.rb +106 -0
  20. data/lib/scalingo/regional/addons.rb +21 -8
  21. data/lib/scalingo/regional/apps.rb +8 -8
  22. data/lib/scalingo/regional/autoscalers.rb +70 -0
  23. data/lib/scalingo/regional/collaborators.rb +4 -4
  24. data/lib/scalingo/regional/containers.rb +4 -4
  25. data/lib/scalingo/regional/deployments.rb +3 -3
  26. data/lib/scalingo/regional/domains.rb +5 -5
  27. data/lib/scalingo/regional/environment.rb +6 -6
  28. data/lib/scalingo/regional/events.rb +4 -4
  29. data/lib/scalingo/regional/logs.rb +2 -2
  30. data/lib/scalingo/regional/metrics.rb +3 -2
  31. data/lib/scalingo/regional/notifiers.rb +7 -7
  32. data/lib/scalingo/regional/operations.rb +1 -1
  33. data/lib/scalingo/regional/scm_repo_links.rb +8 -8
  34. data/lib/scalingo/regional.rb +2 -0
  35. data/lib/scalingo/token_holder.rb +31 -0
  36. data/lib/scalingo/version.rb +1 -1
  37. data/samples/auth/user/stop-free-trial.json +24 -0
  38. data/samples/regional/addons/token-200.json +49 -0
  39. data/samples/regional/addons/token-404.json +24 -0
  40. data/samples/regional/autoscalers/_meta.json +27 -0
  41. data/samples/regional/autoscalers/create-201.json +49 -0
  42. data/samples/regional/autoscalers/create-500.json +32 -0
  43. data/samples/regional/autoscalers/destroy-204.json +20 -0
  44. data/samples/regional/autoscalers/destroy-404.json +25 -0
  45. data/samples/regional/autoscalers/find-200.json +39 -0
  46. data/samples/regional/autoscalers/find-404.json +25 -0
  47. data/samples/regional/autoscalers/for-200.json +41 -0
  48. data/samples/regional/autoscalers/update-200.json +45 -0
  49. data/samples/regional/autoscalers/update-404.json +31 -0
  50. data/samples/regional/autoscalers/update-500.json +30 -0
  51. data/scalingo.gemspec +8 -8
  52. data/spec/scalingo/api/client_spec.rb +60 -13
  53. data/spec/scalingo/api/endpoint_spec.rb +18 -3
  54. data/spec/scalingo/api/response_spec.rb +32 -16
  55. data/spec/scalingo/auth/user_spec.rb +6 -0
  56. data/spec/scalingo/auth_spec.rb +1 -1
  57. data/spec/scalingo/billing_spec.rb +11 -0
  58. data/spec/scalingo/client_spec.rb +2 -2
  59. data/spec/scalingo/configuration_spec.rb +32 -30
  60. data/spec/scalingo/regional/addons_spec.rb +16 -0
  61. data/spec/scalingo/regional/autoscalers_spec.rb +84 -0
  62. data/spec/scalingo/regional_spec.rb +3 -3
  63. metadata +69 -47
  64. data/.travis.yml +0 -24
@@ -0,0 +1,41 @@
1
+ {
2
+ "path": "/apps/example-running-application/autoscalers",
3
+ "method": "get",
4
+ "request": {
5
+ "headers": {
6
+ "Accept": "application/json",
7
+ "Authorization": "Bearer the-bearer-token"
8
+ }
9
+ },
10
+ "response": {
11
+ "status": 200,
12
+ "headers": {
13
+ "Date": "Fri, 28 Aug 2020 11:48:30 GMT",
14
+ "Etag": "W/\"78d382e1680bcf4d9ff9e58c906714ba\"",
15
+ "Content-Type": "application/json; charset=utf-8",
16
+ "Transfer-Encoding": "chunked",
17
+ "Connection": "keep-alive",
18
+ "Cache-Control": "max-age=0, private, must-revalidate",
19
+ "Referrer-Policy": "strict-origin-when-cross-origin"
20
+ },
21
+ "json_body": {
22
+ "autoscalers": [
23
+ {
24
+ "created_at": "2020-08-28T11:48:29.963Z",
25
+ "updated_at": "2020-08-28T11:48:29.963Z",
26
+ "id": "sc-5418fe67-885d-4e50-8cbe-9a9a2d2d690a",
27
+ "app_id": "5f48ecb6f112e2000ef34f14",
28
+ "container_type": "web",
29
+ "alert_id_scale_up": "al-ecf1cff6-c415-4e7b-8a86-e0ef697b2d87",
30
+ "alert_id_scale_down": "al-6ef726e8-d69b-44e1-8d67-3acef2a4802d",
31
+ "min_containers": 3,
32
+ "max_containers": 7,
33
+ "last_scale": "0001-01-01T00:00:00Z",
34
+ "disabled": false,
35
+ "metric": "rpm_per_container",
36
+ "target": 150
37
+ }
38
+ ]
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "path": "/apps/example-running-application/autoscalers/sc-5418fe67-885d-4e50-8cbe-9a9a2d2d690a",
3
+ "method": "patch",
4
+ "request": {
5
+ "headers": {
6
+ "Accept": "application/json",
7
+ "Authorization": "Bearer the-bearer-token",
8
+ "Content-Type": "application/json"
9
+ },
10
+ "json_body": {
11
+ "autoscaler": {
12
+ "target": 200
13
+ }
14
+ }
15
+ },
16
+ "response": {
17
+ "status": 200,
18
+ "headers": {
19
+ "Date": "Fri, 28 Aug 2020 11:48:31 GMT",
20
+ "Etag": "W/\"f11b66f818316c26bb369e2e72009d4e\"",
21
+ "Content-Type": "application/json; charset=utf-8",
22
+ "Transfer-Encoding": "chunked",
23
+ "Connection": "keep-alive",
24
+ "Cache-Control": "max-age=0, private, must-revalidate",
25
+ "Referrer-Policy": "strict-origin-when-cross-origin"
26
+ },
27
+ "json_body": {
28
+ "autoscaler": {
29
+ "created_at": "2020-08-28T11:48:29.963Z",
30
+ "updated_at": "2020-08-28T11:48:31.56609493Z",
31
+ "id": "sc-5418fe67-885d-4e50-8cbe-9a9a2d2d690a",
32
+ "app_id": "5f48ecb6f112e2000ef34f14",
33
+ "container_type": "web",
34
+ "alert_id_scale_up": "al-ecf1cff6-c415-4e7b-8a86-e0ef697b2d87",
35
+ "alert_id_scale_down": "al-6ef726e8-d69b-44e1-8d67-3acef2a4802d",
36
+ "min_containers": 3,
37
+ "max_containers": 7,
38
+ "last_scale": "0001-01-01T00:00:00Z",
39
+ "disabled": false,
40
+ "metric": "rpm_per_container",
41
+ "target": 200
42
+ }
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "path": "/apps/example-running-application/autoscalers/wrong-autoscaler-id",
3
+ "method": "patch",
4
+ "request": {
5
+ "headers": {
6
+ "Accept": "application/json",
7
+ "Authorization": "Bearer the-bearer-token",
8
+ "Content-Type": "application/json"
9
+ },
10
+ "json_body": {
11
+ "autoscaler": {
12
+ "target": 200
13
+ }
14
+ }
15
+ },
16
+ "response": {
17
+ "status": 404,
18
+ "headers": {
19
+ "Date": "Fri, 28 Aug 2020 11:48:30 GMT",
20
+ "Content-Type": "application/json; charset=utf-8",
21
+ "Transfer-Encoding": "chunked",
22
+ "Connection": "keep-alive",
23
+ "Cache-Control": "no-cache",
24
+ "Referrer-Policy": "strict-origin-when-cross-origin"
25
+ },
26
+ "json_body": {
27
+ "resource": "autoscaler",
28
+ "error": "not found"
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "path": "/apps/example-running-application/autoscalers/sc-5418fe67-885d-4e50-8cbe-9a9a2d2d690a",
3
+ "method": "patch",
4
+ "request": {
5
+ "headers": {
6
+ "Accept": "application/json",
7
+ "Authorization": "Bearer the-bearer-token",
8
+ "Content-Type": "application/json"
9
+ },
10
+ "json_body": {
11
+ "autoscaler": {
12
+ "metric": "unknown"
13
+ }
14
+ }
15
+ },
16
+ "response": {
17
+ "status": 500,
18
+ "headers": {
19
+ "Date": "Fri, 28 Aug 2020 11:48:31 GMT",
20
+ "Content-Type": "application/json; charset=utf-8",
21
+ "Transfer-Encoding": "chunked",
22
+ "Connection": "keep-alive",
23
+ "Cache-Control": "no-cache",
24
+ "Referrer-Policy": "strict-origin-when-cross-origin"
25
+ },
26
+ "json_body": {
27
+ "error": "Internal error occured, we're on it!"
28
+ }
29
+ }
30
+ }
data/scalingo.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
  "changelog_uri" => "https://github.com/Scalingo/scalingo-ruby-api/blob/master/CHANGELOG.md",
20
20
  "documentation_uri" => "https://developers.scalingo.com/",
21
21
  "homepage_uri" => "https://www.scalingo.com/",
22
- "source_code_uri" => "https://github.com/Scalingo/scalingo-ruby-api"
22
+ "source_code_uri" => "https://github.com/Scalingo/scalingo-ruby-api",
23
23
  }
24
24
 
25
25
  # Specify which files should be added to the gem when it is released.
@@ -34,16 +34,16 @@ Gem::Specification.new do |s|
34
34
 
35
35
  s.test_files = Dir["spec/**/*_spec.rb"]
36
36
 
37
- s.add_dependency "activesupport", [">= 5", "< 7"]
38
- s.add_dependency "faraday", "~> 1.0.1"
39
- s.add_dependency "faraday_middleware", "~> 1.0.0"
37
+ s.add_dependency "activesupport", [">= 5", "< 8"]
38
+ s.add_dependency "faraday", "~> 1.0"
39
+ s.add_dependency "faraday_middleware", "~> 1.0"
40
40
  s.add_dependency "multi_json", ">= 1.0.3", "~> 1.0"
41
41
 
42
42
  s.add_development_dependency "bundler", "~> 2.0"
43
43
  s.add_development_dependency "rake", "~> 13.0"
44
44
  s.add_development_dependency "rspec", "~> 3.0"
45
- s.add_development_dependency "rubocop", "~> 0.83.0"
46
- s.add_development_dependency "standard", "~> 0.4.2"
47
- s.add_development_dependency "pry", "~> 0.13.1"
48
- s.add_development_dependency "webmock", "~> 3.8.0"
45
+ s.add_development_dependency "standard", "~> 1.1.0"
46
+ s.add_development_dependency "rubocop-rspec"
47
+ s.add_development_dependency "pry", "~> 0.14.1"
48
+ s.add_development_dependency "webmock", "~> 3.12.2"
49
49
  end
@@ -3,14 +3,61 @@ require "spec_helper"
3
3
  RSpec.describe Scalingo::API::Client do
4
4
  let(:url) { "http://localhost" }
5
5
 
6
- subject { described_class.new(scalingo, url) }
6
+ subject { described_class.new(url, scalingo: scalingo) }
7
7
 
8
8
  describe "initialize" do
9
- it "stores the scalingo client and the url" do
10
- instance = described_class.new(:scalingo, :url)
9
+ let(:config) { {default_region: :test} }
11
10
 
12
- expect(instance.scalingo).to eq(:scalingo)
13
- expect(instance.url).to eq(:url)
11
+ describe "with only url" do
12
+ subject { described_class.new(:url) }
13
+
14
+ it "stores the url" do
15
+ expect(subject.url).to eq(:url)
16
+ end
17
+
18
+ it "uses itself as token holder" do
19
+ expect(subject.token_holder).to eq(subject)
20
+ end
21
+
22
+ it "configuration is the global one" do
23
+ expect(Scalingo::Configuration).to receive(:new).with({}, Scalingo.config).and_return(:config).once
24
+
25
+ expect(subject.config).to eq(:config)
26
+ end
27
+ end
28
+
29
+ describe "with scalingo client supplied" do
30
+ subject { described_class.new(:url, scalingo: scalingo) }
31
+
32
+ it "uses the scalingo client as token holder" do
33
+ expect(subject.token_holder).to eq(scalingo)
34
+ end
35
+
36
+ it "configuration is herited from the scalingo client" do
37
+ expect(Scalingo::Configuration).to receive(:new).with({}, scalingo.config).once
38
+
39
+ subject
40
+ end
41
+ end
42
+
43
+ describe "with config supplied" do
44
+ subject { described_class.new(:url, config: config) }
45
+
46
+ it "configuration is herited from the global one" do
47
+ expect(Scalingo::Configuration).to receive(:new).with(config, Scalingo.config).and_return(:config).once
48
+
49
+ expect(subject.config).to eq(:config)
50
+ end
51
+ end
52
+
53
+ describe "with both supplied" do
54
+ subject { described_class.new(:url, scalingo: scalingo, config: config) }
55
+
56
+ it "configuration is herited from the scalingo one" do
57
+ expect(Scalingo::Configuration).to receive(:new).with(config, scalingo.config).once
58
+
59
+ subject
60
+ end
14
61
  end
15
62
  end
16
63
 
@@ -26,17 +73,17 @@ RSpec.describe Scalingo::API::Client do
26
73
  mock = double
27
74
 
28
75
  described_class.register_handler!(:handler, mock)
29
- instance = described_class.new(:scalingo, :url)
76
+ instance = described_class.new(:url, scalingo: scalingo)
30
77
 
31
78
  # Only 1 instanciation should be done, no matter how many calls are done below
32
79
  expect(mock).to receive(:new).with(instance).and_return("1st").once
33
80
 
34
81
  # Not yet loaded...
35
- expect(instance.instance_variable_get(:"@handler")).to eq(nil)
82
+ expect(instance.instance_variable_get(:@handler)).to eq(nil)
36
83
  instance.handler
37
84
 
38
85
  # Memoized...
39
- expect(instance.instance_variable_get(:"@handler")).not_to eq(nil)
86
+ expect(instance.instance_variable_get(:@handler)).not_to eq(nil)
40
87
 
41
88
  # More calls won't try to perform more instanciations
42
89
  instance.handler
@@ -55,20 +102,20 @@ RSpec.describe Scalingo::API::Client do
55
102
  proc { {"X-Another" => "another"} }
56
103
  }
57
104
 
58
- it "only returns the user agent if nothing else is configured" do
59
- expect(subject.headers).to eq("User-Agent" => user_agent)
105
+ it "only returns the user agent and accept if nothing else is configured" do
106
+ expect(subject.headers).to eq("Accept" => "application/json", "User-Agent" => user_agent)
60
107
  end
61
108
 
62
109
  it "allows additional headers to be globally configured" do
63
110
  expect(scalingo.config).to receive(:additional_headers).and_return(extra_hash)
64
111
 
65
- expect(subject.headers).to eq("User-Agent" => user_agent, "X-Other" => "other")
112
+ expect(subject.headers).to eq("Accept" => "application/json", "User-Agent" => user_agent, "X-Other" => "other")
66
113
  end
67
114
 
68
115
  it "additional headers can be a block" do
69
116
  expect(scalingo.config).to receive(:additional_headers).and_return(extra_block)
70
117
 
71
- expect(subject.headers).to eq("User-Agent" => user_agent, "X-Another" => "another")
118
+ expect(subject.headers).to eq("Accept" => "application/json", "User-Agent" => user_agent, "X-Another" => "another")
72
119
  end
73
120
  end
74
121
 
@@ -118,7 +165,7 @@ RSpec.describe Scalingo::API::Client do
118
165
 
119
166
  context "with bearer token" do
120
167
  it "has an authentication header set with a bearer scheme" do
121
- expect(subject.connection.headers["Authorization"]).to eq "Bearer #{subject.scalingo.token.value}"
168
+ expect(subject.connection.headers["Authorization"]).to eq "Bearer #{subject.token_holder.token.value}"
122
169
  end
123
170
  end
124
171
  end
@@ -21,10 +21,25 @@ RSpec.describe Scalingo::API::Endpoint do
21
21
  end
22
22
 
23
23
  describe "unpack" do
24
- it "forwards unpack to Response" do
25
- expect(Scalingo::API::Response).to receive(:unpack).with(client, :a, :b, :c).and_return(:d).once
24
+ it "forwards unpack to Response without keys" do
25
+ mock = proc { 1 }
26
26
 
27
- expect(subject.send(:unpack, :a, :b, :c)).to eq :d
27
+ expect(Scalingo::API::Response).to receive(:unpack).with(client, keys: [], &mock).and_return(:d).once
28
+ expect(subject.send(:unpack, &mock)).to eq :d
29
+ end
30
+
31
+ it "forwards unpack to Response with a single key" do
32
+ mock = proc { 1 }
33
+
34
+ expect(Scalingo::API::Response).to receive(:unpack).with(client, keys: [:a], &mock).and_return(:d).once
35
+ expect(subject.send(:unpack, :a, &mock)).to eq :d
36
+ end
37
+
38
+ it "forwards unpack to Response with many keys" do
39
+ mock = proc { 1 }
40
+
41
+ expect(Scalingo::API::Response).to receive(:unpack).with(client, keys: [:a, :b], &mock).and_return(:d).once
42
+ expect(subject.send(:unpack, :a, :b, &mock)).to eq :d
28
43
  end
29
44
  end
30
45
  end
@@ -33,19 +33,19 @@ RSpec.describe Scalingo::API::Response do
33
33
  }
34
34
 
35
35
  it "passes the client supplied" do
36
- object = described_class.unpack(:some_client, response)
36
+ object = described_class.unpack(:some_client) { response }
37
37
 
38
38
  expect(object.client).to eq :some_client
39
39
  end
40
40
 
41
41
  it "passes the response status" do
42
- object = described_class.unpack(:client, response)
42
+ object = described_class.unpack(:client) { response }
43
43
 
44
44
  expect(object.status).to eq status
45
45
  end
46
46
 
47
47
  it "passes the response headers" do
48
- object = described_class.unpack(:client, response)
48
+ object = described_class.unpack(:client) { response }
49
49
 
50
50
  expect(object.headers).to eq headers
51
51
  end
@@ -54,7 +54,7 @@ RSpec.describe Scalingo::API::Response do
54
54
  let(:body) { "" }
55
55
 
56
56
  it "without key" do
57
- object = described_class.unpack(client, response)
57
+ object = described_class.unpack(client) { response }
58
58
 
59
59
  expect(object.data).to eq ""
60
60
  expect(object.full_body).to eq ""
@@ -62,7 +62,7 @@ RSpec.describe Scalingo::API::Response do
62
62
  end
63
63
 
64
64
  it "ignores key if supplied" do
65
- object = described_class.unpack(client, response, key: :key)
65
+ object = described_class.unpack(client, key: :key) { response }
66
66
 
67
67
  expect(object.data).to eq ""
68
68
  expect(object.full_body).to eq ""
@@ -74,7 +74,7 @@ RSpec.describe Scalingo::API::Response do
74
74
  let(:body) { nil }
75
75
 
76
76
  it "without key" do
77
- object = described_class.unpack(client, response)
77
+ object = described_class.unpack(client) { response }
78
78
 
79
79
  expect(object.data).to eq nil
80
80
  expect(object.full_body).to eq nil
@@ -82,7 +82,7 @@ RSpec.describe Scalingo::API::Response do
82
82
  end
83
83
 
84
84
  it "ignores key if supplied" do
85
- object = described_class.unpack(client, response, key: :key)
85
+ object = described_class.unpack(client, key: :key) { response }
86
86
 
87
87
  expect(object.data).to eq nil
88
88
  expect(object.full_body).to eq nil
@@ -94,7 +94,7 @@ RSpec.describe Scalingo::API::Response do
94
94
  let(:body) { "this is a string body, probably due to an error" }
95
95
 
96
96
  it "without key" do
97
- object = described_class.unpack(client, response)
97
+ object = described_class.unpack(client) { response }
98
98
 
99
99
  expect(object.data).to eq body
100
100
  expect(object.full_body).to eq body
@@ -102,7 +102,7 @@ RSpec.describe Scalingo::API::Response do
102
102
  end
103
103
 
104
104
  it "ignores key if supplied" do
105
- object = described_class.unpack(client, response, key: :key)
105
+ object = described_class.unpack(client, key: :key) { response }
106
106
 
107
107
  expect(object.data).to eq body
108
108
  expect(object.full_body).to eq body
@@ -116,7 +116,7 @@ RSpec.describe Scalingo::API::Response do
116
116
  }
117
117
 
118
118
  it "without key" do
119
- object = described_class.unpack(client, response)
119
+ object = described_class.unpack(client) { response }
120
120
 
121
121
  expect(object.data).to eq body
122
122
  expect(object.full_body).to eq body
@@ -124,7 +124,7 @@ RSpec.describe Scalingo::API::Response do
124
124
  end
125
125
 
126
126
  it "ignores key if supplied" do
127
- object = described_class.unpack(client, response, key: :root)
127
+ object = described_class.unpack(client, key: :root) { response }
128
128
 
129
129
  expect(object.data).to eq body
130
130
  expect(object.full_body).to eq body
@@ -138,7 +138,7 @@ RSpec.describe Scalingo::API::Response do
138
138
  }
139
139
 
140
140
  it "without key" do
141
- object = described_class.unpack(client, response)
141
+ object = described_class.unpack(client) { response }
142
142
 
143
143
  expect(object.data).to eq body
144
144
  expect(object.full_body).to eq body
@@ -146,7 +146,7 @@ RSpec.describe Scalingo::API::Response do
146
146
  end
147
147
 
148
148
  it "with valid key" do
149
- object = described_class.unpack(client, response, key: :root)
149
+ object = described_class.unpack(client, key: :root) { response }
150
150
 
151
151
  expect(object.data).to eq({key: :value})
152
152
  expect(object.full_body).to eq body
@@ -154,7 +154,23 @@ RSpec.describe Scalingo::API::Response do
154
154
  end
155
155
 
156
156
  it "with invalid key" do
157
- object = described_class.unpack(client, response, key: :other)
157
+ object = described_class.unpack(client, key: :other) { response }
158
+
159
+ expect(object.data).to eq nil
160
+ expect(object.full_body).to eq body
161
+ expect(object.meta).to eq nil
162
+ end
163
+
164
+ it "with valid keys" do
165
+ object = described_class.unpack(client, keys: [:root, :key]) { response }
166
+
167
+ expect(object.data).to eq(:value)
168
+ expect(object.full_body).to eq body
169
+ expect(object.meta).to eq nil
170
+ end
171
+
172
+ it "with invalid keys" do
173
+ object = described_class.unpack(client, keys: [:root, :other]) { response }
158
174
 
159
175
  expect(object.data).to eq nil
160
176
  expect(object.full_body).to eq body
@@ -167,7 +183,7 @@ RSpec.describe Scalingo::API::Response do
167
183
  }
168
184
 
169
185
  it "extracts the meta object" do
170
- object = described_class.unpack(client, response)
186
+ object = described_class.unpack(client) { response }
171
187
 
172
188
  expect(object.meta).to eq({meta1: :value})
173
189
  end
@@ -179,7 +195,7 @@ RSpec.describe Scalingo::API::Response do
179
195
  let(:body) { {root: {key: :value}} }
180
196
 
181
197
  it "does not dig in the response hash, even with a valid key" do
182
- object = described_class.unpack(client, response, key: :root)
198
+ object = described_class.unpack(client, key: :root) { response }
183
199
 
184
200
  expect(object.data).to eq body
185
201
  expect(object.full_body).to eq body
@@ -22,4 +22,10 @@ RSpec.describe Scalingo::Auth::User do
22
22
  it_behaves_like "an unprocessable request"
23
23
  end
24
24
  end
25
+
26
+ describe_method "stop_free_trial" do
27
+ let(:stub_pattern) { "stop-free-trial" }
28
+
29
+ it_behaves_like "a successful response"
30
+ end
25
31
  end
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  RSpec.describe Scalingo::Auth do
4
- subject { described_class.new(:client, :url) }
4
+ subject { described_class.new("url") }
5
5
 
6
6
  %w[keys scm_integrations tokens two_factor_auth user].each do |section|
7
7
  it "handles requests for #{section}" do
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Scalingo::Billing do
4
+ subject { described_class.new("url") }
5
+
6
+ %w[profile].each do |section|
7
+ it "handles requests for #{section}" do
8
+ expect(subject.respond_to?(section)).to be true
9
+ end
10
+ end
11
+ end
@@ -51,7 +51,7 @@ RSpec.describe Scalingo::Client do
51
51
  context "with access token" do
52
52
  it "is successful with valid token" do
53
53
  fake_response = OpenStruct.new(
54
- "successful?": true,
54
+ successful?: true,
55
55
  data: {token: "response token"},
56
56
  )
57
57
 
@@ -64,7 +64,7 @@ RSpec.describe Scalingo::Client do
64
64
 
65
65
  it "fails with invalid token" do
66
66
  fake_response = OpenStruct.new(
67
- "successful?": false,
67
+ successful?: false,
68
68
  )
69
69
 
70
70
  expect(subject.auth.tokens).to receive(:exchange).and_return(fake_response)
@@ -3,36 +3,6 @@ require "spec_helper"
3
3
  RSpec.describe Scalingo::Configuration do
4
4
  subject { described_class.default }
5
5
 
6
- describe "default_region" do
7
- it "must be an existing region" do
8
- expect {
9
- subject.default_region = "another-region"
10
- }.to raise_error(ArgumentError)
11
- end
12
- end
13
-
14
- describe "regions" do
15
- it "can be assigned from a hash" do
16
- subject.regions = {
17
- local_name: "some-url"
18
- }
19
-
20
- expect(subject.regions.local_name).to eq "some-url"
21
- end
22
-
23
- it "can be assigned from a openstruct" do
24
- subject.regions = OpenStruct.new(local_name: "some-url")
25
-
26
- expect(subject.regions.local_name).to eq "some-url"
27
- end
28
-
29
- it "raises with an argument from the wrong type" do
30
- expect {
31
- subject.regions = "1"
32
- }.to raise_error(ArgumentError)
33
- end
34
- end
35
-
36
6
  describe "inheritance" do
37
7
  it "can inherit configuration from a parent" do
38
8
  object = described_class.new({}, subject)
@@ -52,4 +22,36 @@ RSpec.describe Scalingo::Configuration do
52
22
  expect(object.user_agent).to eq "Agent"
53
23
  end
54
24
  end
25
+
26
+ describe "faraday adapter" do
27
+ let(:scalingo) { Scalingo::Client.new(config).tap { |s| s.authenticate_with(bearer_token: "some-token") } }
28
+ let(:client) { Scalingo::API::Client.new("http://example.test", scalingo: scalingo) }
29
+
30
+ context "when unspecified" do
31
+ let(:config) { {} }
32
+
33
+ it "uses the default one when unspecificied" do
34
+ expect(client.authenticated_connection.adapter).to eq Faraday::Adapter::NetHttp
35
+ expect(client.unauthenticated_connection.adapter).to eq Faraday::Adapter::NetHttp
36
+ end
37
+ end
38
+
39
+ context "when set to an unkown adapter" do
40
+ let(:config) { {faraday_adapter: :yo} }
41
+
42
+ it "uses the default one when unspecificied" do
43
+ expect { client.authenticated_connection.adapter }.to raise_error(Faraday::Error)
44
+ expect { client.unauthenticated_connection.adapter }.to raise_error(Faraday::Error)
45
+ end
46
+ end
47
+
48
+ context "when set to a valid adapter" do
49
+ let(:config) { {faraday_adapter: :test} }
50
+
51
+ it "uses the default one when unspecificied" do
52
+ expect(client.authenticated_connection.adapter).to eq Faraday::Adapter::Test
53
+ expect(client.unauthenticated_connection.adapter).to eq Faraday::Adapter::Test
54
+ end
55
+ end
56
+ end
55
57
  end
@@ -99,6 +99,22 @@ RSpec.describe Scalingo::Regional::Addons do
99
99
  end
100
100
  end
101
101
 
102
+ describe_method "token" do
103
+ context "success" do
104
+ let(:arguments) { [meta[:app_id], meta[:id]] }
105
+ let(:stub_pattern) { "token-200" }
106
+
107
+ it_behaves_like "a singular object response"
108
+ end
109
+
110
+ context "not found" do
111
+ let(:arguments) { [meta[:app_id], meta[:not_found_id]] }
112
+ let(:stub_pattern) { "token-404" }
113
+
114
+ it_behaves_like "a not found response"
115
+ end
116
+ end
117
+
102
118
  describe_method "update" do
103
119
  context "success" do
104
120
  let(:arguments) { [meta[:app_id], meta[:id], meta[:update][:valid]] }