buffer 0.0.1 → 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 (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
+