garb 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -193,8 +193,9 @@ SSL
193
193
  TODOS
194
194
  -----
195
195
 
196
- * Sessions are currently global, which isn't awesome
197
196
  * Read opensearch header in results
197
+ * Investigate new features from GA to see if they're in the API, implement if so
198
+ * clarify AND/OR filtering behavior in code and documentation
198
199
 
199
200
  Requirements
200
201
  ------------
@@ -8,10 +8,10 @@ module Garb
8
8
  @profiles = profiles
9
9
  end
10
10
 
11
- def self.all
11
+ def self.all(session = Session)
12
12
  # Profile.all.group_to_array{|p| p.account_id}.map{|profiles| new(profiles)}
13
13
 
14
- profile_groups = Profile.all.inject({}) do |hash, profile|
14
+ profile_groups = Profile.all(session).inject({}) do |hash, profile|
15
15
  key = profile.account_id
16
16
 
17
17
  if hash.has_key?(key)
@@ -2,7 +2,8 @@ module Garb
2
2
  class DataRequest
3
3
  class ClientError < StandardError; end
4
4
 
5
- def initialize(base_url, parameters={})
5
+ def initialize(session, base_url, parameters={})
6
+ @session = session
6
7
  @base_url = base_url
7
8
  @parameters = parameters
8
9
  end
@@ -17,9 +18,9 @@ module Garb
17
18
  end
18
19
 
19
20
  def send_request
20
- response = if Session.single_user?
21
+ response = if @session.single_user?
21
22
  single_user_request
22
- elsif Session.oauth_user?
23
+ elsif @session.oauth_user?
23
24
  oauth_user_request
24
25
  end
25
26
 
@@ -31,11 +32,11 @@ module Garb
31
32
  http = Net::HTTP.new(uri.host, uri.port)
32
33
  http.use_ssl = true
33
34
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
34
- http.get("#{uri.path}#{query_string}", 'Authorization' => "GoogleLogin auth=#{Session.auth_token}")
35
+ http.get("#{uri.path}#{query_string}", 'Authorization' => "GoogleLogin auth=#{@session.auth_token}")
35
36
  end
36
37
 
37
38
  def oauth_user_request
38
- Session.access_token.get("#{uri}#{query_string}")
39
+ @session.access_token.get("#{uri}#{query_string}")
39
40
  end
40
41
  end
41
42
  end
@@ -3,7 +3,7 @@ module Garb
3
3
 
4
4
  include ProfileReports
5
5
 
6
- attr_reader :table_id, :title, :account_name, :account_id, :web_property_id
6
+ attr_reader :session, :table_id, :title, :account_name, :account_id, :web_property_id
7
7
 
8
8
  class Property
9
9
  include HappyMapper
@@ -30,7 +30,8 @@ module Garb
30
30
  has_many :properties, Property
31
31
  end
32
32
 
33
- def initialize(entry)
33
+ def initialize(entry, session)
34
+ @session = session
34
35
  @title = entry.title
35
36
  @table_id = entry.tableId
36
37
 
@@ -43,14 +44,14 @@ module Garb
43
44
  Garb.from_google_analytics(@table_id)
44
45
  end
45
46
 
46
- def self.all
47
+ def self.all(session = Session)
47
48
  url = "https://www.google.com/analytics/feeds/accounts/default"
48
- response = DataRequest.new(url).send_request
49
- Entry.parse(response.body).map {|entry| new(entry)}
49
+ response = DataRequest.new(session, url).send_request
50
+ Entry.parse(response.body).map {|entry| new(entry, session)}
50
51
  end
51
52
 
52
- def self.first(id)
53
- all.detect {|profile| profile.id == id || profile.web_property_id == id }
53
+ def self.first(id, session = Session)
54
+ all(session).detect {|profile| profile.id == id || profile.web_property_id == id }
54
55
  end
55
56
  end
56
57
  end
@@ -41,16 +41,20 @@ module Garb
41
41
  end
42
42
 
43
43
  def results(profile, opts = {}, &block)
