garb 0.9.1 → 0.9.7
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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +95 -0
- data/Gemfile +15 -0
- data/README.md +47 -25
- data/Rakefile +8 -34
- data/garb.gemspec +22 -0
- data/lib/garb.rb +71 -48
- data/lib/garb/attributes.rb +35 -0
- data/lib/garb/core_ext/array.rb +13 -0
- data/lib/garb/core_ext/string.rb +48 -0
- data/lib/garb/core_ext/symbol.rb +59 -0
- data/lib/garb/destination.rb +5 -6
- data/lib/garb/errors.rb +20 -0
- data/lib/garb/filter_parameters.rb +20 -29
- data/lib/garb/management/account.rb +10 -16
- data/lib/garb/management/feed.rb +4 -5
- data/lib/garb/management/goal.rb +10 -15
- data/lib/garb/management/profile.rb +11 -20
- data/lib/garb/management/segment.rb +9 -15
- data/lib/garb/management/web_property.rb +11 -16
- data/lib/garb/model.rb +37 -13
- data/lib/garb/path_attribute.rb +7 -0
- data/lib/garb/report_parameter.rb +5 -5
- data/lib/garb/report_response.rb +29 -28
- data/lib/garb/reports/bounces.rb +1 -1
- data/lib/garb/reports/exits.rb +1 -1
- data/lib/garb/reports/pageviews.rb +1 -1
- data/lib/garb/reports/unique_pageviews.rb +1 -1
- data/lib/garb/reports/visits.rb +1 -1
- data/lib/garb/request/authentication.rb +54 -0
- data/lib/garb/request/data.rb +98 -0
- data/lib/garb/result_set.rb +23 -9
- data/lib/garb/session.rb +3 -3
- data/lib/garb/step.rb +4 -4
- data/lib/garb/support.rb +6 -0
- data/lib/garb/version.rb +3 -3
- data/test/fixtures/account_management.json +1 -0
- data/test/fixtures/ga_profile_management.json +1 -0
- data/test/fixtures/ga_segment_management.json +1 -0
- data/test/fixtures/ga_webproperty_management.json +1 -0
- data/test/fixtures/goal_management.json +1 -0
- data/test/fixtures/profile_feed.json +1 -0
- data/test/fixtures/report_feed.json +75 -0
- data/test/test_helper.rb +6 -10
- data/test/unit/garb/filter_parameters_test.rb +15 -46
- data/test/unit/garb/management/account_test.rb +8 -16
- data/test/unit/garb/management/feed_test.rb +5 -10
- data/test/unit/garb/management/goal_test.rb +7 -21
- data/test/unit/garb/management/profile_test.rb +11 -26
- data/test/unit/garb/management/segment_test.rb +7 -6
- data/test/unit/garb/management/web_property_test.rb +10 -12
- data/test/unit/garb/model_test.rb +70 -32
- data/test/unit/garb/report_parameter_test.rb +6 -6
- data/test/unit/garb/report_response_test.rb +23 -13
- data/test/unit/garb/request/authentication_test.rb +152 -0
- data/test/unit/garb/request/data_test.rb +157 -0
- data/test/unit/garb/session_test.rb +13 -13
- data/test/unit/garb_test.rb +4 -11
- data/test/unit/symbol_operator_test.rb +3 -3
- metadata +90 -292
- data/lib/garb/account.rb +0 -22
- data/lib/garb/account_feed_request.rb +0 -25
- data/lib/garb/authentication_request.rb +0 -53
- data/lib/garb/data_request.rb +0 -42
- data/lib/garb/goal.rb +0 -20
- data/lib/garb/profile.rb +0 -33
- data/lib/garb/report.rb +0 -28
- data/lib/garb/resource.rb +0 -115
- data/lib/support.rb +0 -40
- data/test/unit/garb/account_feed_request_test.rb +0 -42
- data/test/unit/garb/account_test.rb +0 -53
- data/test/unit/garb/authentication_request_test.rb +0 -121
- data/test/unit/garb/coverage/assets/0.3.9/app.js +0 -66
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/blank.gif +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_close.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_loading.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_nav_left.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_nav_right.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_e.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_n.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_ne.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_nw.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_s.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_se.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_sw.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_w.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_title_left.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_title_main.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_title_over.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_title_right.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancybox-x.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancybox-y.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancybox.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/jquery.fancybox-1.3.1.css +0 -363
- data/test/unit/garb/coverage/assets/0.3.9/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
- data/test/unit/garb/coverage/assets/0.3.9/favicon.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/jquery-1.4.2.min.js +0 -155
- data/test/unit/garb/coverage/assets/0.3.9/jquery.dataTables.min.js +0 -152
- data/test/unit/garb/coverage/assets/0.3.9/jquery.timeago.js +0 -141
- data/test/unit/garb/coverage/assets/0.3.9/jquery.url.js +0 -174
- data/test/unit/garb/coverage/assets/0.3.9/loading.gif +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/magnify.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/test/unit/garb/coverage/assets/0.3.9/smoothness/jquery-ui-1.8.4.custom.css +0 -295
- data/test/unit/garb/coverage/assets/0.3.9/stylesheet.css +0 -341
- data/test/unit/garb/coverage/index.html +0 -100
- data/test/unit/garb/coverage/resultset.yml +0 -5
- data/test/unit/garb/data_request_test.rb +0 -107
- data/test/unit/garb/destination_test.rb +0 -28
- data/test/unit/garb/goal_test.rb +0 -24
- data/test/unit/garb/management/coverage/assets/0.3.9/app.js +0 -66
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/blank.gif +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_close.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_loading.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_nav_left.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_nav_right.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_e.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_n.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_ne.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_nw.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_s.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_se.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_sw.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_w.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_title_left.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_title_main.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_title_over.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_title_right.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancybox-x.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancybox-y.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancybox.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/jquery.fancybox-1.3.1.css +0 -363
- data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
- data/test/unit/garb/management/coverage/assets/0.3.9/favicon.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/jquery-1.4.2.min.js +0 -155
- data/test/unit/garb/management/coverage/assets/0.3.9/jquery.dataTables.min.js +0 -152
- data/test/unit/garb/management/coverage/assets/0.3.9/jquery.timeago.js +0 -141
- data/test/unit/garb/management/coverage/assets/0.3.9/jquery.url.js +0 -174
- data/test/unit/garb/management/coverage/assets/0.3.9/loading.gif +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/magnify.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/jquery-ui-1.8.4.custom.css +0 -295
- data/test/unit/garb/management/coverage/assets/0.3.9/stylesheet.css +0 -341
- data/test/unit/garb/management/coverage/index.html +0 -100
- data/test/unit/garb/management/coverage/resultset.yml +0 -5
- data/test/unit/garb/profile_test.rb +0 -77
- data/test/unit/garb/report_test.rb +0 -99
- data/test/unit/garb/resource_test.rb +0 -50
- data/test/unit/garb/step_test.rb +0 -15
data/lib/garb/result_set.rb
CHANGED
|
@@ -1,21 +1,35 @@
|
|
|
1
|
+
require 'forwardable'
|
|
2
|
+
|
|
1
3
|
module Garb
|
|
2
4
|
class ResultSet
|
|
3
5
|
include Enumerable
|
|
6
|
+
include Comparable
|
|
7
|
+
extend Forwardable
|
|
4
8
|
|
|
5
|
-
attr_accessor :total_results, :sampled
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
attr_accessor :results, :total_results, :sampled
|
|
10
|
+
alias_method :sampled?, :sampled
|
|
11
|
+
|
|
12
|
+
def_delegators :results, :each, :to_a, :count, :size, :empty?
|
|
8
13
|
|
|
9
14
|
def initialize(results)
|
|
10
15
|
@results = results
|
|
11
16
|
end
|
|
12
|
-
|
|
13
|
-
def
|
|
14
|
-
|
|
17
|
+
|
|
18
|
+
def <=>(other)
|
|
19
|
+
results <=> other.results
|
|
15
20
|
end
|
|
16
|
-
|
|
17
|
-
def
|
|
18
|
-
|
|
21
|
+
|
|
22
|
+
def +(other)
|
|
23
|
+
copy = self.dup
|
|
24
|
+
copy.results = @results + other.to_a
|
|
25
|
+
copy
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def [](*args)
|
|
29
|
+
return @results[*args] if args.size == 1 && args.first.is_a?(Integer)
|
|
30
|
+
copy = self.dup
|
|
31
|
+
copy.results = @results[*args]
|
|
32
|
+
copy
|
|
19
33
|
end
|
|
20
34
|
end
|
|
21
35
|
end
|
data/lib/garb/session.rb
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
module Garb
|
|
2
2
|
class Session
|
|
3
3
|
module Methods
|
|
4
|
-
attr_accessor :auth_token, :access_token, :email
|
|
4
|
+
attr_accessor :auth_token, :access_token, :email, :api_key
|
|
5
5
|
|
|
6
6
|
# use only for single user authentication
|
|
7
|
-
def login(email, password, opts={})
|
|
7
|
+
def login(email, password, opts = {})
|
|
8
8
|
self.email = email
|
|
9
|
-
auth_request =
|
|
9
|
+
auth_request = Request::Authentication.new(email, password, opts)
|
|
10
10
|
self.auth_token = auth_request.auth_token(opts)
|
|
11
11
|
end
|
|
12
12
|
|
data/lib/garb/step.rb
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
module Garb
|
|
2
2
|
class Step
|
|
3
|
-
attr_reader :name, :number, :
|
|
3
|
+
attr_reader :name, :number, :url
|
|
4
4
|
|
|
5
5
|
def initialize(attributes)
|
|
6
|
-
return unless attributes.is_a?
|
|
6
|
+
return unless attributes.is_a? Hash
|
|
7
7
|
|
|
8
8
|
@name = attributes['name']
|
|
9
|
-
@number = attributes['number']
|
|
10
|
-
@
|
|
9
|
+
@number = attributes['number']
|
|
10
|
+
@url = attributes['url']
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
end
|
data/lib/garb/support.rb
ADDED
data/lib/garb/version.rb
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"analytics#accounts","username":"someone@somewhere.com","totalResults":1,"startIndex":1,"itemsPerPage":1000,"items":[{"id":"1234","kind":"analytics#account","selfLink":"https://www.googleapis.com/analytics/v3/management/accounts/1234","name":"www.google.com","created":"2012-1-01T17:52:03.000Z","updated":"2012-01-01T18:52:11.747Z","childLink":{"type":"analytics#webproperties","href":"https://www.googleapis.com/analytics/v3/management/accounts/1234/webproperties"}}]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"analytics#profiles","username":"someone@somewhere.com","totalResults":1,"startIndex":1,"itemsPerPage":1000,"nextLink":"https://www.googleapis.com/analytics/v3/management/accounts/~all/webproperties/~all/profiles?start-index=1001&max-results=1000","items":[{"id":"2","kind":"analytics#profile","selfLink":"https://www.googleapis.com/analytics/v3/management/accounts/1234/webproperties/UA-5555-1/profiles/2","accountId":"1234","webPropertyId":"UA-5555-1","internalWebPropertyId":"7777","name":"the profile name","currency":"USD","timezone":"America/Los_Angeles","defaultPage":"index.html","siteSearchQueryParameters":"q,term","created":"2012-01-01T18:04:04.000Z","updated":"2012-01-01T18:55:51.046Z","parentLink":{"type":"analytics#webproperty","href":"https://www.googleapis.com/analytics/v3/management/accounts/1234/webproperties/UA-5555-1"},"childLink":{"type":"analytics#goals","href":"https://www.googleapis.com/analytics/v3/management/accounts/1234/webproperties/UA-5555-1/profiles/2/goals"}}]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"analytics#segments","username":"someone@somewhere.com","totalResults":1,"startIndex":1,"itemsPerPage":1000,"items":[{"id":"1","kind":"analytics#segment","selfLink":"https://www.googleapis.com/analytics/v3/management/segments/gaid::1","segmentId":"gaid::1","name":"derpy","definition":"ga:pagePath=@derpy","created":"2012-01-01T15:07:11.815Z","updated":"2012-01-01T15:07:11.815Z"}]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"analytics#webproperties","username":"someone@somewhere.com","totalResults":1,"startIndex":1,"itemsPerPage":1000,"items":[{"id":"UA-7777-1","kind":"analytics#webproperty","selfLink":"https://www.googleapis.com/analytics/v3/management/accounts/1/webproperties/UA-7777-1","accountId":"1","internalWebPropertyId":"7777","name":"google","websiteUrl":"http://www.google.com","created":"2012-01-01T17:52:03.000Z","updated":"2012-01-01T16:05:57.532Z","parentLink":{"type":"analytics#account","href":"https://www.googleapis.com/analytics/v3/management/accounts/1"},"childLink":{"type":"analytics#profiles","href":"https://www.googleapis.com/analytics/v3/management/accounts/1/webproperties/UA-7777-1/profiles"}}]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"kind":"analytics#goals","username":"someone@somewhere.com","totalResults":1,"startIndex":1,"itemsPerPage":1000,"nextLink":"https://www.googleapis.com/analytics/v3/management/accounts/~all/webproperties/~all/profiles/~all/goals?start-index=1001&max-results=1000","items":[{"id":"1","kind":"analytics#goal","selfLink":"https://www.googleapis.com/analytics/v3/management/accounts/1234/webproperties/UA-55555-1/profiles/1234/goals/1","accountId":"1234","webPropertyId":"UA-5555-1","internalWebPropertyId":"7777","profileId":"1234","name":"the goal","value":1.0,"active":true,"type":"URL_DESTINATION","created":"2012-01-01T17:32:10.000Z","updated":"2012-01-01T15:54:41.781Z","parentLink":{"type":"analytics#profile","href":"https://www.googleapis.com/analytics/v3/management/accounts/1234/webproperties/UA-5555-1/profiles/1234"},"urlDestinationDetails":{"url":"^/somewhere/results","caseSensitive":false,"matchType":"REGEX","firstStepRequired":false,"steps":[{"number":1,"name":"Intro Page","url":"^/somewhere/index"},{"number":2,"name":"Select A Thing","url":"^/somewhere/select_a_thing"},{"number":3,"name":"Results","url":"^/somewhere/results"}]}}]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"feed":{"id":"http://www.google.com/analytics/feeds/accounts/blah@gmail.com","updated":"2010-05-06T19:27:28.028-07:00","title":"Profile list for blah@gmail.com","link":{"rel":"self","type":"application/atom+xml","href":"https://www.google.com/analytics/feeds/accounts/default"},"author":{"name":"Google Analytics"},"generator":"Google Analytics","openSearch:totalResults":"2","openSearch:startIndex":"1","openSearch:itemsPerPage":"2","dxp$segment":[{"dxp$definition":null,"id":"gaid::-1","name":"All Visits"},{"dxp$definition":"ga:visitorType==New Visitor","id":"gaid::-2","name":"New Visitors"},{"dxp$definition":"ga:medium==cpa,ga:medium==cpc,ga:medium==cpm,ga:medium==cpp,ga:medium==cpv,ga:medium==ppc","id":"gaid::-3","name":"Paid Search Traffic"},{"dxp$definition":"ga:city!=New York","id":"gaid::0","name":"Not New York"}],"entry":[{"id":"http://www.google.com/analytics/feeds/accounts/ga:12345","updated":"2008-07-21T14:05:57.000-07:00","title":"Historical","link":{"rel":"alternate","type":"text/html","href":"http://www.google.com/analytics"},"ga:goal":[{"ga:destination":{"caseSensitive":"false","expression":"/blog.html","matchType":"head","step1Required":"false"},"active":"true","name":"Read Blog","number":"1","value":"10.0"},{"ga:destination":{"caseSensitive":"false","expression":"/support.html","matchType":"head","step1Required":"false"},"active":"true","name":"Go for Support","number":"2","value":"5.0"},{"ga:destination":{"ga:step":{"name":"Contact Form Page","number":"1","path":"/contact.html"},"caseSensitive":"false","expression":"/contact-submit","matchType":"exact","step1Required":"true"},"active":"true","name":"Contact Form Submission","number":"3","value":"100.0"},{"ga:destination":{"caseSensitive":"false","expression":"/newsletter-submit","matchType":"exact","step1Required":"false"},"active":"true","name":"Newsletter Form Submission","number":"4","value":"25.0"}],"dxp$property":[{"name":"ga:accountId","value":"1111"},{"name":"ga:accountName","value":"Blog Beta"},{"name":"ga:profileId","value":"1212"},{"name":"ga:webPropertyId","value":"UA-1111-1"},{"name":"ga:currency","value":"USD"},{"name":"ga:timezone","value":"America/New_York"}],"dxp:tableId":"ga:12345","gd:etag":"W/\"CUcHSXs8fip7I2A9WxBUFUg.\"","gd:kind":"analytics#account"},{"id":"http://www.google.com/analytics/feeds/accounts/ga:12346","updated":"2008-11-24T11:51:07.000-08:00","title":"Presently","link":{"rel":"alternate","type":"text/html","href":"http://www.google.com/analytics"},"ga:goal":[{"ga:destination":{"ga:step":{"name":"Contact Form Page","number":"1","path":"/contact.html"},"caseSensitive":"false","expression":"/contact-submit","matchType":"exact","step1Required":"true"},"active":"true","name":"Contact Form Submission","number":"1","value":"100.0"},{"ga:destination":{"caseSensitive":"false","expression":"/newsletter-submit","matchType":"exact","step1Required":"false"},"active":"true","name":"Newsletter Form Submission","number":"2","value":"25.0"}],"dxp$property":[{"name":"ga:accountId","value":"1111"},{"name":"ga:accountName","value":"Blog Beta"},{"name":"ga:profileId","value":"1213"},{"name":"ga:webPropertyId","value":"UA-1111-2"},{"name":"ga:currency","value":"USD"},{"name":"ga:timezone","value":"America/New_York"}],"dxp:tableId":"ga:12346","gd:etag":"W/\"A0UASX45cCp7I2A9WxFQEUQ.\"","gd:kind":"analytics#account"}],"xmlns":"http://www.w3.org/2005/Atom","xmlns:dxp":"http://schemas.google.com/analytics/2009","xmlns:ga":"http://schemas.google.com/ga/2009","xmlns:openSearch":"http://a9.com/-/spec/opensearch/1.1/","xmlns:gd":"http://schemas.google.com/g/2005","gd:etag":"W/\"A0UASX45cCp7I2A9WxFQEUQ.\"","gd:kind":"analytics#accounts"}}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"kind":"analytics#gaData",
|
|
3
|
+
"id":"https://www.googleapis.com/analytics/v3/data/ga?ids=ga:123456&dimensions=ga:country,ga:city&metrics=ga:pageViews&start-date=2011-12-01&end-date=2011-12-31&start-index=1&max-results=5",
|
|
4
|
+
"query":{
|
|
5
|
+
"start-date":"2011-12-01",
|
|
6
|
+
"end-date":"2011-12-31",
|
|
7
|
+
"ids":"ga:123456",
|
|
8
|
+
"dimensions":"ga:country,ga:city",
|
|
9
|
+
"metrics":[
|
|
10
|
+
"ga:pageViews"
|
|
11
|
+
],
|
|
12
|
+
"start-index":1,
|
|
13
|
+
"max-results":5
|
|
14
|
+
},
|
|
15
|
+
"itemsPerPage":5,
|
|
16
|
+
"totalResults":1261,
|
|
17
|
+
"selfLink":"https://www.googleapis.com/analytics/v3/data/ga?ids=ga:123456&dimensions=ga:country,ga:city&metrics=ga:pageViews&start-date=2011-12-01&end-date=2011-12-31&start-index=1&max-results=5",
|
|
18
|
+
"nextLink":"https://www.googleapis.com/analytics/v3/data/ga?ids=ga:123456&dimensions=ga:country,ga:city&metrics=ga:pageViews&start-date=2011-12-01&end-date=2011-12-31&start-index=6&max-results=5",
|
|
19
|
+
"profileInfo":{
|
|
20
|
+
"profileId":"123456",
|
|
21
|
+
"accountId":"123456",
|
|
22
|
+
"webPropertyId":"UA-123456-1",
|
|
23
|
+
"internalWebPropertyId":"123456",
|
|
24
|
+
"profileName":"example.com",
|
|
25
|
+
"tableId":"ga:123456"
|
|
26
|
+
},
|
|
27
|
+
"containsSampledData":true,
|
|
28
|
+
"columnHeaders":[
|
|
29
|
+
{
|
|
30
|
+
"name":"ga:country",
|
|
31
|
+
"columnType":"DIMENSION",
|
|
32
|
+
"dataType":"STRING"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name":"ga:city",
|
|
36
|
+
"columnType":"DIMENSION",
|
|
37
|
+
"dataType":"STRING"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name":"ga:pageviews",
|
|
41
|
+
"columnType":"METRIC",
|
|
42
|
+
"dataType":"INTEGER"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"totalsForAllResults":{
|
|
46
|
+
"ga:pageviews":"38817"
|
|
47
|
+
},
|
|
48
|
+
"rows":[
|
|
49
|
+
[
|
|
50
|
+
"(not set)",
|
|
51
|
+
"(not set)",
|
|
52
|
+
"4"
|
|
53
|
+
],
|
|
54
|
+
[
|
|
55
|
+
"Australia",
|
|
56
|
+
"Adelaide",
|
|
57
|
+
"4"
|
|
58
|
+
],
|
|
59
|
+
[
|
|
60
|
+
"Australia",
|
|
61
|
+
"Brisbane",
|
|
62
|
+
"17"
|
|
63
|
+
],
|
|
64
|
+
[
|
|
65
|
+
"Australia",
|
|
66
|
+
"Geelong",
|
|
67
|
+
"1"
|
|
68
|
+
],
|
|
69
|
+
[
|
|
70
|
+
"Australia",
|
|
71
|
+
"Melbourne",
|
|
72
|
+
"5"
|
|
73
|
+
]
|
|
74
|
+
]
|
|
75
|
+
}
|
data/test/test_helper.rb
CHANGED
|
@@ -10,35 +10,31 @@ begin
|
|
|
10
10
|
|
|
11
11
|
SimpleCov.start 'garb'
|
|
12
12
|
rescue LoadError
|
|
13
|
-
puts
|
|
13
|
+
puts 'Install simplecov if you use 1.9 and want coverage metrics'
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
$:.reject! { |e| e.include? 'TextMate' }
|
|
17
|
-
|
|
18
|
-
require 'rubygems'
|
|
19
16
|
require 'bundler'
|
|
20
17
|
Bundler.setup(:default, :test)
|
|
21
18
|
|
|
22
19
|
require 'shoulda'
|
|
23
20
|
require 'minitest/unit'
|
|
21
|
+
require 'minitest/autorun'
|
|
24
22
|
require 'mocha'
|
|
25
23
|
|
|
26
24
|
$:.unshift File.expand_path('../../lib', __FILE__)
|
|
27
25
|
require 'garb'
|
|
28
26
|
|
|
29
27
|
class MiniTest::Unit::TestCase
|
|
30
|
-
include Shoulda::
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
extend Shoulda::Macros
|
|
34
|
-
include Shoulda::Helpers
|
|
28
|
+
include Shoulda::Context::Assertions
|
|
29
|
+
include Shoulda::Context::InstanceMethods
|
|
30
|
+
extend Shoulda::Context::ClassMethods
|
|
35
31
|
|
|
36
32
|
def read_fixture(filename)
|
|
37
33
|
File.read(File.dirname(__FILE__) + "/fixtures/#{filename}")
|
|
38
34
|
end
|
|
39
35
|
|
|
40
36
|
def assert_data_params(expected)
|
|
41
|
-
assert_received(Garb::
|
|
37
|
+
assert_received(Garb::Request::Data, :new) {|e| e.with(Garb::Session, Garb::Model::URL, expected)}
|
|
42
38
|
end
|
|
43
39
|
end
|
|
44
40
|
|
|
@@ -2,65 +2,34 @@ require 'test_helper'
|
|
|
2
2
|
|
|
3
3
|
module Garb
|
|
4
4
|
class FilterParametersTest < MiniTest::Unit::TestCase
|
|
5
|
-
def self.should_define_operators(*operators)
|
|
6
|
-
operators.each do |operator|
|
|
7
|
-
should "create an operator and add to parameters for the #{operator} method" do
|
|
8
|
-
new_operator = stub
|
|
9
|
-
symbol = :foo
|
|
10
|
-
|
|
11
|
-
SymbolOperator.expects(:new).with(:bar, operator).returns(new_operator)
|
|
12
|
-
@filter_parameters.filters do
|
|
13
|
-
send(operator.to_sym, :bar, 100)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
parameter = {new_operator => 100}
|
|
17
|
-
assert_equal parameter, @filter_parameters.parameters.last
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
5
|
context "A FilterParameters" do
|
|
23
|
-
setup do
|
|
24
|
-
@filter_parameters = FilterParameters.new
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
should_define_operators :eql, :not_eql, :gt, :gte, :lt, :lte,
|
|
28
|
-
:matches, :does_not_match, :contains, :does_not_contain, :substring, :not_substring
|
|
29
|
-
|
|
30
|
-
should "instance eval for filters" do
|
|
31
|
-
blk = lambda {"in a block"}
|
|
32
|
-
|
|
33
|
-
@filter_parameters.expects(:instance_eval)
|
|
34
|
-
@filter_parameters.filters(&blk)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
6
|
context "when converting parameters hash into query string parameters" do
|
|
38
7
|
should "parameterize hash operators and join elements with AND" do
|
|
39
|
-
|
|
40
|
-
eql(:city, 'New York City')
|
|
41
|
-
eql(:state, 'New York')
|
|
42
|
-
end
|
|
8
|
+
filters = FilterParameters.new({:city.eql => 'New York City', :state.eql => 'New York'})
|
|
43
9
|
|
|
44
10
|
params = ['ga:city%3D%3DNew+York+City', 'ga:state%3D%3DNew+York']
|
|
45
|
-
assert_equal params,
|
|
11
|
+
assert_equal params, filters.to_params['filters'].split('%3B').sort
|
|
46
12
|
end
|
|
47
13
|
|
|
48
14
|
should "properly encode operators" do
|
|
49
|
-
|
|
50
|
-
contains(:page_path, 'New York')
|
|
51
|
-
end
|
|
15
|
+
filters = FilterParameters.new({:page_path.contains => 'New York'})
|
|
52
16
|
|
|
53
17
|
params = {'filters' => 'ga:pagePath%3D~New+York'}
|
|
54
|
-
assert_equal params,
|
|
18
|
+
assert_equal params, filters.to_params
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
should "escape comma, semicolon in values" do
|
|
22
|
+
filters = FilterParameters.new({:url.eql => 'this;that,thing\other'})
|
|
23
|
+
|
|
24
|
+
params = {'filters' => 'ga:url%3D%3Dthis%5C%3Bthat%5C%2Cthing%5Cother'}
|
|
25
|
+
assert_equal params, filters.to_params
|
|
55
26
|
end
|
|
56
27
|
|
|
57
|
-
should "
|
|
58
|
-
|
|
59
|
-
eql(:url, 'this;that,thing\other')
|
|
60
|
-
end
|
|
28
|
+
should "handle nested arrays mixed with hashes" do
|
|
29
|
+
filters = FilterParameters.new([{:page_path.contains => 'NYC'}, [{:city.eql => 'New York City'}, {:state.eql => 'New York'}]])
|
|
61
30
|
|
|
62
|
-
params =
|
|
63
|
-
assert_equal params,
|
|
31
|
+
params = ['ga:pagePath%3D~NYC,ga:city%3D%3DNew+York+City,ga:state%3D%3DNew+York']
|
|
32
|
+
assert_equal params, filters.to_params['filters'].split('%3B').sort
|
|
64
33
|
end
|
|
65
34
|
end
|
|
66
35
|
end
|
|
@@ -8,39 +8,31 @@ module Garb
|
|
|
8
8
|
feed = stub(:entries => ["entry1"])
|
|
9
9
|
Feed.stubs(:new).returns(feed)
|
|
10
10
|
|
|
11
|
-
Account.stubs(:
|
|
11
|
+
Account.stubs(:new)
|
|
12
12
|
Account.all
|
|
13
13
|
|
|
14
14
|
assert_received(Feed, :new) {|e| e.with(Session, '/accounts')}
|
|
15
15
|
assert_received(feed, :entries)
|
|
16
|
-
assert_received(Account, :
|
|
16
|
+
assert_received(Account, :new) {|e| e.with("entry1", Session)}
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
context "an Account" do
|
|
21
21
|
setup do
|
|
22
|
-
entry =
|
|
23
|
-
|
|
24
|
-
"link" => [{"rel" => "self", "href" => Feed::BASE_URL+"/accounts/123456"}],
|
|
25
|
-
"dxp:property" => [
|
|
26
|
-
{"name" => "ga:accountId", "value" => "123456"},
|
|
27
|
-
{"name" => "ga:accountName", "value" => "Garb"}
|
|
28
|
-
]
|
|
29
|
-
}
|
|
30
|
-
@account = Account.new_from_entry(entry, Session)
|
|
22
|
+
entry = MultiJson.load(read_fixture("account_management.json"))['items'].first
|
|
23
|
+
@account = Account.new(entry, Session)
|
|
31
24
|
end
|
|
32
25
|
|
|
33
|
-
should "extract id
|
|
34
|
-
assert_equal "
|
|
35
|
-
assert_equal "123456", @account.id
|
|
26
|
+
should "extract id from GA entry" do
|
|
27
|
+
assert_equal "1234", @account.id
|
|
36
28
|
end
|
|
37
29
|
|
|
38
30
|
should "extract a name from GA entry properties" do
|
|
39
|
-
assert_equal "
|
|
31
|
+
assert_equal "www.google.com", @account.name
|
|
40
32
|
end
|
|
41
33
|
|
|
42
34
|
should "combine the Account.path and the id into an new path" do
|
|
43
|
-
assert_equal "/accounts/
|
|
35
|
+
assert_equal "/accounts/1234", @account.path
|
|
44
36
|
end
|
|
45
37
|
|
|
46
38
|
should "have a reference to the session it was created with" do
|
|
@@ -6,28 +6,23 @@ module Garb
|
|
|
6
6
|
context "a Feed" do
|
|
7
7
|
setup do
|
|
8
8
|
@request = stub
|
|
9
|
-
|
|
9
|
+
Request::Data.stubs(:new).returns(@request)
|
|
10
10
|
@feed = Feed.new(Garb::Session.new, '/accounts')
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
should "have a parsed response" do
|
|
14
|
-
|
|
14
|
+
MultiJson.stubs(:load)
|
|
15
15
|
@feed.stubs(:response).returns(stub(:body => 'response body'))
|
|
16
16
|
@feed.parsed_response
|
|
17
17
|
|
|
18
|
-
assert_received(
|
|
18
|
+
assert_received(MultiJson, :load) {|e| e.with('response body')}
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
should "have entries from the parsed response" do
|
|
22
|
-
@feed.stubs(:parsed_response).returns({'
|
|
22
|
+
@feed.stubs(:parsed_response).returns({'items' => ['entry1', 'entry2']})
|
|
23
23
|
assert_equal ['entry1', 'entry2'], @feed.entries
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
should "handle case of a single entry" do
|
|
27
|
-
@feed.stubs(:parsed_response).returns({'feed' => {'entry' => {'profile_id' => '12345'}}})
|
|
28
|
-
assert_equal [{'profile_id' => '12345'}], @feed.entries
|
|
29
|
-
end
|
|
30
|
-
|
|
31
26
|
should "have an empty array for entries without a response" do
|
|
32
27
|
@feed.stubs(:parsed_response).returns(nil)
|
|
33
28
|
assert_equal [], @feed.entries
|
|
@@ -41,4 +36,4 @@ module Garb
|
|
|
41
36
|
end
|
|
42
37
|
end
|
|
43
38
|
end
|
|
44
|
-
end
|
|
39
|
+
end
|
|
@@ -8,12 +8,12 @@ module Garb
|
|
|
8
8
|
feed = stub(:entries => ["entry1"])
|
|
9
9
|
Feed.stubs(:new).returns(feed)
|
|
10
10
|
|
|
11
|
-
Goal.stubs(:
|
|
11
|
+
Goal.stubs(:new)
|
|
12
12
|
Goal.all
|
|
13
13
|
|
|
14
14
|
assert_received(Feed, :new) {|e| e.with(Session, '/accounts/~all/webproperties/~all/profiles/~all/goals')}
|
|
15
15
|
assert_received(feed, :entries)
|
|
16
|
-
assert_received(Goal, :
|
|
16
|
+
assert_received(Goal, :new) {|e| e.with("entry1", Session)}
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
should "find all goals for a given account" do
|
|
@@ -37,30 +37,16 @@ module Garb
|
|
|
37
37
|
|
|
38
38
|
context "a Goal" do
|
|
39
39
|
setup do
|
|
40
|
-
entry =
|
|
41
|
-
|
|
42
|
-
"ga:goal" => {
|
|
43
|
-
"ga:destination"=>{"caseSensitive"=>"false","expression"=>"/blog.html","matchType"=>"head"},
|
|
44
|
-
"active"=>"true",
|
|
45
|
-
"name"=>"Read Blog",
|
|
46
|
-
"number"=>"1",
|
|
47
|
-
"value"=>"10.0"
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@goal = Goal.new_from_entry(entry, Session)
|
|
40
|
+
entry = MultiJson.load(read_fixture("goal_management.json"))["items"].first
|
|
41
|
+
@goal = Goal.new(entry, Session)
|
|
52
42
|
end
|
|
53
43
|
|
|
54
44
|
should "have a name" do
|
|
55
|
-
assert_equal "
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
should "have a number" do
|
|
59
|
-
assert_equal 1, @goal.number
|
|
45
|
+
assert_equal "the goal", @goal.name
|
|
60
46
|
end
|
|
61
47
|
|
|
62
48
|
should "have a value" do
|
|
63
|
-
assert_equal
|
|
49
|
+
assert_equal 1.0, @goal.value
|
|
64
50
|
end
|
|
65
51
|
|
|
66
52
|
should "know if it is active" do
|
|
@@ -68,7 +54,7 @@ module Garb
|
|
|
68
54
|
end
|
|
69
55
|
|
|
70
56
|
should "know if it is not active" do
|
|
71
|
-
@goal.active
|
|
57
|
+
@goal.instance_variable_set("@active", false)
|
|
72
58
|
assert_equal false, @goal.active?
|
|
73
59
|
end
|
|
74
60
|
|