totter 0.2.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 (46) hide show
  1. data/.gitignore +17 -0
  2. data/.travis.yml +4 -0
  3. data/Contributing.markdown +19 -0
  4. data/Gemfile +22 -0
  5. data/LICENSE +22 -0
  6. data/Rakefile +21 -0
  7. data/Readme.markdown +49 -0
  8. data/lib/totter.rb +26 -0
  9. data/lib/totter/client.rb +152 -0
  10. data/lib/totter/client/choices.rb +74 -0
  11. data/lib/totter/client/decisions.rb +91 -0
  12. data/lib/totter/client/slugs.rb +19 -0
  13. data/lib/totter/client/timelines.rb +16 -0
  14. data/lib/totter/client/users.rb +54 -0
  15. data/lib/totter/client/votes.rb +25 -0
  16. data/lib/totter/error.rb +51 -0
  17. data/lib/totter/version.rb +4 -0
  18. data/test/cassettes/choices/create_choice_upload.yml +85 -0
  19. data/test/cassettes/choices/create_for_image.yml +87 -0
  20. data/test/cassettes/choices/destroy.yml +122 -0
  21. data/test/cassettes/choices/show.yml +42 -0
  22. data/test/cassettes/decisions/analytics.yml +85 -0
  23. data/test/cassettes/decisions/create.yml +44 -0
  24. data/test/cassettes/decisions/destroy.yml +81 -0
  25. data/test/cassettes/decisions/flag.yml +81 -0
  26. data/test/cassettes/decisions/publish.yml +129 -0
  27. data/test/cassettes/decisions/show.yml +84 -0
  28. data/test/cassettes/decisions/unflag.yml +122 -0
  29. data/test/cassettes/slugs/show.yml +75 -0
  30. data/test/cassettes/timelines/global.yml +165 -0
  31. data/test/cassettes/users/following.yml +194 -0
  32. data/test/cassettes/users/me.yml +43 -0
  33. data/test/cassettes/users/user.yml +49 -0
  34. data/test/cassettes/votes/create.yml +96 -0
  35. data/test/support/client_macros.rb +5 -0
  36. data/test/test_helper.rb +24 -0
  37. data/test/totter/client/choices_test.rb +48 -0
  38. data/test/totter/client/decisions_test.rb +77 -0
  39. data/test/totter/client/slugs_test.rb +11 -0
  40. data/test/totter/client/timelines_test.rb +9 -0
  41. data/test/totter/client/users_test.rb +36 -0
  42. data/test/totter/client/votes_test.rb +15 -0
  43. data/test/totter/client_test.rb +31 -0
  44. data/test/totter_test.rb +17 -0
  45. data/totter.gemspec +24 -0
  46. metadata +155 -0