44
- @profile = profile.is_a?(Profile) ? profile : Profile.first(profile)
44
+ @profile = profile.is_a?(Profile) ? profile : Profile.first(profile, opts.fetch(:session, Session))
45
45
 
46
- @start_date = opts.fetch(:start_date, Time.now - MONTH)
47
- @end_date = opts.fetch(:end_date, Time.now)
48
- @limit = opts.fetch(:limit, nil)
49
- @offset = opts.fetch(:offset, nil)
46
+ if @profile
47
+ @start_date = opts.fetch(:start_date, Time.now - MONTH)
48
+ @end_date = opts.fetch(:end_date, Time.now)
49
+ @limit = opts.fetch(:limit, nil)
50
+ @offset = opts.fetch(:offset, nil)
50
51
 
51
- instance_eval(&block) if block_given?
52
+ instance_eval(&block) if block_given?
52
53
 
53
- ReportResponse.new(send_request_for_body).results
54
+ ReportResponse.new(send_request_for_body).results
55
+ else
56
+ []
57
+ end
54
58
  end
55
59
 
56
60
  def page_params
@@ -80,7 +84,7 @@ module Garb
80
84
  end
81
85
 
82
86
  def send_request_for_body
83
- request = DataRequest.new(URL, params)
87
+ request = DataRequest.new(@profile.session, URL, params)
84
88
  response = request.send_request
85
89
  response.body
86
90
  end
@@ -1,22 +1,25 @@
1
1
  module Garb
2
- module Session
3
- extend self
2
+ class Session
3
+ module Methods
4
+ attr_accessor :auth_token, :access_token, :email
4
5
 
5
- attr_accessor :auth_token, :access_token, :email
6
+ # use only for single user authentication
7
+ def login(email, password, opts={})
8
+ self.email = email
9
+ auth_request = AuthenticationRequest.new(email, password, opts)
10
+ self.auth_token = auth_request.auth_token(opts)
11
+ end
6
12
 
7
- # use only for single user authentication
8
- def login(email, password, opts={})
9
- self.email = email
10
- auth_request = AuthenticationRequest.new(email, password, opts)
11
- self.auth_token = auth_request.auth_token(opts)
12
- end
13
+ def single_user?
14
+ auth_token && auth_token.is_a?(String)
15
+ end
13
16
 
14
- def single_user?
15
- auth_token && auth_token.is_a?(String)
17
+ def oauth_user?
18
+ !access_token.nil?
19
+ end
16
20
  end
17
21
 
18
- def oauth_user?
19
- !access_token.nil?
20
- end
22
+ include Methods
23
+ extend Methods
21
24
  end
22
25
  end
@@ -2,7 +2,7 @@ module Garb
2
2
  module Version
3
3
 
4
4
  MAJOR = 0
5
- MINOR = 6
5
+ MINOR = 7
6
6
  TINY = 0
7
7
 
8
8
  def self.to_s # :nodoc:
@@ -18,13 +18,24 @@ module Garb
18
18
  end
19
19
 
20
20
  context "An instance of the Account class" do
21
- context "when creating a new account from an array of profiles" do
22
- setup do
23
- profile = stub(:account_id => '1111', :account_name => 'Blog 1')
24
- @profiles = [profile,profile]
25
- @account = Account.new(@profiles)
21
+ setup do
22
+ profile = stub(:account_id => '1111', :account_name => 'Blog 1')
23
+ @profiles = [profile,profile]
24
+ @account = Account.new(@profiles)
25
+ end
26
+
27
+ context "all" do
28
+ should "use an optional user session" do
29
+ session = Session.new
30
+ Garb::Profile.expects(:all).with(session).returns(@profiles)
31
+
32
+ accounts = Account.all(session)
33
+ assert_equal 1, accounts.size
34
+ assert_equal @profiles, accounts.first.profiles
26
35
  end
36
+ end
27
37
 
38
+ context "when creating a new account from an array of profiles" do
28
39
  should "take the account id from the first profile" do
29
40
  assert_equal @profiles.first.account_id, @account.id
30
41
  end
