readmedia-garb 0.9.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/README.md +198 -0
  2. data/Rakefile +57 -0
  3. data/lib/garb/account.rb +22 -0
  4. data/lib/garb/account_feed_request.rb +25 -0
  5. data/lib/garb/authentication_request.rb +53 -0
  6. data/lib/garb/data_request.rb +42 -0
  7. data/lib/garb/destination.rb +18 -0
  8. data/lib/garb/filter_parameters.rb +42 -0
  9. data/lib/garb/goal.rb +20 -0
  10. data/lib/garb/management/account.rb +39 -0
  11. data/lib/garb/management/feed.rb +26 -0
  12. data/lib/garb/management/goal.rb +44 -0
  13. data/lib/garb/management/profile.rb +44 -0
  14. data/lib/garb/management/segment.rb +27 -0
  15. data/lib/garb/management/web_property.rb +38 -0
  16. data/lib/garb/model.rb +91 -0
  17. data/lib/garb/profile.rb +33 -0
  18. data/lib/garb/profile_reports.rb +16 -0
  19. data/lib/garb/report.rb +28 -0
  20. data/lib/garb/report_parameter.rb +25 -0
  21. data/lib/garb/report_response.rb +56 -0
  22. data/lib/garb/reports/bounces.rb +5 -0
  23. data/lib/garb/reports/exits.rb +5 -0
  24. data/lib/garb/reports/pageviews.rb +5 -0
  25. data/lib/garb/reports/unique_pageviews.rb +5 -0
  26. data/lib/garb/reports/visits.rb +5 -0
  27. data/lib/garb/reports.rb +5 -0
  28. data/lib/garb/resource.rb +115 -0
  29. data/lib/garb/result_set.rb +21 -0
  30. data/lib/garb/session.rb +25 -0
  31. data/lib/garb/step.rb +13 -0
  32. data/lib/garb/version.rb +14 -0
  33. data/lib/garb.rb +69 -0
  34. data/lib/support.rb +40 -0
  35. data/test/fixtures/cacert.pem +67 -0
  36. data/test/fixtures/profile_feed.xml +72 -0
  37. data/test/fixtures/report_feed.xml +48 -0
  38. data/test/test_helper.rb +45 -0
  39. data/test/unit/garb/account_feed_request_test.rb +42 -0
  40. data/test/unit/garb/account_test.rb +53 -0
  41. data/test/unit/garb/authentication_request_test.rb +121 -0
  42. data/test/unit/garb/data_request_test.rb +107 -0
  43. data/test/unit/garb/destination_test.rb +28 -0
  44. data/test/unit/garb/filter_parameters_test.rb +68 -0
  45. data/test/unit/garb/goal_test.rb +24 -0
  46. data/test/unit/garb/management/account_test.rb +70 -0
  47. data/test/unit/garb/management/feed_test.rb +44 -0
  48. data/test/unit/garb/management/goal_test.rb +81 -0
  49. data/test/unit/garb/management/profile_test.rb +81 -0
  50. data/test/unit/garb/management/segment_test.rb +47 -0
  51. data/test/unit/garb/management/web_property_test.rb +64 -0
  52. data/test/unit/garb/model_test.rb +141 -0
  53. data/test/unit/garb/oauth_session_test.rb +11 -0
  54. data/test/unit/garb/profile_reports_test.rb +29 -0
  55. data/test/unit/garb/profile_test.rb +77 -0
  56. data/test/unit/garb/report_parameter_test.rb +43 -0
  57. data/test/unit/garb/report_response_test.rb +47 -0
  58. data/test/unit/garb/report_test.rb +99 -0
  59. data/test/unit/garb/resource_test.rb +50 -0
  60. data/test/unit/garb/session_test.rb +84 -0
  61. data/test/unit/garb/step_test.rb +15 -0
  62. data/test/unit/garb_test.rb +26 -0
  63. data/test/unit/symbol_operator_test.rb +37 -0
  64. metadata +189 -0
