gandi_v5 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +20 -0
  5. data/.travis.yml +23 -0
  6. data/CHANGELOG.md +3 -0
  7. data/Gemfile +6 -0
  8. data/Guardfile +40 -0
  9. data/LICENSE.md +32 -0
  10. data/README.md +94 -0
  11. data/Rakefile +3 -0
  12. data/TODO.md +29 -0
  13. data/bin/console +13 -0
  14. data/gandi_v5.gemspec +41 -0
  15. data/lib/gandi_v5/billing/info/prepaid.rb +33 -0
  16. data/lib/gandi_v5/billing/info.rb +26 -0
  17. data/lib/gandi_v5/billing.rb +28 -0
  18. data/lib/gandi_v5/data/converter/array_of.rb +35 -0
  19. data/lib/gandi_v5/data/converter/symbol.rb +26 -0
  20. data/lib/gandi_v5/data/converter/time.rb +28 -0
  21. data/lib/gandi_v5/data/converter.rb +41 -0
  22. data/lib/gandi_v5/data.rb +244 -0
  23. data/lib/gandi_v5/domain/auto_renew.rb +64 -0
  24. data/lib/gandi_v5/domain/contact.rb +102 -0
  25. data/lib/gandi_v5/domain/contract.rb +22 -0
  26. data/lib/gandi_v5/domain/dates.rb +44 -0
  27. data/lib/gandi_v5/domain/renewal_information.rb +41 -0
  28. data/lib/gandi_v5/domain/restore_information.rb +18 -0
  29. data/lib/gandi_v5/domain/sharing_space.rb +21 -0
  30. data/lib/gandi_v5/domain.rb +431 -0
  31. data/lib/gandi_v5/email/mailbox/responder.rb +36 -0
  32. data/lib/gandi_v5/email/mailbox.rb +236 -0
  33. data/lib/gandi_v5/email/offer.rb +27 -0
  34. data/lib/gandi_v5/email/slot.rb +134 -0
  35. data/lib/gandi_v5/email.rb +11 -0
  36. data/lib/gandi_v5/error/gandi_error.rb +21 -0
  37. data/lib/gandi_v5/error.rb +9 -0
  38. data/lib/gandi_v5/live_dns/domain.rb +211 -0
  39. data/lib/gandi_v5/live_dns/record_set.rb +79 -0
  40. data/lib/gandi_v5/live_dns/zone/snapshot.rb +62 -0
  41. data/lib/gandi_v5/live_dns/zone.rb +301 -0
  42. data/lib/gandi_v5/live_dns.rb +30 -0
  43. data/lib/gandi_v5/organization.rb +66 -0
  44. data/lib/gandi_v5/version.rb +5 -0
  45. data/lib/gandi_v5.rb +178 -0
  46. data/spec/.rubocop.yml +4 -0
  47. data/spec/features/domain_spec.rb +45 -0
  48. data/spec/features/livedns_domain_spec.rb +8 -0
  49. data/spec/features/livedns_zone_spec.rb +45 -0
  50. data/spec/features/mailbox_spec.rb +18 -0
  51. data/spec/fixtures/bodies/GandiV5_Billing/info.yaml +10 -0
  52. data/spec/fixtures/bodies/GandiV5_Domain/availability.yaml +15 -0
  53. data/spec/fixtures/bodies/GandiV5_Domain/fetch_contacts.yaml +8 -0
  54. data/spec/fixtures/bodies/GandiV5_Domain/get.yaml +37 -0
  55. data/spec/fixtures/bodies/GandiV5_Domain/list.yaml +20 -0
  56. data/spec/fixtures/bodies/GandiV5_Domain/renewal_info.yaml +12 -0
  57. data/spec/fixtures/bodies/GandiV5_Domain/restore_info.yaml +5 -0
  58. data/spec/fixtures/bodies/GandiV5_Domain/tld.yaml +10 -0
  59. data/spec/fixtures/bodies/GandiV5_Domain/tlds.yaml +7 -0
  60. data/spec/fixtures/bodies/GandiV5_Email_Mailbox/get.yaml +16 -0
  61. data/spec/fixtures/bodies/GandiV5_Email_Mailbox/list.yaml +8 -0
  62. data/spec/fixtures/bodies/GandiV5_Email_Slot/get.yaml +10 -0
  63. data/spec/fixtures/bodies/GandiV5_Email_Slot/list.yaml +8 -0
  64. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/get.yaml +4 -0
  65. data/spec/fixtures/bodies/GandiV5_LiveDNS_Domain/list.yaml +2 -0
  66. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/get.yaml +11 -0
  67. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone/list.yaml +11 -0
  68. data/spec/fixtures/bodies/GandiV5_LiveDNS_Zone_Snapshot/get.yaml +9 -0
  69. data/spec/fixtures/bodies/GandiV5_Organization/get.yaml +17 -0
  70. data/spec/fixtures/vcr/Domain_features/List_domains.yml +54 -0
  71. data/spec/fixtures/vcr/Domain_features/Renew_domain.yml +133 -0
  72. data/spec/fixtures/vcr/LiveDNS_Domain_features/List_domains.yml +32 -0
  73. data/spec/fixtures/vcr/LiveDNS_Zone_features/List_zones.yml +42 -0
  74. data/spec/fixtures/vcr/LiveDNS_Zone_features/Make_and_save_snapshot.yml +72 -0
  75. data/spec/fixtures/vcr/LiveDNS_Zone_features/Save_zone_to_file.yml +28 -0
  76. data/spec/fixtures/vcr/Mailbox_features/List_mailboxes.yml +39 -0
  77. data/spec/spec_helper.rb +60 -0
  78. data/spec/test.env +1 -0
  79. data/spec/units/gandi_v5/billing/info/prepaid_spec.rb +20 -0
  80. data/spec/units/gandi_v5/billing/info_spec.rb +4 -0
  81. data/spec/units/gandi_v5/billing_spec.rb +41 -0
  82. data/spec/units/gandi_v5/data/converter/array_of_spec.rb +18 -0
  83. data/spec/units/gandi_v5/data/converter/symbol_spec.rb +16 -0
  84. data/spec/units/gandi_v5/data/converter/time_spec.rb +16 -0
  85. data/spec/units/gandi_v5/data/converter_spec.rb +31 -0
  86. data/spec/units/gandi_v5/data_spec.rb +340 -0
  87. data/spec/units/gandi_v5/domain/auto_renew_spec.rb +70 -0
  88. data/spec/units/gandi_v5/domain/contact_spec.rb +36 -0
  89. data/spec/units/gandi_v5/domain/contract_spec.rb +4 -0
  90. data/spec/units/gandi_v5/domain/dates_spec.rb +4 -0
  91. data/spec/units/gandi_v5/domain/renewal_information_spec.rb +81 -0
  92. data/spec/units/gandi_v5/domain/restore_information_spec.rb +4 -0
  93. data/spec/units/gandi_v5/domain/sharing_space_spec.rb +4 -0
  94. data/spec/units/gandi_v5/domain_spec.rb +451 -0
  95. data/spec/units/gandi_v5/email/mailbox/responder_spec.rb +131 -0
  96. data/spec/units/gandi_v5/email/mailbox_spec.rb +384 -0
  97. data/spec/units/gandi_v5/email/offer_spec.rb +17 -0
  98. data/spec/units/gandi_v5/email/slot_spec.rb +102 -0
  99. data/spec/units/gandi_v5/error/gandi_error_spec.rb +30 -0
  100. data/spec/units/gandi_v5/error_spec.rb +4 -0
  101. data/spec/units/gandi_v5/live_dns/domain_spec.rb +247 -0
  102. data/spec/units/gandi_v5/live_dns/record_set_spec.rb +74 -0
  103. data/spec/units/gandi_v5/live_dns/zone/snapshot_spec.rb +37 -0
  104. data/spec/units/gandi_v5/live_dns/zone_spec.rb +329 -0
  105. data/spec/units/gandi_v5/live_dns_spec.rb +17 -0
  106. data/spec/units/gandi_v5/organization_spec.rb +30 -0
  107. data/spec/units/gandi_v5_spec.rb +204 -0
  108. 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
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe GandiV5::Error::GandiError do
4
+ end