gandi_v5 0.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.
- checksums.yaml +7 -0
- data/.gitignore +24 -0
- data/.rspec +3 -0
- data/.rubocop.yml +20 -0
- data/.travis.yml +23 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +6 -0
- data/Guardfile +40 -0
- data/LICENSE.md +32 -0
- data/README.md +94 -0
- data/Rakefile +3 -0
- data/TODO.md +29 -0
- data/bin/console +13 -0
- data/gandi_v5.gemspec +41 -0
- data/lib/gandi_v5/billing/info/prepaid.rb +33 -0
- data/lib/gandi_v5/billing/info.rb +26 -0
- data/lib/gandi_v5/billing.rb +28 -0
- data/lib/gandi_v5/data/converter/array_of.rb +35 -0
- data/lib/gandi_v5/data/converter/symbol.rb +26 -0
- data/lib/gandi_v5/data/converter/time.rb +28 -0
- data/lib/gandi_v5/data/converter.rb +41 -0
- data/lib/gandi_v5/data.rb +244 -0
- data/lib/gandi_v5/domain/auto_renew.rb +64 -0
- data/lib/gandi_v5/domain/contact.rb +102 -0
- data/lib/gandi_v5/domain/contract.rb +22 -0
- data/lib/gandi_v5/domain/dates.rb +44 -0
- data/lib/gandi_v5/domain/renewal_information.rb +41 -0
- data/lib/gandi_v5/domain/restore_information.rb +18 -0
- data/lib/gandi_v5/domain/sharing_space.rb +21 -0
- data/lib/gandi_v5/domain.rb +431 -0
- data/lib/gandi_v5/email/mailbox/responder.rb +36 -0
- data/lib/gandi_v5/email/mailbox.rb +236 -0
- data/lib/gandi_v5/email/offer.rb +27 -0
- data/lib/gandi_v5/email/slot.rb +134 -0
- data/lib/gandi_v5/email.rb +11 -0
- data/lib/gandi_v5/error/gandi_error.rb +21 -0
- data/lib/gandi_v5/error.rb +9 -0
- data/lib/gandi_v5/live_dns/domain.rb +211 -0
- data/lib/gandi_v5/live_dns/record_set.rb +79 -0
- data/lib/gandi_v5/live_dns/zone/snapshot.rb +62 -0
- data/lib/gandi_v5/live_dns/zone.rb +301 -0
- data/lib/gandi_v5/live_dns.rb +30 -0
- data/lib/gandi_v5/organization.rb +66 -0
- data/lib/gandi_v5/version.rb +5 -0
- data/lib/gandi_v5.rb +178 -0
- data/spec/.rubocop.yml +4 -0
- data/spec/features/domain_spec.rb +45 -0
- data/spec/features/livedns_domain_spec.rb +8 -0
- data/spec/features/livedns_zone_spec.rb +45 -0
- data/spec/features/mailbox_spec.rb +18 -0
- data/spec/fixtures/bodies/GandiV5_Billing/info.yaml +10 -0
- data/spec/fixtures/bodies/GandiV5_Domain/availability.yaml +15 -0
- data/spec/fixtures/bodies/GandiV5_Domain/fetch_contacts.yaml +8 -0
- data/spec/fixtures/bodies/GandiV5_Domain/get.yaml +37 -0
- data/spec/fixtures/bodies/GandiV5_Domain/list.yaml +20 -0
- data/spec/fixtures/bodies/GandiV5_Domain/renewal_info.yaml +12 -0
- data/spec/fixtures/bodies/GandiV5_Domain/restore_info.yaml +5 -0
- data/spec/fixtures/bodies/GandiV5_Domain/tld.yaml +10 -0
- data/spec/fixtures/bodies/GandiV5_Domain/tlds.yaml +7 -0
- data/spec/fixtures/bodies/GandiV5_Email_Mailbox/get.yaml +16 -0
- data/spec/fixtures/bodies/GandiV5_Email_Mailbox/list.yaml +8 -0
- data/spec/fixtures/bodies/GandiV5_Email_Slot/get.yaml +10 -0
- data/spec/fixtures/bodies/GandiV5_Email_Slot/list.yaml +8 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/get.yaml +4 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/list.yaml +2 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/get.yaml +11 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/list.yaml +11 -0
- data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/get.yaml +9 -0
- data/spec/fixtures/bodies/GandiV5_Organization/get.yaml +17 -0
- data/spec/fixtures/vcr/Domain_features/List_domains.yml +54 -0
- data/spec/fixtures/vcr/Domain_features/Renew_domain.yml +133 -0
- data/spec/fixtures/vcr/LiveDNS_Domain_features/List_domains.yml +32 -0
- data/spec/fixtures/vcr/LiveDNS_Zone_features/List_zones.yml +42 -0
- data/spec/fixtures/vcr/LiveDNS_Zone_features/Make_and_save_snapshot.yml +72 -0
- data/spec/fixtures/vcr/LiveDNS_Zone_features/Save_zone_to_file.yml +28 -0
- data/spec/fixtures/vcr/Mailbox_features/List_mailboxes.yml +39 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/test.env +1 -0
- data/spec/units/gandi_v5/billing/info/prepaid_spec.rb +20 -0
- data/spec/units/gandi_v5/billing/info_spec.rb +4 -0
- data/spec/units/gandi_v5/billing_spec.rb +41 -0
- data/spec/units/gandi_v5/data/converter/array_of_spec.rb +18 -0
- data/spec/units/gandi_v5/data/converter/symbol_spec.rb +16 -0
- data/spec/units/gandi_v5/data/converter/time_spec.rb +16 -0
- data/spec/units/gandi_v5/data/converter_spec.rb +31 -0
- data/spec/units/gandi_v5/data_spec.rb +340 -0
- data/spec/units/gandi_v5/domain/auto_renew_spec.rb +70 -0
- data/spec/units/gandi_v5/domain/contact_spec.rb +36 -0
- data/spec/units/gandi_v5/domain/contract_spec.rb +4 -0
- data/spec/units/gandi_v5/domain/dates_spec.rb +4 -0
- data/spec/units/gandi_v5/domain/renewal_information_spec.rb +81 -0
- data/spec/units/gandi_v5/domain/restore_information_spec.rb +4 -0
- data/spec/units/gandi_v5/domain/sharing_space_spec.rb +4 -0
- data/spec/units/gandi_v5/domain_spec.rb +451 -0
- data/spec/units/gandi_v5/email/mailbox/responder_spec.rb +131 -0
- data/spec/units/gandi_v5/email/mailbox_spec.rb +384 -0
- data/spec/units/gandi_v5/email/offer_spec.rb +17 -0
- data/spec/units/gandi_v5/email/slot_spec.rb +102 -0
- data/spec/units/gandi_v5/error/gandi_error_spec.rb +30 -0
- data/spec/units/gandi_v5/error_spec.rb +4 -0
- data/spec/units/gandi_v5/live_dns/domain_spec.rb +247 -0
- data/spec/units/gandi_v5/live_dns/record_set_spec.rb +74 -0
- data/spec/units/gandi_v5/live_dns/zone/snapshot_spec.rb +37 -0
- data/spec/units/gandi_v5/live_dns/zone_spec.rb +329 -0
- data/spec/units/gandi_v5/live_dns_spec.rb +17 -0
- data/spec/units/gandi_v5/organization_spec.rb +30 -0
- data/spec/units/gandi_v5_spec.rb +204 -0
- metadata +406 -0
@@ -0,0 +1,384 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe GandiV5::Email::Mailbox do
|
4
|
+
subject do
|
5
|
+
described_class.new fqdn: 'example.com', uuid: 'mailbox-uuid', type: :standard
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:good_password) { 'aA111-___' }
|
9
|
+
|
10
|
+
describe '#refresh' do
|
11
|
+
before :each do
|
12
|
+
body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Email_Mailbox', 'get.yaml'))
|
13
|
+
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/email/mailboxes/example.com/mailbox-uuid')
|
14
|
+
.and_return(YAML.load_file(body_fixture))
|
15
|
+
subject.refresh
|
16
|
+
end
|
17
|
+
|
18
|
+
its('address') { should eq 'address@example.com' }
|
19
|
+
its('aliases') { should match_array %w[alias-1 alias-2] }
|
20
|
+
its('fqdn') { should eq 'example.com' }
|
21
|
+
its('uuid') { should eq 'mailbox-uuid' }
|
22
|
+
its('login') { should eq 'address' }
|
23
|
+
its('type') { should eq :standard }
|
24
|
+
its('quota_used') { should eq 1_000_000 }
|
25
|
+
its('responder.enabled') { should be false }
|
26
|
+
its('responder.starts_at') { should eq Time.new(2000, 1, 1, 0, 0, 0) }
|
27
|
+
its('responder.ends_at') { should eq Time.new(2000, 1, 2, 0, 0, 0) }
|
28
|
+
its('responder.message') { should eq 'This is an autoresponse.' }
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#update' do
|
32
|
+
let(:url) { 'https://api.gandi.net/v5/email/mailboxes/example.com/mailbox-uuid' }
|
33
|
+
|
34
|
+
it 'Aliases' do
|
35
|
+
expect(GandiV5).to receive(:patch).with(url, '{"aliases":["alias-1"]}')
|
36
|
+
.and_return('message' => 'Confirmation message.')
|
37
|
+
expect(subject).to receive(:refresh)
|
38
|
+
expect(subject.update(aliases: ['alias-1'])).to eq 'Confirmation message.'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'Login' do
|
42
|
+
expect(GandiV5).to receive(:patch).with(url, '{"login":"new-login"}')
|
43
|
+
.and_return('message' => 'Confirmation message.')
|
44
|
+
expect(subject).to receive(:refresh)
|
45
|
+
expect(subject.update(login: 'new-login')).to eq 'Confirmation message.'
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'Password' do
|
49
|
+
it 'Password is good' do
|
50
|
+
expect(GandiV5).to receive(:patch).with(url, '{"password":"crypted_password"}')
|
51
|
+
.and_return('message' => 'Confirmation message.')
|
52
|
+
expect(subject).to receive(:refresh)
|
53
|
+
expect(subject).to receive(:crypt_password).with(good_password).and_return('crypted_password')
|
54
|
+
expect(subject.update(password: good_password)).to eq 'Confirmation message.'
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'Password is bad' do
|
58
|
+
expect(described_class).to receive(:check_password).with('password').and_raise(ArgumentError, 'message')
|
59
|
+
expect { subject.update password: 'password' }.to raise_error ArgumentError, 'message'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'Responder' do
|
64
|
+
before(:each) do
|
65
|
+
expect(GandiV5).to receive(:patch).with(url, '{"responder":{"enabled":false}}')
|
66
|
+
.and_return('message' => 'Confirmation message.')
|
67
|
+
|
68
|
+
expect(subject).to receive(:refresh)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'Given a GandiV5::Email::Mailbox::Responder' do
|
72
|
+
responder = double GandiV5::Email::Mailbox::Responder, to_gandi: { 'enabled' => false }
|
73
|
+
expect(subject.update(responder: responder)).to eq 'Confirmation message.'
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'Given a Hash' do
|
77
|
+
responder = { enabled: false }
|
78
|
+
expect(subject.update(responder: responder)).to eq 'Confirmation message.'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'Given nothing' do
|
83
|
+
expect(GandiV5).to_not receive(:patch)
|
84
|
+
expect(subject).to_not receive(:refresh)
|
85
|
+
expect(subject.update).to eq 'Nothing to update.'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
it '#delete' do
|
90
|
+
url = 'https://api.gandi.net/v5/email/mailboxes/example.com/mailbox-uuid'
|
91
|
+
expect(GandiV5).to receive(:delete).with(url)
|
92
|
+
.and_return('message' => 'Confirmation message.')
|
93
|
+
expect(subject.delete).to eq 'Confirmation message.'
|
94
|
+
end
|
95
|
+
|
96
|
+
it '#purge' do
|
97
|
+
url = 'https://api.gandi.net/v5/email/mailboxes/example.com/mailbox-uuid/contents'
|
98
|
+
expect(GandiV5).to receive(:delete).with(url)
|
99
|
+
.and_return('message' => 'Confirmation message.')
|
100
|
+
expect(subject.purge).to eq 'Confirmation message.'
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#quota' do
|
104
|
+
it 'Free mailbox' do
|
105
|
+
mailbox = described_class.new type: :free
|
106
|
+
expect(mailbox.quota).to eq 3_221_225_472
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'Standard mailbox' do
|
110
|
+
mailbox = described_class.new type: :standard
|
111
|
+
expect(mailbox.quota).to eq 3_221_225_472
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'Premium mailbox' do
|
115
|
+
mailbox = described_class.new type: :premium
|
116
|
+
expect(mailbox.quota).to eq 53_687_091_200
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
it '#quota_usage' do
|
121
|
+
# Used / Quota
|
122
|
+
mailbox = described_class.new type: :free, quota_used: 2_000_000_000
|
123
|
+
expect(mailbox.quota_usage).to eq(0.620881716410319)
|
124
|
+
end
|
125
|
+
|
126
|
+
describe '#to_s' do
|
127
|
+
it 'With no responder and no aliases' do
|
128
|
+
mailbox = described_class.new(
|
129
|
+
address: 'mailbox@example.com',
|
130
|
+
type: :standard,
|
131
|
+
quota_used: 1_000_000_000,
|
132
|
+
responder: nil,
|
133
|
+
aliases: []
|
134
|
+
)
|
135
|
+
expect(mailbox.to_s).to eq '[standard] mailbox@example.com (1000000000/3221225472 (31%))'
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'With active responder but no aliases' do
|
139
|
+
mailbox = described_class.new(
|
140
|
+
address: 'mailbox@example.com',
|
141
|
+
type: :standard,
|
142
|
+
quota_used: 1_000_000_000,
|
143
|
+
responder: GandiV5::Email::Mailbox::Responder.new(enabled: true),
|
144
|
+
aliases: []
|
145
|
+
)
|
146
|
+
expect(mailbox.to_s).to eq '[standard] mailbox@example.com (1000000000/3221225472 (31%)) ' \
|
147
|
+
'with active responder'
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'With inactive responder but no aliases' do
|
151
|
+
mailbox = described_class.new(
|
152
|
+
address: 'mailbox@example.com',
|
153
|
+
type: :standard,
|
154
|
+
quota_used: 1_000_000_000,
|
155
|
+
responder: GandiV5::Email::Mailbox::Responder.new(enabled: false),
|
156
|
+
aliases: []
|
157
|
+
)
|
158
|
+
expect(mailbox.to_s).to eq '[standard] mailbox@example.com (1000000000/3221225472 (31%)) ' \
|
159
|
+
'with inactive responder'
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'With aliases but no responder' do
|
163
|
+
mailbox = described_class.new(
|
164
|
+
address: 'mailbox@example.com',
|
165
|
+
type: :standard,
|
166
|
+
quota_used: 1_000_000_000,
|
167
|
+
responder: nil,
|
168
|
+
aliases: %w[mailbox_2 mailbox_3]
|
169
|
+
)
|
170
|
+
expect(mailbox.to_s).to eq '[standard] mailbox@example.com (1000000000/3221225472 (31%)) ' \
|
171
|
+
'aka: mailbox_2, mailbox_3'
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'With active responder and aliases' do
|
175
|
+
mailbox = described_class.new(
|
176
|
+
address: 'mailbox@example.com',
|
177
|
+
type: :standard,
|
178
|
+
quota_used: 1_000_000_000,
|
179
|
+
responder: GandiV5::Email::Mailbox::Responder.new(enabled: true),
|
180
|
+
aliases: %w[mailbox_2 mailbox_3]
|
181
|
+
)
|
182
|
+
expect(mailbox.to_s).to eq '[standard] mailbox@example.com (1000000000/3221225472 (31%)) ' \
|
183
|
+
'with active responder aka: mailbox_2, mailbox_3'
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe '.create' do
|
188
|
+
let(:url) { 'https://api.gandi.net/v5/email/mailboxes/example.com' }
|
189
|
+
|
190
|
+
it 'No aliases and :standard type' do
|
191
|
+
body = '{"mailbox_type":"standard","login":"login","password":"crypted_password","aliases":[]}'
|
192
|
+
expect(GandiV5).to receive(:post).with(url, body)
|
193
|
+
.and_return('message' => 'Confirmation message.')
|
194
|
+
expect(described_class).to receive(:crypt_password).with(good_password).and_return('crypted_password')
|
195
|
+
|
196
|
+
expect(described_class.create('example.com', 'login', good_password)).to eq 'Confirmation message.'
|
197
|
+
end
|
198
|
+
|
199
|
+
it 'With aliases' do
|
200
|
+
body = '{"mailbox_type":"standard","login":"login","password":"crypted_password","aliases":["alias-1"]}'
|
201
|
+
expect(GandiV5).to receive(:post).with(url, body)
|
202
|
+
.and_return('message' => 'Confirmation message.')
|
203
|
+
expect(described_class).to receive(:crypt_password).with(good_password).and_return('crypted_password')
|
204
|
+
|
205
|
+
expect(described_class.create('example.com', 'login', good_password, aliases: ['alias-1']))
|
206
|
+
.to eq 'Confirmation message.'
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'With different type' do
|
210
|
+
body = '{"mailbox_type":"premium","login":"login","password":"crypted_password","aliases":[]}'
|
211
|
+
expect(GandiV5).to receive(:post).with(url, body)
|
212
|
+
.and_return('message' => 'Confirmation message.')
|
213
|
+
expect(described_class).to receive(:crypt_password).with(good_password).and_return('crypted_password')
|
214
|
+
|
215
|
+
expect(described_class.create('example.com', 'login', good_password, type: :premium)).to eq 'Confirmation message.'
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'Bad password' do
|
219
|
+
expect(described_class).to receive(:check_password).with('password').and_raise(ArgumentError, 'message')
|
220
|
+
expect { described_class.create 'example.com', 'login', 'password' }.to raise_error ArgumentError, 'message'
|
221
|
+
end
|
222
|
+
|
223
|
+
# TODO: pending 'Bad type'
|
224
|
+
# TODO: pending 'No available slots'
|
225
|
+
end
|
226
|
+
|
227
|
+
describe '.fetch' do
|
228
|
+
subject { described_class.fetch 'example.com', 'mailbox-uuid' }
|
229
|
+
|
230
|
+
before :each do
|
231
|
+
body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Email_Mailbox', 'get.yaml'))
|
232
|
+
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/email/mailboxes/example.com/mailbox-uuid')
|
233
|
+
.and_return(YAML.load_file(body_fixture))
|
234
|
+
end
|
235
|
+
|
236
|
+
its('address') { should eq 'address@example.com' }
|
237
|
+
its('aliases') { should match_array %w[alias-1 alias-2] }
|
238
|
+
its('fqdn') { should eq 'example.com' }
|
239
|
+
its('uuid') { should eq 'mailbox-uuid' }
|
240
|
+
its('login') { should eq 'address' }
|
241
|
+
its('type') { should eq :standard }
|
242
|
+
its('quota_used') { should eq 1_000_000 }
|
243
|
+
its('responder.enabled') { should be false }
|
244
|
+
its('responder.starts_at') { should eq Time.new(2000, 1, 1, 0, 0, 0) }
|
245
|
+
its('responder.ends_at') { should eq Time.new(2000, 1, 2, 0, 0, 0) }
|
246
|
+
its('responder.message') { should eq 'This is an autoresponse.' }
|
247
|
+
end
|
248
|
+
|
249
|
+
describe '.list' do
|
250
|
+
let(:body_fixture) do
|
251
|
+
File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Email_Mailbox', 'list.yaml'))
|
252
|
+
end
|
253
|
+
|
254
|
+
describe 'With default values' do
|
255
|
+
subject { described_class.list 'example.com' }
|
256
|
+
|
257
|
+
before :each do
|
258
|
+
headers = { params: { page: 1 } }
|
259
|
+
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/email/mailboxes/example.com', headers)
|
260
|
+
.and_return(YAML.load_file(body_fixture))
|
261
|
+
end
|
262
|
+
|
263
|
+
its('count') { should eq 1 }
|
264
|
+
its('first.address') { should eq 'address@example.com' }
|
265
|
+
its('first.fqdn') { should eq 'example.com' }
|
266
|
+
its('first.uuid') { should eq 'mailbox-uuid' }
|
267
|
+
its('first.login') { should eq 'address' }
|
268
|
+
its('first.type') { should eq :standard }
|
269
|
+
its('first.quota_used') { should eq 1_000_000 }
|
270
|
+
end
|
271
|
+
|
272
|
+
it 'Keeps fetching until no more to get' do
|
273
|
+
headers1 = { params: { page: 1, per_page: 1 } }
|
274
|
+
headers2 = { params: { page: 2, per_page: 1 } }
|
275
|
+
# rubocop:disable Layout/MultilineMethodCallIndentation
|
276
|
+
# https://github.com/rubocop-hq/rubocop/issues/7088
|
277
|
+
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/email/mailboxes/example.com', headers1)
|
278
|
+
.ordered
|
279
|
+
.and_return(YAML.load_file(body_fixture))
|
280
|
+
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/email/mailboxes/example.com', headers2)
|
281
|
+
.ordered
|
282
|
+
.and_return([])
|
283
|
+
# rubocop:enable Layout/MultilineMethodCallIndentation
|
284
|
+
|
285
|
+
expect(described_class.list('example.com', per_page: 1).count).to eq 1
|
286
|
+
end
|
287
|
+
|
288
|
+
it 'Given a range as page number' do
|
289
|
+
headers1 = { params: { page: 1, per_page: 1 } }
|
290
|
+
headers2 = { params: { page: 2, per_page: 1 } }
|
291
|
+
# rubocop:disable Layout/MultilineMethodCallIndentation
|
292
|
+
# https://github.com/rubocop-hq/rubocop/issues/7088
|
293
|
+
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/email/mailboxes/example.com', headers1)
|
294
|
+
.ordered
|
295
|
+
.and_return(YAML.load_file(body_fixture))
|
296
|
+
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/email/mailboxes/example.com', headers2)
|
297
|
+
.ordered
|
298
|
+
.and_return([])
|
299
|
+
# rubocop:enable Layout/MultilineMethodCallIndentation
|
300
|
+
|
301
|
+
expect(described_class.list('example.com', page: (1..2), per_page: 1).count).to eq 1
|
302
|
+
end
|
303
|
+
|
304
|
+
describe 'Passes optional query params' do
|
305
|
+
{
|
306
|
+
login: '~login',
|
307
|
+
sort_by: :sort_by
|
308
|
+
}.each do |param, query_param|
|
309
|
+
it param.to_s do
|
310
|
+
headers = { params: { page: 1 }.merge(query_param => 'value') }
|
311
|
+
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/email/mailboxes/example.com', headers)
|
312
|
+
.and_return([])
|
313
|
+
expect(described_class.list('example.com', param => 'value')).to eq []
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
describe '.check_password' do
|
320
|
+
it 'Too short' do
|
321
|
+
expect { described_class.send :check_password, 'a' * 8 }.to raise_error ArgumentError,
|
322
|
+
'password must be between ' \
|
323
|
+
'9 and 200 characters'
|
324
|
+
end
|
325
|
+
|
326
|
+
it 'Too long' do
|
327
|
+
expect { described_class.send :check_password, 'a' * 201 }.to raise_error ArgumentError,
|
328
|
+
'password must be between ' \
|
329
|
+
'9 and 200 characters'
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'At least 1 upper case' do
|
333
|
+
expect { described_class.send :check_password, 'a1!' * 3 }.to raise_error ArgumentError,
|
334
|
+
'password must contain at least ' \
|
335
|
+
'one upper case character'
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'At least 3 numbers' do
|
339
|
+
expect { described_class.send :check_password, 'aA!' * 3 }.to raise_error ArgumentError,
|
340
|
+
'password must contain at least ' \
|
341
|
+
'three numbers'
|
342
|
+
end
|
343
|
+
|
344
|
+
it 'At least 1 special character' do
|
345
|
+
expect { described_class.send :check_password, 'aA1' * 3 }.to raise_error ArgumentError,
|
346
|
+
'password must contain at least ' \
|
347
|
+
'one special character'
|
348
|
+
end
|
349
|
+
|
350
|
+
it 'Is a \'good\' password' do
|
351
|
+
expect { described_class.send :check_password, good_password }.to_not raise_error
|
352
|
+
end
|
353
|
+
|
354
|
+
it 'Is delegated to by #check_password' do
|
355
|
+
returns = double NilClass
|
356
|
+
expect(described_class).to receive(:check_password).with('password').and_return(returns)
|
357
|
+
expect(subject.send(:check_password, 'password')).to be returns
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
describe '.crypt_password' do
|
362
|
+
let(:random_number) { 2_674_341_316_769 }
|
363
|
+
|
364
|
+
before :each do
|
365
|
+
allow(SecureRandom).to receive(:random_number).with(36**8).and_return(random_number)
|
366
|
+
end
|
367
|
+
|
368
|
+
it 'For "password_1"' do
|
369
|
+
expect(described_class.send(:crypt_password, 'password_1')).to eq '$6$y4kprqn5$HcA7fWQKZOkt2if38EmourBSgUtgQer0QEao' \
|
370
|
+
'N/qxw/2HamYbq1.EQn0lx6q6sf6etlWhHe0PDBXZ7k1Y4VZkN/'
|
371
|
+
end
|
372
|
+
|
373
|
+
it 'For "password_2"' do
|
374
|
+
expect(described_class.send(:crypt_password, 'password_2')).to eq '$6$y4kprqn5$HQbp65drFzXYwUHH.FDHsvtZ9u4EYM2sVKp4' \
|
375
|
+
'U.w9IgStZf2OeLgP0ifYo9LKE8pr30l8MUwDtmhS8.ztK8o8p/'
|
376
|
+
end
|
377
|
+
|
378
|
+
it 'Is delegated to by #crypt_password' do
|
379
|
+
returns = double NilClass
|
380
|
+
expect(described_class).to receive(:crypt_password).with('password').and_return(returns)
|
381
|
+
expect(subject.send(:crypt_password, 'password')).to be returns
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe GandiV5::Email::Offer do
|
4
|
+
subject { described_class.new status: :active }
|
5
|
+
|
6
|
+
describe '.fetch' do
|
7
|
+
subject { described_class.fetch('example.com') }
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/email/offers/example.com')
|
11
|
+
.and_return('status' => 'active', 'version' => 2)
|
12
|
+
end
|
13
|
+
|
14
|
+
its('status') { should be :active }
|
15
|
+
its('version') { should eq 2 }
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe GandiV5::Email::Slot do
|
4
|
+
subject do
|
5
|
+
described_class.new id: 123, capacity: 1, mailbox_type: :standard, status: :inactive, fqdn: 'example.com'
|
6
|
+
end
|
7
|
+
|
8
|
+
it '#delete' do
|
9
|
+
expect(GandiV5).to receive(:delete).with('https://api.gandi.net/v5/email/slots/example.com/123')
|
10
|
+
.and_return('message' => 'Confirmation message.')
|
11
|
+
expect(subject.delete).to eq 'Confirmation message.'
|
12
|
+
end
|
13
|
+
# TODO: check for inactiveness
|
14
|
+
# TODO: check for refundableness
|
15
|
+
|
16
|
+
describe '#refresh' do
|
17
|
+
before :each do
|
18
|
+
body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Email_Slot', 'get.yaml'))
|
19
|
+
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/email/slots/example.com/123')
|
20
|
+
.and_return(YAML.load_file(body_fixture))
|
21
|
+
subject.refresh
|
22
|
+
end
|
23
|
+
|
24
|
+
its('fqdn') { should eq 'example.com' }
|
25
|
+
its('id') { should eq 125 }
|
26
|
+
its('created_at') { should eq Time.new(2019, 4, 8, 8, 48, 41, 0) }
|
27
|
+
its('mailbox_type') { should be :premium }
|
28
|
+
its('status') { should be :inactive }
|
29
|
+
its('refundable') { should be true }
|
30
|
+
its('capacity') { should eq 53_687_091_200 }
|
31
|
+
its('refund_amount') { should eq 16.16 }
|
32
|
+
its('refund_currency') { should eq 'EUR' }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#active?' do
|
36
|
+
it 'When active' do
|
37
|
+
slot = described_class.new status: :active
|
38
|
+
expect(slot.active?).to be true
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'When inactive' do
|
42
|
+
slot = described_class.new status: :inactive
|
43
|
+
expect(slot.active?).to be false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '.create' do
|
48
|
+
let(:url) { 'https://api.gandi.net/v5/email/slots/example.com' }
|
49
|
+
it 'With default type' do
|
50
|
+
expect(GandiV5).to receive(:post).with(url, '{"mailbox_type":"standard"}')
|
51
|
+
.and_return('message' => 'Confirmation message.')
|
52
|
+
expect(described_class.create('example.com')).to eq 'Confirmation message.'
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'With passed type' do
|
56
|
+
expect(GandiV5).to receive(:post).with(url, '{"mailbox_type":"premium"}')
|
57
|
+
.and_return('message' => 'Confirmation message.')
|
58
|
+
expect(described_class.create('example.com', :premium)).to eq 'Confirmation message.'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '.fetch' do
|
63
|
+
subject { described_class.fetch 'example.com', 123 }
|
64
|
+
|
65
|
+
before :each do
|
66
|
+
body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Email_Slot', 'get.yaml'))
|
67
|
+
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/email/slots/example.com/123')
|
68
|
+
.and_return(YAML.load_file(body_fixture))
|
69
|
+
end
|
70
|
+
|
71
|
+
its('fqdn') { should eq 'example.com' }
|
72
|
+
its('id') { should eq 125 }
|
73
|
+
its('created_at') { should eq Time.new(2019, 4, 8, 8, 48, 41, 0) }
|
74
|
+
its('mailbox_type') { should be :premium }
|
75
|
+
its('status') { should be :inactive }
|
76
|
+
its('refundable') { should be true }
|
77
|
+
its('capacity') { should eq 53_687_091_200 }
|
78
|
+
its('refund_amount') { should eq 16.16 }
|
79
|
+
its('refund_currency') { should eq 'EUR' }
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '.list' do
|
83
|
+
subject { described_class.list 'example.com' }
|
84
|
+
|
85
|
+
before :each do
|
86
|
+
body_fixture = File.expand_path(File.join('spec', 'fixtures', 'bodies', 'GandiV5_Email_Slot', 'list.yaml'))
|
87
|
+
expect(GandiV5).to receive(:get).with('https://api.gandi.net/v5/email/slots/example.com')
|
88
|
+
.and_return(YAML.load_file(body_fixture))
|
89
|
+
end
|
90
|
+
|
91
|
+
its('count') { should eq 1 }
|
92
|
+
its('first.fqdn') { should eq 'example.com' }
|
93
|
+
its('first.id') { should eq 125 }
|
94
|
+
its('first.created_at') { should eq Time.new(2019, 4, 8, 8, 48, 41, 0) }
|
95
|
+
its('first.mailbox_type') { should be :standard }
|
96
|
+
its('first.status') { should be :inactive }
|
97
|
+
its('first.refundable') { should be true }
|
98
|
+
its('first.capacity') { should eq 3_221_225_472 }
|
99
|
+
its('first.refund_amount') { should be nil }
|
100
|
+
its('first.refund_currency') { should be nil }
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe GandiV5::Error::GandiError::GandiError do
|
4
|
+
describe 'Generate from Hash returned by Gandi' do
|
5
|
+
it 'Single error' do
|
6
|
+
hash = {
|
7
|
+
'errors' => [
|
8
|
+
{ 'location' => 'body', 'name' => 'field', 'description' => 'message' }
|
9
|
+
]
|
10
|
+
}
|
11
|
+
error = described_class.from_hash hash
|
12
|
+
expect(error.message).to eq 'body->field: message'
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'Multiple errors' do
|
16
|
+
hash = {
|
17
|
+
'errors' => [
|
18
|
+
{ 'location' => 'body', 'name' => 'field', 'description' => 'message 1' },
|
19
|
+
{ 'location' => 'body', 'name' => 'field.sub', 'description' => 'message 2' },
|
20
|
+
{ 'location' => 'body', 'name' => 'field2', 'description' => 'message 3' }
|
21
|
+
]
|
22
|
+
}
|
23
|
+
error = described_class.from_hash hash
|
24
|
+
expect(error.message).to eq "\n" \
|
25
|
+
"body->field: message 1\n" \
|
26
|
+
"body->field.sub: message 2\n" \
|
27
|
+
'body->field2: message 3'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|