@@ -0,0 +1,67 @@
1
+ ##
2
+ ## cacert.pem-foo -- Bundle of CA Root Certificates
3
+ ##
4
+ ## Converted at: Thu Mar 26 21:23:06 2009 UTC
5
+ ##
6
+ ## This is a bundle of X.509 certificates of public Certificate Authorities
7
+ ## (CA). These were automatically extracted from Mozilla's root certificates
8
+ ## file (certdata.txt). This file can be found in the mozilla source tree:
9
+ ## '/mozilla/security/nss/lib/ckfw/builtins/certdata.txt'
10
+ ##
11
+ ## It contains the certificates in PEM format and therefore
12
+ ## can be directly used with curl / libcurl / php_curl, or with
13
+ ## an Apache+mod_ssl webserver for SSL client authentication.
14
+ ## Just configure this file as the SSLCACertificateFile.
15
+ ##
16
+
17
+ # ***** BEGIN LICENSE BLOCK *****
18
+ # Version: MPL 1.1/GPL 2.0/LGPL 2.1
19
+ #
20
+ # The contents of this file are subject to the Mozilla Public License Version
21
+ # 1.1 (the "License"); you may not use this file except in compliance with
22
+ # the License. You may obtain a copy of the License at
23
+ # http://www.mozilla.org/MPL/
24
+ #
25
+ # Software distributed under the License is distributed on an "AS IS" basis,
26
+ # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
27
+ # for the specific language governing rights and limitations under the
28
+ # License.
29
+ #
30
+ # The Original Code is the Netscape security libraries.
31
+ #
32
+ # The Initial Developer of the Original Code is
33
+ # Netscape Communications Corporation.
34
+ # Portions created by the Initial Developer are Copyright (C) 1994-2000
35
+ # the Initial Developer. All Rights Reserved.
36
+ #
37
+ # Contributor(s):
38
+ #
39
+ # Alternatively, the contents of this file may be used under the terms of
40
+ # either the GNU General Public License Version 2 or later (the "GPL"), or
41
+ # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
42
+ # in which case the provisions of the GPL or the LGPL are applicable instead
43
+ # of those above. If you wish to allow use of your version of this file only
44
+ # under the terms of either the GPL or the LGPL, and not to allow others to
45
+ # use your version of this file under the terms of the MPL, indicate your
46
+ # decision by deleting the provisions above and replace them with the notice
47
+ # and other provisions required by the GPL or the LGPL. If you do not delete
48
+ # the provisions above, a recipient may use your version of this file under
49
+ # the terms of any one of the MPL, the GPL or the LGPL.
50
+ #
51
+ # ***** END LICENSE BLOCK *****
52
+ # @(#) $RCSfile: certdata.txt,v $ $Revision: 1.51 $ $Date: 2009/01/15 22:35:15 $
53
+
54
+ Verisign/RSA Secure Server CA
55
+ =============================
56
+ -----BEGIN CERTIFICATE-----
57
+ MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx
58
+ IDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy
59
+ IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVow
60
+ XzELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQL
61
+ EyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUA
62
+ A4GJADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII0haGN1Xp
63
+ sSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphIuR2nKRoTLkoRWZweFdVJ
64
+ VCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZIhvcNAQECBQADfgBl3X7hsuyw4jrg7HFG
65
+ mhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2
66
+ qUtN8iD3zV9/ZHuO3ABc1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA==
67
+ -----END CERTIFICATE-----
@@ -0,0 +1,72 @@
1
+ <?xml version='1.0' encoding='UTF-8'?>
2
+ <feed 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/&quot;A0UASX45cCp7I2A9WxFQEUQ.&quot;' gd:kind='analytics#accounts'>
3
+ <id>http://www.google.com/analytics/feeds/accounts/tpitale@gmail.com</id>
4
+ <updated>2010-05-06T19:27:28.028-07:00</updated>
5
+ <title>Profile list for tpitale@gmail.com</title>
6
+ <link rel='self' type='application/atom+xml' href='https://www.google.com/analytics/feeds/accounts/default'/>
7
+ <author><name>Google Analytics</name></author>
8
+ <generator version='1.0'>Google Analytics</generator>
9
+ <openSearch:totalResults>2</openSearch:totalResults>
10
+ <openSearch:startIndex>1</openSearch:startIndex>
11
+ <openSearch:itemsPerPage>2</openSearch:itemsPerPage>
12
+ <dxp:segment id='gaid::-1' name='All Visits'>
13
+ <dxp:definition> </dxp:definition>
14
+ </dxp:segment>
15
+ <dxp:segment id='gaid::-2' name='New Visitors'>
16
+ <dxp:definition>ga:visitorType==New Visitor</dxp:definition>
17
+ </dxp:segment>
18
+ <dxp:segment id='gaid::-3' name='Paid Search Traffic'>
19
+ <dxp:definition>ga:medium==cpa,ga:medium==cpc,ga:medium==cpm,ga:medium==cpp,ga:medium==cpv,ga:medium==ppc</dxp:definition>
20
+ </dxp:segment>
21
+ <dxp:segment id='gaid::0' name='Not New York'>
22
+ <dxp:definition>ga:city!=New York</dxp:definition>
23
+ </dxp:segment>
24
+ <entry gd:etag='W/&quot;CUcHSXs8fip7I2A9WxBUFUg.&quot;' gd:kind='analytics#account'>
25
+ <id>http://www.google.com/analytics/feeds/accounts/ga:12345</id>
26
+ <updated>2008-07-21T14:05:57.000-07:00</updated>
27
+ <title>Historical</title>
28
+ <link rel='alternate' type='text/html' href='http://www.google.com/analytics'/>
29
+ <ga:goal active='true' name='Read Blog' number='1' value='10.0'>
30
+ <ga:destination caseSensitive='false' expression='/blog.html' matchType='head' step1Required='false'/>
31
+ </ga:goal>
32
+ <ga:goal active='true' name='Go for Support' number='2' value='5.0'>
33
+ <ga:destination caseSensitive='false' expression='/support.html' matchType='head' step1Required='false'/>
34
+ </ga:goal>
35
+ <ga:goal active='true' name='Contact Form Submission' number='3' value='100.0'>
36
+ <ga:destination caseSensitive='false' expression='/contact-submit' matchType='exact' step1Required='true'>
37
+ <ga:step name='Contact Form Page' number='1' path='/contact.html'/>
38
+ </ga:destination>
39
+ </ga:goal>
40
+ <ga:goal active='true' name='Newsletter Form Submission' number='4' value='25.0'>
41
+ <ga:destination caseSensitive='false' expression='/newsletter-submit' matchType='exact' step1Required='false'/>
42
+ </ga:goal>
43
+ <dxp:property name="ga:accountId" value="1111"/>
44
+ <dxp:property name="ga:accountName" value="Blog Beta"/>
45
+ <dxp:property name="ga:profileId" value="1212"/>
46
+ <dxp:property name="ga:webPropertyId" value="UA-1111-1"/>
47
+ <dxp:property name="ga:currency" value="USD"/>
48
+ <dxp:property name="ga:timezone" value="America/New_York"/>
49
+ <dxp:tableId>ga:12345</dxp:tableId>
50
+ </entry>
51
+ <entry gd:etag='W/&quot;A0UASX45cCp7I2A9WxFQEUQ.&quot;' gd:kind='analytics#account'>
52
+ <id>http://www.google.com/analytics/feeds/accounts/ga:12346</id>
53
+ <updated>2008-11-24T11:51:07.000-08:00</updated>
54
+ <title>Presently</title>
55
+ <link rel='alternate' type='text/html' href='http://www.google.com/analytics'/>
56
+ <ga:goal active='true' name='Contact Form Submission' number='1' value='100.0'>
57
+ <ga:destination caseSensitive='false' expression='/contact-submit' matchType='exact' step1Required='true'>
58
+ <ga:step name='Contact Form Page' number='1' path='/contact.html'/>
59
+ </ga:destination>
60
+ </ga:goal>
61
+ <ga:goal active='true' name='Newsletter Form Submission' number='2' value='25.0'>
62
+ <ga:destination caseSensitive='false' expression='/newsletter-submit' matchType='exact' step1Required='false'/>
63
+ </ga:goal>
64
+ <dxp:property name="ga:accountId" value="1111"/>
65
+ <dxp:property name="ga:accountName" value="Blog Beta"/>
66
+ <dxp:property name="ga:profileId" value="1213"/>
67
+ <dxp:property name="ga:webPropertyId" value="UA-1111-2"/>
68
+ <dxp:property name="ga:currency" value="USD"/>
69
+ <dxp:property name="ga:timezone" value="America/New_York"/>
70
+ <dxp:tableId>ga:12346</dxp:tableId>
71
+ </entry>
72
+ </feed>
@@ -0,0 +1,48 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <feed xmlns="http://www.w3.org/2005/Atom"
3
+ xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
4
+ xmlns:dxp="http://schemas.google.com/analytics/2009"
5
+ xmlns:ga="http://schemas.google.com/analytics/2008">
6
+ <id>http://www.google.com/analytics/feeds/data?ids=ga:983247&amp;dimensions=ga:country,ga:city&amp;metrics=ga:pageViews&amp;start-date=2008-01-01&amp;end-date=2008-01-02</id>
7
+ <updated>2008-01-02T15:59:59.999-08:00 </updated>
8
+ <title type="text">Google Analytics Data for Profile 983247</title>
9
+ <link href="http://www.google.com/analytics/feeds/data" rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml"/>
10
+ <link href="http://www.google.com/analytics/feeds/data?end-date=2008-01-02&amp;start-date=2008-01-01&amp;metrics=ga%3ApageViews&amp;ids=ga%3A983247&amp;dimensions=ga%3Acountry%2Cga%3Acity" rel="self" type="application/atom+xml"/>
11
+ <link href="http://www.google.com/analytics/feeds/data?start-index=1001&amp;max-results=1000&amp;end-date=2008-01-02&amp;start-date=2008-01-01&amp;metrics=ga%3ApageViews&amp;ids=ga%3A983247&amp;dimensions=ga%3Acountry%2Cga%3Acity" rel="next" type="application/atom+xml"/>
12
+ <author>
13
+ <name>Google Analytics</name>
14
+ </author>
15
+ <openSearch:startIndex>3</openSearch:startIndex>
16
+ <openSearch:itemsPerPage>4</openSearch:itemsPerPage>
17
+ <openSearch:totalResults>18</openSearch:totalResults>
18
+ <dxp:containsSampledData>true</dxp:containsSampledData>
19
+ <ga:webPropertyID>UA-983247-67</ga:webPropertyID>
20
+ <ga:start-date>2008-01-01</ga:start-date>
21
+ <ga:end-date>2008-01-02</ga:end-date>
22
+
23
+ <entry>
24
+ <id> http://www.google.com/analytics/feeds/data?ids=ga:1174&amp;ga:country=%28not%20set%29&amp;ga:city=%28not%20set%29&amp;start-date=2008-01-01&amp;end-date=2008-01-02 </id>
25
+ <updated> 2008-01-01T16:00:00.001-08:00 </updated>
26
+ <title type="text"> ga:country=(not set) | ga:city=(not set) </title>
27
+ <link href="http://www.google.com/analytics/feeds/data" rel="self" type="application/atom+xml"/>
28
+ <dxp:dimension name="ga:country" value="(not set)" />
29
+ <dxp:dimension name="ga:city" value="(not set)" />
30
+ <dxp:metric name="ga:pageviews" value="33" />
31
+ </entry>
32
+ <entry>
33
+ <id> http://www.google.com/analytics/feeds/data?ids=ga:1174&amp;ga:country=Afghanistan&amp;ga:city=Kabul&amp;start-date=2008-01-01&amp;end-date=2008-01-02 </id>
34
+ <updated> 2008-01-01T16:00:00.001-08:00 </updated>
35
+ <title type="text"> ga:country=Afghanistan | ga:city=Kabul </title>
36
+ <dxp:dimension name="ga:country" value="Afghanistan" />
37
+ <dxp:dimension name="ga:city" value="Kabul" />
38
+ <dxp:metric name="ga:pageviews" value="2" />
39
+ </entry>
40
+ <entry>
41
+ <id> http://www.google.com/analytics/feeds/data?ids=ga:1174&amp;ga:country=Albania&amp;ga:city=Tirana&amp;start-date=2008-01-01&amp;end-date=2008-01-02 </id>
42
+ <updated> 2008-01-01T16:00:00.001-08:00 </updated>
43
+ <title type="text"> ga:country=Albania | ga:city=Tirana </title>
44
+ <dxp:dimension name="ga:country" value="Albania" />
45
+ <dxp:dimension name="ga:city" value="Tirana" />
46
+ <dxp:metric name="ga:pageviews" value="1" />
47
+ </entry>
48
+ </feed>
@@ -0,0 +1,45 @@
1
+ begin
2
+ require 'simplecov'
3
+ SimpleCov.adapters.define 'garb' do
4
+ add_filter '/test/'
5
+ add_filter '/config/'
6
+ add_filter 'version'
7
+
8
+ add_group 'Libraries', 'lib'
9
+ end
10
+
11
+ SimpleCov.start 'garb'
12
+ rescue LoadError
13
+ puts "Install simplecov if you use 1.9 and want coverage metrics"
14
+ end
15
+
16
+ $:.reject! { |e| e.include? 'TextMate' }
17
+
18
+ require 'rubygems'
19
+ require 'bundler'
20
+ Bundler.setup(:default, :test)
21
+
22
+ require 'shoulda'
23
+ require 'minitest/unit'
24
+ require 'mocha'
25
+
26
+ $:.unshift File.expand_path('../../lib', __FILE__)
27
+ require 'garb'
28
+
29
+ class MiniTest::Unit::TestCase
30
+ include Shoulda::InstanceMethods
31
+ extend Shoulda::ClassMethods
32
+ include Shoulda::Assertions
33
+ extend Shoulda::Macros
34
+ include Shoulda::Helpers
35
+
36
+ def read_fixture(filename)
37
+ File.read(File.dirname(__FILE__) + "/fixtures/#{filename}")
38
+ end
39
+
40
+ def assert_data_params(expected)
41
+ assert_received(Garb::DataRequest, :new) {|e| e.with(Garb::Session, Garb::Model::URL, expected)}
42
+ end
43
+ end
44
+
45
+ MiniTest::Unit.autorun
@@ -0,0 +1,42 @@
1
+ require 'test_helper'
2
+
3
+ module Garb
4
+ class AccountFeedRequestTest < MiniTest::Unit::TestCase
5
+ context "An AccountFeedRequest" do
6
+ setup do
7
+ @request = stub
8
+ DataRequest.stubs(:new).returns(@request)
9
+ @feed = AccountFeedRequest.new
10
+ end
11
+
12
+ should "have a parsed response" do
13
+ Crack::XML.stubs(:parse)
14
+ @feed.stubs(:response).returns(stub(:body => 'response body'))
15
+ @feed.parsed_response
16
+
17
+ assert_received(Crack::XML, :parse) {|e| e.with('response body')}
18
+ end
19
+
20
+ should "have entries from the parsed response" do
21
+ @feed.stubs(:parsed_response).returns({'feed' => {'entry' => ['entry1', 'entry2']}})
22
+ assert_equal ['entry1', 'entry2'], @feed.entries
23
+ end
24
+
25
+ should "have segements from the parsed response" do
26
+ @feed.stubs(:parsed_response).returns({'feed' => {'dxp:segment' => ['segment1', 'segment2']}})
27
+ assert_equal ['segment1', 'segment2'], @feed.segments
28
+ end
29
+
30
+ should "have an empty array for entries without a response" do
31
+ @feed.stubs(:parsed_response).returns(nil)
32
+ assert_equal [], @feed.entries
33
+ end
34
+
35
+ should "have a response from the request" do
36
+ @request.stubs(:send_request)
37
+ @feed.response
38
+ assert_received(@request, :send_request)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,53 @@
1
+ require 'test_helper'
2
+
3
+ module Garb
4
+ class AccountTest < MiniTest::Unit::TestCase
5
+ context "The Account class" do
6
+ should "have an array of accounts with all profiles" do
7
+ p1 = stub(:account_id => '1111', :account_name => 'Blog 1')
8
+ p2 = stub(:account_id => '1112', :account_name => 'Blog 2')
9
+
10
+ Profile.stubs(:all).returns([p1,p2,p1,p2])
11
+ Account.stubs(:new).returns('account1', 'account2')
12
+
13
+ assert_equal ['account1','account2'], Account.all
14
+ assert_received(Profile, :all)
15
+ assert_received(Account, :new) {|e| e.with([p1,p1])}
16
+ assert_received(Account, :new) {|e| e.with([p2,p2])}
17
+ end
18
+ end
19
+
20
+ context "An instance of the Account class" do
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
35
+ end
36
+ end
37
+
38
+ context "when creating a new account from an array of profiles" do
39
+ should "take the account id from the first profile" do
40
+ assert_equal @profiles.first.account_id, @account.id
41
+ end
42
+
43
+ should "take the account name from the first profile" do
44
+ assert_equal @profiles.first.account_name, @account.name
45
+ end
46
+
47
+ should "store the array of profiles" do
48
+ assert_equal @profiles, @account.profiles
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,121 @@
1
+ require 'test_helper'
2
+
3
+ CA_CERT_FILE = File.join(File.dirname(__FILE__), '..', '/cacert.pem')
4
+
5
+ module Garb
6
+ class AuthenticationRequestTest < MiniTest::Unit::TestCase
7
+
8
+ context "An instance of the AuthenticationRequest class" do
9
+
10
+ setup { @request = AuthenticationRequest.new('email', 'password') }
11
+
12
+ should "have a collection of parameters that include the email and password" do
13
+ expected =
14
+ {
15
+ 'Email' => 'user@example.com',
16
+ 'Passwd' => 'fuzzybunnies',
17
+ 'accountType' => 'HOSTED_OR_GOOGLE',
18
+ 'service' => 'analytics',
19
+ 'source' => 'vigetLabs-garb-001'
20
+ }
21
+
22
+ request = AuthenticationRequest.new('user@example.com', 'fuzzybunnies')
23
+ assert_equal expected, request.parameters
24
+ end
25
+
26
+ should "have a URI" do
27
+ assert_equal URI.parse('https://www.google.com/accounts/ClientLogin'), @request.uri
28
+ end
29
+
30
+ should "be able to send a request to the GAAPI service with proper ssl" do
31
+ @request.expects(:build_request).returns('post')
32
+
33
+ response = mock {|m| m.expects(:is_a?).with(Net::HTTPOK).returns(true) }
34
+
35
+ http = mock do |m|
36
+ m.expects(:use_ssl=).with(true)
37
+ m.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER)
38
+ m.expects(:ca_file=).with(CA_CERT_FILE)
39
+ m.expects(:request).with('post').yields(response)
40
+ end
41
+
42
+ Net::HTTP.expects(:new).with('www.google.com', 443).returns(http)
43
+
44
+ @request.send_request(OpenSSL::SSL::VERIFY_PEER)
45
+ end
46
+
47
+ should "be able to send a request to the GAAPI service with ignoring ssl" do
48
+ @request.expects(:build_request).returns('post')
49
+
50
+ response = mock {|m| m.expects(:is_a?).with(Net::HTTPOK).returns(true) }
51
+
52
+ http = mock do |m|
53
+ m.expects(:use_ssl=).with(true)
54
+ m.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
55
+ m.expects(:request).with('post').yields(response)
56
+ end
57
+
58
+ Net::HTTP.expects(:new).with('www.google.com', 443).returns(http)
59
+
60
+ @request.send_request(OpenSSL::SSL::VERIFY_NONE)
61
+ end
62
+
63
+ should "be able to build a request for the GAAPI service" do
64
+ params = "param"
65
+ @request.expects(:parameters).with().returns(params)
66
+
67
+ post = mock
68
+ post.expects(:set_form_data).with(params)
69
+
70
+ Net::HTTP::Post.expects(:new).with('/accounts/ClientLogin').returns(post)
71
+
72
+ @request.build_request
73
+ end
74
+
75
+ should "be able to retrieve an auth_token from the body" do
76
+ response_data =
77
+ "SID=mysid\n" +
78
+ "LSID=mylsid\n" +
79
+ "Auth=auth_token\n"
80
+
81
+ @request.expects(:send_request).with(OpenSSL::SSL::VERIFY_NONE).returns(stub(:body => response_data))
82
+
83
+ assert_equal 'auth_token', @request.auth_token
84
+ end
85
+
86
+ should "use VERIFY_PEER if auth_token needs to be secure" 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_PEER).returns(stub(:body => response_data))
93
+
94
+ assert_equal 'auth_token', @request.auth_token(:secure => true)
95
+ end
96
+
97
+ should "raise an exception when requesting an auth_token when the authorization fails" do
98
+ @request.stubs(:build_request)
99
+ response = mock do |m|
100
+ m.expects(:is_a?).with(Net::HTTPOK).returns(false)
101
+ end
102
+
103
+ http = stub do |s|
104
+ s.stubs(:use_ssl=)
105
+ s.stubs(:verify_mode=)
106
+ s.stubs(:request).yields(response)
107
+ end
108
+
109
+ Net::HTTP.stubs(:new).with('www.google.com', 443).returns(http)
110
+
111
+ assert_raises(Garb::AuthenticationRequest::AuthError) do
112
+ @request.send_request(OpenSSL::SSL::VERIFY_NONE)
113
+ end
114
+ end
115
+
116
+ end
117
+
118
+
119
+
120
+ end
121
+ end
@@ -0,0 +1,107 @@
1
+ require 'test_helper'
2
+
3
+ module Garb
4
+ class DataRequestTest < MiniTest::Unit::TestCase
5
+
6
+ context "An instance of the DataRequest class" do
7
+ setup do
8
+ @session = Session.new
9
+ @session.auth_token = 'abcdefg123456'
10
+ end
11
+
12
+ should "be able to build the query string from parameters" do
13
+ parameters = {'ids' => '12345', 'metrics' => 'country'}
14
+ data_request = DataRequest.new(@session, "", parameters)
15
+
16
+ query_string = data_request.query_string
17
+
18
+ assert_match(/^\?/, query_string)
19
+
20
+ query_string.sub!(/^\?/, '')
21
+
22
+ assert_equal ["ids=12345", "metrics=country"], query_string.split('&').sort
23
+ end
24
+
25
+ should "return an empty query string if parameters are empty" do
26
+ data_request = DataRequest.new(@session, "")
27
+ assert_equal "", data_request.query_string
28
+ end
29
+
30
+ should "be able to build a uri" do
31
+ url = 'http://example.com'
32
+ assert_equal URI.parse(url), DataRequest.new(@session, url).uri
33
+ end
34
+
35
+ should "be able to send a request for a single user" do
36
+ @session.stubs(:single_user?).returns(true)
37
+ response = mock('Net::HTTPOK') do |m|
38
+ m.expects(:kind_of?).with(Net::HTTPSuccess).returns(true)
39
+ end
40
+
41
+ data_request = DataRequest.new(@session, 'https://example.com/data', 'key' => 'value')
42
+ data_request.stubs(:single_user_request).returns(response)
43
+ data_request.send_request
44
+
45
+ assert_received(data_request, :single_user_request)
46
+ end
47
+
48
+ should "be able to send a request for an oauth user" do
49
+ @session.stubs(:single_user?).returns(false)
50
+ @session.stubs(:oauth_user?).returns(true)
51
+ response = mock('Net::HTTPOK') do |m|
52
+ m.expects(:kind_of?).with(Net::HTTPSuccess).returns(true)
53
+ end
54
+
55
+ data_request = DataRequest.new(@session, 'https://example.com/data', 'key' => 'value')
56
+ data_request.stubs(:oauth_user_request).returns(response)
57
+ data_request.send_request
58
+
59
+ assert_received(data_request, :oauth_user_request)
60
+ end
61
+
62
+ should "raise if the request is unauthorized" do
63
+ @session.stubs(:single_user?).returns(false)
64
+ @session.stubs(:oauth_user?).returns(true)
65
+ response = mock('Net::HTTPUnauthorized', :body => 'Error')
66
+
67
+ data_request = DataRequest.new(@session, 'https://example.com/data', 'key' => 'value')
68
+ data_request.stubs(:oauth_user_request).returns(response)
69
+
70
+ assert_raises(Garb::DataRequest::ClientError) do
71
+ data_request.send_request
72
+ end
73
+ end
74
+
75
+ should "be able to request via the ouath access token" do
76
+ access_token = stub(:get => "responseobject")
77
+ @session.stubs(:access_token).returns(access_token)
78
+
79
+ data_request = DataRequest.new(@session, 'https://example.com/data', 'key' => 'value')
80
+ assert_equal 'responseobject', data_request.oauth_user_request
81
+
82
+ assert_received(@session, :access_token)
83
+ assert_received(access_token, :get) {|e| e.with('https://example.com/data?key=value', {'GData-Version' => '2'})}
84
+ end
85
+
86
+ should "be able to request via http with an auth token" do
87
+ @session.expects(:auth_token).with().returns('toke')
88
+ response = mock
89
+
90
+ http = mock do |m|
91
+ m.expects(:use_ssl=).with(true)
92
+ m.expects(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
93
+ m.expects(:get).with('/data?key=value', {
94
+ 'Authorization' => 'GoogleLogin auth=toke',
95
+ 'GData-Version' => '2'
96
+ }).returns(response)
97
+ end
98
+
99
+ Net::HTTP.expects(:new).with('example.com', 443).returns(http)
100
+
101
+ data_request = DataRequest.new(@session, 'https://example.com/data', 'key' => 'value')
102
+ assert_equal response, data_request.single_user_request
103
+ end
104
+ end
105
+
106
+ end
107
+ end
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+
3
+ module Garb
4
+ class DestinationTest < MiniTest::Unit::TestCase
5
+ context 'A Destination' do
6
+ should "have a match_type and an expression" do
7
+ destination = Destination.new({'matchType' => 'exact', 'expression' => '/contact.html', 'caseSensitive' => 'false'})
8
+ assert_equal 'exact', destination.match_type
9
+ assert_equal '/contact.html', destination.expression
10
+ end
11
+
12
+ should "know if it's case sensitive" do
13
+ destination = Destination.new({'matchType' => 'exact', 'expression' => '/contact.html', 'caseSensitive' => 'true'})
14
+ assert_equal true, destination.case_sensitive?
15
+ end
16
+
17
+ should "know if it's not case sensitive" do
18
+ destination = Destination.new({'matchType' => 'exact', 'expression' => '/contact.html', 'caseSensitive' => 'false'})
19
+ assert_equal false, destination.case_sensitive?
20
+ end
21
+
22
+ should "have steps" do
23
+ destination = Destination.new({'ga:step' => {'name' => 'Contact', 'number' => '1', 'path' => '/'}})
24
+ assert_equal ['Contact'], destination.steps.map(&:name)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,68 @@
1
+ require 'test_helper'
2
+
3
+ module Garb
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
+ 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
+ context "when converting parameters hash into query string parameters" do
38
+ should "parameterize hash operators and join elements with AND" do
39
+ @filter_parameters.filters do
40
+ eql(:city, 'New York City')
41
+ eql(:state, 'New York')
42
+ end
43
+
44
+ params = ['ga:city%3D%3DNew+York+City', 'ga:state%3D%3DNew+York']
45
+ assert_equal params, @filter_parameters.to_params['filters'].split('%3B').sort
46
+ end
47
+
48
+ should "properly encode operators" do
49
+ @filter_parameters.filters do
50
+ contains(:page_path, 'New York')
51
+ end
52
+
53
+ params = {'filters' => 'ga:pagePath%3D~New+York'}
54
+ assert_equal params, @filter_parameters.to_params
55
+ end
56
+
57
+ should "escape comma, semicolon, and backslash in values" do
58
+ @filter_parameters.filters do
59
+ eql(:url, 'this;that,thing\other')
60
+ end
61
+
62
+ params = {'filters' => 'ga:url%3D%3Dthis%5C%3Bthat%5C%2Cthing%5C%5Cother'}
63
+ assert_equal params, @filter_parameters.to_params
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end