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.
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