garb 0.9.1 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.travis.yml +7 -0
  4. data/CHANGELOG.md +95 -0
  5. data/Gemfile +15 -0
  6. data/README.md +47 -25
  7. data/Rakefile +8 -34
  8. data/garb.gemspec +22 -0
  9. data/lib/garb.rb +71 -48
  10. data/lib/garb/attributes.rb +35 -0
  11. data/lib/garb/core_ext/array.rb +13 -0
  12. data/lib/garb/core_ext/string.rb +48 -0
  13. data/lib/garb/core_ext/symbol.rb +59 -0
  14. data/lib/garb/destination.rb +5 -6
  15. data/lib/garb/errors.rb +20 -0
  16. data/lib/garb/filter_parameters.rb +20 -29
  17. data/lib/garb/management/account.rb +10 -16
  18. data/lib/garb/management/feed.rb +4 -5
  19. data/lib/garb/management/goal.rb +10 -15
  20. data/lib/garb/management/profile.rb +11 -20
  21. data/lib/garb/management/segment.rb +9 -15
  22. data/lib/garb/management/web_property.rb +11 -16
  23. data/lib/garb/model.rb +37 -13
  24. data/lib/garb/path_attribute.rb +7 -0
  25. data/lib/garb/report_parameter.rb +5 -5
  26. data/lib/garb/report_response.rb +29 -28
  27. data/lib/garb/reports/bounces.rb +1 -1
  28. data/lib/garb/reports/exits.rb +1 -1
  29. data/lib/garb/reports/pageviews.rb +1 -1
  30. data/lib/garb/reports/unique_pageviews.rb +1 -1
  31. data/lib/garb/reports/visits.rb +1 -1
  32. data/lib/garb/request/authentication.rb +54 -0
  33. data/lib/garb/request/data.rb +98 -0
  34. data/lib/garb/result_set.rb +23 -9
  35. data/lib/garb/session.rb +3 -3
  36. data/lib/garb/step.rb +4 -4
  37. data/lib/garb/support.rb +6 -0
  38. data/lib/garb/version.rb +3 -3
  39. data/test/fixtures/account_management.json +1 -0
  40. data/test/fixtures/ga_profile_management.json +1 -0
  41. data/test/fixtures/ga_segment_management.json +1 -0
  42. data/test/fixtures/ga_webproperty_management.json +1 -0
  43. data/test/fixtures/goal_management.json +1 -0
  44. data/test/fixtures/profile_feed.json +1 -0
  45. data/test/fixtures/report_feed.json +75 -0
  46. data/test/test_helper.rb +6 -10
  47. data/test/unit/garb/filter_parameters_test.rb +15 -46
  48. data/test/unit/garb/management/account_test.rb +8 -16
  49. data/test/unit/garb/management/feed_test.rb +5 -10
  50. data/test/unit/garb/management/goal_test.rb +7 -21
  51. data/test/unit/garb/management/profile_test.rb +11 -26
  52. data/test/unit/garb/management/segment_test.rb +7 -6
  53. data/test/unit/garb/management/web_property_test.rb +10 -12
  54. data/test/unit/garb/model_test.rb +70 -32
  55. data/test/unit/garb/report_parameter_test.rb +6 -6
  56. data/test/unit/garb/report_response_test.rb +23 -13
  57. data/test/unit/garb/request/authentication_test.rb +152 -0
  58. data/test/unit/garb/request/data_test.rb +157 -0
  59. data/test/unit/garb/session_test.rb +13 -13
  60. data/test/unit/garb_test.rb +4 -11
  61. data/test/unit/symbol_operator_test.rb +3 -3
  62. metadata +90 -292
  63. data/lib/garb/account.rb +0 -22
  64. data/lib/garb/account_feed_request.rb +0 -25
  65. data/lib/garb/authentication_request.rb +0 -53
  66. data/lib/garb/data_request.rb +0 -42
  67. data/lib/garb/goal.rb +0 -20
  68. data/lib/garb/profile.rb +0 -33
  69. data/lib/garb/report.rb +0 -28
  70. data/lib/garb/resource.rb +0 -115
  71. data/lib/support.rb +0 -40
  72. data/test/unit/garb/account_feed_request_test.rb +0 -42
  73. data/test/unit/garb/account_test.rb +0 -53
  74. data/test/unit/garb/authentication_request_test.rb +0 -121
  75. data/test/unit/garb/coverage/assets/0.3.9/app.js +0 -66
  76. data/test/unit/garb/coverage/assets/0.3.9/fancybox/blank.gif +0 -0
  77. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_close.png +0 -0
  78. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_loading.png +0 -0
  79. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_nav_left.png +0 -0
  80. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_nav_right.png +0 -0
  81. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_e.png +0 -0
  82. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_n.png +0 -0
  83. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_ne.png +0 -0
  84. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_nw.png +0 -0
  85. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_s.png +0 -0
  86. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_se.png +0 -0
  87. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_sw.png +0 -0
  88. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_shadow_w.png +0 -0
  89. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_title_left.png +0 -0
  90. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_title_main.png +0 -0
  91. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_title_over.png +0 -0
  92. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancy_title_right.png +0 -0
  93. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancybox-x.png +0 -0
  94. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancybox-y.png +0 -0
  95. data/test/unit/garb/coverage/assets/0.3.9/fancybox/fancybox.png +0 -0
  96. data/test/unit/garb/coverage/assets/0.3.9/fancybox/jquery.fancybox-1.3.1.css +0 -363
  97. data/test/unit/garb/coverage/assets/0.3.9/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
  98. data/test/unit/garb/coverage/assets/0.3.9/favicon.png +0 -0
  99. data/test/unit/garb/coverage/assets/0.3.9/jquery-1.4.2.min.js +0 -155
  100. data/test/unit/garb/coverage/assets/0.3.9/jquery.dataTables.min.js +0 -152
  101. data/test/unit/garb/coverage/assets/0.3.9/jquery.timeago.js +0 -141
  102. data/test/unit/garb/coverage/assets/0.3.9/jquery.url.js +0 -174
  103. data/test/unit/garb/coverage/assets/0.3.9/loading.gif +0 -0
  104. data/test/unit/garb/coverage/assets/0.3.9/magnify.png +0 -0
  105. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  106. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  107. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  108. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  109. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  110. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  111. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  112. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  113. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-icons_222222_256x240.png +0 -0
  114. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  115. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-icons_454545_256x240.png +0 -0
  116. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-icons_888888_256x240.png +0 -0
  117. data/test/unit/garb/coverage/assets/0.3.9/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  118. data/test/unit/garb/coverage/assets/0.3.9/smoothness/jquery-ui-1.8.4.custom.css +0 -295
  119. data/test/unit/garb/coverage/assets/0.3.9/stylesheet.css +0 -341
  120. data/test/unit/garb/coverage/index.html +0 -100
  121. data/test/unit/garb/coverage/resultset.yml +0 -5
  122. data/test/unit/garb/data_request_test.rb +0 -107
  123. data/test/unit/garb/destination_test.rb +0 -28
  124. data/test/unit/garb/goal_test.rb +0 -24
  125. data/test/unit/garb/management/coverage/assets/0.3.9/app.js +0 -66
  126. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/blank.gif +0 -0
  127. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_close.png +0 -0
  128. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_loading.png +0 -0
  129. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_nav_left.png +0 -0
  130. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_nav_right.png +0 -0
  131. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_e.png +0 -0
  132. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_n.png +0 -0
  133. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_ne.png +0 -0
  134. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_nw.png +0 -0
  135. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_s.png +0 -0
  136. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_se.png +0 -0
  137. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_sw.png +0 -0
  138. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_shadow_w.png +0 -0
  139. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_title_left.png +0 -0
  140. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_title_main.png +0 -0
  141. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_title_over.png +0 -0
  142. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancy_title_right.png +0 -0
  143. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancybox-x.png +0 -0
  144. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancybox-y.png +0 -0
  145. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/fancybox.png +0 -0
  146. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/jquery.fancybox-1.3.1.css +0 -363
  147. data/test/unit/garb/management/coverage/assets/0.3.9/fancybox/jquery.fancybox-1.3.1.pack.js +0 -44
  148. data/test/unit/garb/management/coverage/assets/0.3.9/favicon.png +0 -0
  149. data/test/unit/garb/management/coverage/assets/0.3.9/jquery-1.4.2.min.js +0 -155
  150. data/test/unit/garb/management/coverage/assets/0.3.9/jquery.dataTables.min.js +0 -152
  151. data/test/unit/garb/management/coverage/assets/0.3.9/jquery.timeago.js +0 -141
  152. data/test/unit/garb/management/coverage/assets/0.3.9/jquery.url.js +0 -174
  153. data/test/unit/garb/management/coverage/assets/0.3.9/loading.gif +0 -0
  154. data/test/unit/garb/management/coverage/assets/0.3.9/magnify.png +0 -0
  155. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  156. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  157. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  158. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  159. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  160. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  161. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  162. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  163. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-icons_222222_256x240.png +0 -0
  164. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  165. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-icons_454545_256x240.png +0 -0
  166. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-icons_888888_256x240.png +0 -0
  167. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  168. data/test/unit/garb/management/coverage/assets/0.3.9/smoothness/jquery-ui-1.8.4.custom.css +0 -295
  169. data/test/unit/garb/management/coverage/assets/0.3.9/stylesheet.css +0 -341
  170. data/test/unit/garb/management/coverage/index.html +0 -100
  171. data/test/unit/garb/management/coverage/resultset.yml +0 -5
  172. data/test/unit/garb/profile_test.rb +0 -77
  173. data/test/unit/garb/report_test.rb +0 -99
  174. data/test/unit/garb/resource_test.rb +0 -50
  175. data/test/unit/garb/step_test.rb +0 -15
