brickset_api 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 (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