brickset_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +4 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +145 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/brickset.gemspec +30 -0
  13. data/lib/brickset.rb +55 -0
  14. data/lib/brickset/api/auth.rb +22 -0
  15. data/lib/brickset/api/collection/advanced.rb +34 -0
  16. data/lib/brickset/api/collection/minifig.rb +35 -0
  17. data/lib/brickset/api/collection/set.rb +117 -0
  18. data/lib/brickset/api/set.rb +157 -0
  19. data/lib/brickset/client.rb +56 -0
  20. data/lib/brickset/configuration.rb +9 -0
  21. data/lib/brickset/elements/additional_image.rb +13 -0
  22. data/lib/brickset/elements/collection_detail.rb +28 -0
  23. data/lib/brickset/elements/collection_total.rb +15 -0
  24. data/lib/brickset/elements/condition.rb +11 -0
  25. data/lib/brickset/elements/instruction.rb +12 -0
  26. data/lib/brickset/elements/minifig_collection.rb +15 -0
  27. data/lib/brickset/elements/review.rb +20 -0
  28. data/lib/brickset/elements/set.rb +67 -0
  29. data/lib/brickset/elements/subtheme.rb +15 -0
  30. data/lib/brickset/elements/theme.rb +15 -0
  31. data/lib/brickset/elements/user_note.rb +12 -0
  32. data/lib/brickset/elements/year.rb +13 -0
  33. data/lib/brickset/version.rb +3 -0
  34. data/spec/brickset/api/auth_spec.rb +84 -0
  35. data/spec/brickset/api/collection/advanced_spec.rb +59 -0
  36. data/spec/brickset/api/collection/minifig_spec.rb +95 -0
  37. data/spec/brickset/api/collection/set_spec.rb +350 -0
  38. data/spec/brickset/api/set_spec.rb +658 -0
  39. data/spec/brickset/client_spec.rb +155 -0
  40. data/spec/brickset/configuration_spec.rb +9 -0
  41. data/spec/brickset/elements/additional_image_spec.rb +26 -0
  42. data/spec/brickset/elements/collection_detail_spec.rb +40 -0
  43. data/spec/brickset/elements/collection_total_spec.rb +27 -0
  44. data/spec/brickset/elements/condition_spec.rb +23 -0
  45. data/spec/brickset/elements/instruction_spec.rb +24 -0
  46. data/spec/brickset/elements/minifig_collection_spec.rb +27 -0
  47. data/spec/brickset/elements/review_spec.rb +32 -0
  48. data/spec/brickset/elements/set_spec.rb +72 -0
  49. data/spec/brickset/elements/subtheme_spec.rb +27 -0
  50. data/spec/brickset/elements/theme_spec.rb +27 -0
  51. data/spec/brickset/elements/user_note_spec.rb +24 -0
  52. data/spec/brickset/elements/year_spec.rb +25 -0
  53. data/spec/brickset_spec.rb +59 -0
  54. data/spec/fixtures/api_key_invalid.xml +2 -0
  55. data/spec/fixtures/api_key_valid.xml +2 -0
  56. data/spec/fixtures/get_additional_images.xml +24 -0
  57. data/spec/fixtures/get_additional_images_no_result.xml +2 -0
  58. data/spec/fixtures/get_collection_detail.xml +23 -0
  59. data/spec/fixtures/get_collection_detail_conditions.xml +24 -0
  60. data/spec/fixtures/get_collection_detail_no_result.xml +2 -0
  61. data/spec/fixtures/get_collection_totals.xml +8 -0
  62. data/spec/fixtures/get_collection_totals_no_result.xml +8 -0
  63. data/spec/fixtures/get_instructions.xml +7 -0
  64. data/spec/fixtures/get_instructions_no_result.xml +2 -0
  65. data/spec/fixtures/get_minifig_collection.xml +31 -0
  66. data/spec/fixtures/get_minifig_collection_owned.xml +17 -0
  67. data/spec/fixtures/get_minifig_collection_wanted.xml +10 -0
  68. data/spec/fixtures/get_recently_updated_sets.xml +52 -0
  69. data/spec/fixtures/get_recently_updated_sets_invalid_key.xml +1 -0
  70. data/spec/fixtures/get_reviews.xml +28 -0
  71. data/spec/fixtures/get_reviews_no_result.xml +2 -0
  72. data/spec/fixtures/get_set.xml +52 -0
  73. data/spec/fixtures/get_set_no_result.xml +2 -0
  74. data/spec/fixtures/get_sets.xml +101 -0
  75. data/spec/fixtures/get_sets_no_result.xml +2 -0
  76. data/spec/fixtures/get_subthemes.xml +24 -0
  77. data/spec/fixtures/get_subthemes_for_user.xml +24 -0
  78. data/spec/fixtures/get_subthemes_for_user_no_result.xml +2 -0
  79. data/spec/fixtures/get_subthemes_for_user_owned.xml +24 -0
  80. data/spec/fixtures/get_subthemes_for_user_wanted.xml +31 -0
  81. data/spec/fixtures/get_subthemes_no_result.xml +2 -0
  82. data/spec/fixtures/get_themes.xml +17 -0
  83. data/spec/fixtures/get_themes_for_user.xml +17 -0
  84. data/spec/fixtures/get_themes_for_user_no_result.xml +2 -0
  85. data/spec/fixtures/get_themes_for_user_owned.xml +17 -0
  86. data/spec/fixtures/get_themes_for_user_wanted.xml +25 -0
  87. data/spec/fixtures/get_themes_no_result.xml +2 -0
  88. data/spec/fixtures/get_user_notes.xml +11 -0
  89. data/spec/fixtures/get_user_notes_no_result.xml +2 -0
  90. data/spec/fixtures/get_years.xml +18 -0
  91. data/spec/fixtures/get_years_for_user.xml +18 -0
  92. data/spec/fixtures/get_years_for_user_no_result.xml +2 -0
  93. data/spec/fixtures/get_years_for_user_owned.xml +13 -0
  94. data/spec/fixtures/get_years_for_user_wanted.xml +13 -0
  95. data/spec/fixtures/get_years_no_result.xml +2 -0
  96. data/spec/fixtures/login.xml +2 -0
  97. data/spec/fixtures/login_invalid_credentials.xml +2 -0
  98. data/spec/fixtures/login_invalid_key.xml +2 -0
  99. data/spec/fixtures/set_collection.xml +2 -0
  100. data/spec/fixtures/set_collection_invalid.xml +2 -0
  101. data/spec/fixtures/set_collection_owns.xml +2 -0
  102. data/spec/fixtures/set_collection_owns_invalid.xml +2 -0
  103. data/spec/fixtures/set_collection_qty_owned.xml +2 -0
  104. data/spec/fixtures/set_collection_qty_owned_invalid.xml +2 -0
  105. data/spec/fixtures/set_collection_user_notes.xml +2 -0
  106. data/spec/fixtures/set_collection_user_notes_invalid.xml +2 -0
  107. data/spec/fixtures/set_collection_wants.xml +2 -0
  108. data/spec/fixtures/set_collection_wants_invalid.xml +2 -0
  109. data/spec/fixtures/set_minifig_collection.xml +2 -0
  110. data/spec/fixtures/set_minifig_collection_invalid.xml +2 -0
  111. data/spec/fixtures/set_user_rating.xml +2 -0
  112. data/spec/fixtures/set_user_rating_invalid.xml +2 -0
  113. data/spec/fixtures/token_invalid.xml +2 -0
  114. data/spec/fixtures/token_valid.xml +2 -0
  115. data/spec/spec_helper.rb +43 -0
  116. metadata +355 -0