@@ -8,18 +8,18 @@ module Garb
8
8
  feed = stub(:entries => ["entry1"])
9
9
  Feed.stubs(:new).returns(feed)
10
10
 
11
- Profile.stubs(:new_from_entry)
11
+ Profile.stubs(:new)
12
12
  Profile.all
13
13
 
14
14
  assert_received(Feed, :new) {|e| e.with(Session, '/accounts/~all/webproperties/~all/profiles')}
15
15
  assert_received(feed, :entries)
16
- assert_received(Profile, :new_from_entry) {|e| e.with("entry1", Session)}
16
+ assert_received(Profile, :new) {|e| e.with("entry1", Session)}
17
17
  end
18
18
 
19
19
  should "find all profiles for a given account" do
20
20
  Profile.stubs(:all)
21
21
  Profile.for_account(stub(:session => 'session', :path => '/accounts/123'))
22
- assert_received(Profile, :all) {|e| e.with('session', '/accounts/123/webproperties/~all/profiles')}
22
+ assert_received(Profile, :all) {|e| e.with('session', '/accounts/123/webproperties/~all/profiles')}
23
23
  end
24
24
 
25
25
  should "find all profiles for a given web_property" do
@@ -31,43 +31,28 @@ module Garb
31
31
 
32
32
  context "A Profile" do
