bgg 1.0.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 (57) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +20 -0
  6. data/Gemfile.lock +54 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.md +73 -0
  9. data/Rakefile +38 -0
  10. data/VERSION +1 -0
  11. data/bgg.gemspec +122 -0
  12. data/lib/bgg.rb +53 -0
  13. data/lib/bgg/collection.rb +58 -0
  14. data/lib/bgg/collection_item.rb +69 -0
  15. data/lib/bgg/game.rb +57 -0
  16. data/lib/bgg/play.rb +64 -0
  17. data/lib/bgg/plays.rb +26 -0
  18. data/lib/bgg/plays_iterator.rb +64 -0
  19. data/lib/bgg/search.rb +34 -0
  20. data/lib/bgg/search_result.rb +18 -0
  21. data/lib/bgg/user.rb +60 -0
  22. data/sample_data/collection?username=texasjdl +5224 -0
  23. data/sample_data/collection?username=texasjdl&own=1&excludesubtype=boardgameexpansion +2606 -0
  24. data/sample_data/collection?username=yyyyyyy +3 -0
  25. data/sample_data/hot?type=boardgame +253 -0
  26. data/sample_data/plays?pages=9999999999999&username=ryanmacg +2 -0
  27. data/sample_data/plays?username=beetss&page=1 +3 -0
  28. data/sample_data/plays?username=ryanmacg +504 -0
  29. data/sample_data/plays?username=texasjdl&id=84876 +192 -0
  30. data/sample_data/plays?username=texasjdl&id=84876&type=thing +199 -0
  31. data/sample_data/plays?username=texasjdl&page=1 +717 -0
  32. data/sample_data/plays?username=texasjdl&page=2 +709 -0
  33. data/sample_data/plays?username=texasjdl&page=3 +707 -0
  34. data/sample_data/plays?username=yyyyyyy&page=1 +667 -0
  35. data/sample_data/search?query=Burgun +47 -0
  36. data/sample_data/search?query=Burgun&exact=1 +3 -0
  37. data/sample_data/search?query=Burgund&type=boardgame +12 -0
  38. data/sample_data/search?query=The+Castles+of+Burgundy&exact=1 +7 -0
  39. data/sample_data/search?query=yyyyyyy +3 -0
  40. data/sample_data/thing?id=10000000&type=boardgame +3 -0
  41. data/sample_data/thing?id=29773&type=boardgame +90 -0
  42. data/sample_data/thing?id=70512&type=boardgame +82 -0
  43. data/sample_data/thing?id=84876&type=boardgame +82 -0
  44. data/sample_data/user?name=texasjdl +17 -0
  45. data/sample_data/user?name=yyyyyyy +17 -0
  46. data/spec/bgg_api_spec.rb +113 -0
  47. data/spec/bgg_collection_item_spec.rb +259 -0
  48. data/spec/bgg_collection_spec.rb +83 -0
  49. data/spec/bgg_game_spec.rb +232 -0
  50. data/spec/bgg_play_spec.rb +166 -0
  51. data/spec/bgg_plays_iterator_spec.rb +156 -0
  52. data/spec/bgg_plays_spec.rb +60 -0
  53. data/spec/bgg_search_result_spec.rb +73 -0
  54. data/spec/bgg_search_spec.rb +84 -0
  55. data/spec/bgg_user_spec.rb +113 -0
  56. data/spec/spec_helper.rb +29 -0
  57. metadata +241 -0
