buffer 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.bufferapprc.template +23 -0
  3. data/.gitignore +6 -0
  4. data/.rubocop.yml +18 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +5 -0
  7. data/API_COVERAGE.md +19 -0
  8. data/Gemfile +1 -1
  9. data/Guardfile +10 -0
  10. data/{LICENSE → LICENSE.txt} +1 -1
  11. data/README.md +62 -80
  12. data/Rakefile +25 -1
  13. data/TODO.md +3 -0
  14. data/bin/buffer +35 -0
  15. data/buffer.gemspec +26 -16
  16. data/lib/buffer/client.rb +26 -0
  17. data/lib/buffer/core.rb +64 -0
  18. data/lib/buffer/datastructure.rb +18 -0
  19. data/lib/buffer/encode.rb +33 -0
  20. data/lib/buffer/error.rb +10 -0
  21. data/lib/buffer/info.rb +10 -0
  22. data/lib/buffer/link.rb +10 -0
  23. data/lib/buffer/profile.rb +27 -0
  24. data/lib/buffer/update.rb +75 -0
  25. data/lib/buffer/user.rb +9 -0
  26. data/lib/buffer/version.rb +1 -1
  27. data/lib/buffer.rb +16 -102
  28. data/spec/fixtures/destroy.txt +10 -0
  29. data/spec/fixtures/info.txt +10 -0
  30. data/spec/fixtures/interactions_by_update_id.txt +10 -0
  31. data/spec/fixtures/link.txt +12 -0
  32. data/spec/fixtures/profile_authenticated.txt +11 -0
  33. data/spec/fixtures/profile_schedules_by_id.txt +10 -0
  34. data/spec/fixtures/profiles_by_id.txt +10 -0
  35. data/spec/fixtures/update_by_id.txt +10 -0
  36. data/spec/fixtures/update_by_id_non_auth.txt +9 -0
  37. data/spec/fixtures/updates_by_profile_id.txt +10 -0
  38. data/spec/fixtures/updates_by_profile_id_pending.txt +10 -0
  39. data/spec/fixtures/user_authenticated.txt +19 -0
  40. data/spec/lib/buffer/encode_spec.rb +42 -0
  41. data/spec/lib/buffer/link_spec.rb +22 -0
  42. data/spec/lib/buffer/profile_spec.rb +87 -0
  43. data/spec/lib/buffer/schedule_spec.rb +80 -0
  44. data/spec/lib/buffer/update_spec.rb +227 -0
  45. data/spec/lib/buffer/user_spec.rb +26 -0
  46. data/spec/lib/buffer_spec.rb +30 -0
  47. data/spec/lib/core_spec.rb +60 -0
  48. data/spec/spec_helper.rb +171 -0
  49. metadata +215 -67
  50. data/spec/buffer_spec.rb +0 -354
  51. data/spec/fixtures/create_body.txt +0 -1
  52. data/spec/fixtures/success.json +0 -1
  53. data/spec/fixtures/user.json +0 -1
  54. data/spec/helper.rb +0 -43