33
33
  setup do
34
- entry = {
35
- "link" => [{"rel" => "self", "href" => Feed::BASE_URL+"/accounts/1189765/webproperties/UA-1189765-1/profiles/98765"}],
36
- "dxp:property" => [
37
- {"name" => "ga:profileId", "value" => "98765"},
38
- {"name" => "ga:accountId", "value" => "1189765"},
39
- {"name" => "ga:webPropertyId", "value" => 'UA-1189765-1'},
40
- {"name" => "ga:profileName", "value" => "example.com"},
41
- {"name"=>"dxp:tableId", "value"=>"ga:4506"},
42
- {"name"=>"ga:currency", "value"=>"USD"},
43
- {"name"=>"ga:timezone", "value"=>"America/New_York"}
44
- ]
45
- }
46
- @profile = Profile.new_from_entry(entry, Session)
34
+ entry = MultiJson.load(read_fixture("ga_profile_management.json"))["items"].first
35
+ @profile = Profile.new(entry, Session)
47
36
  end
48
37
 
49
- should "have a title" do
50
- assert_equal "example.com", @profile.title
38
+ should "have a name" do
39
+ assert_equal "the profile name", @profile.name
51
40
  end
52
41
 
53
42
  should "have an id" do
54
- assert_equal '98765', @profile.id
43
+ assert_equal '2', @profile.id
55
44
  end
56
45
 
57
46
  should "have an account_id" do
58
- assert_equal '1189765', @profile.account_id
47
+ assert_equal '1234', @profile.account_id
59
48
  end
60
49
 
61
50
  should "have a web_property_id" do
62
- assert_equal 'UA-1189765-1', @profile.web_property_id
63
- end
64
-
65
- should "have a table_id (for old Garb::Report)" do
66
- assert_equal 'ga:4506', @profile.table_id
51
+ assert_equal 'UA-5555-1', @profile.web_property_id
67
52
  end
68
53
 
69
54
  should "have a path" do
70
- assert_equal "/accounts/1189765/webproperties/UA-1189765-1/profiles/98765", @profile.path
55
+ assert_equal "/accounts/1234/webproperties/UA-5555-1/profiles/2", @profile.path
71
56
  end
72
57
 
73
58
  should "have goals" do
@@ -8,12 +8,12 @@ module Garb
8
8
  feed = stub(:entries => ["entry1"])
9
9
  Feed.stubs(:new).returns(feed)
10
10
 