@@ -0,0 +1,43 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://localhost:5000/v1/me
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - ! '*/*'
12
+ User-Agent:
13
+ - Ruby
14
+ Authorization:
15
+ - Bearer 9774e653f7b3c1de5f21b61adc08ba24
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Content-Type:
22
+ - application/json; charset=utf-8
23
+ X-Ua-Compatible:
24
+ - IE=Edge
25
+ Etag:
26
+ - ! '"95c71ccb1067d7d65324be5f15d45f2c"'
27
+ Cache-Control:
28
+ - max-age=0, private, must-revalidate
29
+ X-Request-Id:
30
+ - 28038b85d34b3e315b81dfde649c2b0c
31
+ X-Runtime:
32
+ - '0.678551'
33
+ Connection:
34
+ - close
35
+ Server:
36
+ - thin 1.5.0 codename Knife
37
+ body:
38
+ encoding: US-ASCII
39
+ string: ! '{"biography":null,"created_at":"2013-01-25T21:06:59Z","email":"test@seesaw.co","family_name":null,"given_name":null,"id":1,"meta":null,"phone_number":"+12147093337","preferences":{"notification_friends":false,"notification_invitee_votes":true,"notification_comments":true,"notification_following_votes":true,"notification_other_votes":true,"notification_after_votes":false,"notification_following":true,"opt_in_to_sms":true},"updated_at":"2013-01-29T23:39:18Z","username":"test123","website":null,"avatar_url":"https://recess-dev.s3.amazonaws.com/default_avatars/v1/photo_1.png","full_name":"test123","short_name":"test123","display_name":"test123","short_display_name":"test123","analytics":{"votes":0,"decisions":0,"followers":0,"following":0},"formatted_phone_number":"(214)
40
+ 709-3337","roles":[],"default_timeline":"g"}'
41
+ http_version:
42
+ recorded_at: Wed, 30 Jan 2013 15:45:06 GMT
43
+ recorded_with: VCR 2.4.0
@@ -0,0 +1,49 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://api.seesaw.co/v1/users/gotwalt
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - ! '*/*'
12
+ User-Agent:
13
+ - Ruby
14
+ response:
15
+ status:
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ Cache-Control:
20
+ - max-age=0, private, must-revalidate
21
+ Content-Type:
22
+ - application/json; charset=utf-8
23
+ Date:
24
+ - Wed, 30 Jan 2013 16:10:55 GMT
25
+ Etag:
26
+ - ! '"4a15d340e2051046340cd2fc1443cba1"'
27
+ Server:
28
+ - thin 1.5.0 codename Knife
29
+ Strict-Transport-Security:
30
+ - max-age=31536000
31
+ X-Rack-Cache:
32
+ - miss
33
+ X-Request-Id:
34
+ - 008de3c6c1b64956f4c0518074b15acb
35
+ X-Runtime:
36
+ - '0.009899'
37
+ X-Ua-Compatible:
38
+ - IE=Edge,chrome=1
39
+ Transfer-Encoding:
40
+ - chunked
41
+ Connection:
42
+ - keep-alive
43
+ body:
44
+ encoding: US-ASCII
45
+ string: ! '{"biography":null,"created_at":"2012-11-13T22:40:33Z","family_name":"Gotwalt","given_name":"Aaron","id":1,"meta":null,"moderated_decisions_count":null,"updated_at":"2013-01-30T15:01:17Z","username":"gotwalt","website":null,"avatar_url":"https://recess.s3.amazonaws.com/avatars/530/1355442979/photo.jpg","full_name":"Aaron
46
+ Gotwalt","short_name":"Aaron G","display_name":"gotwalt","short_display_name":"gotwalt","analytics":{"votes":133,"decisions":17,"following":19,"followers":39,"updated_at":"2013-01-30T15:01:00Z"}}'
47
+ http_version:
48
+ recorded_at: Wed, 30 Jan 2013 16:10:56 GMT
49
+ recorded_with: VCR 2.4.0
@@ -0,0 +1,96 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://api.seesaw.co/v1/users/5/decisions/3276/votes
6
+ body:
7
+ encoding: UTF-8
8
+ string: ! '{"choice_id":5381,"unique_id":"021a997d8aa785abed0a25c47b9a07be"}'
9
+ headers:
10
+ Accept:
11
+ - ! '*/*'
12
+ User-Agent:
13
+ - Ruby
14
+ Content-Type:
15
+ - application/json
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Cache-Control:
22
+ - max-age=0, private, must-revalidate
23
+ Content-Type:
24
+ - application/json; charset=utf-8
25
+ Date:
26
+ - Wed, 30 Jan 2013 23:41:18 GMT
27
+ Etag:
28
+ - ! '"380b1c2aadcb06b0b3c3c006df2ec706"'
29
+ Server:
30
+ - thin 1.5.0 codename Knife
31
+ Strict-Transport-Security:
32
+ - max-age=31536000
33
+ X-Rack-Cache:
34
+ - invalidate, pass
35
+ X-Request-Id:
36
+ - 910c33f18f74e972a8cc2b0070a2b5b8
37
+ X-Runtime:
38
+ - '0.071101'
39
+ X-Ua-Compatible:
40
+ - IE=Edge,chrome=1
41
+ Transfer-Encoding:
42
+ - chunked
43
+ Connection:
44
+ - keep-alive
45
+ body:
46
+ encoding: US-ASCII
47
+ string: ! '{"choice_id":5381,"created_at":"2013-01-30T23:41:18Z","decision_id":3276,"id":5432,"meta":null,"reason":null}'
48
+ http_version:
49
+ recorded_at: Wed, 30 Jan 2013 23:41:17 GMT
50
+ - request:
51
+ method: post
52
+ uri: https://api.seesaw.co/v1/users/5/decisions/3276/votes
53
+ body:
54
+ encoding: UTF-8
55
+ string: ! '{"choice_id":5381,"unique_id":"021a997d8aa785abed0a25c47b9a07be"}'
56
+ headers:
57
+ Accept:
58
+ - ! '*/*'
59
+ User-Agent:
60
+ - Ruby
61
+ Content-Type:
62
+ - application/json
63
+ response:
64
+ status:
65
+ code: 400
66
+ message: Bad Request
67
+ headers:
68
+ Cache-Control:
69
+ - no-cache
70
+ Content-Type:
71
+ - application/json; charset=utf-8
72
+ Date:
73
+ - Wed, 30 Jan 2013 23:41:18 GMT
74
+ Server:
75
+ - thin 1.5.0 codename Knife
76
+ Strict-Transport-Security:
77
+ - max-age=31536000
78
+ X-Rack-Cache:
79
+ - invalidate, pass
80
+ X-Request-Id:
81
+ - 5736b4d2f98ef71c14b3c53fdedca28a
82
+ X-Runtime:
83
+ - '0.111517'
84
+ X-Ua-Compatible:
85
+ - IE=Edge,chrome=1
86
+ Transfer-Encoding:
87
+ - chunked
88
+ Connection:
89
+ - keep-alive
90
+ body:
91
+ encoding: US-ASCII
92
+ string: ! '{"error":"invalid_vote","error_description":"Vote has already been
93
+ recorded"}'
94
+ http_version:
95
+ recorded_at: Wed, 30 Jan 2013 23:41:18 GMT
96
+ recorded_with: VCR 2.4.0
@@ -0,0 +1,5 @@
1
+ module ClientMacros
2
+ def local_client
3
+ client = Totter::Client.new(access_token: '9774e653f7b3c1de5f21b61adc08ba24', api_host: 'localhost:5000', api_scheme: 'http')
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.require :test
4
+
5
+ require 'simplecov'
6
+ SimpleCov.start
7
+
8
+ require 'minitest/autorun'
9
+ require 'totter'
10
+
11
+ # Support files
12
+ Dir["#{File.expand_path(File.dirname(__FILE__))}/support/*.rb"].each do |file|
13
+ require file
14
+ end
15
+
16
+ # VCR
17
+ VCR.configure do |c|
18
+ c.cassette_library_dir = 'test/cassettes'
19
+ c.hook_into :webmock
20
+ end
21
+
22
+ class Totter::TestCase < MiniTest::Unit::TestCase
23
+ include ::ClientMacros
24
+ end
@@ -0,0 +1,48 @@
1
+ require 'test_helper'
2
+
3
+ class ChoicesTest < Totter::TestCase
4
+ def test_decision
5
+ VCR.use_cassette 'choices/show' do
6
+ client = local_client
7
+ choice = client.choice(3, 12, 1)
8
+ assert_equal 'ImageChoice', choice.type
9
+ end
10
+ end
11
+
12
+ def test_create_choice_for_image
13
+ VCR.use_cassette 'choices/create_for_image' do
14
+ client = local_client
15
+ data = {
16
+ image_url: 'http://recess.s3.amazonaws.com/default_avatars/v1/photo_1.png',
17
+ subject: 'Test Image',
18
+ link_url: 'http://seesaw.co',
19
+ link_title: 'Seesaw'
20
+ }
21
+ decision = client.create_decision(1)
22
+ choice = client.create_choice_for_image(decision.user_id, decision.id, data)
23
+ assert_equal data[:subject], choice.subject
24
+ assert_equal data[:link_url], choice.meta.link_url
25
+ assert_equal data[:link_title], choice.meta.link_title
26
+ refute choice.respond_to?(:upload), 'should not have an upload form'
27
+ end
28
+ end
29
+
30
+ def test_create_choice_upload
31
+ VCR.use_cassette 'choices/create_choice_upload' do
32
+ client = local_client
33
+ decision = client.create_decision(1)
34
+ choice = client.create_choice_upload(decision.user_id, decision.id)
35
+
36
+ assert choice.respond_to?(:upload), 'should have an upload form'
37
+ end
38
+ end
39
+
40
+ def test_destroy_choice
41
+ VCR.use_cassette 'choices/destroy' do
42
+ client = local_client
43
+ decision = client.create_decision(1)
44
+ choice = client.create_choice_upload(decision.user_id, decision.id)
45
+ assert client.destroy_choice(decision.user_id, decision.id, choice.id)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,77 @@
1
+ require 'test_helper'
2
+
3
+ class DecisionsTest < Totter::TestCase
4
+ def test_decision
5
+ VCR.use_cassette 'decisions/show' do
6
+ decision = Totter.decision(5, 3276)
7
+ assert_equal 'Which lamp for the new apartment?', decision.question
8
+ end
9
+ end
10
+
11
+ def test_create_decision
12
+ VCR.use_cassette 'decisions/create' do
13
+ client = local_client
14
+ decision = client.create_decision(1)
15
+ assert_equal 1, decision.id
16
+ assert_equal 1, decision.user_id
17
+ assert decision.timeline_key
18
+ end
19
+ end
20
+
21
+ def test_publish_decision
22
+ VCR.use_cassette 'decisions/publish' do
23
+ client = local_client
24
+ decision = client.create_decision(1)
25
+ choice = create_test_choice(client, decision.user_id, decision.id)
26
+ result = client.publish_decision(decision.user_id, decision.id, question: 'Why is the sky blue?')
27
+ assert result.published_at
28
+ assert 1, result.choices.length
29
+ end
30
+ end
31
+
32
+ def test_destroy_decision
33
+ VCR.use_cassette 'decisions/destroy' do
34
+ client = local_client
35
+ decision = client.create_decision(1)
36
+ assert client.destroy_decision(decision.user_id, decision.id)
37
+ end
38
+ end
39
+
40
+ def test_decision_analytics
41
+ VCR.use_cassette 'decisions/analytics' do
42
+ client = local_client
43
+ decision = client.create_decision(1)
44
+ analytics = client.decision_analytics(decision.user_id, decision.id)
45
+ assert_equal 0, analytics.total_votes
46
+ end
47
+ end
48
+
49
+ def test_flag_decision
50
+ VCR.use_cassette 'decisions/flag' do
51
+ client = local_client
52
+ decision = client.create_decision(1)
53
+ assert client.flag_decision(decision.user_id, decision.id)
54
+ end
55
+ end
56
+
57
+ def test_unflag_decision
58
+ VCR.use_cassette 'decisions/unflag' do
59
+ client = local_client
60
+ decision = client.create_decision(1)
61
+ assert client.flag_decision(decision.user_id, decision.id)
62
+ assert client.unflag_decision(decision.user_id, decision.id)
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def create_test_choice(client, user_id, decision_id)
69
+ data = {
70
+ image_url: 'http://recess.s3.amazonaws.com/default_avatars/v1/photo_1.png',
71
+ subject: 'Test Image',
72
+ link_url: 'http://seesaw.co',
73
+ link_title: 'Seesaw'
74
+ }
75
+ client.create_choice_for_image(user_id, decision_id, data)
76
+ end
77
+ end
@@ -0,0 +1,11 @@
1
+ require 'test_helper'
2
+
3
+ class SlugsTest < Totter::TestCase
4
+ def test_slug
5
+ VCR.use_cassette 'slugs/show' do
6
+ client = Totter::Client.new
7
+ slug = client.slug('d/3I0n0g')
8
+ assert_equal 'soffes', slug.decision.user.username
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ require 'test_helper'
2
+
3
+ class TimelinesTest < Totter::TestCase
4
+ def test_global
5
+ VCR.use_cassette 'timelines/global' do
6
+ assert_equal 15, Totter.global_timeline(15).length
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+
3
+ class UsersTest < Totter::TestCase
4
+ def test_me
5
+ VCR.use_cassette 'users/me' do
6
+ user = local_client.me
7
+ assert_equal 'test123', user.username
8
+ end
9
+ end
10
+
11
+ def test_user
12
+ VCR.use_cassette 'users/user' do
13
+ client = Totter::Client.new
14
+ user = client.user('gotwalt')
15
+ assert_equal 'gotwalt', user.username
16
+ end
17
+ end
18
+
19
+ def test_following
20
+ VCR.use_cassette 'users/following' do
21
+ assert local_client.follow('gotwalt'), 'follow user'
22
+ assert local_client.unfollow('gotwalt'), 'unfollow user'
23
+
24
+ # Still true, even if you aren't following them
25
+ assert local_client.unfollow('gotwalt'), 'unfollow user twice'
26
+
27
+ assert_raises Totter::NotFound do
28
+ local_client.follow('nobody')
29
+ end
30
+
31
+ assert_raises Totter::NotFound do
32
+ refute local_client.follow('unnobody')
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+
3
+ class VotesTest < Totter::TestCase
4
+ def test_create_vote
5
+ VCR.use_cassette 'votes/create' do
6
+ vote = Totter.create_vote(5, 3276, 5381, unique_id: '021a997')
7
+ assert_equal 5381, vote.choice_id
8
+
9
+ # Prevent duplicates
10
+ assert_raises Totter::BadRequest do
11
+ Totter.create_vote(5, 3276, 5381, unique_id: '021a997')
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ require 'test_helper'
2
+
3
+ class ClientTest < Totter::TestCase
4
+ def test_initialization
5
+ client = Totter::Client.new(access_token: 'asdf1234')
6
+ assert_equal 'asdf1234', client.access_token
7
+ assert client.authenticated?
8
+
9
+ client = Totter::Client.new('asdf1234')
10
+ assert_equal 'asdf1234', client.access_token
11
+
12
+ client = Totter::Client.new
13
+ refute client.authenticated?
14
+ end
15
+
16
+ def test_base_url
17
+ client = Totter::Client.new
18
+ assert_equal 'https://api.seesaw.co/v1/', client.base_url
19
+
20
+ client = Totter::Client.new(api_scheme: 'http', api_host: 'example.com', api_version: 42)
21
+ assert_equal 'http://example.com/v42/', client.base_url
22
+ end
23
+
24
+ def test_ssl?
25
+ client = Totter::Client.new
26
+ assert client.ssl?
27
+
28
+ client = Totter::Client.new(api_scheme: 'http')
29
+ refute client.ssl?
30
+ end
31
+ end