ariadna 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,40 @@
1
+ module Ariadna
2
+ class WebProperty
3
+
4
+ class << self;
5
+ attr_accessor :owner
6
+ end
7
+
8
+ def self.all
9
+ @properties ||= create_properties
10
+ end
11
+
12
+ def initialize(item)
13
+ item.each do |k,v|
14
+ instance_variable_set("@#{k}", v)
15
+ end
16
+ end
17
+
18
+ def profiles
19
+ Delegator.new(Profile, self)
20
+ end
21
+
22
+ private
23
+
24
+ def self.create_properties
25
+ properties = Ariadna.connexion.get_url("https://www.googleapis.com/analytics/v3/management/accounts/#{@owner.id}/webproperties")
26
+ if (properties["totalResults"].to_i > 0)
27
+ create_attributes(properties["items"])
28
+ properties["items"].map do |property|
29
+ WebProperty.new(property)
30
+ end
31
+ end
32
+ end
33
+
34
+ def self.create_attributes(items)
35
+ items.first.each do |k,v|
36
+ attr_reader k.to_sym
37
+ end
38
+ end
39
+ end
40
+ end
data/lib/ariadna.rb ADDED
@@ -0,0 +1,16 @@
1
+ module Ariadna
2
+ class << self
3
+ attr_accessor :connexion
4
+ end
5
+ end
6
+
7
+ require "ariadna/version"
8
+ require "ariadna/account"
9
+ require "ariadna/analytics"
10
+ require "ariadna/connexion"
11
+ require "ariadna/delegator"
12
+ require "ariadna/profile"
13
+ require "ariadna/result"
14
+ require "ariadna/error"
15
+ require "ariadna/error_code"
16
+ require "ariadna/web_property"
@@ -0,0 +1,13 @@
1
+ account_111:
2
+ id: 111
3
+ name: 'name'
4
+ selfLink: 'www.example.com/self/111'
5
+ childLink:
6
+ href: 'www.example.com/child/111'
7
+
8
+ account_222:
9
+ id: 222
10
+ name: 'name 222'
11
+ selfLink: 'www.example.com/self/222'
12
+ childLink:
13
+ href: 'https://www.googleapis.com/analytics/v3/management/accounts/111/webproperties/909090'
@@ -0,0 +1,11 @@
1
+ invalid_request_error:
2
+ error:
3
+ errors:
4
+ -
5
+ domain: "global"
6
+ reason: "invalidParameter"
7
+ message: "Invalid value '-1' for max-results. Value must be within the range: [1, 1000]"
8
+ locationType: "parameter"
9
+ location: "max-results"
10
+ code: 400
11
+ message: "Invalid value '-1' for max-results. Value must be within the range: [1, 1000]"
@@ -0,0 +1,45 @@
1
+ profile:
2
+ id: 123456
3
+ kind: 'analytics#profile'
4
+ selfLink: 'selfLink'
5
+ accountId: 111
6
+ webPropertyId: 909090
7
+ internalWebPropertyId: 4321432
8
+ name: 'profile_name'
9
+ currency: 'EUR'
10
+ timezone: 'GMT'
11
+ defaultPage: 'index.html'
12
+ excludeQueryParameters: 's'
13
+ siteSearchQueryParameters: 's,search'
14
+ siteSearchCategoryParameters: 'cat'
15
+ created: Date.today
16
+ updated: Date.today
17
+ parentLink:
18
+ type: 'analytics#webProperty'
19
+ href: 'https://www.googleapis.com/analytics/v3/management/accounts/111/webproperties/909090'
20
+ childLink:
21
+ type: 'analytics#goals'
22
+ href: 'https://www.googleapis.com/analytics/v3/management/accounts/111/webproperties/909090/profiles/123456/goals'
23
+
24
+ profile2:
25
+ id: 654321
26
+ kind: 'analytics#profile'
27
+ selfLink: 'selfLink'
28
+ accountId: 111
29
+ webPropertyId: 909090
30
+ internalWebPropertyId: 4321432
31
+ name: 'profile_name'
32
+ currency: 'EUR'
33
+ timezone: 'GMT'
34
+ defaultPage: ''
35
+ excludeQueryParameters: ''
36
+ siteSearchQueryParameters: ''
37
+ siteSearchCategoryParameters: ''
38
+ created: Date.today
39
+ updated: Date.today
40
+ parentLink:
41
+ type: 'analytics#webProperty'
42
+ href: 'https://www.googleapis.com/analytics/v3/management/accounts/111/webproperties/909090'
43
+ childLink:
44
+ type: 'analytics#goals'
45
+ href: 'https://www.googleapis.com/analytics/v3/management/accounts/111/webproperties/909090/profiles/654321/goals'
@@ -0,0 +1,51 @@
1
+ result:
2
+ kind: "analytics#gaData"
3
+ id: "https://www.googleapis.com/analytics/v3/data/ga?ids=ga:1174&dimensions=ga:country&metrics=ga:visits&sort=-ga:visits&start-date=2010-04-01&end-date=2010-04-20&max-results=5"
4
+ query:
5
+ start-date: "2010-04-01"
6
+ end-date: "2010-04-20"
7
+ ids: "ga:1174"
8
+ dimensions: "ga:country"
9
+ metrics: "ga:visits"
10
+ sort: "-ga:visits"
11
+ max-results: 5
12
+ start-index: 1
13
+ itemsPerPage: 5
14
+ totalResults: 201
15
+ selfLink: "https://www.googleapis.com/analytics/v3/data/ga?ids=ga:1174&dimensions=ga:country&metrics=ga:visits&sort=-ga:visits&start-date=2010-04-01&end-date=2010-04-20&max-results=5"
16
+ nextLink: "https://www.googleapis.com/analytics/v3/data/ga?ids=ga:1174&dimensions=ga:country&metrics=ga:visits&sort=-ga:visits&start-date=2010-04-01&end-date=2010-04-20&start-index=6&max-results=5"
17
+ profileInfo:
18
+ profileId: "1174"
19
+ accountId: "30481"
20
+ webPropertyId: "UA-30481-1"
21
+ internalWebPropertyId: "3516338"
22
+ profileName: "www.googlestore.com - goals & ecomm"
23
+ tableId: "ga:1174"
24
+ containsSampledData: false
25
+ columnHeaders:
26
+ -
27
+ name: "ga:country"
28
+ columnType: "DIMENSION"
29
+ dataType: "STRING"
30
+ -
31
+ name: "ga:visits"
32
+ columnType: "METRIC"
33
+ dataType: "INTEGER"
34
+ totalsForAllResults:
35
+ "ga:visits": "241543"
36
+ rows:
37
+ -
38
+ - "United States"
39
+ - "94351"
40
+ -
41
+ - "Brazil"
42
+ - "15826"
43
+ -
44
+ - "Spain"
45
+ - "13967"
46
+ -
47
+ - "United Kingdom"
48
+ - "13234"
49
+ -
50
+ - "Germany"
51
+ - "11347"
@@ -0,0 +1,16 @@
1
+ property:
2
+ id: 909090
3
+ kind: 'analytics#webProperty'
4
+ selfLink: 'selfLink'
5
+ accountId: 111
6
+ internalWebPropertyId: 4321432
7
+ name: 'web_property_name'
8
+ websiteUrl: 'http://www.url.com'
9
+ created: Date.today
10
+ updated: Date.today
11
+ parentLink:
12
+ type: 'analytics#account'
13
+ href: 'https://www.googleapis.com/analytics/v3/management/accounts/111'
14
+ childLink:
15
+ type: 'analytics#profiles'
16
+ href: 'https://www.googleapis.com/analytics/v3/management/accounts/111/webproperties/909090/profiles'
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Accounts" do
4
+ before :each do
5
+ @conn = Ariadna::Analytics.new("token")
6
+ @accounts = @conn.accounts.all
7
+ end
8
+
9
+ it "uses version 3 of the api" do
10
+ Ariadna::Account.url.should == "https://www.googleapis.com/analytics/v3/management/accounts"
11
+ end
12
+
13
+ context "A new account" do
14
+ before :each do
15
+ new_account = {
16
+ "id" => 43214321,
17
+ "name" => "New account",
18
+ "selfLink" => "www.example.com/self",
19
+ "childLink" => {"href"=>"www.example.com/child/43214231"}
20
+ }
21
+
22
+ @account = Ariadna::Account.new(new_account)
23
+ end
24
+
25
+ it "should map each value into attributes" do
26
+ @account.name.should == "New account"
27
+ @account.id.should == 43214321
28
+ @account.selfLink == "www.example.com/self"
29
+ @account.childLink["href"] == "www.example.com/child/43214231"
30
+ end
31
+ end
32
+
33
+ context :properties do
34
+ before :each do
35
+ @properties = @accounts.first.properties.all
36
+ end
37
+
38
+ it "gets a list of properties" do
39
+ @properties.size.should == 1
40
+ end
41
+
42
+ it "returns a list of WebProperty objects" do
43
+ @properties.first.class == Ariadna::WebProperty
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Analytics" do
4
+ before :each do
5
+ @conn = Ariadna::Analytics.new("token")
6
+ end
7
+
8
+ it "creates a new connexion" do
9
+ Ariadna.connexion.class.should == Ariadna::FakeConnector
10
+ end
11
+
12
+ context :accounts do
13
+ before :each do
14
+ @accounts = @conn.accounts.all
15
+ end
16
+
17
+ it "gets a list of accounts" do
18
+ @accounts.size.should == 2
19
+ end
20
+
21
+ it "returns a list of Account objects" do
22
+ @accounts.first.class == Ariadna::Account
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe "ErrorCode" do
4
+ context "A new error code" do
5
+ before :each do
6
+ new_error = {
7
+ "error" => {
8
+ "errors" => [
9
+ {
10
+ "domain" => "global",
11
+ "reason" => "invalidParameter",
12
+ "message" => "Invalid value '-1' for max-results. Value must be within the range: [1, 1000]",
13
+ "locationType" => "parameter",
14
+ "location" => "max-results"
15
+ }
16
+ ],
17
+ "code" => 400,
18
+ "message" => "Invalid value '-1' for max-results. Value must be within the range: [1, 1000]"
19
+ }
20
+ }
21
+
22
+ @error = Ariadna::Error.new(new_error)
23
+ @error_code = @error.errors.first
24
+ end
25
+
26
+ it "should have all information mapped as attributes" do
27
+ @error_code.domain.should == "global"
28
+ @error_code.reason.should == "invalidParameter"
29
+ @error_code.message.should == "Invalid value '-1' for max-results. Value must be within the range: [1, 1000]"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Error" do
4
+
5
+ before :each do
6
+ new_error = {
7
+ "error" => {
8
+ "errors" => [
9
+ {
10
+ "domain" => "global",
11
+ "reason" => "invalidParameter",
12
+ "message" => "Invalid value '-1' for max-results. Value must be within the range: [1, 1000]",
13
+ "locationType" => "parameter",
14
+ "location" => "max-results"
15
+ }
16
+ ],
17
+ "code" => 400,
18
+ "message" => "Invalid value '-1' for max-results. Value must be within the range: [1, 1000]"
19
+ }
20
+ }
21
+
22
+ @error = Ariadna::Error.new(new_error)
23
+ end
24
+
25
+ context "when a new error is created" do
26
+ it "should contain an array of errors" do
27
+ @error.errors.size.should == 1
28
+ end
29
+
30
+ it "should have an error code" do
31
+ @error.code.should == 400
32
+ end
33
+
34
+ it "should have an error message" do
35
+ @error.message.should == "Invalid value '-1' for max-results. Value must be within the range: [1, 1000]"
36
+ end
37
+ end
38
+
39
+ context "a bad request" do
40
+ it "should return an error object" do
41
+ conn = Ariadna::Analytics.new("token")
42
+ Ariadna.connexion.stub(:get_url).with("error").and_return(["bad request", @error])
43
+ error = Ariadna.connexion.get_url("error")
44
+
45
+ error[1].class.should == Ariadna::Error
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,67 @@
1
+ describe "Profile" do
2
+ before :each do
3
+ conn = Ariadna::Analytics.new("token")
4
+ @account = conn.accounts.all.first
5
+ @property = @account.properties.all.first
6
+ @profiles = @property.profiles.all
7
+ end
8
+
9
+ context "A new web_property" do
10
+ before :each do
11
+ new_profile = {
12
+ "id" => 888888,
13
+ "kind" => "analytics#profile",
14
+ "selfLink" => "selfLink",
15
+ "accountId" => @account.id,
16
+ "webPropertyId" => 8383,
17
+ "internalWebPropertyId" => 4321432,
18
+ "name" => "web_profile_name",
19
+ "currency" => "USD",
20
+ "timezone" => "CET",
21
+ "defaultPage" => "index.html",
22
+ "excludeQueryParameters" => "s",
23
+ "siteSearchQueryParameters" => "",
24
+ "siteSearchCategoryParameters" => "",
25
+ "created" => Date.today,
26
+ "updated" => Date.today,
27
+ "parentLink" => {
28
+ "type" => "analytics#webProperty",
29
+ "href" => "parentLink"
30
+ },
31
+ "childLink" => {
32
+ "type" => "analytics#goals",
33
+ "href" => "childLink"
34
+ }
35
+ }
36
+
37
+ @profile = Ariadna::Profile.new(new_profile)
38
+ end
39
+
40
+ it "should map each value into attributes" do
41
+ @profile.timezone.should == "CET"
42
+ @profile.excludeQueryParameters.should == "s"
43
+ @profile.defaultPage.should == "index.html"
44
+ @profile.childLink["href"].should == "childLink"
45
+ end
46
+ end
47
+
48
+ context :properties do
49
+ it "returns a list of result objects" do
50
+ @profiles.first.class == Ariadna::Result
51
+ end
52
+ end
53
+
54
+ context :results do
55
+ before :each do
56
+ @profile = @profiles.first
57
+ end
58
+
59
+ it "gets a list of profiles" do
60
+ @profiles.size.should == 2
61
+ end
62
+
63
+ it "returns a list of profiles objects" do
64
+ @profile.class == Ariadna::Profile
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Result" do
4
+ before :each do
5
+ conn = Ariadna::Analytics.new("token")
6
+ @account = conn.accounts.all.first
7
+ @property = @account.properties.all.first
8
+ @profile = @property.profiles.all.first
9
+ @results = @profile.results.all
10
+ end
11
+
12
+ context "Results from a query" do
13
+ it "should save dimensions and metrics as attributes" do
14
+ @results.first.country.should == "United States"
15
+ @results.first.visits.should == 94351
16
+ end
17
+
18
+ it "should save general query information" do
19
+ @results.first.itemsPerPage.should == 5
20
+ @results.first.query["start-date"].should == "2010-04-01"
21
+ end
22
+
23
+ it "should return data" do
24
+ @results.size.should == 5
25
+ end
26
+
27
+ it "returns an array of results objects" do
28
+ @results.first.class.should == Ariadna::Result
29
+ end
30
+ end
31
+
32
+ context "generates a url following google api rules" do
33
+
34
+ before :each do
35
+ @profile.results.select(
36
+ :metrics => [:visits, :bounces, :timeOnSite],
37
+ :dimensions => [:country]
38
+ )
39
+ .where(
40
+ :start_date => Date.today,
41
+ :end_date => Date.today,
42
+ :browser => "==Firefox"
43
+ )
44
+ .limit(100)
45
+ .offset(40)
46
+ .order([:visits, :bounces])
47
+ .all
48
+ end
49
+
50
+ it "should include google api v3" do
51
+ Ariadna::Result.url.include?("https://www.googleapis.com/analytics/v3/data/ga").should be
52
+ end
53
+
54
+ it "should include profile id" do
55
+ Ariadna::Result.url.include?("ga:#{@profile.id}").should be
56
+ end
57
+
58
+ it "should include start and end date" do
59
+ #Ariadna::Result.url.should == ""
60
+ Ariadna::Result.url.include?("start-date=#{Date.today.strftime("%Y-%m-%d")}").should be
61
+ Ariadna::Result.url.include?("end-date=#{Date.today.strftime("%Y-%m-%d")}").should be
62
+ end
63
+
64
+ it "should add metrics" do
65
+ Ariadna::Result.url.include?("metrics=ga:visits,ga:bounces,ga:timeOnSite").should be
66
+ end
67
+
68
+ it "should add dimensions" do
69
+ Ariadna::Result.url.include?("dimensions=ga:country").should be
70
+ end
71
+
72
+ it "should add max results" do
73
+ Ariadna::Result.url.include?("max-results=100").should be
74
+ end
75
+
76
+ it "should add an offset" do
77
+ Ariadna::Result.url.include?("start-index=40").should be
78
+ end
79
+
80
+ it "should add filters" do
81
+ Ariadna::Result.url.include?("filters=ga:browser%3D%3DFirefox").should be
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe "WebProperty" do
4
+ before :each do
5
+ conn = Ariadna::Analytics.new("token")
6
+ @account = conn.accounts.all.first
7
+ @properties = @account.properties.all
8
+ end
9
+
10
+ context "A new web_property" do
11
+ before :each do
12
+ new_property = {
13
+ "id" => 888888,
14
+ "kind" => "analytics#webProperty",
15
+ "selfLink" => "selfLink",
16
+ "accountId" => @account.id,
17
+ "internalWebPropertyId" => 4321432,
18
+ "name" => "web_property_name",
19
+ "websiteUrl" => "http://www.url.com",
20
+ "created" => Date.today,
21
+ "updated" => Date.today,
22
+ "parentLink" => {
23
+ "type" => "analytics#account",
24
+ "href" => "https://www.googleapis.com/analytics/v3/management/accounts/#{@account_id}"
25
+ },
26
+ "childLink" => {
27
+ "type" => "analytics#profiles",
28
+ "href" => "https://www.googleapis.com/analytics/v3/management/accounts/#{@account_id}/webproperties/888888/profiles"
29
+ }
30
+ }
31
+
32
+ @property = Ariadna::WebProperty.new(new_property)
33
+ end
34
+
35
+ it "should map each value into attributes" do
36
+ @property.kind.should == "analytics#webProperty"
37
+ @property.accountId.should == @account.id
38
+ @property.selfLink.should == "selfLink"
39
+ @property.childLink["href"].should == "https://www.googleapis.com/analytics/v3/management/accounts/#{@account_id}/webproperties/888888/profiles"
40
+ end
41
+ end
42
+
43
+ context :profiles do
44
+ before :each do
45
+ @profiles = @properties.first.profiles.all
46
+ end
47
+
48
+ it "gets a list of profiles" do
49
+ @profiles.size.should == 2
50
+ end
51
+
52
+ it "returns an array of profiles objects" do
53
+ @profiles.first.class == Ariadna::Profile
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,26 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper.rb"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ require 'ariadna'
8
+
9
+ module Ariadna
10
+ # The test of the api is made through an sqlite in memory database
11
+ # It is easier to test things than adding JSon stuff all over the place
12
+
13
+ class Analytics
14
+ def initialize(token, proxy_options=nil, refresh_info=nil)
15
+ Ariadna.connexion = FakeConnector.new(token, proxy_options, refresh_info)
16
+ end
17
+ end
18
+ end
19
+
20
+ Dir["#{File.dirname(__FILE__)}/../spec/support/*.rb"].sort.each { |ext| require ext }
21
+
22
+ RSpec.configure do |config|
23
+ config.treat_symbols_as_metadata_keys_with_true_values = true
24
+ config.run_all_when_everything_filtered = true
25
+ config.filter_run :focus
26
+ end
@@ -0,0 +1,55 @@
1
+ require 'yaml'
2
+
3
+ module Ariadna
4
+ #Sqlite3 in memoroy connector to simulate Zuora in test environments
5
+ class FakeConnector
6
+ def initialize(token, proxy_options, refresh_token_options)
7
+ #build_schema
8
+ end
9
+
10
+ def get_url(url)
11
+ if url.include? "data/ga"
12
+ load_results
13
+ elsif url.include? "goals"
14
+ #goals
15
+ elsif url.include? "profiles"
16
+ load_data('profiles')
17
+ elsif url.include? "webproperties"
18
+ load_data('webProperties')
19
+ elsif url.include? "accounts"
20
+ load_data('accounts')
21
+ elsif url.include? "error"
22
+ load_errors
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def load_data(analytics_kind)
29
+ items = YAML.load_file("#{File.dirname(__FILE__)}/../../spec/fixtures/#{analytics_kind}.yml")
30
+ hashed_items = items.map do |name, item|
31
+ item
32
+ end
33
+ {
34
+ "kind" => "analytics##{analytics_kind}",
35
+ "username" => "string",
36
+ "totalResults" => hashed_items.size,
37
+ "startIndex" => 1,
38
+ "itemsPerPage" => 1000,
39
+ "previousLink" => "prev",
40
+ "nextLink" => "next",
41
+ "items" => hashed_items
42
+ }
43
+ end
44
+
45
+ def load_results
46
+ items = YAML.load_file("#{File.dirname(__FILE__)}/../../spec/fixtures/results.yml")
47
+ items.first[1]
48
+ end
49
+
50
+ def load_errors
51
+ items = YAML.load_file("#{File.dirname(__FILE__)}/../../spec/fixtures/errors.yml")
52
+ items.first[1]
53
+ end
54
+ end
55
+ end