11
- Segment.stubs(:new_from_entry)
11
+ Segment.stubs(:new)
12
12
  Segment.all
13
13
 
14
14
  assert_received(Feed, :new) {|e| e.with(Session, '/segments')}
15
15
  assert_received(feed, :entries)
16
- assert_received(Segment, :new_from_entry) {|e| e.with("entry1", Session)}
16
+ assert_received(Segment, :new) {|e| e.with("entry1", Session)}
17
17
  end
18
18
  end
19
19
 
@@ -27,19 +27,20 @@ module Garb
27
27
  "dxp:definition" => "ga:visitorType==Returning Visitor"
28
28
  }
29
29
  }
30
- @segment = Segment.new_from_entry(entry, Session)
30
+ entry = MultiJson.load(read_fixture("ga_segment_management.json"))["items"].first
31
+ @segment = Segment.new(entry, Session)
31
32
  end
32
33
 
33
34
  should "have an id" do
34
- assert_equal "gaid::-3", @segment.id
35
+ assert_equal "gaid::1", @segment.id
35
36
  end
36
37
 
37
38
  should "have a name" do
38
- assert_equal "Returning Visitor", @segment.name
39
+ assert_equal "derpy", @segment.name
39
40
  end
40
41
 
41
42
  should "have a definition" do
42
- assert_equal "ga:visitorType==Returning Visitor", @segment.definition
43
+ assert_equal "ga:pagePath=@derpy", @segment.definition
43
44
  end
44
45
  end
45
46
  end
@@ -8,12 +8,12 @@ module Garb
8
8
  feed = stub(:entries => ["entry1"])
9
9
  Feed.stubs(:new).returns(feed)
10
10
 
11
- WebProperty.stubs(:new_from_entry)
11
+ WebProperty.stubs(:new)
12
12
  WebProperty.all
13
13
 
14
14
  assert_received(Feed, :new) {|e| e.with(Session, '/accounts/~all/webproperties')}
15
15
  assert_received(feed, :entries)
16
- assert_received(WebProperty, :new_from_entry) {|e| e.with("entry1", Session)}
16
+ assert_received(WebProperty, :new) {|e| e.with("entry1", Session)}
17
17
  end
18
18
 
19
19
  should "find all web properties for a given account" do
@@ -28,23 +28,21 @@ module Garb
28
28
 
29
29
  context "a WebProperty" do
30
30
  setup do
31
- entry = {
32
- "link" => [{"rel" => "self", "href" => Feed::BASE_URL+"/accounts/1189765/webproperties/UA-1189765-1"}],
33
- "dxp:property" => [
34
- {"name" => "ga:accountId", "value" => "1189765"},
35
- {"name" => "ga:webPropertyId", "value" => 'UA-1189765-1'}
36
- ]
37
- }
31
+ entry = MultiJson.load(read_fixture("ga_webproperty_management.json"))["items"].first
38
32
 
39
- @web_property = WebProperty.new_from_entry(entry, Session)
33
+ @web_property = WebProperty.new(entry, Session)
40
34
  end
41
35
 
42
36
  should "have an id" do
43
- assert_equal "UA-1189765-1", @web_property.id
37
+ assert_equal "UA-7777-1", @web_property.id
44
38
  end
45
39
 
46
40
  should "have an account_id" do
47
- assert_equal "1189765", @web_property.account_id
41
+ assert_equal "1", @web_property.account_id
42
+ end
43
+
44
+ should "combine the WebProperty.path and the id into an new path" do
45
+ assert_equal "/accounts/1/webproperties/UA-7777-1", @web_property.path
48
46
  end
49
47
 
50
48
  should "have profiles" do
@@ -41,77 +41,96 @@ module Garb
41
41
 
42
42
  context "with a profile" do
43
43
  setup do
44
- entry = {
45
- "title" => "Google Analytics Profile example.com",
46
- "link" => [{"rel" => "self", "href" => Garb::Management::Feed::BASE_URL+"/accounts/1189765/webproperties/UA-1189765-1/profiles/98765"}],
47
- "dxp:property" => [
48
- {"name" => "ga:profileId", "value" => "98765"},
49
- {"name" => "ga:accountId", "value" => "1189765"},
50
- {"name" => "ga:webPropertyId", "value" => 'UA-1189765-1'}
51
- ]
52
- }
53
-
54
- @profile = Garb::Management::Profile.new_from_entry(entry, Session)
44
+ entry = MultiJson.load(read_fixture('ga_profile_management.json'))['items'].first
45
+
46
+ @profile = Garb::Management::Profile.new(entry, Session)
55
47
  end
56
48
 
57
49
  context "when getting results" do
