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,12 @@
1
+ module Brickset
2
+ module Elements
3
+ class UserNote
4
+ include HappyMapper
5
+
6
+ tag 'userNotes'
7
+
8
+ element :set_id, Integer, tag: 'setID'
9
+ element :user_notes, String, tag: 'userNotes'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Brickset
2
+ module Elements
3
+ class Year
4
+ include HappyMapper
5
+
6
+ tag 'years'
7
+
8
+ element :theme, String
9
+ element :year, String
10
+ element :set_count, Integer, tag: 'setCount'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Brickset
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Brickset::Client do
4
+ let(:api_key) { Brickset.configuration.api_key }
5
+
6
+ describe '#login' do
7
+ let(:username) { 'darth-vader' }
8
+ let(:password) { 'i-am-your-father' }
9
+
10
+ context 'with valid credentials and API key' do
11
+ before { stub_post('/login').with(body: "username=#{username}&password=#{password}&apiKey=#{api_key}").to_return body: fixture('login.xml') }
12
+
13
+ it 'receives an user hash' do
14
+ expect(subject.login(username, password)).to eq 'abc123!@#'
15
+ end
16
+ end
17
+
18
+ context 'with invalid credentials' do
19
+ let(:password) { 'invalid' }
20
+
21
+ before { stub_post('/login').with(body: "username=#{username}&password=#{password}&apiKey=#{api_key}").to_return body: fixture('login_invalid_credentials.xml') }
22
+
23
+ it 'receives an error response' do
24
+ expect(subject.login(username, password)).to eq 'ERROR: invalid username and/or password'
25
+ end
26
+ end
27
+
28
+ context 'with an invalid API key' do
29
+ before do
30
+ allow(Brickset).to receive(:configuration).and_return double(api_key: 'invalid')
31
+ stub_post('/login').with(body: "username=#{username}&password=#{password}&apiKey=#{api_key}").to_return body: fixture('login_invalid_key.xml')
32
+ end
33
+
34
+ it 'receives an INVALIDKEY response' do
35
+ expect(subject.login(username, password)).to eq 'INVALIDKEY'
36
+ end
37
+ end
38
+ end
39
+
40
+ describe '#valid_api_key?' do
41
+ context 'with a valid API key' do
42
+ before { stub_post('/checkKey').with(body: "apiKey=#{api_key}").to_return body: fixture('api_key_valid.xml') }
43
+
44
+ it 'returns true' do
45
+ expect(subject.valid_api_key?).to eq true
46
+ end
47
+ end
48
+
49
+ context 'with an invalid API key' do
50
+ before do
51
+ allow(Brickset).to receive(:configuration).and_return double(api_key: 'invalid')
52
+ stub_post('/checkKey').with(body: "apiKey=#{api_key}").to_return body: fixture('api_key_invalid.xml')
53
+ end
54
+
55
+ it 'returns false' do
56
+ expect(subject.valid_api_key?).to eq false
57
+ end
58
+ end
59
+ end
60
+
61
+ describe '#valid_token?' do
62
+ subject { described_class.new(token: token) }
63
+
64
+ context 'with a valid token' do
65
+ let(:token) { 'valid' }
66
+
67
+ before { stub_post('/checkUserHash').with(body: "apiKey=#{api_key}&userHash=#{token}").to_return body: fixture('token_valid.xml') }
68
+
69
+ it 'returns true' do
70
+ expect(subject.valid_token?).to eq true
71
+ end
72
+ end
73
+
74
+ context 'with an invalid token' do
75
+ let(:token) { 'invalid' }
76
+
77
+ before { stub_post('/checkUserHash').with(body: "apiKey=#{api_key}&userHash=#{token}").to_return body: fixture('token_invalid.xml') }
78
+
79
+ it 'returns false' do
80
+ expect(subject.valid_token?).to eq false
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,59 @@
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 'validations' do
10
+ it { is_expected.to validate_inclusion_of(:condition).in_array(%w(acquired now)).on :collection_detail_conditions }
11
+ end
12
+
13
+ describe 'getCollectionDetail' do
14
+ context 'with valid parameters' do
15
+ before { stub_post('/getCollectionDetail').with(body: "setID=26907&apiKey=#{api_key}&userHash=#{token}").to_return body: fixture('get_collection_detail.xml') }
16
+
17
+ it 'receives the collection detail' do
18
+ expect(subject.collection_detail(26907)).to be_a Brickset::Elements::CollectionDetail
19
+ end
20
+ end
21
+
22
+ context 'with an invalid parameter' do
23
+ before do
24
+ stub_post('/getCollectionDetail').with(body: "setID=non-existent&apiKey=#{api_key}&userHash=#{token}").to_return body: fixture('get_collection_detail_no_result.xml')
25
+ end
26
+
27
+ it 'does not receive any collection detail' do
28
+ expect(subject.collection_detail('non-existent')).to be_nil
29
+ end
30
+ end
31
+ end
32
+
33
+ describe 'getCollectionDetailConditions' do
34
+ context 'with a valid condition' do
35
+ before do
36
+ stub_post('/getCollectionDetailConditions').with(body: "which=acquired&apiKey=#{api_key}&userHash=#{token}").to_return body: fixture('get_collection_detail_conditions.xml')
37
+ end
38
+
39
+ it 'receives the collection detail conditions' do
40
+ expect(subject.collection_detail_conditions('acquired')).to match_array [
41
+ an_instance_of(Brickset::Elements::Condition),
42
+ an_instance_of(Brickset::Elements::Condition),
43
+ an_instance_of(Brickset::Elements::Condition),
44
+ an_instance_of(Brickset::Elements::Condition),
45
+ an_instance_of(Brickset::Elements::Condition),
46
+ an_instance_of(Brickset::Elements::Condition),
47
+ an_instance_of(Brickset::Elements::Condition)
48
+ ]
49
+ end
50
+ end
51
+
52
+ context 'with an invalid condition' do
53
+ it 'raises a ValidationError' do
54
+ expect { subject.collection_detail_conditions('invalid-condition') }.to raise_error Brickset::ValidationError, 'Condition is not included in the list'
55
+ end
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,95 @@
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
+ context 'validations' do
10
+ it { is_expected.to validate_presence_of(:minifig_number).on :update_minifig_collection }
11
+ it { is_expected.to validate_presence_of(:number_owned).on :update_minifig_collection }
12
+ it { is_expected.to validate_presence_of(:wanted).on :update_minifig_collection }
13
+ it { is_expected.to validate_inclusion_of(:number_owned).in_range(0..999).on :update_minifig_collection }
14
+ it { is_expected.to validate_inclusion_of(:wanted).in_array([0, 1]).on :update_minifig_collection }
15
+ end
16
+
17
+ describe '#minifig_collection' do
18
+ context 'with valid parameters' do
19
+ context 'when using the query parameter' do
20
+ before { stub_post('/getMinifigCollection').with(body: "query=Star%20Wars&owned=&wanted=&apiKey=#{api_key}&userHash=#{token}").to_return body: fixture('get_minifig_collection.xml') }
21
+
22
+ it 'returns the minifig collections that match the search query' do
23
+ expect(subject.minifig_collection(query: 'Star Wars')).to match_array [
24
+ an_instance_of(Brickset::Elements::MinifigCollection),
25
+ an_instance_of(Brickset::Elements::MinifigCollection),
26
+ an_instance_of(Brickset::Elements::MinifigCollection),
27
+ an_instance_of(Brickset::Elements::MinifigCollection)
28
+ ]
29
+ end
30
+ end
31
+
32
+ context 'when using the owned parameter' do
33
+ before { stub_post('/getMinifigCollection').with(body: "query=&owned=1&wanted=&apiKey=#{api_key}&userHash=#{token}").to_return body: fixture('get_minifig_collection_owned.xml') }
34
+
35
+ it 'returns the owned minifig collections' do
36
+ expect(subject.minifig_collection(owned: '1')).to match_array [
37
+ an_instance_of(Brickset::Elements::MinifigCollection),
38
+ an_instance_of(Brickset::Elements::MinifigCollection)
39
+ ]
40
+ end
41
+ end
42
+ context 'when using the wanted parameter' do
43
+ before { stub_post('/getMinifigCollection').with(body: "query=&owned=&wanted=1&apiKey=#{api_key}&userHash=#{token}").to_return body: fixture('get_minifig_collection_wanted.xml') }
44
+
45
+ it 'returns the wanted minifig collections' do
46
+ expect(subject.minifig_collection(wanted: '1')).to match_array [
47
+ an_instance_of(Brickset::Elements::MinifigCollection)
48
+ ]
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '#update_minifig_collection' do
55
+ let(:minifig_number) { '47205pb026' }
56
+ let(:number_owned) { 2 }
57
+ let(:wanted) { 1 }
58
+
59
+ let(:update_minifig_collection) { subject.update_minifig_collection(minifig_number: minifig_number, number_owned: number_owned, wanted: wanted) }
60
+
61
+ context 'when all required parameters are specified' do
62
+ before { stub_post('/setMinifigCollection').with(body: "minifigNumber=#{minifig_number}&qtyOwned=#{number_owned}&wanted=#{wanted}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
63
+
64
+ context 'when all parameters are valid' do
65
+ let(:body) { fixture('set_minifig_collection.xml') }
66
+
67
+ it 'updates the specified minifig collection' do
68
+ expect(update_minifig_collection).to eq true
69
+ end
70
+ end
71
+
72
+ context 'when a parameter is invalid' do
73
+ let(:body) { fixture('set_minifig_collection_invalid.xml') }
74
+
75
+ it 'does not update the specified minifig collection' do
76
+ expect(update_minifig_collection).to eq false
77
+ end
78
+
79
+ it 'sets the error on the client' do
80
+ update_minifig_collection
81
+ expect(subject.errors[:base]).to match_array [ 'ERROR: invalid userHash' ]
82
+ end
83
+ end
84
+ end
85
+
86
+ context 'when not all parameters are valid' do
87
+ let(:minifig_number) { nil }
88
+ let(:wanted) { true }
89
+
90
+ it 'raises a ValidationError' do
91
+ expect { update_minifig_collection }.to raise_error Brickset::ValidationError, "Minifig number can't be blank and Wanted is not included in the list"
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,350 @@
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 'validations' do
10
+ it { is_expected.to validate_presence_of(:set_id).on :update_collection }
11
+ it { is_expected.to validate_presence_of(:number_owned).on :update_collection }
12
+ it { is_expected.to validate_presence_of(:wanted).on :update_collection }
13
+ it { is_expected.to validate_inclusion_of(:number_owned).in_range(0..999).on :update_collection }
14
+ it { is_expected.to validate_inclusion_of(:wanted).in_array([0, 1]).on :update_collection }
15
+
16
+ it { is_expected.to validate_presence_of(:set_id).on :update_collection_owned }
17
+ it { is_expected.to validate_presence_of(:owned).on :update_collection_owned }
18
+ it { is_expected.to validate_inclusion_of(:owned).in_array([0, 1]).on :update_collection_owned }
19
+
20
+ it { is_expected.to validate_presence_of(:set_id).on :update_collection_wanted }
21
+ it { is_expected.to validate_presence_of(:wanted).on :update_collection_wanted }
22
+ it { is_expected.to validate_inclusion_of(:wanted).in_array([0, 1]).on :update_collection_wanted }
23
+
24
+ it { is_expected.to validate_presence_of(:set_id).on :update_collection_number_owned }
25
+ it { is_expected.to validate_presence_of(:number_owned).on :update_collection_number_owned }
26
+ it { is_expected.to validate_inclusion_of(:number_owned).in_range(0..999).on :update_collection_number_owned }
27
+
28
+ it { is_expected.to validate_presence_of(:set_id).on :update_collection_user_notes }
29
+ it { is_expected.to validate_presence_of(:notes).on :update_collection_user_notes }
30
+ it { is_expected.to validate_length_of(:notes).is_at_most(200).on :update_collection_user_notes }
31
+
32
+ it { is_expected.to validate_presence_of(:set_id).on :update_user_rating }
33
+ it { is_expected.to validate_presence_of(:rating).on :update_user_rating }
34
+ it { is_expected.to validate_inclusion_of(:rating).in_range(0..5).on :update_user_rating }
35
+ end
36
+
37
+ describe '#collection_totals' do
38
+ let(:body) { fixture('get_collection_totals.xml') }
39
+
40
+ before { stub_post('/getCollectionTotals').with(body: "apiKey=#{api_key}&userHash=#{token}").to_return body: body }
41
+
42
+ context 'with valid parameters' do
43
+ it 'returns the collection totals' do
44
+ aggregate_failures do
45
+ expect(subject.collection_totals).to be_a Brickset::Elements::CollectionTotal
46
+ expect(subject.collection_totals.total_sets_owned).to eq 126
47
+ expect(subject.collection_totals.total_sets_wanted).to eq 85
48
+ expect(subject.collection_totals.total_minifigs_owned).to eq 156
49
+ expect(subject.collection_totals.total_minifigs_wanted).to eq 40
50
+ expect(subject.collection_totals.total_distinct_sets_owned).to eq 121
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'with invalid parameters' do
56
+ let(:token) { 'invalid' }
57
+ let(:body) { fixture('get_collection_totals_no_result.xml') }
58
+
59
+ it 'returns a collection total with default values' do
60
+ aggregate_failures do
61
+ expect(subject.collection_totals).to be_a Brickset::Elements::CollectionTotal
62
+ expect(subject.collection_totals.total_sets_owned).to eq 0
63
+ expect(subject.collection_totals.total_sets_wanted).to eq 0
64
+ expect(subject.collection_totals.total_minifigs_owned).to eq 0
65
+ expect(subject.collection_totals.total_minifigs_wanted).to eq 0
66
+ expect(subject.collection_totals.total_distinct_sets_owned).to eq 0
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ describe '#update_collection' do
73
+ let(:set_id) { 26725 }
74
+ let(:number_owned) { 2 }
75
+ let(:wanted) { 1 }
76
+
77
+ let(:update_collection) { subject.update_collection(set_id: set_id, number_owned: number_owned, wanted: wanted) }
78
+
79
+ context 'when all required parameters are specified' do
80
+ before { stub_post('/setCollection').with(body: "setID=#{set_id}&qtyOwned=#{number_owned}&wanted=#{wanted}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
81
+
82
+ context 'when all parameters are valid' do
83
+ let(:body) { fixture('set_collection.xml') }
84
+
85
+ it 'updates the specified collection' do
86
+ expect(update_collection).to eq true
87
+ end
88
+ end
89
+
90
+ context 'when a parameter is invalid' do
91
+ let(:body) { fixture('set_collection_invalid.xml') }
92
+
93
+ it 'does not update the specified collection' do
94
+ expect(update_collection).to eq false
95
+ end
96
+
97
+ it 'sets the error on the client' do
98
+ update_collection
99
+ expect(subject.errors[:base]).to match_array [ 'ERROR: invalid userHash' ]
100
+ end
101
+ end
102
+ end
103
+
104
+ context 'when not all parameters are valid' do
105
+ let(:set_id) { nil }
106
+ let(:wanted) { true }
107
+
108
+ it 'raises a ValidationError' do
109
+ expect { update_collection }.to raise_error Brickset::ValidationError, "Set can't be blank and Wanted is not included in the list"
110
+ end
111
+ end
112
+ end
113
+
114
+ describe '#update_collection_owned' do
115
+ let(:set_id) { 26725 }
116
+ let(:owned) { 1 }
117
+
118
+ let(:update_collection_owned) { subject.update_collection_owned(set_id: set_id, owned: owned) }
119
+
120
+ context 'when all required parameters are specified' do
121
+ before { stub_post('/setCollection_owns').with(body: "setID=#{set_id}&owned=#{owned}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
122
+
123
+ context 'when all parameters are valid' do
124
+ let(:body) { fixture('set_collection_owns.xml') }
125
+
126
+ it 'updates the specified collection owned' do
127
+ expect(update_collection_owned).to eq true
128
+ end
129
+ end
130
+
131
+ context 'when a parameter is invalid' do
132
+ let(:body) { fixture('set_collection_owns_invalid.xml') }
133
+
134
+ it 'does not update the specified collection owned' do
135
+ expect(update_collection_owned).to eq false
136
+ end
137
+
138
+ it 'sets the error on the client' do
139
+ update_collection_owned
140
+ expect(subject.errors[:base]).to match_array [ 'ERROR: invalid userHash' ]
141
+ end
142
+ end
143
+ end
144
+
145
+ context 'when not all parameters are valid' do
146
+ let(:set_id) { nil }
147
+ let(:owned) { true }
148
+
149
+ it 'raises a ValidationError' do
150
+ expect { update_collection_owned }.to raise_error Brickset::ValidationError, "Set can't be blank and Owned is not included in the list"
151
+ end
152
+ end
153
+ end
154
+
155
+ describe '#update_collection_wanted' do
156
+ let(:set_id) { 26725 }
157
+ let(:wanted) { 1 }
158
+
159
+ let(:update_collection_wanted) { subject.update_collection_wanted(set_id: set_id, wanted: wanted) }
160
+
161
+ context 'when all required parameters are specified' do
162
+ before { stub_post('/setCollection_wants').with(body: "setID=#{set_id}&wanted=#{wanted}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
163
+
164
+ context 'when all parameters are valid' do
165
+ let(:body) { fixture('set_collection_wants.xml') }
166
+
167
+ it 'updates the specified collection wanted' do
168
+ expect(update_collection_wanted).to eq true
169
+ end
170
+ end
171
+
172
+ context 'when a parameter is invalid' do
173
+ let(:body) { fixture('set_collection_wants_invalid.xml') }
174
+
175
+ it 'does not update the specified collection wanted' do
176
+ expect(update_collection_wanted).to eq false
177
+ end
178
+
179
+ it 'sets the error on the client' do
180
+ update_collection_wanted
181
+ expect(subject.errors[:base]).to match_array [ 'ERROR: invalid userHash' ]
182
+ end
183
+ end
184
+ end
185
+
186
+ context 'when not all parameters are valid' do
187
+ let(:set_id) { nil }
188
+ let(:wanted) { true }
189
+
190
+ it 'raises a ValidationError' do
191
+ expect { update_collection_wanted }.to raise_error Brickset::ValidationError, "Set can't be blank and Wanted is not included in the list"
192
+ end
193
+ end
194
+ end
195
+
196
+ describe '#update_collection_number_owned' do
197
+ let(:set_id) { 26725 }
198
+ let(:number_owned) { 1 }
199
+
200
+ let(:update_collection_number_owned) { subject.update_collection_number_owned(set_id: set_id, number_owned: number_owned) }
201
+
202
+ context 'when all required parameters are specified' do
203
+ before { stub_post('/setCollection_qtyOwned').with(body: "setID=#{set_id}&qtyOwned=#{number_owned}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
204
+
205
+ context 'when all parameters are valid' do
206
+ let(:body) { fixture('set_collection_qty_owned.xml') }
207
+
208
+ it 'updates the specified collection number owned' do
209
+ expect(update_collection_number_owned).to eq true
210
+ end
211
+ end
212
+
213
+ context 'when a parameter is invalid' do
214
+ let(:body) { fixture('set_collection_qty_owned_invalid.xml') }
215
+
216
+ it 'does not update the specified collection number owned' do
217
+ expect(update_collection_number_owned).to eq false
218
+ end
219
+
220
+ it 'sets the error on the client' do
221
+ update_collection_number_owned
222
+ expect(subject.errors[:base]).to match_array [ 'ERROR: invalid userHash' ]
223
+ end
224
+ end
225
+ end
226
+
227
+ context 'when not all parameters are valid' do
228
+ let(:set_id) { nil }
229
+ let(:number_owned) { true }
230
+
231
+ it 'raises a ValidationError' do
232
+ expect { update_collection_number_owned }.to raise_error Brickset::ValidationError, "Set can't be blank and Number owned is not included in the list"
233
+ end
234
+ end
235
+ end
236
+
237
+ describe '#update_collection_user_notes' do
238
+ let(:set_id) { 26725 }
239
+ let(:notes) { "She's the fastest hunk of junk in the galaxy!" }
240
+
241
+ let(:update_collection_user_notes) { subject.update_collection_user_notes(set_id: set_id, notes: notes) }
242
+
243
+ context 'when all required parameters are specified' do
244
+ before { stub_post('/setCollection_userNotes').with(body: "setID=#{set_id}&notes=#{ERB::Util.url_encode(notes)}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
245
+
246
+ context 'when all parameters are valid' do
247
+ let(:body) { fixture('set_collection_user_notes.xml') }
248
+
249
+ it 'updates the specified collection user notes' do
250
+ expect(update_collection_user_notes).to eq true
251
+ end
252
+ end
253
+
254
+ context 'when a parameter is invalid' do
255
+ let(:body) { fixture('set_collection_user_notes_invalid.xml') }
256
+
257
+ it 'does not update the specified collection user notes' do
258
+ expect(update_collection_user_notes).to eq false
259
+ end
260
+
261
+ it 'sets the error on the client' do
262
+ update_collection_user_notes
263
+ expect(subject.errors[:base]).to match_array [ 'ERROR: invalid userHash' ]
264
+ end
265
+ end
266
+ end
267
+
268
+ context 'when not all parameters are valid' do
269
+ let(:set_id) { nil }
270
+ let(:notes) { 'Star Wars. ' * 20 }
271
+
272
+ it 'raises a ValidationError' do
273
+ expect { update_collection_user_notes }.to raise_error Brickset::ValidationError, "Set can't be blank and Notes is too long (maximum is 200 characters)"
274
+ end
275
+ end
276
+ end
277
+
278
+ describe '#update_user_rating' do
279
+ let(:set_id) { 26725 }
280
+ let(:rating) { 4 }
281
+
282
+ let(:update_user_rating) { subject.update_user_rating(set_id: set_id, rating: rating) }
283
+
284
+ context 'when all required parameters are specified' do
285
+ before { stub_post('/setUserRating').with(body: "setID=#{set_id}&rating=#{rating}&apiKey=#{api_key}&userHash=#{token}").to_return body: body }
286
+
287
+ context 'when all parameters are valid' do
288
+ let(:body) { fixture('set_user_rating.xml') }
289
+
290
+ it 'updates the specified user rating' do
291
+ expect(update_user_rating).to eq true
292
+ end
293
+ end
294
+
295
+ context 'when a parameter is invalid' do
296
+ let(:body) { fixture('set_user_rating_invalid.xml') }
297
+
298
+ it 'does not update the specified user rating' do
299
+ expect(update_user_rating).to eq false
300
+ end
301
+
302
+ it 'sets the error on the client' do
303
+ update_user_rating
304
+ expect(subject.errors[:base]).to match_array [ 'ERROR: invalid userHash' ]
305
+ end
306
+ end
307
+ end
308
+
309
+ context 'when not all parameters are valid' do
310
+ let(:set_id) { nil }
311
+ let(:rating) { 6 }
312
+
313
+ it 'raises a ValidationError' do
314
+ expect { update_user_rating }.to raise_error Brickset::ValidationError, "Set can't be blank and Rating is not included in the list"
315
+ end
316
+ end
317
+ end
318
+
319
+ describe '#user_notes' do
320
+ let(:body) { fixture('get_user_notes.xml') }
321
+
322
+ before { stub_post('/getUserNotes').with(body: "apiKey=#{api_key}&userHash=#{token}").to_return body: body }
323
+
324
+ context 'with valid parameters' do
325
+ it 'returns the users notes' do
326
+ aggregate_failures do
327
+ expect(subject.user_notes).to match_array [
328
+ an_instance_of(Brickset::Elements::UserNote),
329
+ an_instance_of(Brickset::Elements::UserNote)
330
+ ]
331
+ expect(subject.user_notes.count).to eq 2
332
+ expect(subject.user_notes.first.set_id).to eq 5860
333
+ expect(subject.user_notes.first.user_notes).to eq 'A long time ago in a galaxy far, far away...'
334
+ expect(subject.user_notes.last.set_id).to eq 26725
335
+ expect(subject.user_notes.last.user_notes).to eq 'The ship that made the Kessel Run in less than 12 parsecs.'
336
+ end
337
+ end
338
+ end
339
+
340
+ context 'with invalid parameters' do
341
+ let(:token) { 'invalid' }
342
+ let(:body) { fixture('get_user_notes_no_result.xml') }
343
+
344
+ it 'does not receive any user notes' do
345
+ expect(subject.user_notes).to match_array []
346
+ end
347
+ end
348
+ end
349
+
350
+ end