@@ -4,10 +4,14 @@ module Garb
4
4
  class DataRequestTest < MiniTest::Unit::TestCase
5
5
 
6
6
  context "An instance of the DataRequest class" do
7
+ setup do
8
+ @session = Session.new
9
+ @session.auth_token = 'abcdefg123456'
10
+ end
7
11
 
8
12
  should "be able to build the query string from parameters" do
9
13
  parameters = {'ids' => '12345', 'metrics' => 'country'}
10
- data_request = DataRequest.new("", parameters)
14
+ data_request = DataRequest.new(@session, "", parameters)
11
15
 
12
16
  query_string = data_request.query_string
13
17
 
@@ -19,7 +23,7 @@ module Garb
19
23
  end
20
24
 
21
25
  should "return an empty query string if parameters are empty" do
22
- data_request = DataRequest.new("")
26
+ data_request = DataRequest.new(@session, "")
23
27
  assert_equal "", data_request.query_string
24
28
  end
25
29
 
@@ -27,16 +31,16 @@ module Garb
27
31
  url = 'http://example.com'
28
32
  expected = URI.parse('http://example.com')
29
33
 
30
- assert_equal expected, DataRequest.new(url).uri
34
+ assert_equal expected, DataRequest.new(@session, url).uri
31
35
  end
32
36
 
33
37
  should "be able to send a request for a single user" do
34
- Session.stubs(:single_user?).returns(true)
38
+ @session.stubs(:single_user?).returns(true)
35
39
  response = mock('Net::HTTPOK') do |m|
36
40
  m.expects(:kind_of?).with(Net::HTTPSuccess).returns(true)
37
41
  end
38
42
 
39
- data_request = DataRequest.new('https://example.com/data', 'key' => 'value')
43
+ data_request = DataRequest.new(@session, 'https://example.com/data', 'key' => 'value')
40
44
  data_request.stubs(:single_user_request).returns(response)
41
45
  data_request.send_request
42
46
 
@@ -44,13 +48,13 @@ module Garb
44
48
  end
45
49
 
46
50
  should "be able to send a request for an oauth user" do
47
- Session.stubs(:single_user?).returns(false)
48
- Session.stubs(:oauth_user?).returns(true)
51
+ @session.stubs(:single_user?).returns(false)
52
+ @session.stubs(:oauth_user?).returns(true)
49
53
  response = mock('Net::HTTPOK') do |m|
50
54
  m.expects(:kind_of?).with(Net::HTTPSuccess).returns(true)
51
55
  end
52
56
 
53
- data_request = DataRequest.new('https://example.com/data', 'key' => 'value')
57
+ data_request = DataRequest.new(@session, 'https://example.com/data', 'key' => 'value')
54
58
  data_request.stubs(:oauth_user_request).returns(response)
55
59
  data_request.send_request
56
60
 
@@ -58,11 +62,11 @@ module Garb
58
62
  end
59
63
 
60
64
  should "raise if the request is unauthorized" do
61
- Session.stubs(:single_user?).returns(false)
62
- Session.stubs(:oauth_user?).returns(true)
65
+ @session.stubs(:single_user?).returns(false)
66
+ @session.stubs(:oauth_user?).returns(true)
63
67
  response = mock('Net::HTTPUnauthorized', :body => 'Error')
64
68
 
65
- data_request = DataRequest.new('https://example.com/data', 'key' => 'value')
69
+ data_request = DataRequest.new(@session, 'https://example.com/data', 'key' => 'value')
66
70
  data_request.stubs(:oauth_user_request).returns(response)
67
71
 
68
72
  assert_raises(Garb::DataRequest::ClientError) do
@@ -72,17 +76,17 @@ module Garb
72
76
 
73
77
  should "be able to request via the ouath access token" do
74
78
  access_token = stub(:get => "responseobject")
75
- Session.stubs(:access_token).returns(access_token)
79
+ @session.stubs(:access_token).returns(access_token)
76
80
 