@@ -0,0 +1,658 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Brickset::Client, type: :model do
4
+ let(:api_key) { Brickset.configuration.api_key }
5
+ let(:token) { 'valid' }
6
+
7
+ subject { described_class.new(token: token) }
8
+
9
+ describe 'constants' do
10
+ it { expect(described_class::Order::Types::NUMBER).to eq 'number' }
11
+ it { expect(described_class::Order::Types::NAME).to eq 'name' }
12
+ it { expect(described_class::Order::Types::THEME).to eq 'theme' }
13
+ it { expect(described_class::Order::Types::PIECES).to eq 'pieces' }
14
+ it { expect(described_class::Order::Types::RATING).to eq 'rating' }
15
+ it { expect(described_class::Order::Types::SUBTHEME).to eq 'subtheme' }
16
+ it { expect(described_class::Order::Types::MINIFIGS).to eq 'minifigs' }
17
+ it { expect(described_class::Order::Types::YEAR_FROM).to eq 'yearfrom' }
18
+ it { expect(described_class::Order::Types::RETAIL_PRICE_UK).to eq 'ukretailprice' }
19
+ it { expect(described_class::Order::Types::RETAIL_PRICE_US).to eq 'usretailprice' }
20
+ it { expect(described_class::Order::Types::RETAIL_PRICE_CA).to eq 'caretailprice' }
21
+ it { expect(described_class::Order::Types::RETAIL_PRICE_EU).to eq 'euretailprice' }
22
+ it { expect(described_class::Order::Types::RANDOM).to eq 'random' }
23
+ it { expect(described_class::Order::Types::ALL).to match_array %w(number name theme pieces rating subtheme minifigs yearfrom ukretailprice usretailprice caretailprice euretailprice random) }
24
+
25
+ it { expect(described_class::Order::Direction::ASC).to eq 'asc' }
26
+ it { expect(described_class::Order::Direction::DESC).to eq 'desc' }
27
+ it { expect(described_class::Order::Direction::ALL).to match_array %w(asc desc) }
28
+ end
29
+
30
+ describe 'validations' do
31
+ it { is_expected.to allow_values('75192-1', 'darthvader-1').for(:set_number).on(:sets) }
32
+ it { is_expected.to validate_numericality_of(:page_size).only_integer.on(:sets) }
33
+ it { is_expected.to validate_numericality_of(:page_number).only_integer.on(:sets) }
34
+ it { is_expected.to validate_inclusion_of(:order_by).in_array(described_class::Order::Types::ALL).on :sets }
35
+ it { is_expected.to validate_inclusion_of(:order_direction).in_array(described_class::Order::Direction::ALL).on :sets }
36
+
37
+ it { is_expected.to validate_numericality_of(:set_id).only_integer.on(:set) }
38
+ it { is_expected.to validate_numericality_of(:set_id).only_integer.on(:additional_images) }
39
+ it { is_expected.to validate_numericality_of(:set_id).only_integer.on(:reviews) }
40
+ it { is_expected.to validate_numericality_of(:set_id).only_integer.on(:instructions) }
41
+
42
+ it { is_expected.to validate_numericality_of(:minutes_ago).only_integer.on(:recently_updated_sets) }
43
+ end
44
+
45
+ describe '#sets' do
46
+ let(:query) { '' }
47
+ let(:theme) { '' }
48
+ let(:subtheme) { '' }
49
+ let(:set_number) { '' }
50
+ let(:year) { '' }
51
+ let(:owned) { '' }
52
+ let(:wanted) { '' }
53
+ let(:order_by) { 'number' }
54
+ let(:page_size) { 20 }
55
+ let(:page_number) { 1 }
56
+ let(:username) { '' }
57
+
58
+ let(:sets) { subject.sets(query: query, theme: theme, subtheme: subtheme, set_number: set_number, year: year, owned: owned, wanted: wanted, order_by: order_by, page_size: page_size, page_number: page_number, username: username) }
59
+
60
+ context 'when all of the parameters are valid' do
61
+ before { stub_post('/getSets').with(body: "query=#{query}&theme=#{theme}&subtheme=#{subtheme}&setNumber=#{set_number}&year=#{year}&owned=#{owned}&wanted=#{wanted}&orderBy=#{order_by}&pageSize=#{page_size}&pageNumber=#{page_number}&userName=#{username}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
62
+
63
+ context 'when there is a result' do
64
+ let(:body) { fixture('get_sets.xml') }
65
+
66
+ it 'returns the sets' do
67
+ expect(sets).to match_array [
68
+ an_instance_of(Brickset::Elements::Set),
69
+ an_instance_of(Brickset::Elements::Set)
70
+ ]
71
+ end
72
+ end
73
+
74
+ context 'when there is no result' do
75
+ let(:body) { fixture('get_sets_no_result.xml') }
76
+
77
+ it 'returns an empty array' do
78
+ expect(sets).to match_array []
79
+ end
80
+ end
81
+ end
82
+
83
+ context 'when not all of the parameters are valid' do
84
+ let(:set_number) { '12345-a' }
85
+ let(:order_by) { 'non-existent' }
86
+
87
+ it 'raises a ValidationError' do
88
+ expect { sets }.to raise_error Brickset::ValidationError, 'Set number format of <number>-<variant>, e.g. 75192-1 or darthvader-1 and Order by is not included in the list'
89
+ end
90
+ end
91
+ end
92
+
93
+ describe '#set' do
94
+ let(:set_id) { 5860 }
95
+ let(:set) { subject.set(set_id) }
96
+
97
+ context 'when the set ID is an integer' do
98
+ before { stub_post('/getSet').with(body: "setID=#{set_id}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
99
+
100
+ context 'when there is a result' do
101
+ let(:body) { fixture('get_set.xml') }
102
+
103
+ it 'returns the set' do
104
+ expect(set).to an_instance_of(Brickset::Elements::Set)
105
+ end
106
+ end
107
+
108
+ context 'when there is no result' do
109
+ let(:body) { fixture('get_set_no_result.xml') }
110
+
111
+ it 'returns nil' do
112
+ expect(set).to be_nil
113
+ end
114
+ end
115
+ end
116
+
117
+ context 'when the set ID is not an integer' do
118
+ let(:set_id) { 'set-number' }
119
+
120
+ it 'raises a ValidationError' do
121
+ expect { set }.to raise_error Brickset::ValidationError, 'Set is not a number'
122
+ end
123
+ end
124
+ end
125
+
126
+ describe '#recently_updated_sets' do
127
+ let(:minutes_ago) { 60 }
128
+
129
+ let(:recently_updated_sets) { subject.recently_updated_sets(minutes_ago) }
130
+
131
+ context 'when minutes ago is an integer' do
132
+ context 'with a valid API key' do
133
+ before { stub_post('/getRecentlyUpdatedSets').with(body: "minutesAgo=#{minutes_ago}&apiKey=#{api_key}&userHash=#{token}").to_return body: fixture('get_recently_updated_sets.xml') }
134
+
135
+ it 'receives the recently updated sets' do
136
+ expect(recently_updated_sets).to match_array [ an_instance_of(Brickset::Elements::Set) ]
137
+ end
138
+ end
139
+
140
+ context 'with an invalid API key' do
141
+ let(:api_key) { 'invalid' }
142
+
143
+ before do
144
+ allow(Brickset).to receive(:configuration).and_return double(api_key: api_key)
145
+ stub_post('/getRecentlyUpdatedSets').with(body: "minutesAgo=#{minutes_ago}&apiKey=#{api_key}&userHash=#{token}").to_return body: fixture('get_recently_updated_sets_invalid_key.xml')
146
+ end
147
+
148
+ it 'does not receive any recently updated sets' do
149
+ expect(recently_updated_sets).to match_array []
150
+ end
151
+ end
152
+ end
153
+
154
+ context 'when minutes ago is not an integer' do
155
+ let(:minutes_ago) { 'five' }
156
+
157
+ it 'raises a ValidationError' do
158
+ expect { recently_updated_sets }.to raise_error Brickset::ValidationError, 'Minutes ago is not a number'
159
+ end
160
+ end
161
+ end
162
+
163
+ describe '#additional_images' do
164
+ let(:set_id) { 5860 }
165
+ let(:additional_images) { subject.additional_images(set_id) }
166
+
167
+ context 'when the set ID is an integer' do
168
+ before { stub_post('/getAdditionalImages').with(body: "setID=#{set_id}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
169
+
170
+ context 'when there is a result' do
171
+ let(:body) { fixture('get_additional_images.xml') }
172
+
173
+ it 'returns the instructions' do
174
+ expect(additional_images).to match_array [
175
+ an_instance_of(Brickset::Elements::AdditionalImage),
176
+ an_instance_of(Brickset::Elements::AdditionalImage),
177
+ an_instance_of(Brickset::Elements::AdditionalImage),
178
+ an_instance_of(Brickset::Elements::AdditionalImage),
179
+ an_instance_of(Brickset::Elements::AdditionalImage)
180
+ ]
181
+ end
182
+ end
183
+
184
+ context 'when there is no result' do
185
+ let(:body) { fixture('get_additional_images_no_result.xml') }
186
+
187
+ it 'returns an empty array' do
188
+ expect(additional_images).to match_array []
189
+ end
190
+ end
191
+ end
192
+
193
+ context 'when the set ID is not an integer' do
194
+ let(:set_id) { 'set-number' }
195
+
196
+ it 'raises a ValidationError' do
197
+ expect { additional_images }.to raise_error Brickset::ValidationError, 'Set is not a number'
198
+ end
199
+ end
200
+ end
201
+
202
+ describe '#reviews' do
203
+ let(:set_id) { 5860 }
204
+ let(:reviews) { subject.reviews(set_id) }
205
+
206
+ context 'when the set ID is an integer' do
207
+ before { stub_post('/getReviews').with(body: "setID=#{set_id}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
208
+
209
+ context 'when there is a result' do
210
+ let(:body) { fixture('get_reviews.xml') }
211
+
212
+ it 'returns the instructions' do
213
+ expect(reviews).to match_array [ an_instance_of(Brickset::Elements::Review) ]
214
+ end
215
+ end
216
+
217
+ context 'when there is no result' do
218
+ let(:body) { fixture('get_reviews_no_result.xml') }
219
+
220
+ it 'returns an empty array' do
221
+ expect(reviews).to match_array []
222
+ end
223
+ end
224
+ end
225
+
226
+ context 'when the set ID is not an integer' do
227
+ let(:set_id) { 'set-number' }
228
+
229
+ it 'raises a ValidationError' do
230
+ expect { reviews }.to raise_error Brickset::ValidationError, 'Set is not a number'
231
+ end
232
+ end
233
+ end
234
+
235
+ describe '#instructions' do
236
+ let(:set_id) { 5860 }
237
+ let(:instructions) { subject.instructions(set_id) }
238
+
239
+ context 'when the set ID is an integer' do
240
+ before { stub_post('/getInstructions').with(body: "setID=#{set_id}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
241
+
242
+ context 'when there is a result' do
243
+ let(:body) { fixture('get_instructions.xml') }
244
+
245
+ it 'returns the instructions' do
246
+ expect(instructions).to match_array [ an_instance_of(Brickset::Elements::Instruction) ]
247
+ end
248
+ end
249
+
250
+ context 'when there is no result' do
251
+ let(:body) { fixture('get_instructions_no_result.xml') }
252
+
253
+ it 'returns an empty array' do
254
+ expect(instructions).to match_array []
255
+ end
256
+ end
257
+ end
258
+
259
+ context 'when the set ID is not an integer' do
260
+ let(:set_id) { 'set-number' }
261
+
262
+ it 'raises a ValidationError' do
263
+ expect { instructions }.to raise_error Brickset::ValidationError, 'Set is not a number'
264
+ end
265
+ end
266
+ end
267
+
268
+ describe '#themes' do
269
+ let(:themes) { subject.themes }
270
+
271
+ before { stub_post('/getThemes').with(body: "apiKey=#{api_key}&userHash=#{token}").to_return body: body }
272
+
273
+ context 'when there is a result' do
274
+ let(:body) { fixture('get_themes.xml') }
275
+
276
+ it 'returns the themes' do
277
+ expect(themes).to match_array [
278
+ an_instance_of(Brickset::Elements::Theme),
279
+ an_instance_of(Brickset::Elements::Theme)
280
+ ]
281
+ end
282
+
283
+ it 'knows the number of sets and subthemes of the a theme' do
284
+ aggregate_failures do
285
+ expect(themes.last.theme).to eq 'Star Wars'
286
+ expect(themes.last.set_count).to eq 821
287
+ expect(themes.last.subtheme_count).to eq 29
288
+ end
289
+ end
290
+ end
291
+
292
+ context 'when there is no result' do
293
+ let(:body) { fixture('get_themes_no_result.xml') }
294
+
295
+ it 'returns an empty array' do
296
+ expect(themes).to match_array []
297
+ end
298
+ end
299
+ end
300
+
301
+ describe '#subthemes' do
302
+ let(:theme) { 'Star Wars' }
303
+ let(:subthemes) { subject.subthemes(theme) }
304
+
305
+ before { stub_post('/getSubthemes').with(body: "theme=#{ERB::Util.url_encode(theme)}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
306
+
307
+ context 'when there is a result' do
308
+ let(:body) { fixture('get_subthemes.xml') }
309
+
310
+ it 'returns the subthemes for the specified theme' do
311
+ expect(subthemes).to match_array [
312
+ an_instance_of(Brickset::Elements::Subtheme),
313
+ an_instance_of(Brickset::Elements::Subtheme),
314
+ an_instance_of(Brickset::Elements::Subtheme)
315
+ ]
316
+ end
317
+
318
+ it 'knows the number of sets of the subtheme for the specified theme' do
319
+ aggregate_failures do
320
+ expect(subthemes.last.subtheme).to eq 'MicroFighters'
321
+ expect(subthemes.last.set_count).to eq 26
322
+ end
323
+ end
324
+ end
325
+
326
+ context 'when there is no result' do
327
+ let(:theme) { 'Star Warz' }
328
+
329
+ let(:body) { fixture('get_subthemes_no_result.xml') }
330
+
331
+ it 'returns an empty array' do
332
+ expect(subthemes).to match_array []
333
+ end
334
+ end
335
+ end
336
+
337
+ describe '#years' do
338
+ let(:theme) { 'Star Wars' }
339
+ let(:years) { subject.years(theme) }
340
+
341
+ before { stub_post('/getYears').with(body: "theme=#{ERB::Util.url_encode(theme)}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
342
+
343
+ context 'when there is a result' do
344
+ let(:body) { fixture('get_years.xml') }
345
+
346
+ it 'returns the years for the specified theme' do
347
+ expect(years).to match_array [
348
+ an_instance_of(Brickset::Elements::Year),
349
+ an_instance_of(Brickset::Elements::Year),
350
+ an_instance_of(Brickset::Elements::Year)
351
+ ]
352
+ end
353
+
354
+ it 'knows the number of sets of the years for the specified theme' do
355
+ aggregate_failures do
356
+ expect(years.last.year).to eq '2018'
357
+ expect(years.last.set_count).to eq 64
358
+ end
359
+ end
360
+ end
361
+
362
+ context 'when there is no result' do
363
+ let(:theme) { 'Star Warz' }
364
+
365
+ let(:body) { fixture('get_years_no_result.xml') }
366
+
367
+ it 'returns an empty array' do
368
+ expect(years).to match_array []
369
+ end
370
+ end
371
+ end
372
+
373
+ describe '#themes_for_user' do
374
+ let(:owned) { nil }
375
+ let(:wanted) { nil }
376
+
377
+ let(:themes_for_user) { subject.themes_for_user(owned: owned, wanted: wanted) }
378
+
379
+ before { stub_post('/getThemesForUser').with(body: "owned=#{owned}&wanted=#{wanted}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
380
+
381
+ context 'when there is a result' do
382
+ context 'when no parameter is specified' do
383
+ let(:body) { fixture('get_themes_for_user.xml') }
384
+
385
+ it 'returns the themes for the user' do
386
+ expect(themes_for_user).to match_array [
387
+ an_instance_of(Brickset::Elements::Theme),
388
+ an_instance_of(Brickset::Elements::Theme)
389
+ ]
390
+ end
391
+
392
+ it 'knows the subtheme count, year from and to of the themes for the user' do
393
+ aggregate_failures do
394
+ expect(themes_for_user.last.subtheme_count).to eq 29
395
+ expect(themes_for_user.last.year_from).to eq 1999
396
+ expect(themes_for_user.last.year_to).to eq 2018
397
+ end
398
+ end
399
+
400
+ it 'knows the number of sets of the themes for the user' do
401
+ expect(themes_for_user.last.set_count).to eq 821
402
+ end
403
+ end
404
+
405
+ context 'when an owned theme is specified' do
406
+ let(:body) { fixture('get_themes_for_user_owned.xml') }
407
+
408
+ it 'returns the owned themes for the user' do
409
+ expect(themes_for_user).to match_array [
410
+ an_instance_of(Brickset::Elements::Theme),
411
+ an_instance_of(Brickset::Elements::Theme)
412
+ ]
413
+ end
414
+
415
+ it 'knows that the subtheme count, year from and to of the owned themes for the user are not populated' do
416
+ aggregate_failures do
417
+ expect(themes_for_user.last.subtheme_count).to eq 0
418
+ expect(themes_for_user.last.year_from).to eq 0
419
+ expect(themes_for_user.last.year_to).to eq 0
420
+ end
421
+ end
422
+
423
+ it 'knows the number of sets of the owned themes for the user' do
424
+ expect(themes_for_user.last.set_count).to eq 26
425
+ end
426
+ end
427
+
428
+ context 'when a wanted theme is specified' do
429
+ let(:body) { fixture('get_themes_for_user_wanted.xml') }
430
+
431
+ it 'returns the wanted themes for the user' do
432
+ expect(themes_for_user).to match_array [
433
+ an_instance_of(Brickset::Elements::Theme),
434
+ an_instance_of(Brickset::Elements::Theme),
435
+ an_instance_of(Brickset::Elements::Theme)
436
+ ]
437
+ end
438
+
439
+ it 'knows that the subtheme count, year from and to of the wanted themes for the user are not populated' do
440
+ aggregate_failures do
441
+ expect(themes_for_user.last.subtheme_count).to eq 0
442
+ expect(themes_for_user.last.year_from).to eq 0
443
+ expect(themes_for_user.last.year_to).to eq 0
444
+ end
445
+ end
446
+
447
+ it 'knows the number of sets of the wanted themes for the user' do
448
+ expect(themes_for_user.last.set_count).to eq 3
449
+ end
450
+ end
451
+ end
452
+
453
+ context 'when there is no result' do
454
+ let(:body) { fixture('get_themes_for_user_no_result.xml') }
455
+
456
+ it 'returns an empty array' do
457
+ expect(themes_for_user).to match_array []
458
+ end
459
+ end
460
+ end
461
+
462
+ describe '#subthemes_for_user' do
463
+ let(:theme) { 'Star Wars' }
464
+ let(:owned) { nil }
465
+ let(:wanted) { nil }
466
+
467
+ let(:subthemes_for_user) { subject.subthemes_for_user(theme, owned: owned, wanted: wanted) }
468
+
469
+ before { stub_post('/getSubthemesForUser').with(body: "theme=#{ERB::Util.url_encode(theme)}&owned=#{owned}&wanted=#{wanted}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
470
+
471
+ context 'when there is a result' do
472
+ context 'when only a theme is specified' do
473
+ let(:body) { fixture('get_subthemes_for_user.xml') }
474
+
475
+ it 'returns the subthemes for the specified theme' do
476
+ expect(subthemes_for_user).to match_array [
477
+ an_instance_of(Brickset::Elements::Subtheme),
478
+ an_instance_of(Brickset::Elements::Subtheme),
479
+ an_instance_of(Brickset::Elements::Subtheme)
480
+ ]
481
+ end
482
+
483
+ it 'knows the year from and to of the subthemes for the specified theme' do
484
+ aggregate_failures do
485
+ expect(subthemes_for_user.last.year_from).to eq 2014
486
+ expect(subthemes_for_user.last.year_to).to eq 2018
487
+ end
488
+ end
489
+
490
+ it 'knows the number of sets of the subthemes for the specified theme' do
491
+ expect(subthemes_for_user.last.set_count).to eq 26
492
+ end
493
+ end
494
+
495
+ context 'when an owned theme is specified' do
496
+ let(:body) { fixture('get_subthemes_for_user_owned.xml') }
497
+
498
+ it 'returns the subthemes for the specified owned theme' do
499
+ expect(subthemes_for_user).to match_array [
500
+ an_instance_of(Brickset::Elements::Subtheme),
501
+ an_instance_of(Brickset::Elements::Subtheme),
502
+ an_instance_of(Brickset::Elements::Subtheme)
503
+ ]
504
+ end
505
+
506
+ it 'knows that the year from and to of the subthemes for the specified owned theme are not populated' do
507
+ aggregate_failures do
508
+ expect(subthemes_for_user.last.year_from).to eq 0
509
+ expect(subthemes_for_user.last.year_to).to eq 0
510
+ end
511
+ end
512
+
513
+ it 'knows the number of sets of the subthemes for the specified owned theme' do
514
+ expect(subthemes_for_user.last.set_count).to eq 2
515
+ end
516
+ end
517
+
518
+ context 'when a wanted theme is specified' do
519
+ let(:body) { fixture('get_subthemes_for_user_wanted.xml') }
520
+
521
+ it 'returns the subthemes for the specified wanted theme' do
522
+ expect(subthemes_for_user).to match_array [
523
+ an_instance_of(Brickset::Elements::Subtheme),
524
+ an_instance_of(Brickset::Elements::Subtheme),
525
+ an_instance_of(Brickset::Elements::Subtheme),
526
+ an_instance_of(Brickset::Elements::Subtheme)
527
+ ]
528
+ end
529
+
530
+ it 'knows that the year from and to of the subthemes for the specified wanted theme are not populated' do
531
+ aggregate_failures do
532
+ expect(subthemes_for_user.last.year_from).to eq 0
533
+ expect(subthemes_for_user.last.year_to).to eq 0
534
+ end
535
+ end
536
+
537
+ it 'knows the number of sets of the subthemes for the specified wanted theme' do
538
+ expect(subthemes_for_user.last.set_count).to eq 1
539
+ end
540
+ end
541
+ end
542
+
543
+ context 'when there is no result' do
544
+ let(:theme) { 'Star Warz' }
545
+
546
+ let(:body) { fixture('get_subthemes_for_user_no_result.xml') }
547
+
548
+ it 'returns an empty array' do
549
+ expect(subthemes_for_user).to match_array []
550
+ end
551
+ end
552
+ end
553
+
554
+ describe '#years_for_user' do
555
+ let(:theme) { 'Star Wars' }
556
+ let(:owned) { nil }
557
+ let(:wanted) { nil }
558
+
559
+ let(:years_for_user) { subject.years_for_user(theme, owned: owned, wanted: wanted) }
560
+
561
+ before { stub_post('/getYearsForUser').with(body: "theme=#{ERB::Util.url_encode(theme)}&owned=#{owned}&wanted=#{wanted}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
562
+
563
+ context 'when there is a result' do
564
+ context 'when only a theme is specified' do
565
+ let(:body) { fixture('get_years_for_user.xml') }
566
+
567
+ it 'returns the years for the specified theme' do
568
+ expect(years_for_user).to match_array [
569
+ an_instance_of(Brickset::Elements::Year),
570
+ an_instance_of(Brickset::Elements::Year),
571
+ an_instance_of(Brickset::Elements::Year)
572
+ ]
573
+ end
574
+
575
+ it 'knows the number of sets of the years for the specified theme' do
576
+ aggregate_failures do
577
+ expect(years_for_user.last.year).to eq '2018'
578
+ expect(years_for_user.last.set_count).to eq 64
579
+ end
580
+ end
581
+ end
582
+
583
+ context 'when an owned theme is specified' do
584
+ let(:body) { fixture('get_years_for_user_owned.xml') }
585
+
586
+ it 'returns the years for the specified owned theme' do
587
+ expect(years_for_user).to match_array [
588
+ an_instance_of(Brickset::Elements::Year),
589
+ an_instance_of(Brickset::Elements::Year)
590
+ ]
591
+ end
592
+
593
+ it 'knows the number of sets of the years for the specified owned theme' do
594
+ aggregate_failures do
595
+ expect(years_for_user.last.year).to eq '2018'
596
+ expect(years_for_user.last.set_count).to eq 3
597
+ end
598
+ end
599
+ end
600
+
601
+ context 'when a wanted theme is specified' do
602
+ let(:body) { fixture('get_years_for_user_wanted.xml') }
603
+
604
+ it 'returns the years for the specified wanted theme' do
605
+ expect(years_for_user).to match_array [
606
+ an_instance_of(Brickset::Elements::Year),
607
+ an_instance_of(Brickset::Elements::Year)
608
+ ]
609
+ end
610
+
611
+ it 'knows the number of sets of the years for the specified wanted theme' do
612
+ aggregate_failures do
613
+ expect(years_for_user.last.year).to eq '2018'
614
+ expect(years_for_user.last.set_count).to eq 50
615
+ end
616
+ end
617
+ end
618
+ end
619
+
620
+ context 'when there is no result' do
621
+ let(:theme) { 'Star Warz' }
622
+
623
+ let(:body) { fixture('get_years_for_user_no_result.xml') }
624
+
625
+ it 'returns an empty array' do
626
+ expect(years_for_user).to match_array []
627
+ end
628
+ end
629
+ end
630
+
631
+ describe '#order' do
632
+ let(:order) { subject.send(:order) }
633
+
634
+ let(:order_by) { 'number' }
635
+
636
+ before do
637
+ subject.order_by = order_by
638
+ subject.order_direction = order_direction
639
+ end
640
+
641
+ context 'when the order direction is desc' do
642
+ let(:order_direction) { described_class::Order::Direction::DESC }
643
+
644
+ it 'concatenates the order by and order direction' do
645
+ expect(order).to eq 'numberDESC'
646
+ end
647
+ end
648
+
649
+ context 'when the order is not desc' do
650
+ let(:order_direction) { described_class::Order::Direction::ASC }
651
+
652
+ it 'returns the order_by' do
653
+ expect(order).to eq 'number'
654
+ end
655
+ end
656
+ end
657
+
658
+ end