58
50
  setup do
59
51
  @response = stub(:body => "raw report data")
60
- DataRequest.stubs(:new).returns(stub(:send_request => @response))
61
- ReportResponse.stubs(:new).returns(stub(:results => ['result']))
52
+ Request::Data.stubs(:new).returns(stub(:send_request => @response))
53
+ @results = ResultSet.new(Array.new(10) { |i| 'result #%d' % i })
54
+ ReportResponse.stubs(:new).returns(stub(:results => @results))
62
55
 
63
56
  @test_model.stubs(:metrics).returns(stub(:to_params => {'metrics' => 'ga:visits'}))
64
57
  @test_model.stubs(:dimensions).returns(stub(:to_params => {'dimensions' => 'ga:pagePath'}))
65
58
 
66
59
  now = Time.now
67
60
  Time.stubs(:now).returns(now)
61
+ @params = {
62
+ 'ids' => Garb.to_ga(@profile.id),
63
+ 'start-date' => (now - Model::MONTH).strftime('%Y-%m-%d'),
64
+ 'end-date' => now.strftime('%Y-%m-%d'),
65
+ 'metrics' => 'ga:visits',
66
+ 'dimensions' => 'ga:pagePath'
67
+ }
68
+ end
68
69
 
69
- # p @profile.id
70
+ should "get results" do
71
+ assert_equal @results, @test_model.results(@profile)
72
+ assert_received(ReportResponse, :new) {|e| e.with('raw report data', OpenStruct)}
73
+ assert_data_params(@params)
74
+ end
70
75
 
71
- @params = {'ids' => Garb.to_ga(@profile.id),
72
- 'start-date' => (now - Model::MONTH).strftime('%Y-%m-%d'),
73
- 'end-date' => now.strftime('%Y-%m-%d'),
74
- 'metrics' => 'ga:visits',
75
- 'dimensions' => 'ga:pagePath'}
76
+ should "get subset of results using bracket notation" do
77
+ assert_equal @results[0..2], @test_model.results(@profile)[0..2]
78
+ assert_received(ReportResponse, :new) {|e| e.with('raw report data', OpenStruct)}
79
+ assert_data_params(@params)
76
80
  end
77
81
 
78
- should "get all results" do
79
- assert_equal ['result'], @test_model.results(@profile)
80
- assert_received(ReportResponse, :new) {|e| e.with("raw report data", OpenStruct)}
82
+ should "get one of the results using bracket notation" do
83
+ assert_equal @results[2], @test_model.results(@profile)[2]
84
+ assert_received(ReportResponse, :new) {|e| e.with('raw report data', OpenStruct)}
81
85
  assert_data_params(@params)
82
86
  end
83
87
 
84
88
  should "be able to filter" do
85
- filter_parameters = stub(:<<)
86
- FilterParameters.stubs(:new).returns(stub(:parameters => filter_parameters, :to_params => {'filters' => "params"}))
87
- assert_equal ['result'], @test_model.results(@profile, :filters => {:page_path => '/'})
89
+ FilterParameters.stubs(:new).returns(stub(:to_params => {'filters' => 'params'}))
90
+ assert_equal @results, @test_model.results(@profile, :filters => {:page_path => '/'})
88
91
 
89
92
  assert_data_params(@params.merge({'filters' => 'params'}))
90
- assert_received(filter_parameters, :<<) {|e| e.with({:page_path => '/'})}
93
+ assert_received(FilterParameters, :new) {|e| e.with({:page_path => '/'})}
91
94
  end
92
95
 
93
96
  should "be able to set the filter segment by id" do
94
- assert_equal ['result'], @test_model.results(@profile, :segment_id => 1)
97
+ assert_equal @results, @test_model.results(@profile, :segment_id => 1)
95
98
  assert_data_params(@params.merge({'segment' => 'gaid::1'}))
96
99
  end
97
100
 
101
+ should "be able to set the filter segment by alphanumeric id" do
102
+ assert_equal @results, @test_model.results(@profile, :segment_id => '1a')
103
+ assert_data_params(@params.merge({'segment' => 'gaid::1a'}))
104
+ end
105
+
106
+ should "be able to filter with a dynamic segment" do
107
+ # parse_filters called first...
108
+ filter_parameters = stub(:<<)
109
+ filters = stub(:parameters => filter_parameters, :to_params => {'filters' => nil})
110
+ segments = stub(:parameters => filter_parameters, :to_params => {'filters' => 'dynamic_segment_params'})
111
+ FilterParameters.stubs(:new).returns(filters).then.returns(segments)
112
+
113
+ assert_equal @results, @test_model.results(@profile, :dynamic_segment => 'dynamic_segment_params')
114
+ assert_data_params(@params.merge({'segment' => 'dynamic::dynamic_segment_params'}))
115
+ end
116
+
98
117
  should "be able to sort" do
