ariadna 1.0.0

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.
@@ -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