@@ -0,0 +1,75 @@
1
+ module Buffer
2
+ class Client
3
+ module Update
4
+ def update_by_id(id, options = {})
5
+ check_id(id)
6
+ response = get("/updates/#{id}.json")
7
+ Buffer::Update.new(response)
8
+ end
9
+
10
+ def updates_by_profile_id(id, options = {})
11
+ status = options.fetch(:status) do
12
+ raise Buffer::Error::MissingStatus, "Include :pending or :sent in args"
13
+ end
14
+ options.delete(:status)
15
+ response = get("/profiles/#{id}/updates/#{status.to_s}.json", options)
16
+ updates = response['updates'].map { |r| Buffer::Update.new(r) }
17
+ Buffer::Updates.new (
18
+ { total: response['total'],
19
+ updates: updates }
20
+ )
21
+ end
22
+
23
+ def interactions_by_update_id(id, options = {})
24
+ check_id(id)
25
+ response = get("/updates/#{id}/interactions.json", options)
26
+ interactions = response['interactions'].map do |r|
27
+ Buffer::Interaction.new(r)
28
+ end
29
+ Buffer::Interactions.new(
30
+ { total: response['total'], interactions: interactions }
31
+ )
32
+ end
33
+
34
+ def reorder_updates(profile_id, options = {})
35
+ options.fetch(:order) { raise ArgumentError }
36
+ post("/profiles/#{profile_id}/updates/reorder.json", body: options)
37
+ end
38
+
39
+ def shuffle_updates(profile_id, options = {})
40
+ post("/profiles/#{profile_id}/updates/shuffle.json",
41
+ body: options)
42
+ end
43
+
44
+ def create_update(options = {})
45
+ options[:body].fetch(:text) do
46
+ raise ArgumentError, "Must include text for update"
47
+ end
48
+ options[:body].fetch(:profile_ids) do
49
+ raise ArgumentError, "Must include array of profile_ids"
50
+ end
51
+ post("/updates/create.json", options)
52
+ end
53
+
54
+ def modify_update_text(update_id, options = {})
55
+ options[:body].fetch(:text) do
56
+ raise ArgumentError, "Must include updated text"
57
+ end
58
+ post("/updates/#{update_id}/update.json", options)
59
+ end
60
+
61
+ def share_update(update_id)
62
+ post("/updates/#{update_id}/share.json")
63
+ end
64
+
65
+ def destroy_update(update_id)
66
+ post("/updates/#{update_id}/destroy.json")
67
+ end
68
+
69
+ def check_id(id)
70
+ raise Buffer::Error::InvalidIdLength unless id.length == 24
71
+ raise Buffer::Error::InvalidIdContent unless id[/^[a-f0-9]+$/i]
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,9 @@
1
+ module Buffer
2
+ class Client
3
+ module User
4
+ def user_info(options = {})
5
+ Buffer::UserInfo.new(get("/user.json"))
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module Buffer
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/buffer.rb CHANGED
@@ -1,107 +1,21 @@
1
- require 'buffer/version'
2
1
  require 'faraday'
3
- require 'multi_json'
2
+ require 'faraday_middleware'
3
+ require 'json'
4
+ require 'hashie/mash'
4
5
  require 'addressable/uri'
5
- require 'active_support/core_ext'
6
-
7
- module Buffer
8
- class Client
9
-
10
- attr_reader :token
11
-
12
- # Initialize a new Buffer::Client
13
- #
14
- # Also sets up a Faraday connection object
15
- #
16
- # token - string access token for use with all API requests
17
- def initialize(token)
18
- if token.kind_of? String
19
- @token = token
20
- else
21
- raise ArgumentError, "token must be a string"
22
- end
23
-
24
- @conn = Faraday.new :url => 'https://api.bufferapp.com/1/'
25
- @addr = Addressable::URI.new
26
- end
27
-
28
- # get is a shorthand method for api :get
29
- #
30
- # uri - string endpoint uri
31
- def get(uri)
32
- api :get, uri
33
- end
34
-
35
- # post is a shorthand method for api :post
36
- #
37
- # uri - string endpoint uri
38
- # data - hash or array for POST body
39
- def post(uri, data = {})
40
- api :post, uri, data
41
- end
42
-
43
- # api is the root method of the Client, handling all requests.
44
- #
45
- # type - HTTP verb, :get or :post
46
- # url - enpoint uri, with or without .json
47
- # data - hash or array of data to be sent in POST body
48
- def api(type, uri, data = {})
49
- uri << '.json' unless uri =~ /\.json$/
50
- res = if type == :get
51
- @conn.get uri, :access_token => @token
52
- elsif type == :post
53
- @conn.post do |req|
54
- req.url uri, :access_token => @token
55
- req.body = data.to_query
56
- end
57
- end
58
- # Return nil if the body is less that 2 characters long,
59
- # ie. '{}' is the minimum valid JSON, or if the decoder
60
- # raises an exception when passed mangled JSON
61
- begin
62
- MultiJson.load res.body if res.body && res.body.length >= 2
63
- rescue
64
- end
65
- end
66
-
67
- end
6
+ require 'environs'
68
7
 