99
118
  sort_parameter = stub(:<<)
100
119
  sort_parameter.stubs(:to_params => {'sort' => 'sort value'})
101
120
  ReportParameter.stubs(:new).returns(sort_parameter)
102
121
 
103
- assert_equal ['result'], @test_model.results(@profile, :sort => [:visits])
122
+ assert_equal @results, @test_model.results(@profile, :sort => [:visits])
104
123
  assert_received(sort_parameter, :<<) {|e| e.with([:visits])}
105
124
  assert_data_params(@params.merge({'sort' => 'sort value'}))
106
125
  end
107
126
 
108
127
  should "be able to limit" do
109
- assert_equal ['result'], @test_model.results(@profile, :limit => 20)
128
+ assert_equal @results, @test_model.results(@profile, :limit => 20)
110
129
  assert_data_params(@params.merge({'max-results' => 20}))
111
130
  end
112
131
 
113
132
  should "be able to offset" do
114
- assert_equal ['result'], @test_model.results(@profile, :offset => 10)
133
+ assert_equal @results, @test_model.results(@profile, :offset => 10)
115
134
  assert_data_params(@params.merge({'start-index' => 10}))
116
135
  end
117
136
 
@@ -119,16 +138,35 @@ module Garb
119
138
  start_date = (Time.now - 1296000)
120
139
  end_date = Time.now
121
140
 
122
- assert_equal ['result'], @test_model.results(@profile, :start_date => start_date, :end_date => end_date)
141
+ assert_equal @results, @test_model.results(@profile, :start_date => start_date, :end_date => end_date)
123
142
  assert_data_params(@params.merge({'start-date' => start_date.strftime('%Y-%m-%d'), 'end-date' => end_date.strftime('%Y-%m-%d')}))
124
143
  end
125
144
 
126
145
  should "return a set of results in the defined class" do
127
146
  @test_model.stubs(:instance_klass).returns(ResultKlass)
128
147
 
129
- assert_equal ['result'], @test_model.results(@profile)
148
+ assert_equal @results, @test_model.results(@profile)
130
149
  assert_received(ReportResponse, :new) {|e| e.with("raw report data", ResultKlass)}
131
150
  end
151
+
152
+ should "be able to fetch multiple pages of results" do
153
+ @results.total_results = 25
154
+ results = @test_model.all_results(@profile)
155
+ assert_equal results.size, 30
156
+ end
157
+
158
+ should "be able to pass :all symbol to fetch multiple pages of results" do
159
+ @results.results = ['result']
160
+ @results.total_results = 25
161
+ results = @test_model.results(@profile, :all => true)
162
+ assert_equal results.size, @results.total_results
163
+ end
164
+
165
+ should "be able to fetch multiple pages of results with a limit" do
166
+ @results.total_results = 25
167
+ results = @test_model.all_results(@profile, :limit => 1)
168
+ assert_equal results.size, 1
169
+ end
132
170
  end
133
171
 
134
172
  # should "return results as an array of the class it belongs to, if that class is an ActiveRecord descendant"
@@ -2,25 +2,25 @@ require 'test_helper'
2
2
 
3
3
  module Garb
4
4
  class ReportParameterTest < MiniTest::Unit::TestCase
5
-
5
+
6
6
  context "An instance of the ReportParameter class" do
7
7
  setup do
8
8
  @metrics = ReportParameter.new(:metrics)
9
9
  end
10
-
10
+
11
11
  should "have a name" do
12
12
  assert_equal "metrics", @metrics.name
13
13
  end
14
-
14
+
15
15
  should "have a list of elements" do
16
16
  assert_equal [], @metrics.elements
17
17
  end
18
-
18
+
19
19
  should "be able to add new elements" do
20
20
  assert_equal(@metrics, @metrics << :page_path)
21
21
  assert_equal [:page_path], @metrics.elements
22
22
  end
23
-
23
+
24
24
  should "merge an array of elements" do
25
25
  assert_equal(@metrics, @metrics << [:page_path])
26
26
  assert_equal [:page_path], @metrics.elements
@@ -38,6 +38,6 @@ module Garb
38
38
  end
39
39
  end
40
40
  end
41
-
41
+
42
42
  end
43
43
  end
@@ -7,38 +7,48 @@ module Garb
7
7
  context "A ReportResponse" do