77
- data_request = DataRequest.new('https://example.com/data', 'key' => 'value')
81
+ data_request = DataRequest.new(@session, 'https://example.com/data', 'key' => 'value')
78
82
  assert_equal 'responseobject', data_request.oauth_user_request
79
83
 
80
- assert_received(Session, :access_token)
84
+ assert_received(@session, :access_token)
81
85
  assert_received(access_token, :get) {|e| e.with('https://example.com/data?key=value')}
82
86
  end
83
87
 
84
88
  should "be able to request via http with an auth token" do
85
- Session.expects(:auth_token).with().returns('toke')
89
+ @session.expects(:auth_token).with().returns('toke')
86
90
  response = mock
87
91
 
88
92
  http = mock do |m|
@@ -93,7 +97,7 @@ module Garb
93
97
 
94
98
  Net::HTTP.expects(:new).with('example.com', 443).returns(http)
95
99
 
96
- data_request = DataRequest.new('https://example.com/data', 'key' => 'value')
100
+ data_request = DataRequest.new(@session, 'https://example.com/data', 'key' => 'value')
97
101
  assert_equal response, data_request.single_user_request
98
102
  end
99
103
  end
@@ -4,6 +4,7 @@ module Garb
4
4
  class ProfileTest < MiniTest::Unit::TestCase
5
5
 
6
6
  context "The Profile class" do
7
+ setup {@session = Session.new}
7
8
 
8
9
  should "be able to return a list of all profiles" do
9
10
  url = 'https://www.google.com/analytics/feeds/accounts/default'
@@ -13,7 +14,7 @@ module Garb
13
14
  data_request = mock
14
15
  data_request.expects(:send_request).with().returns(stub(:body => xml))
15
16
 
16
- DataRequest.expects(:new).with(url).returns(data_request)
17
+ DataRequest.expects(:new).with(@session, url).returns(data_request)
17
18
 
18
19
  entries = [stub]
19
20
 
@@ -23,10 +24,10 @@ module Garb
23
24
  entries.each do |entry|
24
25
  profile = stub
25
26
  profiles << profile
26
- Garb::Profile.expects(:new).with(entry).returns(profile)
27
+ Garb::Profile.expects(:new).with(entry, @session).returns(profile)
27
28
  end
28
29
 
29
- assert_equal profiles, Profile.all
30
+ assert_equal profiles, Profile.all(@session)
30
31
  end
31
32
 
32
33
  should "return the first profile for a given web property id" do
@@ -36,7 +37,9 @@ module Garb
36
37
 
37
38
  Garb::Profile.stubs(:all).returns(entries)
38
39
 
39
- assert_equal profile1, Garb::Profile.first('12345')
40
+ assert_equal profile1, Garb::Profile.first('12345', @session)
41
+
42
+ assert_received(Garb::Profile, :all) {|e| e.with(@session)}
40
43
  end
41
44
 
42
45
  should "return the first profile for a given table id" do
@@ -46,25 +49,27 @@ module Garb
46
49
 
47
50
  Garb::Profile.stubs(:all).returns(entries)
48
51
 
49
- assert_equal profile2, Garb::Profile.first('67890')
52
+ assert_equal profile2, Garb::Profile.first('67890', @session)
53
+
54
+ assert_received(Garb::Profile, :all) {|e| e.with(@session)}
50
55
  end
51
56
  end
52
-
57
+
53
58
  context "An instance of the Profile class" do
54
-
59
+
55
60
  setup do
56
61
  @entry = (Profile::Entry.parse(read_fixture('profile_feed.xml'))).first
57
- @profile = Profile.new(@entry)
62
+ @profile = Profile.new(@entry, Session)
58
63
  end
59
-
64
+
60
65
  should "have a value for :title" do
61
66
  assert_equal "Historical", @profile.title
62
67
  end
63
-
68
+
64
69
  should "have a value for :table_id" do
65
70
  assert_equal 'ga:12345', @profile.table_id
66
71
  end
67
-
72
+
68
73
  should "have a value for :id" do
69
74
  assert_equal '12345', @profile.id
70
75
  end