@@ -0,0 +1,166 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Bgg::Play do
5
+ describe 'instance' do
6
+ let(:item_data) { {'id'=>'7680984',
7
+ 'date'=>'2012-06-23',
8
+ 'quantity'=>'1',
9
+ 'length'=>'0',
10
+ 'incomplete'=>'0',
11
+ 'nowinstats'=>'0',
12
+ 'location'=>'',
13
+ 'item'=>[{'name'=>'Cheeky Monkey', 'objecttype'=>'thing', 'objectid'=>'29773', 'subtypes'=>[{'subtype'=>[{'value'=>'boardgame'}]}]}]} }
14
+
15
+ let(:item) { Bgg::Play.new(item_data) }
16
+
17
+ describe '.id' do
18
+ it 'exists' do
19
+ expect( item ).to respond_to(:id)
20
+ end
21
+
22
+ it 'returns correct value' do
23
+ expect( item.id ).to eq(7680984)
24
+ end
25
+ end
26
+
27
+ describe '.date' do
28
+ it 'exists' do
29
+ expect( item ).to respond_to(:date)
30
+ end
31
+
32
+ # FIXME: should move to an actual date object
33
+ it 'returns the correct value' do
34
+ expect( item.date ).to eq('2012-06-23')
35
+ end
36
+ end
37
+
38
+ describe '.quantity' do
39
+ it 'exists' do
40
+ expect( item ).to respond_to(:quantity)
41
+ end
42
+
43
+ it 'returns the correct value' do
44
+ expect( item.quantity ).to eq(1)
45
+ end
46
+ end
47
+
48
+ describe '.length' do
49
+ it 'exists' do
50
+ expect( item ).to respond_to(:length)
51
+ end
52
+
53
+ it 'returns the correct value' do
54
+ expect( item.length ).to eq(0)
55
+ end
56
+ end
57
+
58
+ describe '.incomplete?' do
59
+ it 'exists' do
60
+ expect( item ).to respond_to(:incomplete?)
61
+ end
62
+
63
+ it 'returns true when incomplete == 0' do
64
+ item_data['incomplete'] = '0'
65
+ expect( item.incomplete? ).to eq(false)
66
+ end
67
+
68
+ it 'returns true when incomplete == 1' do
69
+ item_data['incomplete'] = '1'
70
+ expect( item.incomplete? ).to eq(true)
71
+ end
72
+ end
73
+
74
+ describe '.location' do
75
+ it 'exists' do
76
+ expect( item ).to respond_to(:location)
77
+ end
78
+
79
+ it 'returns empty string when it is empty' do
80
+ expect( item.location ).to eq('')
81
+ end
82
+
83
+ it 'returns a string when it is filled in' do
84
+ item_data['location'] = 'BGGCon!'
85
+ expect( item.location ).to eq('BGGCon!')
86
+ end
87
+ end
88
+
89
+ describe '.nowinstats?' do
90
+ it 'exists' do
91
+ expect( item ).to respond_to(:nowinstats?)
92
+ end
93
+
94
+ it 'returns true when nowinstats == 1' do
95
+ item_data['nowinstats'] = '1'
96
+ expect( item.nowinstats? ).to eq(true)
97
+ end
98
+
99
+ it 'returns false when nowinstats == 0' do
100
+ item_data['nowinstats'] = '0'
101
+ expect( item.nowinstats? ).to eq(false)
102
+ end
103
+ end
104
+
105
+ describe '.players' do
106
+ it 'exists' do
107
+ expect( item ).to respond_to(:players)
108
+ end
109
+
110
+ it 'returns the list of players' do
111
+ expect( item.players ).to match_array([])
112
+ end
113
+ end
114
+
115
+ describe '.game_name' do
116
+ it 'exists' do
117
+ expect( item ).to respond_to(:game_name)
118
+ end
119
+
120
+ it 'returns the correct value' do
121
+ expect( item.game_name ).to eq('Cheeky Monkey')
122
+ end
123
+ end
124
+
125
+ describe '.game_id' do
126
+ it 'exists' do
127
+ expect( item ).to respond_to(:game_id)
128
+ end
129
+
130
+ it 'returns the correct value' do
131
+ expect( item.game_id ).to eq(29773)
132
+ end
133
+ end
134
+
135
+ describe '.game_type' do
136
+ it 'exists' do
137
+ expect( item ).to respond_to(:game_type)
138
+ end
139
+
140
+ it 'returns the correct value' do
141
+ expect( item.game_type ).to eq('boardgame')
142
+ end
143
+ end
144
+
145
+ describe '.game' do
146
+ it 'exists' do
147
+ expect( item ).to respond_to(:game)
148
+ end
149
+
150
+ it 'returns a Bgg::Game object corresponding to the entry' do
151
+ response_file = 'sample_data/thing?id=29773&type=boardgame'
152
+ request_url = 'http://www.boardgamegeek.com/xmlapi2/thing'
153
+
154
+ stub_request(:any, request_url).
155
+ with(query: {id: 29773, type: 'boardgame'}).
156
+ to_return(body: File.open(response_file), status: 200)
157
+
158
+ game = item.game
159
+
160
+ expect( game ).to be_instance_of(Bgg::Game)
161
+ expect( game.name ).to eq('Cheeky Monkey')
162
+ expect( game.designers ).to eq(['Reiner Knizia'])
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,156 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Bgg::Plays::Iterator do
5
+ describe 'instance' do
6
+ let(:username) { 'texasjdl' }
7
+ let(:request_url) { 'http://www.boardgamegeek.com/xmlapi2/plays' }
8
+ let(:query) { {username: username, page: 1} }
9
+ let(:response_file) { "sample_data/plays?username=#{username}&page=1" }
10
+ let(:iterator) { Bgg::Plays::Iterator.new(username) }
11
+
12
+ before do
13
+ stub_request(:any, request_url).
14
+ with(query: query).
15
+ to_return(body: File.open(response_file), status: 200)
16
+ end
17
+
18
+ it 'is Enumerable' do
19
+ expect( iterator ).to be_a_kind_of(Enumerable)
20
+ end
21
+
22
+ context 'when the user has no plays' do
23
+ let(:username) { 'beetss' }
24
+ it 'returns an empty iterator' do
25
+ expect( iterator.empty? ).to eq(true)
26
+ end
27
+ end
28
+
29
+ context 'when the user does not exist' do
30
+ let(:username) { 'yyyyyyy' }
31
+ it 'returns an empty iterator' do
32
+ expect{ iterator }.to raise_error(ArgumentError, 'user does not exist')
33
+ end
34
+ end
35
+
36
+ context 'when the user exists and has plays' do
37
+ it 'returns an instance' do
38
+ expect( iterator ).to be_instance_of(Bgg::Plays::Iterator)
39
+ end
40
+ end
41
+
42
+ describe '.each' do
43
+ it 'exists' do
44
+ expect( iterator ).to respond_to(:each)
45
+ end
46
+
47
+ it 'allows stepping through results' do
48
+ iterator.each do |item|
49
+ expect( item ).to be_instance_of(Bgg::Play)
50
+ break if iterator.iteration == 3
51
+ end
52
+ end
53
+
54
+ it 'only allows stepping through the results once' do
55
+ iterator.each { break if iterator.iteration == 2 }
56
+ iterator.each { fail }
57
+ end
58
+
59
+ it 'returns multiple pages of results' do
60
+ [2,3].each do |i|
61
+ stub_request(:any, request_url).
62
+ with(query: {username: username, page: i}).
63
+ to_return(body: File.open("sample_data/plays?username=#{username}&page=#{i}"),
64
+ status: 200)
65
+ end
66
+
67
+ iterator.each { }
68
+ expect( iterator.iteration ).to eq(299)
69
+ end
70
+ end
71
+
72
+ describe '.iteration' do
73
+ it 'exists' do
74
+ expect( iterator ).to respond_to(:iteration)
75
+ end
76
+
77
+ it 'returns the maximum value when the iterator is exhausted' do
78
+ count = 0
79
+ iterator.each do |item|
80
+ count += 1
81
+ expect( iterator.iteration ).to eq(count)
82
+ break if iterator.iteration == 3
83
+ end
84
+ end
85
+
86
+ it 'returns the current iteration through the block' do
87
+ count = 0
88
+ iterator.each do |item|
89
+ count += 1
90
+ expect( iterator.iteration ).to eq(count)
91
+ break if iterator.iteration == 3
92
+ end
93
+ end
94
+
95
+ context 'when the iterator starts empty,' do
96
+ let(:username) { 'beetss' }
97
+ it 'returns 0' do
98
+ expect( iterator.iteration ).to eq(0)
99
+ end
100
+ end
101
+ end
102
+
103
+ describe '.empty?' do
104
+ it 'exists' do
105
+ expect( iterator ).to respond_to(:empty?)
106
+ end
107
+
108
+ context 'when the iterator has no results' do
109
+ let(:username) { 'beetss' }
110
+ it 'returns true' do
111
+ expect( iterator.empty? ).to eq(true)
112
+ end
113
+ end
114
+
115
+ context 'when the iterator has results' do
116
+ it 'returns false' do
117
+ expect( iterator.empty? ).to eq(false)
118
+ end
119
+ end
120
+
121
+ context 'when the iterator has paged through results' do
122
+ it 'returns true if each() has already reached the end' do
123
+ [2,3].each do |i|
124
+ stub_request(:any, request_url).
125
+ with(query: {username: username, page: i}).
126
+ to_return(body: File.open("sample_data/plays?username=#{username}&page=#{i}"),
127
+ status: 200)
128
+ end
129
+
130
+ iterator.each{ }
131
+ expect( iterator.empty? ).to eq(true)
132
+ end
133
+ end
134
+ end
135
+
136
+ describe '.total_count' do
137
+ it 'exists' do
138
+ expect( iterator ).to respond_to(:total_count)
139
+ end
140
+
141
+ context 'when the user has no plays' do
142
+ let(:username) { 'beetss' }
143
+ it 'returns 0' do
144
+ expect( iterator.total_count ).to eq(0)
145
+ end
146
+ end
147
+
148
+ context 'when the user has plays' do
149
+ let(:username) { 'texasjdl' }
150
+ it 'returns the correct count' do
151
+ expect( iterator.total_count ).to eq(299)
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,60 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Bgg::Plays do
5
+ describe 'class method' do
6
+ describe 'find_by_username' do
7
+ it 'throws an ArgumentError when a number is passed in' do
8
+ expect{ Bgg::Collection.find_by_username(38383) }.to raise_error(ArgumentError)
9
+ end
10
+
11
+ it 'throws an ArgumentError when an empty string is passed in' do
12
+ expect{ Bgg::Collection.find_by_username('') }.to raise_error(ArgumentError)
13
+ end
14
+
15
+ it 'throws an ArgumentError when a string of only numbers is passed in' do
16
+ expect{ Bgg::Collection.find_by_username('38383') }.to raise_error(ArgumentError)
17
+ end
18
+
19
+ it 'throws an ArgumentError when a non-existent user is passed in' do
20
+ response_file = 'sample_data/plays?username=yyyyyyy&page=1'
21
+ request_url = 'http://www.boardgamegeek.com/xmlapi2/plays'
22
+
23
+ stub_request(:any, request_url).
24
+ with(query: {username: 'yyyyyyy', page: 1}).
25
+ to_return(body: File.open(response_file), status: 200)
26
+
27
+ expect{ Bgg::Plays.find_by_username('yyyyyyy') }.to raise_error(ArgumentError)
28
+ end
29
+
30
+ it 'returns an empty iterator when a valid user has no plays' do
31
+ response_file = 'sample_data/plays?username=beetss&page=1'
32
+ request_url = 'http://www.boardgamegeek.com/xmlapi2/plays'
33
+
34
+ stub_request(:any, request_url).
35
+ with(query: {username: 'beetss', page: 1}).
36
+ to_return(body: File.open(response_file), status: 200)
37
+
38
+ iterator = Bgg::Plays.find_by_username('beetss')
39
+ expect( iterator ).to be_an_instance_of(Bgg::Plays::Iterator)
40
+ expect( iterator.empty? ).to eq(true)
41
+ end
42
+
43
+ it 'creates a Bgg::Plays::Iterator object for a user who has plays' do
44
+ response_file = 'sample_data/plays?username=texasjdl&page=1'
45
+ request_url = 'http://www.boardgamegeek.com/xmlapi2/plays'
46
+
47
+ stub_request(:any, request_url).
48
+ with(query: {username: 'texasjdl', page: 1}).
49
+ to_return(body: File.open(response_file), status: 200)
50
+
51
+ plays = Bgg::Plays.find_by_username('texasjdl')
52
+ first_play = plays.first
53
+
54
+ expect( plays ).to be_a_kind_of(Bgg::Plays::Iterator)
55
+ expect( first_play ).to be_instance_of(Bgg::Play)
56
+ expect( first_play.players ).to be_instance_of(Array)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,73 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Bgg::Search::Result do
5
+ describe 'instance' do
6
+ let(:item_data) { {'type'=>'boardgame',
7
+ 'id'=>'84876',
8
+ 'name'=>[{'type'=>'primary', 'value'=>'The Castles of Burgundy'}],
9
+ 'yearpublished'=>[{'value'=>'2011'}]} }
10
+ let(:search_result) { Bgg::Search::Result.new(item_data) }
11
+
12
+ describe '.id' do
13
+ it 'exists' do
14
+ expect( search_result ).to respond_to(:id)
15
+ end
16
+
17
+ it 'returns correct value' do
18
+ expect( search_result.id ).to eq(84876)
19
+ end
20
+ end
21
+
22
+ describe '.name' do
23
+ it 'exists' do
24
+ expect( search_result ).to respond_to(:name)
25
+ end
26
+
27
+ it 'returns the correct value' do
28
+ expect( search_result.name ).to eq('The Castles of Burgundy')
29
+ end
30
+ end
31
+
32
+ describe '.type' do
33
+ it 'exists' do
34
+ expect( search_result ).to respond_to(:type)
35
+ end
36
+
37
+ it 'returns boardgame when it is a boardgame' do
38
+ expect( search_result.type ).to eq('boardgame')
39
+ end
40
+ end
41
+
42
+ describe '.year_published' do
43
+ it 'exists' do
44
+ expect( search_result ).to respond_to(:year_published)
45
+ end
46
+
47
+ it 'returns the year it was published' do
48
+ expect( search_result.year_published ).to eq(2011)
49
+ end
50
+ end
51
+
52
+ describe '.game' do
53
+ it 'exists' do
54
+ expect( search_result ).to respond_to(:game)
55
+ end
56
+
57
+ it 'returns a Bgg::Game object corresponding to the entry' do
58
+ response_file = 'sample_data/thing?id=84876&type=boardgame'
59
+ request_url = 'http://www.boardgamegeek.com/xmlapi2/thing'
60
+
61
+ stub_request(:any, request_url).
62
+ with(query: {id: 84876, type: 'boardgame'}).
63
+ to_return(body: File.open(response_file), status: 200)
64
+
65
+ game = search_result.game
66
+
67
+ expect( game ).to be_instance_of(Bgg::Game)
68
+ expect( game.name ).to eq('The Castles of Burgundy')
69
+ expect( game.designers ).to eq(['Stefan Feld'])
70
+ end
71
+ end
72
+ end
73
+ end