8
8
  context "with a report feed" do
9
9
  setup do
10
- @xml = File.read(File.join(File.dirname(__FILE__), '..', '..', "/fixtures/report_feed.xml"))
10
+ @json = File.read(File.join(File.dirname(__FILE__), '..', '..', "/fixtures/report_feed.json"))
11
11
  end
12
12
 
13
- should "parse results from atom xml" do
14
- response = ReportResponse.new(@xml)
15
- assert_equal ['33', '2', '1'], response.results.map(&:pageviews)
13
+ should "parse results from json" do
14
+ response = ReportResponse.new(@json)
15
+ assert_equal ['4', '4', '17', '1', '5'], response.results.map(&:pageviews)
16
16
  end
17
17
 
18
18
  should "default to returning an array of OpenStruct objects" do
19
- response = ReportResponse.new(@xml)
20
- assert_equal [OpenStruct, OpenStruct, OpenStruct], response.results.map(&:class)
19
+ response = ReportResponse.new(@json)
20
+ assert_equal [OpenStruct, OpenStruct, OpenStruct, OpenStruct, OpenStruct], response.results.map(&:class)
21
21
  end
22
22
 
23
23
  should "return an array of instances of a specified class" do
24
- response = ReportResponse.new(@xml, SpecialKlass)
25
- assert_equal [SpecialKlass, SpecialKlass, SpecialKlass], response.results.map(&:class)
24
+ response = ReportResponse.new(@json, SpecialKlass)
25
+ assert_equal [SpecialKlass, SpecialKlass, SpecialKlass, SpecialKlass, SpecialKlass], response.results.map(&:class)
26
26
  end
27
27
 
28
28
  should "know the total number of results" do
29
- response = ReportResponse.new(@xml)
30
- assert_equal 18, response.results.total_results
29
+ response = ReportResponse.new(@json)
30
+ assert_equal 1261, response.results.total_results
31
31
  end
32
32
 
33
33
  should "know if the data has been sampled" do
34
- response = ReportResponse.new(@xml)
34
+ response = ReportResponse.new(@json)
35
35
  assert_equal true, response.results.sampled?
36
36
  end
37
+
38
+ should "return results as ResultSet which acts as Array proxy" do
39
+ response = ReportResponse.new(@json, SpecialKlass)
40
+ results = response.results
41
+ results_subset = results[0..1]
42
+
43
+ assert_equal ResultSet, results.class
44
+ assert_equal ResultSet, results_subset.class
45
+ assert_equal results_subset.results, results.results[0..1]
46
+ end
37
47
  end
38
48
 
39
49
  should "return an empty array if there are no results" do
40
- response = ReportResponse.new("result xml")
41
- Crack::XML.stubs(:parse).with("result xml").returns({'feed' => {'entry' => nil}})
50
+ response = ReportResponse.new('result json')
51
+ MultiJson.stubs(:load).with('result json').returns({'rows' => []})
42
52
 
43
53
  assert_equal [], response.results.to_a
44
54
  end