69
- class User < Client
70
-
71
- def initialize(token)
72
- super
73
- invalidate
74
- end
75
-
76
- private
77
-
78
- # user is a method for handling the cache of the user
79
- # data from the Buffer API.
80
- #
81
- # Returns a hash of user data.
82
- def user
83
- @cache[:user] ||= get 'user'
84
- end
85
-
86
- public
87
-
88
- # invalidate wipes the cache so that future requests
89
- # rebuild it from server data
90
- def invalidate
91
- @cache = {}
92
- end
93
-
94
- # method_missing steps in to enable the helper methods
95
- # by trying to get a particular key from self.user
96
- #
97
- # Returns the user data or the result of super
98
- def method_missing(method, *args, &block)
99
- user[method.to_s] || super
100
- end
101
-
102
- def respond_to?(name)
103
- user.key_exist? name
104
- end
8
+ require 'buffer/version'
9
+ require 'buffer/core'
10
+ require 'buffer/user'
11
+ require 'buffer/profile'
12
+ require 'buffer/update'
13
+ require 'buffer/link'
14
+ require 'buffer/error'
15
+ require 'buffer/encode'
16
+ require 'buffer/datastructure'
17
+ require 'buffer/info'
18
+ require 'buffer/client'
105
19
 
106
- end
20
+ module Buffer
107
21
  end
