gandi_v5 0.1.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +14 -4
- data/.travis.yml +16 -1
- data/CHANGELOG.md +80 -2
- data/FUNDING.yml +10 -0
- data/Guardfile +5 -6
- data/LICENSE.md +2 -6
- data/README.md +17 -23
- data/gandi_v5.gemspec +4 -3
- data/lib/gandi_v5.rb +54 -15
- data/lib/gandi_v5/billing.rb +2 -4
- data/lib/gandi_v5/billing/info.rb +0 -2
- data/lib/gandi_v5/data.rb +1 -2
- data/lib/gandi_v5/data/converter.rb +0 -4
- data/lib/gandi_v5/data/converter/integer.rb +26 -0
- data/lib/gandi_v5/domain.rb +201 -101
- data/lib/gandi_v5/domain/auto_renew.rb +4 -4
- data/lib/gandi_v5/domain/availability.rb +46 -0
- data/lib/gandi_v5/domain/availability/product.rb +49 -0
- data/lib/gandi_v5/domain/availability/product/period.rb +24 -0
- data/lib/gandi_v5/domain/availability/product/price.rb +36 -0
- data/lib/gandi_v5/domain/availability/tax.rb +20 -0
- data/lib/gandi_v5/domain/live_dns.rb +42 -0
- data/lib/gandi_v5/domain/renewal_information.rb +0 -3
- data/lib/gandi_v5/domain/sharing_space.rb +10 -2
- data/lib/gandi_v5/domain/tld.rb +57 -0
- data/lib/gandi_v5/email.rb +0 -4
- data/lib/gandi_v5/email/forward.rb +108 -0
- data/lib/gandi_v5/email/mailbox.rb +85 -24
- data/lib/gandi_v5/email/mailbox/responder.rb +43 -2
- data/lib/gandi_v5/email/offer.rb +2 -2
- data/lib/gandi_v5/email/slot.rb +52 -18
- data/lib/gandi_v5/error.rb +0 -2
- data/lib/gandi_v5/error/gandi_error.rb +2 -2
- data/lib/gandi_v5/live_dns.rb +20 -4
- data/lib/gandi_v5/live_dns/domain.rb +21 -150
- data/lib/gandi_v5/live_dns/has_zone_records.rb +153 -0
- data/lib/gandi_v5/live_dns/record_set.rb +1 -1
- data/lib/gandi_v5/live_dns/zone.rb +24 -165
- data/lib/gandi_v5/live_dns/zone/snapshot.rb +27 -8
- data/lib/gandi_v5/organization.rb +39 -6
- data/lib/gandi_v5/organization/customer.rb +90 -0
- data/lib/gandi_v5/version.rb +1 -1
- data/spec/.rubocop.yml +9 -2
- data/spec/features/domain_spec.rb +2 -2
- data/spec/features/livedns_zone_spec.rb +12 -13
- data/spec/fixtures/bodies/GandiV5_Billing/{info.yaml → info.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_Domain/{get.yaml → fetch.yml} +8 -0
- data/spec/fixtures/bodies/GandiV5_Domain/{fetch_contacts.yaml → fetch_contacts.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_Domain/fetch_glue_records.yml +7 -0
- data/spec/fixtures/bodies/GandiV5_Domain/fetch_livedns.yml +6 -0
- data/spec/fixtures/bodies/GandiV5_Domain/fetch_name_servers.yml +2 -0
- data/spec/fixtures/bodies/GandiV5_Domain/{renewal_info.yaml → fetch_renewal_info.yml} +0 -3
- data/spec/fixtures/bodies/GandiV5_Domain/{restore_info.yaml → fetch_restore_info.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_Domain/{list.yaml → list.yml} +1 -0
- data/spec/fixtures/bodies/{GandiV5_Domain/availability.yaml → GandiV5_Domain_Availability/fetch.yml} +0 -0
- data/spec/fixtures/bodies/{GandiV5_Domain/tld.yaml → GandiV5_Domain_TLD/fetch.yml} +0 -0
- data/spec/fixtures/bodies/{GandiV5_Domain/tlds.yaml → GandiV5_Domain_TLD/list.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_Email_Forward/list.yml +6 -0
- data/spec/fixtures/bodies/GandiV5_Email_Mailbox/{get.yaml → fetch.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_Email_Mailbox/{list.yaml → list.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_Email_Slot/{get.yaml → fetch.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_Email_Slot/{list.yaml → list.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/{get.yaml → fetch.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/{list.yaml → list.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/{get.yaml → fetch.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/{list.yaml → list.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/{get.yaml → fetch.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/list.yml +3 -0
- data/spec/fixtures/bodies/GandiV5_Organization/{get.yaml → fetch.yml} +0 -0
- data/spec/fixtures/bodies/GandiV5_Organization/list.yml +7 -0
- data/spec/fixtures/bodies/GandiV5_Organization_Customer/list.yml +8 -0
- data/spec/fixtures/vcr/Domain_features/List_domains.yml +2 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/units/gandi_v5/billing_spec.rb +4 -4
- data/spec/units/gandi_v5/data/converter/integer_spec.rb +16 -0
- data/spec/units/gandi_v5/domain/auto_renew_spec.rb +5 -5
- data/spec/units/gandi_v5/domain/availability/product/period_spec.rb +4 -0
- data/spec/units/gandi_v5/domain/availability/product/price_spec.rb +4 -0
- data/spec/units/gandi_v5/domain/availability/product_spec.rb +4 -0
- data/spec/units/gandi_v5/domain/availability/tax_spec.rb +4 -0
- data/spec/units/gandi_v5/domain/availability_spec.rb +43 -0
- data/spec/units/gandi_v5/domain/live_dns_spec.rb +45 -0
- data/spec/units/gandi_v5/domain/tld_spec.rb +29 -0
- data/spec/units/gandi_v5/domain_spec.rb +359 -91
- data/spec/units/gandi_v5/email/forward_spec.rb +121 -0
- data/spec/units/gandi_v5/email/mailbox/responder_spec.rb +52 -0
- data/spec/units/gandi_v5/email/mailbox_spec.rb +174 -33
- data/spec/units/gandi_v5/email/offer_spec.rb +1 -1
- data/spec/units/gandi_v5/email/slot_spec.rb +113 -17
- data/spec/units/gandi_v5/live_dns/domain_spec.rb +73 -43
- data/spec/units/gandi_v5/live_dns/zone/snapshot_spec.rb +32 -3
- data/spec/units/gandi_v5/live_dns/zone_spec.rb +70 -52
- data/spec/units/gandi_v5/live_dns_spec.rb +24 -0
- data/spec/units/gandi_v5/organization/customer_spec.rb +81 -0
- data/spec/units/gandi_v5/organization_spec.rb +52 -1
- data/spec/units/gandi_v5_spec.rb +56 -19
- metadata +71 -29
- data/TODO.md +0 -29
@@ -28,32 +28,51 @@ class GandiV5
|
|
28
28
|
|
29
29
|
# Delete this snapshot.
|
30
30
|
# @return [String] The confirmation message from Gandi.
|
31
|
-
# @raise [GandiV5::Error::GandiError
|
31
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
32
32
|
def delete
|
33
|
-
data = GandiV5.delete url
|
33
|
+
_response, data = GandiV5.delete url
|
34
34
|
data['message']
|
35
35
|
end
|
36
36
|
|
37
|
+
# @see GandiV5::LiveDNS::Zone.fetch
|
38
|
+
def fetch_zone
|
39
|
+
GandiV5::LiveDNS::Zone.fetch zone_uuid
|
40
|
+
end
|
41
|
+
|
42
|
+
# The snapshot's zone (fetching from Gandi if required).
|
43
|
+
# @return [GandiV5::LiveDNS::Zone]
|
44
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
45
|
+
def zone
|
46
|
+
@zone ||= fetch_zone
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get snapshot UUIDs for this zone from Gandi.
|
50
|
+
# @return [Hash{String => Time}] Mapping UUID to time made.
|
51
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
52
|
+
def self.list(zone_uuid)
|
53
|
+
_response, data = GandiV5.get url(zone_uuid)
|
54
|
+
Hash[data.map { |snapshot| [snapshot['uuid'], Time.parse(snapshot['date_created'])] }]
|
55
|
+
end
|
56
|
+
|
37
57
|
# Get snapshot from Gandi.
|
38
58
|
# @param zone_uuid [String, #to_s] the UUID of the zone the snapshot was made of.
|
39
59
|
# @param snapshot_uuid [String, #to_s] the UUID of the snapshot to fetch.
|
40
60
|
# @return [GandiV5::LiveDNS::Zone::Snapshot]
|
41
|
-
# @raise [GandiV5::Error::GandiError
|
61
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
42
62
|
def self.fetch(zone_uuid, snapshot_uuid)
|
43
|
-
data = GandiV5.get url(zone_uuid, snapshot_uuid)
|
63
|
+
_response, data = GandiV5.get url(zone_uuid, snapshot_uuid)
|
44
64
|
from_gandi data
|
45
65
|
end
|
46
66
|
|
47
|
-
# TODO: Move listing snapshots to here
|
48
|
-
|
49
67
|
private
|
50
68
|
|
51
69
|
def url
|
52
70
|
"#{BASE}zones/#{CGI.escape zone_uuid}/snapshots/#{CGI.escape uuid}"
|
53
71
|
end
|
54
72
|
|
55
|
-
def self.url(zone_uuid, snapshot_uuid)
|
56
|
-
"#{BASE}zones/#{CGI.escape zone_uuid}/snapshots
|
73
|
+
def self.url(zone_uuid, snapshot_uuid = nil)
|
74
|
+
"#{BASE}zones/#{CGI.escape zone_uuid}/snapshots" +
|
75
|
+
(snapshot_uuid ? "/#{CGI.escape snapshot_uuid}" : '')
|
57
76
|
end
|
58
77
|
private_class_method :url
|
59
78
|
end
|
@@ -1,9 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'email/mailbox'
|
4
|
-
require_relative 'email/offer'
|
5
|
-
require_relative 'email/slot'
|
6
|
-
|
7
3
|
class GandiV5
|
8
4
|
# The Organization API is a read-only API.
|
9
5
|
# All organization management must be performed via the web interface.
|
@@ -54,13 +50,50 @@ class GandiV5
|
|
54
50
|
|
55
51
|
alias organization_uuid uuid
|
56
52
|
|
53
|
+
# @see GandiV5::Organization::Customer.list
|
54
|
+
def customers(org_uuid, **params)
|
55
|
+
GandiV5::Organization::Customer.list(org_uuid, **params)
|
56
|
+
end
|
57
|
+
|
58
|
+
# @see GandiV5::Organization::Customer.create
|
59
|
+
def create_customer(org_uuid, **params)
|
60
|
+
GandiV5::Organization::Customer.create(org_uuid, **params)
|
61
|
+
end
|
62
|
+
|
57
63
|
# Get information about the current authenticated user.
|
58
64
|
# @see https://api.gandi.net/docs/organization#get-v5-organization-user-info
|
59
65
|
# @return [GandiV5::Organization]
|
60
|
-
# @raise [GandiV5::Error::GandiError
|
66
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
61
67
|
def self.fetch
|
62
|
-
data = GandiV5.get "#{
|
68
|
+
_response, data = GandiV5.get "#{url}/user-info"
|
63
69
|
from_gandi data
|
64
70
|
end
|
71
|
+
|
72
|
+
# List organisations.
|
73
|
+
# @see https://api.gandi.net/docs/domains#get-v5-organization-organizations
|
74
|
+
# @param name [String, #to_s] (optional)
|
75
|
+
# filters the list by name, with optional patterns.
|
76
|
+
# e.g. "alice", "ali*", "*ice"
|
77
|
+
# @param type [String, #to_s] (optional)
|
78
|
+
# filters the list by type of organization.
|
79
|
+
# One of: "individual", "company", "association", "publicbody"
|
80
|
+
# @param permission [String, #to_s] (optional)
|
81
|
+
# filters the list by the permission the authenticated user
|
82
|
+
# has on that organization and products in it.
|
83
|
+
# @param sort_by [String, #to_s] (optional default "name") how to sort the list.
|
84
|
+
# @return [Array<GandiV5::Organization>]
|
85
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
86
|
+
def self.list(**params)
|
87
|
+
params['~name'] = params.delete(:name) if params.key?(:name)
|
88
|
+
_resp, data = GandiV5.get "#{url}/organizations", params: params
|
89
|
+
data.map { |organisation| from_gandi organisation }
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def self.url
|
95
|
+
"#{BASE}organization"
|
96
|
+
end
|
97
|
+
private_class_method :url
|
65
98
|
end
|
66
99
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class GandiV5
|
4
|
+
class Organization
|
5
|
+
# A customer of a reseller organization
|
6
|
+
# @!attribute [r] id
|
7
|
+
# @return [String] The main identifier of the customer.
|
8
|
+
# Also known as sharing_id in many routes.
|
9
|
+
# @!attribute [r] email
|
10
|
+
# @return [String] Email of the customer.
|
11
|
+
# @!attribute [r] first_name
|
12
|
+
# @return [String] First name of the customer.
|
13
|
+
# @!attribute [r] last_name
|
14
|
+
# @return [String] Last name of the customer.
|
15
|
+
# @!attribute [r] name
|
16
|
+
# @return [String] Name of the customer.
|
17
|
+
# @!attribute [r] type
|
18
|
+
# @return [:individual, :company, :association, :publicbody]
|
19
|
+
# @!attribute [r] org_name
|
20
|
+
# @return [nil, String] Organization legal name of the customer..
|
21
|
+
class Customer
|
22
|
+
include GandiV5::Data
|
23
|
+
|
24
|
+
members :email, :name
|
25
|
+
member :uuid, gandi_key: 'id'
|
26
|
+
member :first_name, gandi_key: 'firstname'
|
27
|
+
member :last_name, gandi_key: 'lastname'
|
28
|
+
member :org_name, gandi_key: 'orgname'
|
29
|
+
member :type, converter: GandiV5::Data::Converter::Symbol
|
30
|
+
|
31
|
+
# Create a new customer for this organization.
|
32
|
+
# @see https://api.gandi.net/docs/organization/#post-v5-organization-organizations-id-customers
|
33
|
+
# @param org_uuid [String] UUID of the organization to create the customer for.
|
34
|
+
# @param firstname [String, #to_s] (required) Customer's first name.
|
35
|
+
# @param lastname [String, #to_s] (required) Customer's last name.
|
36
|
+
# @param type [String, #to_s] (required) Type of customer
|
37
|
+
# ("individual", "company", "association" or "publicbody").
|
38
|
+
# @param streetaddr [String, #to_s] (required) Customer's street address.
|
39
|
+
# @param city [String, #to_s] (required) Customer's city.
|
40
|
+
# @param country [String, #to_s] (required) Customer's country.
|
41
|
+
# @param email [String, #to_s] (required) Customer's email address.
|
42
|
+
# @param phone [String, #to_s] (required) Customer's phone number.
|
43
|
+
# @param fax [String, #to_s] (optional) Customer's fax number.
|
44
|
+
# @param streetaddr2 [String, #to_s] (optional) Customer's street address (2nd line).
|
45
|
+
# @param state [String, #to_s] (optional) Customer's state/province/region.
|
46
|
+
# @param zip [String, #to_s] (optional) Customer's postal/zip code.
|
47
|
+
# @param reference [String, #to_s] (optional)
|
48
|
+
# Optional text to display on the invoice, such as your own customer reference info.
|
49
|
+
# @param orgname [String, #to_s] (optional) Customer Organization's legal name.
|
50
|
+
# @return [nil]
|
51
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error
|
52
|
+
def self.create(org_uuid, **params)
|
53
|
+
%i[city country email firstname lastname phone streetaddr type].each do |attr|
|
54
|
+
fail ArgumentError, "missing keyword: #{attr}" unless params.key?(attr)
|
55
|
+
end
|
56
|
+
unless %w[individual company association publicbody].include?(params[:type].to_s)
|
57
|
+
fail ArgumentError, "invalid type: #{params[:type].inspect}"
|
58
|
+
end
|
59
|
+
|
60
|
+
_response, _data = GandiV5.post(url(org_uuid), params.to_json)
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
# List organisation's customers.
|
65
|
+
# @see https://api.gandi.net/docs/organization/#get-v5-organization-organizations-id-customers
|
66
|
+
# @param org_uuid [String] UUID of the organization to fetch customers for.
|
67
|
+
# @param name [String, #to_s] (optional)
|
68
|
+
# filters the list by name, with optional patterns.
|
69
|
+
# e.g. "alice", "ali*", "*ice"
|
70
|
+
# @param permission [String, #to_s] (optional)
|
71
|
+
# filters the list by the permission the authenticated user has on
|
72
|
+
# that organization and products in it.
|
73
|
+
# @param sort_by [String, #to_s] (optional default "name") how to sort the list.
|
74
|
+
# @return [Array<GandiV5::Organization>]
|
75
|
+
# @raise [GandiV5::Error::GandiError] if Gandi returns an error.
|
76
|
+
def self.list(org_uuid, **params)
|
77
|
+
params['~name'] = params.delete(:name) if params.key?(:name)
|
78
|
+
_resp, data = GandiV5.get url(org_uuid), params: params
|
79
|
+
data.map { |organisation| from_gandi organisation }
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def self.url(org_uuid)
|
85
|
+
"#{BASE}organization/organizations/#{org_uuid}/customers"
|
86
|
+
end
|
87
|
+
private_class_method :url
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/gandi_v5/version.rb
CHANGED
data/spec/.rubocop.yml
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
describe 'Domain features' do
|
4
4
|
it 'List domains', :vcr do
|
5
|
-
list = GandiV5
|
5
|
+
list = GandiV5.domains
|
6
6
|
|
7
7
|
expect(list.count).to eq 1
|
8
8
|
expect(list.first.fqdn).to eq 'example.net'
|
9
9
|
expect(list.first.fqdn_unicode).to eq 'example.net'
|
10
|
-
expect(list.first.name_servers).to
|
10
|
+
expect(list.first.name_servers).to eq []
|
11
11
|
expect(list.first.services).to be nil
|
12
12
|
expect(list.first.sharing_space).to be nil
|
13
13
|
expect(list.first.status).to match_array [:clientTransferProhibited]
|
@@ -25,21 +25,20 @@ describe 'LiveDNS Zone features' do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'Make and save snapshot', :vcr do
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
expect(File).to receive(:write).with('/path/to/file', yaml)
|
28
|
+
hash = {
|
29
|
+
uuid: 'snapshot-uuid',
|
30
|
+
zone_uuid: 'zone-uuid',
|
31
|
+
created_at: Time.new(2016, 12, 16, 16, 51, 26),
|
32
|
+
records: [
|
33
|
+
type: 'A',
|
34
|
+
ttl: 10_800,
|
35
|
+
name: 'www',
|
36
|
+
values: ['10.0.1.42']
|
37
|
+
]
|
38
|
+
}
|
40
39
|
|
41
40
|
zone = GandiV5::LiveDNS::Zone.new uuid: 'zone-uuid'
|
42
41
|
snapshot = zone.take_snapshot
|
43
|
-
|
42
|
+
expect(snapshot.to_h).to eq hash
|
44
43
|
end
|
45
44
|
end
|
File without changes
|
File without changes
|
File without changes
|
data/spec/fixtures/bodies/{GandiV5_Domain/availability.yaml → GandiV5_Domain_Availability/fetch.yml}
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/spec/spec_helper.rb
CHANGED
@@ -13,12 +13,12 @@ allow_http_connections_to = %w[localhost 127.0.0.1]
|
|
13
13
|
|
14
14
|
Dotenv.load File.join(__dir__, 'test.env')
|
15
15
|
|
16
|
-
SimpleCov.coverage_dir(File.join('tmp', 'coverage'))
|
16
|
+
SimpleCov.coverage_dir(File.join('tmp', 'coverage')) unless ENV.key?('TRAVIS')
|
17
17
|
SimpleCov.start do
|
18
18
|
add_filter 'spec/'
|
19
19
|
end
|
20
20
|
|
21
|
-
if ENV
|
21
|
+
if ENV.key?('TRAVIS')
|
22
22
|
Coveralls.wear!
|
23
23
|
allow_http_connections_to.push 'coveralls.io'
|
24
24
|
end
|
@@ -4,9 +4,9 @@ describe GandiV5::Billing do
|
|
4
4
|
describe '.info' do
|
5
5
|
subject { described_class.info }
|
6
6
|
before :each do
|
7
|
-
body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Billing', 'info.
|
7
|
+
body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Billing', 'info.yml'))
|
8
8
|
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/billing/info')
|
9
|
-
.and_return(YAML.load_file(body_fixture))
|
9
|
+
.and_return([nil, YAML.load_file(body_fixture)])
|
10
10
|
end
|
11
11
|
|
12
12
|
its('annual_balance') { should eq 123.45 }
|
@@ -23,9 +23,9 @@ describe GandiV5::Billing do
|
|
23
23
|
describe '.info (for a sharing_id)' do
|
24
24
|
subject { described_class.info('sharing-id') }
|
25
25
|
before :each do
|
26
|
-
body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Billing', 'info.
|
26
|
+
body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Billing', 'info.yml'))
|
27
27
|
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/billing/info/sharing-id')
|
28
|
-
.and_return(YAML.load_file(body_fixture))
|
28
|
+
.and_return([nil, YAML.load_file(body_fixture)])
|
29
29
|
end
|
30
30
|
|
31
31
|
its('annual_balance') { should eq 123.45 }
|