auth0 5.8.1 → 5.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.bundle/config +2 -1
- data/.circleci/config.yml +6 -4
- data/.devcontainer/Dockerfile +19 -0
- data/.devcontainer/devcontainer.json +37 -0
- data/CHANGELOG.md +24 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +52 -80
- data/auth0.gemspec +2 -2
- data/examples/ruby-api/Gemfile +3 -2
- data/examples/ruby-api/Gemfile.lock +32 -0
- data/examples/ruby-api/README.md +2 -2
- data/lib/auth0/api/authentication_endpoints.rb +0 -2
- data/lib/auth0/api/v2/connections.rb +6 -3
- data/lib/auth0/api/v2/device_credentials.rb +1 -1
- data/lib/auth0/api/v2/jobs.rb +15 -4
- data/lib/auth0/api/v2/organizations.rb +1 -1
- data/lib/auth0/api/v2/users.rb +10 -1
- data/lib/auth0/mixins/httpproxy.rb +11 -12
- data/lib/auth0/mixins/token_management.rb +1 -1
- data/lib/auth0/version.rb +1 -1
- data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Clients/_patch_client/should_update_the_client_with_the_correct_attributes.yml +2 -1
- data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Connections/_update_connection/should_update_the_connection.yml +1 -1
- data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Rules/_update_rule/should_update_the_disabled_rule_to_be_enabled.yml +1 -1
- data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Tenants/_update_tenant_settings/should_revert_the_tenant_name.yml +1 -1
- data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Tenants/_update_tenant_settings/should_update_the_tenant_settings_with_a_new_tenant_name.yml +1 -1
- data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Users/_add_user_roles/should_add_a_Role_to_a_User_successfully.yml +1 -1
- data/spec/fixtures/vcr_cassettes/Auth0_Api_V2_Users/_patch_user/should_patch_the_User_successfully.yml +1 -1
- data/spec/lib/auth0/api/v2/connections_spec.rb +24 -4
- data/spec/lib/auth0/api/v2/jobs_spec.rb +18 -0
- data/spec/lib/auth0/api/v2/users_spec.rb +15 -0
- data/spec/lib/auth0/mixins/httpproxy_spec.rb +53 -17
- data/spec/lib/auth0/mixins/token_management_spec.rb +2 -7
- data/spec/spec_helper.rb +6 -2
- metadata +14 -241
@@ -8,11 +8,12 @@ module Auth0
|
|
8
8
|
# for now, if you want to feel free to use your own http client
|
9
9
|
module HTTPProxy
|
10
10
|
attr_accessor :headers, :base_uri, :timeout, :retry_count
|
11
|
-
|
11
|
+
DEFAULT_RETRIES = 3
|
12
12
|
MAX_ALLOWED_RETRIES = 10
|
13
13
|
MAX_REQUEST_RETRY_JITTER = 250
|
14
14
|
MAX_REQUEST_RETRY_DELAY = 1000
|
15
|
-
MIN_REQUEST_RETRY_DELAY =
|
15
|
+
MIN_REQUEST_RETRY_DELAY = 250
|
16
|
+
BASE_DELAY = 100
|
16
17
|
|
17
18
|
# proxying requests from instance methods to HTTP class methods
|
18
19
|
%i(get post post_file put patch delete delete_with_body).each do |method|
|
@@ -26,14 +27,14 @@ module Auth0
|
|
26
27
|
|
27
28
|
def retry_options
|
28
29
|
sleep_timer = lambda do |attempt|
|
29
|
-
wait =
|
30
|
-
wait += rand(wait..wait+MAX_REQUEST_RETRY_JITTER) # Add jitter to the delay window.
|
30
|
+
wait = BASE_DELAY * (2**attempt-1) # Exponential delay with each subsequent request attempt.
|
31
|
+
wait += rand(wait+1..wait+MAX_REQUEST_RETRY_JITTER) # Add jitter to the delay window.
|
31
32
|
wait = [MAX_REQUEST_RETRY_DELAY, wait].min # Cap delay at MAX_REQUEST_RETRY_DELAY.
|
32
33
|
wait = [MIN_REQUEST_RETRY_DELAY, wait].max # Ensure delay is no less than MIN_REQUEST_RETRY_DELAY.
|
33
34
|
wait / 1000.to_f.round(2) # convert ms to seconds
|
34
35
|
end
|
35
36
|
|
36
|
-
tries = 1 + [Integer(retry_count ||
|
37
|
+
tries = 1 + [Integer(retry_count || DEFAULT_RETRIES), MAX_ALLOWED_RETRIES].min # Cap retries at MAX_ALLOWED_RETRIES
|
37
38
|
|
38
39
|
{
|
39
40
|
tries: tries,
|
@@ -72,15 +73,13 @@ module Auth0
|
|
72
73
|
|
73
74
|
def request(method, uri, body = {}, extra_headers = {})
|
74
75
|
result = if method == :get
|
75
|
-
|
76
|
-
|
77
|
-
# Merge custom headers into existing ones for this req.
|
78
|
-
# This prevents future calls from using them.
|
79
|
-
get_headers = headers.merge extra_headers
|
80
|
-
# Make the call with extra_headers, if provided.
|
76
|
+
@headers ||= {}
|
77
|
+
get_headers = @headers.merge({params: body}).merge(extra_headers)
|
81
78
|
call(:get, encode_uri(uri), timeout, get_headers)
|
82
79
|
elsif method == :delete
|
83
|
-
|
80
|
+
@headers ||= {}
|
81
|
+
delete_headers = @headers.merge({ params: body })
|
82
|
+
call(:delete, encode_uri(uri), timeout, delete_headers)
|
84
83
|
elsif method == :delete_with_body
|
85
84
|
call(:delete, encode_uri(uri), timeout, headers, body.to_json)
|
86
85
|
elsif method == :post_file
|
@@ -6,7 +6,6 @@ module Auth0
|
|
6
6
|
|
7
7
|
def initialize_token(options)
|
8
8
|
@token = options[:access_token] || options[:token]
|
9
|
-
|
10
9
|
# default expiry to an hour if a token was given but no expires_at
|
11
10
|
@token_expires_at = @token ? options[:token_expires_at] || Time.now.to_i + 3600 : nil
|
12
11
|
|
@@ -15,6 +14,7 @@ module Auth0
|
|
15
14
|
end
|
16
15
|
|
17
16
|
def get_token
|
17
|
+
# pp @token_expires_at
|
18
18
|
has_expired = @token && @token_expires_at ? @token_expires_at < (Time.now.to_i + 10) : false
|
19
19
|
|
20
20
|
if (@token.nil? || has_expired) && @client_id && @client_secret
|
data/lib/auth0/version.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: patch
|
5
|
-
uri: https://auth0-sdk-tests.auth0.com/api/v2/clients/SftKo9ySyHnMPezQUFd0C70GBoNFM21F
|
5
|
+
uri: https://auth0-sdk-tests.auth0.com/api/v2/clients/SftKo9ySyHnMPezQUFd0C70GBoNFM21F
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
8
|
string: '{"custom_login_page_on":false,"sso":true}'
|
@@ -12,6 +12,7 @@ http_interactions:
|
|
12
12
|
User-Agent:
|
13
13
|
- rest-client/2.1.0 (darwin19.6.0 x86_64) ruby/2.7.0p0
|
14
14
|
Content-Type:
|
15
|
+
|
15
16
|
- application/json
|
16
17
|
Auth0-Client:
|
17
18
|
- eyJuYW1lIjoicnVieS1hdXRoMCIsInZlcnNpb24iOiI1LjUuMCIsImVudiI6eyJydWJ5IjoiMi43LjAifX0=
|
@@ -2,7 +2,7 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: patch
|
5
|
-
uri: https://auth0-sdk-tests.auth0.com/api/v2/connections/con_WltM0fv20JCnxOuY
|
5
|
+
uri: https://auth0-sdk-tests.auth0.com/api/v2/connections/con_WltM0fv20JCnxOuY
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
8
|
string: '{"options":{"mfa":{"active":true,"return_enroll_settings":true},"passwordPolicy":"excellent","strategy_version":2,"brute_force_protection":true}}'
|
@@ -2,7 +2,7 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: patch
|
5
|
-
uri: https://auth0-sdk-tests.auth0.com/api/v2/rules/rul_bsg64xEPZz4WOkXz
|
5
|
+
uri: https://auth0-sdk-tests.auth0.com/api/v2/rules/rul_bsg64xEPZz4WOkXz
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
8
|
string: '{"enabled":true}'
|
@@ -2,7 +2,7 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: patch
|
5
|
-
uri: https://auth0-sdk-tests.auth0.com/api/v2/tenants/settings
|
5
|
+
uri: https://auth0-sdk-tests.auth0.com/api/v2/tenants/settings
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
8
|
string: '{"friendly_name":"Auth0"}'
|
@@ -2,7 +2,7 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: patch
|
5
|
-
uri: https://auth0-sdk-tests.auth0.com/api/v2/tenants/settings
|
5
|
+
uri: https://auth0-sdk-tests.auth0.com/api/v2/tenants/settings
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
8
|
string: '{"friendly_name":"Auth0-CHANGED"}'
|
@@ -2,7 +2,7 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: post
|
5
|
-
uri: https://auth0-sdk-tests.auth0.com/api/v2/users/auth0%7C613282adac819400692c0dd9/roles
|
5
|
+
uri: https://auth0-sdk-tests.auth0.com/api/v2/users/auth0%7C613282adac819400692c0dd9/roles
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
8
|
string: '{"roles":["rol_2VZOCes8HgBar3Tp"]}'
|
@@ -2,7 +2,7 @@
|
|
2
2
|
http_interactions:
|
3
3
|
- request:
|
4
4
|
method: patch
|
5
|
-
uri: https://auth0-sdk-tests.auth0.com/api/v2/users/auth0%7C613282adac819400692c0dd9
|
5
|
+
uri: https://auth0-sdk-tests.auth0.com/api/v2/users/auth0%7C613282adac819400692c0dd9
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
8
|
string: '{"email_verified":true,"user_metadata":{"addresses":{"home_address":"742
|
@@ -18,7 +18,8 @@ describe Auth0::Api::V2::Connections do
|
|
18
18
|
fields: nil,
|
19
19
|
include_fields: nil,
|
20
20
|
page: nil,
|
21
|
-
per_page: nil
|
21
|
+
per_page: nil,
|
22
|
+
include_totals: nil
|
22
23
|
})
|
23
24
|
expect { @instance.connections }.not_to raise_error
|
24
25
|
end
|
@@ -31,7 +32,8 @@ describe Auth0::Api::V2::Connections do
|
|
31
32
|
strategy: nil,
|
32
33
|
name: nil,
|
33
34
|
page: nil,
|
34
|
-
per_page: nil
|
35
|
+
per_page: nil,
|
36
|
+
include_totals: nil
|
35
37
|
})
|
36
38
|
expect {
|
37
39
|
@instance.connections(fields: 'name', include_fields: true)
|
@@ -46,7 +48,8 @@ describe Auth0::Api::V2::Connections do
|
|
46
48
|
strategy: nil,
|
47
49
|
name: nil,
|
48
50
|
page: nil,
|
49
|
-
per_page: nil
|
51
|
+
per_page: nil,
|
52
|
+
include_totals: nil
|
50
53
|
})
|
51
54
|
expect {
|
52
55
|
@instance.connections(fields: ['name','strategy'], include_fields: true)
|
@@ -61,12 +64,29 @@ describe Auth0::Api::V2::Connections do
|
|
61
64
|
strategy: nil,
|
62
65
|
name: nil,
|
63
66
|
fields: nil,
|
64
|
-
include_fields: nil
|
67
|
+
include_fields: nil,
|
68
|
+
include_totals: nil
|
65
69
|
})
|
66
70
|
expect {
|
67
71
|
@instance.connections(page: 1, per_page: 10)
|
68
72
|
}.not_to raise_error
|
69
73
|
end
|
74
|
+
|
75
|
+
it 'is expected to include totals' do
|
76
|
+
expect(@instance).to receive(:get).with(
|
77
|
+
'/api/v2/connections', {
|
78
|
+
page: 1,
|
79
|
+
per_page: 10,
|
80
|
+
strategy: nil,
|
81
|
+
name: nil,
|
82
|
+
fields: nil,
|
83
|
+
include_fields: nil,
|
84
|
+
include_totals: true
|
85
|
+
})
|
86
|
+
expect {
|
87
|
+
@instance.connections(page: 1, per_page: 10, include_totals: true)
|
88
|
+
}.not_to raise_error
|
89
|
+
end
|
70
90
|
end
|
71
91
|
|
72
92
|
context '.create_connection' do
|
@@ -67,6 +67,7 @@ describe Auth0::Api::V2::Jobs do
|
|
67
67
|
format: 'csv',
|
68
68
|
limit: 10
|
69
69
|
})
|
70
|
+
|
70
71
|
@instance.export_users(
|
71
72
|
fields: ['author'],
|
72
73
|
connection_id: 'test-connection',
|
@@ -74,6 +75,23 @@ describe Auth0::Api::V2::Jobs do
|
|
74
75
|
limit: 10
|
75
76
|
)
|
76
77
|
end
|
78
|
+
|
79
|
+
it 'sends post to /api/v2/jobs/users-exports with export_as field' do
|
80
|
+
expect(@instance).to receive(:post).with(
|
81
|
+
'/api/v2/jobs/users-exports', {
|
82
|
+
fields: [{ name: 'author', export_as: 'writer' }],
|
83
|
+
connection_id: 'test-connection',
|
84
|
+
format: 'csv',
|
85
|
+
limit: 10
|
86
|
+
})
|
87
|
+
|
88
|
+
@instance.export_users(
|
89
|
+
fields: [{ name: 'author', export_as: 'writer' }],
|
90
|
+
connection_id: 'test-connection',
|
91
|
+
format: 'csv',
|
92
|
+
limit: 10
|
93
|
+
)
|
94
|
+
end
|
77
95
|
end
|
78
96
|
|
79
97
|
context '.send_verification_email' do
|
@@ -139,6 +139,21 @@ describe Auth0::Api::V2::Users do
|
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
142
|
+
context '.delete_user_authenticators' do
|
143
|
+
it 'is expected to respond to a delete_user_authenticators method' do
|
144
|
+
expect(@instance).to respond_to(:delete_user_authenticators)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'is expected to delete /api/v2/users/userId/authenticators' do
|
148
|
+
expect(@instance).to receive(:delete).with('/api/v2/users/USER_ID/authenticators')
|
149
|
+
@instance.delete_user_authenticators('USER_ID')
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'is expected to raise an exception when the user ID is empty' do
|
153
|
+
expect { @instance.delete_user_authenticators(nil) }.to raise_exception(Auth0::MissingUserId)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
142
157
|
context '.delete_user_provider' do
|
143
158
|
it 'is expected to respond to a delete_user_provider method' do
|
144
159
|
expect(@instance).to respond_to(:delete_user_provider)
|
@@ -494,12 +494,13 @@ describe Auth0::Mixins::HTTPProxy do
|
|
494
494
|
end
|
495
495
|
|
496
496
|
context "Renewing tokens" do
|
497
|
-
|
498
|
-
|
497
|
+
let(:httpproxy_instance) {
|
498
|
+
DummyClassForTokens.new(
|
499
499
|
client_id: 'test-client-id',
|
500
500
|
client_secret: 'test-client-secret',
|
501
|
-
domain: 'auth0.com'
|
502
|
-
|
501
|
+
domain: 'auth0.com',
|
502
|
+
)
|
503
|
+
}
|
503
504
|
|
504
505
|
%i(get delete).each do |http_method|
|
505
506
|
context "for #{http_method}" do
|
@@ -507,7 +508,7 @@ describe Auth0::Mixins::HTTPProxy do
|
|
507
508
|
expect(RestClient::Request).to receive(:execute).with(hash_including(
|
508
509
|
method: :post,
|
509
510
|
url: 'https://auth0.com/oauth/token',
|
510
|
-
)
|
511
|
+
)).and_return(StubResponse.new({
|
511
512
|
"access_token" => "access_token",
|
512
513
|
"expires_in" => 86400},
|
513
514
|
true,
|
@@ -515,11 +516,10 @@ describe Auth0::Mixins::HTTPProxy do
|
|
515
516
|
|
516
517
|
expect(RestClient::Request).to receive(:execute).with(hash_including(
|
517
518
|
method: http_method,
|
518
|
-
url: 'https://auth0.com/test'
|
519
|
-
headers: { params: {}, "Authorization" => "Bearer access_token" }
|
519
|
+
url: 'https://auth0.com/test'
|
520
520
|
)).and_return(StubResponse.new('Some random text here', true, 200))
|
521
521
|
|
522
|
-
expect {
|
522
|
+
expect { httpproxy_instance.send(http_method, '/test') }.not_to raise_error
|
523
523
|
end
|
524
524
|
end
|
525
525
|
end
|
@@ -539,24 +539,24 @@ describe Auth0::Mixins::HTTPProxy do
|
|
539
539
|
expect(RestClient::Request).to receive(:execute).with(hash_including(
|
540
540
|
method: http_method,
|
541
541
|
url: 'https://auth0.com/test',
|
542
|
-
headers:
|
542
|
+
headers: hash_including( "Authorization" => "Bearer access_token")
|
543
543
|
)).and_return(StubResponse.new('Some random text here', true, 200))
|
544
544
|
|
545
|
-
expect {
|
545
|
+
expect { httpproxy_instance.send(http_method, '/test') }.not_to raise_error
|
546
546
|
end
|
547
547
|
end
|
548
548
|
end
|
549
549
|
end
|
550
550
|
|
551
551
|
context "Using cached tokens" do
|
552
|
-
|
553
|
-
|
552
|
+
let(:httpproxy_instance) {
|
553
|
+
DummyClassForTokens.new(
|
554
554
|
client_id: 'test-client-id',
|
555
555
|
client_secret: 'test-client-secret',
|
556
556
|
domain: 'auth0.com',
|
557
557
|
token: 'access_token',
|
558
558
|
token_expires_at: Time.now.to_i + 86400)
|
559
|
-
|
559
|
+
}
|
560
560
|
|
561
561
|
%i(get delete).each do |http_method|
|
562
562
|
context "for #{http_method}" do
|
@@ -569,10 +569,10 @@ describe Auth0::Mixins::HTTPProxy do
|
|
569
569
|
expect(RestClient::Request).to receive(:execute).with(hash_including(
|
570
570
|
method: http_method,
|
571
571
|
url: 'https://auth0.com/test',
|
572
|
-
headers:
|
572
|
+
headers: hash_including(params: {}, "Authorization" => "Bearer access_token")
|
573
573
|
)).and_return(StubResponse.new('Some random text here', true, 200))
|
574
574
|
|
575
|
-
expect {
|
575
|
+
expect { httpproxy_instance.send(http_method, '/test') }.not_to raise_error
|
576
576
|
end
|
577
577
|
end
|
578
578
|
end
|
@@ -588,10 +588,46 @@ describe Auth0::Mixins::HTTPProxy do
|
|
588
588
|
expect(RestClient::Request).to receive(:execute).with(hash_including(
|
589
589
|
method: http_method,
|
590
590
|
url: 'https://auth0.com/test',
|
591
|
-
headers:
|
591
|
+
headers: hash_including("Authorization" => "Bearer access_token")
|
592
592
|
)).and_return(StubResponse.new('Some random text here', true, 200))
|
593
593
|
|
594
|
-
expect {
|
594
|
+
expect { httpproxy_instance.send(http_method, '/test') }.not_to raise_error
|
595
|
+
end
|
596
|
+
end
|
597
|
+
end
|
598
|
+
end
|
599
|
+
|
600
|
+
context 'Normal operation' do
|
601
|
+
let(:httpproxy_instance) {
|
602
|
+
DummyClassForTokens.new(
|
603
|
+
client_id: 'test-client-id',
|
604
|
+
client_secret: 'test-client-secret',
|
605
|
+
domain: 'auth0.com',
|
606
|
+
token: 'access_token',
|
607
|
+
token_expires_at: Time.now.to_i + 86400)
|
608
|
+
}
|
609
|
+
|
610
|
+
# This sets up a test matrix to verify that both :get and :delete calls (the only two HTTP methods in the proxy that mutated headers)
|
611
|
+
# don't bleed query params into subsequent calls to :post :patch and :put.
|
612
|
+
%i(get delete).each do |http_get_delete|
|
613
|
+
%i(post patch put).each do |http_ppp|
|
614
|
+
it "should not bleed :#{http_get_delete} headers/parameters to the subsequent :#{http_ppp} request" do
|
615
|
+
expect(RestClient::Request).to receive(:execute).with(hash_including(
|
616
|
+
method: http_get_delete,
|
617
|
+
url: "https://auth0.com/test-#{http_get_delete}",
|
618
|
+
headers: hash_including(params: { email: 'test@test.com' })
|
619
|
+
)).and_return(StubResponse.new('OK', true, 200))
|
620
|
+
|
621
|
+
# email: parameter that is sent in the GET request should not appear
|
622
|
+
# as a parameter in the `headers` hash for the subsequent PATCH request.
|
623
|
+
expect(RestClient::Request).to receive(:execute).with(hash_including(
|
624
|
+
method: http_ppp,
|
625
|
+
url: "https://auth0.com/test-#{http_ppp}",
|
626
|
+
headers: hash_not_including(:params)
|
627
|
+
)).and_return(StubResponse.new('OK', true, 200))
|
628
|
+
|
629
|
+
expect { httpproxy_instance.send(http_get_delete, "/test-#{http_get_delete}", { email: 'test@test.com' }) }.not_to raise_error
|
630
|
+
expect { httpproxy_instance.send(http_ppp, "/test-#{http_ppp}") }.not_to raise_error
|
595
631
|
end
|
596
632
|
end
|
597
633
|
end
|
@@ -110,16 +110,11 @@ describe Auth0::Mixins::TokenManagement do
|
|
110
110
|
|
111
111
|
it 'does not renew existing token if no token_expires_at' do
|
112
112
|
params[:token] = 'test-token'
|
113
|
+
instance.instance_variable_set '@token_expires_at', nil
|
113
114
|
|
114
|
-
expect(RestClient::Request).not_to receive(:execute)
|
115
|
-
method: :post,
|
116
|
-
url: 'https://samples.auth0.com/oauth/token',
|
117
|
-
))
|
115
|
+
expect(RestClient::Request).not_to receive(:execute)
|
118
116
|
|
119
117
|
instance.send(:get_token)
|
120
|
-
|
121
|
-
expect(instance.instance_variable_get('@token')).to eq('test-token')
|
122
|
-
expect(instance.instance_variable_get('@token_expires_at')).to be_nil
|
123
118
|
end
|
124
119
|
end
|
125
120
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -13,8 +13,8 @@ require 'simplecov'
|
|
13
13
|
SimpleCov.start
|
14
14
|
|
15
15
|
if ENV['CI'] == 'true'
|
16
|
-
require '
|
17
|
-
SimpleCov.formatter = SimpleCov::Formatter::
|
16
|
+
require 'simplecov-cobertura'
|
17
|
+
SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter
|
18
18
|
end
|
19
19
|
|
20
20
|
require 'dotenv'
|
@@ -51,6 +51,10 @@ RSpec.configure do |config|
|
|
51
51
|
config.filter_run focus: true
|
52
52
|
config.run_all_when_everything_filtered = true
|
53
53
|
config.include Credentials
|
54
|
+
|
55
|
+
config.expect_with :rspec do |c|
|
56
|
+
c.max_formatted_output_length = 1000000
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
60
|
def wait(time, increment = 5, elapsed_time = 0, &block)
|