@@ -0,0 +1,10 @@
1
+ HTTP/1.1 200 Awesome
2
+ Content-Type: application/json;charset=UTF-8
3
+ Date: Wed, 15 May 2013 01:43:34 GMT
4
+ Server: Apache
5
+ Vary: Accept-Encoding,User-Agent
6
+ x-frame-options: SAMEORIGIN
7
+ Content-Length: 828
8
+ Connection: keep-alive
9
+
10
+ {"success":true,"message":"Update deleted successfully"}
@@ -0,0 +1,10 @@
1
+ HTTP/1.1 200 Awesome
2
+ Content-Type: application/json;charset=UTF-8
3
+ Date: Thu, 16 May 2013 22:05:18 GMT
4
+ Server: Apache
5
+ Vary: Accept-Encoding,User-Agent
6
+ x-frame-options: SAMEORIGIN
7
+ Content-Length: 2820
8
+ Connection: keep-alive
9
+
10
+ {"services":{"twitter":{"types":{"profile":{"name":"Twitter","character_limit":140,"schedule_limit":288,"icons":{"16":"http:\/\/static.bufferapp.com\/images\/services\/twitter-16x16.png","32":"http:\/\/static.bufferapp.com\/images\/services\/twitter-32x32.png","64":"http:\/\/static.bufferapp.com\/images\/services\/twitter-64x64.png"},"supported_interactions":["favorites","favorite","mentions","mention","retweets","retweet"]}},"urls":{"user":"https:\/\/twitter.com\/","hashtag":"https:\/\/twitter.com\/#!\/search?q=%23","cashtag":"https:\/\/twitter.com\/#!\/search?q=%24"}},"facebook":{"types":{"profile":{"name":"Facebook","character_limit":5000,"schedule_limit":5,"icons":{"16":"http:\/\/static.bufferapp.com\/images\/services\/facebook-16x16.png","32":"http:\/\/static.bufferapp.com\/images\/services\/facebook-32x32.png","64":"http:\/\/static.bufferapp.com\/images\/services\/facebook-64x64.png"},"supported_interactions":["likes","like","comments","comment"]},"page":{"name":"Facebook Page","character_limit":5000,"schedule_limit":5,"icons":{"16":"http:\/\/static.bufferapp.com\/images\/services\/facebook-16x16.png","32":"http:\/\/static.bufferapp.com\/images\/services\/facebook-32x32.png","64":"http:\/\/static.bufferapp.com\/images\/services\/facebook-64x64.png"},"supported_interactions":["likes","like","comments","comment"]}},"urls":{"user":"https:\/\/www.facebook.com\/"}},"linkedin":{"types":{"profile":{"name":"LinkedIn","character_limit":700,"schedule_limit":25,"icons":{"16":"http:\/\/static.bufferapp.com\/images\/services\/linkedin-16x16.png","32":"http:\/\/static.bufferapp.com\/images\/services\/linkedin-32x32.png","64":"http:\/\/static.bufferapp.com\/images\/services\/linkedin-64x64.png"},"supported_interactions":["comments","comment","likes","like"]},"group":{"name":"LinkedIn Group","character_limit":200,"schedule_limit":100,"icons":{"16":"http:\/\/static.bufferapp.com\/images\/services\/linkedin-16x16.png","32":"http:\/\/static.bufferapp.com\/images\/services\/linkedin-32x32.png","64":"http:\/\/static.bufferapp.com\/images\/services\/linkedin-64x64.png"},"supported_interactions":["comments","comment","likes","like"]}},"urls":{"user":"http:\/\/www.linkedin.com\/search\/fpsearch?type=people&keywords="}},"appdotnet":{"types":{"profile":{"name":"App.net","character_limit":256,"schedule_limit":288,"icons":{"16":"http:\/\/static.bufferapp.com\/images\/services\/appdotnet-alpha-16x16.png","32":"http:\/\/static.bufferapp.com\/images\/services\/appdotnet-alpha2-32x32.png","64":"http:\/\/static.bufferapp.com\/images\/services\/appdotnet-alpha-64x64.png"},"supported_interactions":[]}},"urls":{"user":"https:\/\/alpha.app.net\/","hashtag":"https:\/\/alpha.app.net\/hashtags\/"}}},"media":{"picture_size_min":0,"picture_size_max":5242880,"picture_filetypes":["jpeg","jpg","gif","png"]}}
@@ -0,0 +1,10 @@
1
+ HTTP/1.1 200 Awesome
2
+ Content-Type: application/json;charset=UTF-8
3
+ Date: Fri, 17 May 2013 04:21:13 GMT
4
+ Server: Apache
5
+ Vary: Accept-Encoding,User-Agent
6
+ x-frame-options: SAMEORIGIN
7
+ Content-Length: 29
8
+ Connection: keep-alive
9
+
10
+ {"total":0,"interactions":[]}
@@ -0,0 +1,12 @@
1
+ HTTP/1.1 200 Awesome
2
+ Content-Type: application/json;charset=UTF-8
3
+ Date: Wed, 15 May 2013 01:43:34 GMT
4
+ Server: Apache
5
+ Vary: Accept-Encoding,User-Agent
6
+ x-frame-options: SAMEORIGIN
7
+ Content-Length: 828
8
+ Connection: keep-alive
9
+
10
+ {
11
+ "shares":47348
12
+ }
@@ -0,0 +1,11 @@
1
+ HTTP/1.1 200 Awesome
2
+ Content-Type: application/json;charset=UTF-8
3
+ Date: Tue, 14 May 2013 05:02:18 GMT
4
+ Server: Apache
5
+ Vary: Accept-Encoding,User-Agent
6
+ X-Cache: Awwww Yea
7
+ x-frame-options: SAMEORIGIN
8
+ Content-Length: 845
9
+ Connection: keep-alive
10
+
11
+ [{"_id":"5160746d13f04a5e3a00000f","avatar":"http:\/\/a0.twimg.com\/profile_images\/3604112130.jpeg","avatar_https":"https:\/\/twimg0-a.akamaihd.net\/profile_images\/3604112130.jpeg","counts":{"pending":1,"sent":40},"created_at":1365275757,"default":true,"disconnected":null,"formatted_service":"Twitter","formatted_username":"@example","id":"5160746d13d04a5e3a00000f","quick_signin":true,"schedules":[{"days":["mon","tue","wed","thu","fri","sat","sun"],"times":["06:13","09:10","11:58","12:17","13:49","18:07","21:04","22:13"]}],"service":"twitter","service_id":"737649619","service_type":"profile","service_username":"example","statistics":{"followers":179},"timezone":"America\/New_York","user_id":"5160746d13d04a5e3a00000d","utm_tracking":"enabled","verb":"tweet"}]
@@ -0,0 +1,10 @@
1
+ HTTP/1.1 200 Awesome
2
+ Content-Type: application/json;charset=UTF-8
3
+ Date: Wed, 15 May 2013 01:53:50 GMT
4
+ Server: Apache
5
+ Vary: Accept-Encoding,User-Agent
6
+ x-frame-options: SAMEORIGIN
7
+ Content-Length: 128
8
+ Connection: keep-alive
9
+
10
+ [{"days":["mon","tue","wed","thu","fri","sat","sun"],"times":["06:13","09:10","11:58","12:17","13:49","18:07","21:04","22:13"]}]
@@ -0,0 +1,10 @@
1
+ HTTP/1.1 200 Awesome
2
+ Content-Type: application/json;charset=UTF-8
3
+ Date: Wed, 15 May 2013 01:43:34 GMT
4
+ Server: Apache
5
+ Vary: Accept-Encoding,User-Agent
6
+ x-frame-options: SAMEORIGIN
7
+ Content-Length: 828
8
+ Connection: keep-alive
9
+
10
+ {"_id":"5160746d13d04a5e3a00000f","avatar":"http:\/\/a0.twimg.com\/profile_images\/3604112130.jpeg","avatar_https":"https:\/\/twimg0-a.akamaihd.net\/profile_images\/3604112130.jpeg","counts":{"pending":1,"sent":46},"created_at":1365275757,"disconnected":null,"formatted_service":"Twitter","formatted_username":"@example","id":"5160746d13d04a5e3a00000f","quick_signin":true,"schedules":[{"days":["mon","tue","wed","thu","fri","sat","sun"],"times":["06:13","09:10","11:58","12:17","13:49","18:07","21:04","22:13"]}],"service":"twitter","service_id":"737649619","service_type":"profile","service_username":"example","statistics":{"followers":179},"timezone":"America\/New_York","user_id":"5160746d13d04a5e3a00000d","utm_tracking":"enabled","verb":"tweet"}
@@ -0,0 +1,10 @@
1
+ HTTP/1.1 200 Awesome
2
+ Content-Type: application/json;charset=UTF-8
3
+ Date: Wed, 15 May 2013 01:43:34 GMT
4
+ Server: Apache
5
+ Vary: Accept-Encoding,User-Agent
6
+ x-frame-options: SAMEORIGIN
7
+ Content-Length: 828
8
+ Connection: keep-alive
9
+
10
+ {"id":"4eb8565e0acb04bb82000004","created_at":1320703582,"day":"Monday 7th November","due_at":1320742680,"due_time":"10:09 pm","profile_id":"4eb854340acb04e870000010","profile_service":"twitter","sent_at":1320744001,"service_update_id":"133667319959392256","statistics":{"reach":2460,"clicks":56,"retweets":20,"favorites":1,"mentions":1},"status":"sent","text":"This is just the beginning, the very beginning, of the transfor...","text_formatted":"This is just the beginning, the very beginning, of th...","user_id":"4eb9276e0acb04bb81000067","via":"chrome"}
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 401 Authorization Required
2
+ Content-Type: text/html; charset=UTF-8
3
+ Date: Fri, 17 May 2013 02:46:37 GMT
4
+ Server: Apache
5
+ Vary: Accept-Encoding,User-Agent
6
+ WWW-Authenticate: OAuth realm='Service', error='invalid_request', error_description='The request is missing a required parameter, includes an unsupported parameter or parameter value, repeats the same parameter, uses more than one method for including an access token, or is otherwise malformed.'
7
+ Content-Length: 0
8
+ Connection: keep-alive
9
+
@@ -0,0 +1,10 @@
1
+ HTTP/1.1 200 Awesome
2
+ Content-Type: application/json;charset=UTF-8
3
+ Date: Wed, 15 May 2013 01:43:34 GMT
4
+ Server: Apache
5
+ Vary: Accept-Encoding,User-Agent
6
+ x-frame-options: SAMEORIGIN
7
+ Content-Length: 828
8
+ Connection: keep-alive
9
+
10
+ {"total":8,"updates":[{"id":"4ec93ae4512f7e6307000002","created_at":1320703582,"day":"Monday 7th November","due_at":1320543480,"due_time":"07:01 pm","profile_id":"4eb854340acb04e870000010","profile_service":"twitter","status":"buffer","text":"This is me in an alternate life where i can breakdance j.mp/w...","text_formatted":"This is me in an alternate life where i can breakda...","user_id":"4eb9276e0acb04bb81000067","via":"firefox"},] }
@@ -0,0 +1,10 @@
1
+ HTTP/1.1 200 Awesome
2
+ Content-Type: application/json;charset=UTF-8
3
+ Date: Thu, 16 May 2013 04:48:14 GMT
4
+ Server: Apache
5
+ Vary: Accept-Encoding,User-Agent
6
+ x-frame-options: SAMEORIGIN
7
+ Content-Length: 737
8
+ Connection: keep-alive
9
+
10
+ {"total":1,"updates":[{"_id":"519464f2872cad3734000028","created_at":1368679666,"day":"Today","due_at":1368699180,"due_time":"6:13 am","id":"519464f2872cad3734000028","profile_id":"5160746d13d04a5e3a00000f","profile_service":"twitter","shared_now":false,"status":"buffer","text":"Exciting to have even 1 person fork my fork of a repo :) jaysonlane\/buffer-ruby \u00b7 GitHub http:\/\/bit.ly\/15OS4ap","text_formatted":"Exciting to have even 1 person fork my fork of a repo :) jaysonlane\/buffer-ruby \u00b7 GitHub <a class=\"url\" href=\"http:\/\/bit.ly\/15OS4ap\" rel=\"external nofollow\" target=\"_blank\">http:\/\/bit.ly\/15OS4ap<\/a>","type":"link","updated_at":1368679666,"user_id":"5160746d54f04a5e3a00000d","via":"bookmarklet"}]}
@@ -0,0 +1,19 @@
1
+ HTTP/1.1 200 OK
2
+ Server: nginx/0.7.65
3
+ Date: Thu, 03 Mar 2011 19:25:34 GMT
4
+ Content-Type: application/json
5
+ Connection: keep-alive
6
+ Keep-Alive: timeout=20
7
+ Content-Length: 380
8
+
9
+ {
10
+ "_id":"4f0c0a06512f7ef214000000",
11
+ "activity_at":1343654640,
12
+ "created_at":1326189062,
13
+ "id":"4f0c0a06512f7ef214000000",
14
+ "plan":"free",
15
+ "referral_link":"http:\/\/bufferapp.com\/r\/abcde",
16
+ "referral_token":"abcde",
17
+ "secret_email":"supersecret@to.bufferapp.com",
18
+ "timezone":"Asia\/Tel_Aviv"
19
+ }
@@ -0,0 +1,42 @@
1
+ require "spec_helper"
2
+
3
+ describe Buffer::Encode do
4
+
5
+ context "successful code" do
6
+
7
+ let(:schedule_first) { { :days => ["mon", "tue", "wed", "thu"], :times => ["12:00", "13:00"]} }
8
+ let(:schedule_second) { { :days => ["sun", "sat"], :times => ["09:00", "24:00"]} }
9
+ let(:schedules_hash) { { schedules: [schedule_first, schedule_second] } }
10
+ let(:short_schedule) { { days: ["mon", "tue", "wed"], times: ["12:00", "17:00", "18:00"]} }
11
+ let(:short_schedule_encoded) { "[days][]=mon&[days][]=tue&[times][]=12%3A00&[times][]=13%3A00" }
12
+ let(:schedules_encoded) { "schedules[0][days][]=mon&schedules[0][days][]=tue&schedules[0][days][]=wed&schedules[0][times][]=12:00&schedules[0][times][]=17:00&schedules[0][times][]=18:00" }
13
+ let(:very_short_schedule) { { :days => ["sun", "sat"], :times => ["09:00", "24:00"]} }
14
+
15
+
16
+ describe "#encode"
17
+ it "converts to match Buffer API specs encoding" do
18
+ Buffer::Encode.encode([short_schedule]).
19
+ should eq(schedules_encoded.gsub(/:/, '%3A'))
20
+ end
21
+
22
+ it "processes an input array of schedules" do
23
+ Buffer::Encode.encode([very_short_schedule, very_short_schedule]).
24
+ should eq("schedules[0][days][]=sun&schedules[0][days][]=sat&schedules[0][times][]=09%3A00&schedules[0][times][]=24%3A00&schedules[1][days][]=sun&schedules[1][days][]=sat&schedules[1][times][]=09%3A00&schedules[1][times][]=24%3A00")
25
+ end
26
+
27
+ it "includes index in conversion when multiple schedules present" do
28
+ Buffer::Encode.encode([very_short_schedule, very_short_schedule, very_short_schedule]).
29
+ should eq("schedules[0][days][]=sun&schedules[0][days][]=sat&schedules[0][times][]=09%3A00&schedules[0][times][]=24%3A00&schedules[1][days][]=sun&schedules[1][days][]=sat&schedules[1][times][]=09%3A00&schedules[1][times][]=24%3A00&schedules[2][days][]=sun&schedules[2][days][]=sat&schedules[2][times][]=09%3A00&schedules[2][times][]=24%3A00")
30
+ end
31
+
32
+ it "processes an input hash" do
33
+ Buffer::Encode.encode({ schedules: [very_short_schedule, very_short_schedule, very_short_schedule] }).
34
+ should eq("schedules[0][days][]=sun&schedules[0][days][]=sat&schedules[0][times][]=09%3A00&schedules[0][times][]=24%3A00&schedules[1][days][]=sun&schedules[1][days][]=sat&schedules[1][times][]=09%3A00&schedules[1][times][]=24%3A00&schedules[2][days][]=sun&schedules[2][days][]=sat&schedules[2][times][]=09%3A00&schedules[2][times][]=24%3A00")
35
+ end
36
+ end
37
+
38
+ describe "#encode_schedule_primary" do
39
+ end
40
+
41
+
42
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe Buffer::Client do
4
+ describe "#link" do
5
+ let(:client) { Buffer::Client.new("some_token") }
6
+ let(:url) { %q{http://bufferapp.com} }
7
+
8
+ before do
9
+ stub_request(:get, "#{ base_path }/links/shares.json?#{ access_token_param }&url=http://bufferapp.com").
10
+ to_return(fixture('link.txt'))
11
+ end
12
+
13
+ it "connects to the correct endpoint" do
14
+ client.link({url: url})
15
+ end
16
+
17
+ it "parses the shares of a link" do
18
+ client.link({url: url}).shares.should eq(47348)
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ describe Buffer::Client::Profile do
4
+ let(:id) { "5160746d54f04a5e3a00000f" }
5
+
6
+ subject do
7
+ Buffer::Client.new("some_token")
8
+ end
9
+
10
+ describe "#profiles" do
11
+ let(:rash) { Buffer::Client.new("some_token").profiles }
12
+
13
+ before(:each) do
14
+ url = "#{ base_path }/profiles.json"
15
+ stub_with_to_return(:get, url, 'profile_authenticated.txt')
16
+ end
17
+
18
+ it "makes the correct url request" do
19
+ subject.profiles
20
+ end
21
+
22
+ it "returns a Rash collection object" do
23
+ rash[0].class.should eq(Buffer::Profile)
24
+ end
25
+
26
+ it "provides an accessor for plan" do
27
+ rash[0].service.should eq("twitter")
28
+ end
29
+ end
30
+
31
+ describe "#profile_by_id" do
32
+ let(:id) { "5160746d54f04a5e3a00000f" }
33
+ before(:each) do
34
+ url = "#{base_path}/profiles/#{id}.json"
35
+ fixture_name = "profiles_by_id.txt"
36
+ stub_with_to_return(:get, url, fixture_name)
37
+ end
38
+
39
+ let(:rash) { Buffer::Client.new("some_token").profile_by_id(id) }
40
+
41
+ it "returns a rash collection" do
42
+ rash.class.should eq(Buffer::Profile)
43
+ end
44
+
45
+ it "accesses formatted service" do
46
+ rash.formatted_service.should eq("Twitter")
47
+ end
48
+ end
49
+
50
+ describe "#schedules_by_profile_id" do
51
+ before(:each) do
52
+ url = "#{base_path}/profiles/#{id}/schedules.json"
53
+ fixture_name = 'profile_schedules_by_id.txt'
54
+ stub_with_to_return(:get, url, fixture_name)
55
+ end
56
+
57
+ let(:rash) { Buffer::Client.new("some_token").schedules_by_profile_id(id) }
58
+
59
+ it "returns a rash collection" do
60
+ rash[0].class.should eq(Buffer::Schedule)
61
+ end
62
+
63
+ it "accesses days" do
64
+ expect(rash[0].days).to include("mon")
65
+ end
66
+
67
+ it "accesses times" do
68
+ expect(rash[0].times).to include("06:13")
69
+ end
70
+ end
71
+
72
+
73
+ describe "#info" do
74
+ before do
75
+ stub_request(:get, "#{base_path}/info/configuration.json?access_token=some_token").
76
+ to_return(fixture("info.txt"))
77
+ end
78
+
79
+ it "connects to the correct endpoint" do
80
+ subject.info
81
+ end
82
+
83
+ it "retrieves the correct name" do
84
+ subject.info.services.twitter.types.profile.name.should eq("Twitter")
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe Buffer::Schedules do
4
+ before do
5
+ @schedule = JSON.parse <<EOF
6
+ {
7
+ "days" : [
8
+ "mon",
9
+ "tue",
10
+ "wed",
11
+ "thu",
12
+ "fri"
13
+ ],
14
+ "times" : [
15
+ "12:00",
16
+ "17:00",
17
+ "18:00"
18
+ ]
19
+ }
20
+ EOF
21
+
22
+ @sample_schedules = JSON.parse <<EOF
23
+ { "schedules" : [{
24
+ "days" : [
25
+ "mon",
26
+ "tue",
27
+ "wed",
28
+ "thu",
29
+ "fri"
30
+ ],
31
+ "times" : [
32
+ "12:00",
33
+ "17:00",
34
+ "18:00"
35
+ ]
36
+ },
37
+ {
38
+ "days" : [
39
+ "mon",
40
+ "tue",
41
+ "wed",
42
+ "thu",
43
+ "fri"
44
+ ],
45
+ "times" : [
46
+ "12:00",
47
+ "17:00",
48
+ "18:00"
49
+ ]
50
+ }]
51
+ }
52
+ EOF
53
+ end
54
+
55
+ it "accepts an array of days" do
56
+ lambda {
57
+ schedules = Buffer::Schedules.new
58
+ schedules << Buffer::Schedule.new
59
+ }.should_not raise_error
60
+ end
61
+
62
+ it "dumping a double schedule yields correct json" do
63
+ schedules = Buffer::Schedules.new
64
+ schedules << @schedule << @schedule
65
+ @sample_schedules = @sample_schedules.to_json
66
+
67
+ schedules.dump.should eq(@sample_schedules)
68
+ end
69
+
70
+ describe "#set_schedules" do
71
+ let(:id) { "5160746d54f04a5e3a00000f" }
72
+ it "throw error if schedules is empty" do
73
+ lambda {
74
+ Buffer::Client.new("some_token").set_schedules(id) }.
75
+ should raise_error(ArgumentError)
76
+
77
+ end
78
+ end
79
+ end
80
+