@@ -0,0 +1,152 @@
1
+ require 'test_helper'
2
+
3
+ module Garb
4
+ module Request
5
+ class AuthenticationTest < MiniTest::Unit::TestCase
6
+
7
+ context "An instance of the Request::Authentication class" do
8
+
9
+ setup do
10
+ @request = Request::Authentication.new('email', 'password')
11
+ Garb.ca_cert_file = File.join(File.dirname(__FILE__), '..', '/cacert.pem')
12
+ end
13
+ teardown do
14
+ Garb.proxy_address = nil
15
+ Garb.proxy_port = nil
16
+ Garb.ca_cert_file = nil
17
+ end
18
+
19
+ should "have a collection of parameters that include the email and password" do
20
+ expected =
21
+ {
22
+ 'Email' => 'user@example.com',
23
+ 'Passwd' => 'fuzzybunnies',
24
+ 'accountType' => 'HOSTED_OR_GOOGLE',
25
+ 'service' => 'analytics',
26
+ 'source' => "sija-garb-v#{Garb::VERSION}"
27
+ }
28
+
29
+ request = Request::Authentication.new('user@example.com', 'fuzzybunnies')
30
+ assert_equal expected, request.parameters
31
+ end
32
+
33
+ should "have a URI" do
34
+ assert_equal URI.parse('https://www.google.com/accounts/ClientLogin'), @request.uri
35
+ end
36
+
37
+ should "be able to send a request to the GAAPI service with proper ssl" do
38
+ @request.expects(:build_request).returns('post')
39
+
40
+ response = mock {|m| m.expects(:is_a?).with(Net::HTTPOK).returns(true) }
41
+
42
+ http = mock do |m|
43
+ m.expects(:open_timeout=).with(Garb.open_timeout)
44
+ m.expects(:read_timeout=).with(Garb.read_timeout)
45
+ m.expects(:use_ssl=).with(true)
46
+ m.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
47
+ m.expects(:ca_file=).with(Garb.ca_cert_file)
48
+ m.expects(:request).with('post').yields(response)
49
+ end
50
+
51
+ Net::HTTP.expects(:new).with('www.google.com', 443, nil, nil).returns(http)
52
+
53
+ @request.send_request(OpenSSL::SSL::VERIFY_PEER)
54
+ end
55
+
56
+ should "be able to send a request to the GAAPI service with ignoring ssl" do
57
+ @request.expects(:build_request).returns('post')
58
+
59
+ response = mock {|m| m.expects(:is_a?).with(Net::HTTPOK).returns(true) }
60
+
61
+ http = mock do |m|
62
+ m.expects(:open_timeout=).with(Garb.open_timeout)
63
+ m.expects(:read_timeout=).with(Garb.read_timeout)
64
+ m.expects(:use_ssl=).with(true)
65
+ m.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
66
+ m.expects(:request).with('post').yields(response)
67
+ end
68
+
69
+ Net::HTTP.expects(:new).with('www.google.com', 443, nil, nil).returns(http)
70
+
71
+ @request.send_request(OpenSSL::SSL::VERIFY_NONE)
72
+ end
73
+
74
+ should "be able to build a request for the GAAPI service" do
75
+ params = 'param'
76
+ @request.expects(:parameters).with().returns(params)
77
+
78
+ post = mock
79
+ post.expects(:set_form_data).with(params)
80
+
81
+ Net::HTTP::Post.expects(:new).with('/accounts/ClientLogin').returns(post)
82
+
83
+ @request.build_request
84
+ end
85
+
86
+ should "be able to retrieve an auth_token from the body" do
87
+ response_data =
88
+ "SID=mysid\n" +
89
+ "LSID=mylsid\n" +
90
+ "Auth=auth_token\n"
91
+
92
+ @request.expects(:send_request).with(OpenSSL::SSL::VERIFY_NONE).returns(stub(:body => response_data))
93
+
94
+ assert_equal 'auth_token', @request.auth_token
95
+ end
96
+
97
+ should "use VERIFY_PEER if auth_token needs to be secure" do
98
+ response_data =
99
+ "SID=mysid\n" +
100
+ "LSID=mylsid\n" +
101
+ "Auth=auth_token\n"
102
+
103
+ @request.expects(:send_request).with(OpenSSL::SSL::VERIFY_PEER).returns(stub(:body => response_data))
104
+
105
+ assert_equal 'auth_token', @request.auth_token(:secure => true)
106
+ end
107
+
108
+ should "raise an exception when requesting an auth_token when the authorization fails" do
109
+ @request.stubs(:build_request)
110
+ response = mock do |m|
111
+ m.expects(:is_a?).with(Net::HTTPOK).returns(false)
112
+ end
113
+
114
+ http = stub do |s|
115
+ s.stubs(:use_ssl=)
116
+ s.expects(:open_timeout=).with(Garb.open_timeout)
117
+ s.expects(:read_timeout=).with(Garb.read_timeout)
118
+ s.stubs(:verify_mode=)
119
+ s.stubs(:request).yields(response)
120
+ end
121
+
122
+ Net::HTTP.stubs(:new).with('www.google.com', 443, nil, nil).returns(http)
123
+
124
+ assert_raises(Garb::AuthError) do
125
+ @request.send_request(OpenSSL::SSL::VERIFY_NONE)
126
+ end
127
+ end
128
+
129
+ should "make use of Garb proxy settings in Net::HTTP request" do
130
+ @request.expects(:build_request).returns('post')
131
+
132
+ response = stub {|s| s.stubs(:is_a?).returns(true) }
133
+
134
+ http = mock do |m|
135
+ m.stubs(:open_timeout=)
136
+ m.stubs(:read_timeout=)
137
+ m.stubs(:use_ssl=)
138
+ m.stubs(:verify_mode=)
139
+ m.stubs(:request).yields(response)
140
+ end
141
+
142
+ Garb.proxy_address = '127.0.0.1'
143
+ Garb.proxy_port = '1234'
144
+
145
+ Net::HTTP.expects(:new).with('www.google.com', 443, '127.0.0.1', '1234').returns(http)
146
+
147
+ @request.send_request(nil)
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end