@@ -76,7 +81,6 @@ module Garb
76
81
  should "have a value for :account_name" do
77
82
  assert_equal 'Blog Beta', @profile.account_name
78
83
  end
79
-
80
84
  end
81
85
 
82
86
  end
@@ -7,7 +7,7 @@ module Garb
7
7
  setup do
8
8
  @now = Time.now
9
9
  Time.stubs(:now).returns(@now)
10
- @profile = stub(:table_id => 'ga:1234')
10
+ @profile = stub(:table_id => 'ga:1234', :session => Session)
11
11
  @report = Report.new(@profile)
12
12
  end
13
13
 
@@ -64,7 +64,7 @@ module Garb
64
64
  request = mock {|m| m.expects(:send_request).returns(response) }
65
65
  @report.expects(:params).returns('params')
66
66
 
67
- DataRequest.expects(:new).with(Garb::Report::URL, 'params').returns(request)
67
+ DataRequest.expects(:new).with(Session, Garb::Report::URL, 'params').returns(request)
68
68
  assert_equal 'response body', @report.send_request_for_body
69
69
  end
70
70
 
@@ -15,5 +15,24 @@ class ResourceTest < MiniTest::Unit::TestCase
15
15
 
16
16
  assert_equal 'analytics', TestReport.results(profile)
17
17
  end
18
+
19
+ should "get results from GA using a specific user session" do
20
+ profile = '123'
21
+ session = Garb::Session.new
22
+ TestReport.expects(:send_request_for_body).returns('xml')
23
+ Garb::ReportResponse.expects(:new).with('xml').returns(mock(:results => 'analytics'))
24
+ Garb::Profile.expects(:first).with(profile, session).returns(mock('Garb::Profile'))
25
+
26
+ assert_equal 'analytics', TestReport.results(profile, :session => session)
27
+ end
28
+
29
+ should "return an empty result set if profile is invalid" do
30
+ profile = '123'
31
+ TestReport.expects(:send_request_for_body).never
32
+ Garb::ReportResponse.expects(:new).never
33
+
34
+ Garb::Profile.expects(:first).returns(nil)
35
+ assert_equal [], TestReport.results(profile)
36
+ end
18
37
  end
19
38
  end
@@ -40,5 +40,45 @@ module Garb
40
40
  end
41
41
  end
42
42
 
43
+ context "A Session" do
44
+ setup do
45
+ @session = Session.new
46
+ end
47
+
48
+ should "be able retrieve an auth_token for a user" do
49
+ auth_request = mock {|m| m.expects(:auth_token).with({}).returns('toke') }
50
+ AuthenticationRequest.expects(:new).with('email', 'password', {}).returns(auth_request)
51
+
52
+ @session.login('email', 'password')
53
+ assert_equal 'toke', @session.auth_token
54
+ end
55
+
56
+ should "be able retrieve an auth_token for a user with secure ssl" do
57
+ opts = {:secure => true, :account_type => 'GOOGLE'}
58
+ auth_request = mock {|m| m.expects(:auth_token).with(opts).returns('toke') }
59
+ AuthenticationRequest.expects(:new).with('email', 'password', opts).returns(auth_request)
60
+
61
+ @session.login('email', 'password', opts)
62
+ assert_equal 'toke', @session.auth_token
63
+ end
64
+
65
+ should "retain the email address for this session" do
66
+ AuthenticationRequest.stubs(:new).returns(stub(:auth_token => 'toke'))
67
+
68
+ @session.login('email', 'password')
69
+ assert_equal 'email', @session.email
70
+ end
71
+
72
+ should "know if the Session is for a single user" do
73
+ @session.auth_token = "abcdefg1234567"
74
+ assert_equal true, @session.single_user?
75
+ end
76
+
77
+ should "know if the Session is for oauth" do
78
+ @session.access_token = 'some_oauth_access_token'
79
+ assert_equal true, @session.oauth_user?
80
+ end
81
+ end
82
+
43
83
  end
44
84
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: garb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Pitale
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-10 00:00:00 -05:00
12
+ date: 2010-02-16 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency