legato 0.0.1
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.
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/README.md +171 -0
- data/Rakefile +31 -0
- data/legato.gemspec +29 -0
- data/lib/legato/core_ext/array.rb +13 -0
- data/lib/legato/core_ext/string.rb +49 -0
- data/lib/legato/filter.rb +57 -0
- data/lib/legato/filter_set.rb +27 -0
- data/lib/legato/list_parameter.rb +29 -0
- data/lib/legato/management/account.rb +31 -0
- data/lib/legato/management/finder.rb +14 -0
- data/lib/legato/management/profile.rb +33 -0
- data/lib/legato/management/web_property.rb +28 -0
- data/lib/legato/model.rb +42 -0
- data/lib/legato/profile_methods.rb +16 -0
- data/lib/legato/query.rb +183 -0
- data/lib/legato/reports.rb +16 -0
- data/lib/legato/request.rb +21 -0
- data/lib/legato/response.rb +91 -0
- data/lib/legato/result_set.rb +21 -0
- data/lib/legato/user.rb +34 -0
- data/lib/legato/version.rb +3 -0
- data/lib/legato.rb +51 -0
- data/spec/cassettes/management/accounts.json +1 -0
- data/spec/cassettes/management/profiles.json +1 -0
- data/spec/cassettes/management/web_properties.json +1 -0
- data/spec/cassettes/model/basic.json +1 -0
- data/spec/fixtures/simple_response.json +1 -0
- data/spec/integration/management_spec.rb +34 -0
- data/spec/integration/model_spec.rb +20 -0
- data/spec/lib/legato/filter_spec.rb +49 -0
- data/spec/lib/legato/list_parameter_spec.rb +35 -0
- data/spec/lib/legato/management/account_spec.rb +39 -0
- data/spec/lib/legato/management/profile_spec.rb +45 -0
- data/spec/lib/legato/management/web_property_spec.rb +34 -0
- data/spec/lib/legato/model_spec.rb +77 -0
- data/spec/lib/legato/query_spec.rb +324 -0
- data/spec/lib/legato/response_spec.rb +15 -0
- data/spec/lib/legato/user_spec.rb +38 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/support/examples/management_finder.rb +18 -0
- data/spec/support/macros/oauth.rb +26 -0
- metadata +182 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Legato::ListParameter do
|
|
4
|
+
context "an instance of ListParameter" do
|
|
5
|
+
before :each do
|
|
6
|
+
@list_parameter = Legato::ListParameter.new(:metrics, [:exits])
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'appends to the list' do
|
|
10
|
+
@list_parameter << :pageviews
|
|
11
|
+
@list_parameter.elements.should == [:exits, :pageviews]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'has a name' do
|
|
15
|
+
@list_parameter.name.should == "metrics"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'knows if it is equal another list parameter' do
|
|
19
|
+
@list_parameter.should == Legato::ListParameter.new(:metrics, [:exits])
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'knows it is not equal another list parameter with a different name' do
|
|
23
|
+
@list_parameter.should_not == Legato::ListParameter.new(:dimensions, [:exits])
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'knows it is not equal another list parameter with different elements' do
|
|
27
|
+
@list_parameter.should_not == Legato::ListParameter.new(:metrics, [:exits, :pageviews])
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'converts itself to params' do
|
|
31
|
+
@list_parameter << :pageviews
|
|
32
|
+
@list_parameter.to_params.should == {"metrics" => "ga:exits,ga:pageviews"}
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Legato::Management::Account do
|
|
4
|
+
context "The Account class" do
|
|
5
|
+
def self.subject_class_name
|
|
6
|
+
"accounts"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it_behaves_like "a management finder"
|
|
10
|
+
|
|
11
|
+
it 'creates a new account instance from a hash of attributes' do
|
|
12
|
+
user = stub
|
|
13
|
+
account = Legato::Management::Account.new({"id" => 12345, "name" => "Account 1"}, user)
|
|
14
|
+
account.user.should == user
|
|
15
|
+
account.id.should == 12345
|
|
16
|
+
account.name.should == "Account 1"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "An Account instance" do
|
|
21
|
+
let(:account) {Legato::Management::Account.new({"id" => 123456}, stub)}
|
|
22
|
+
|
|
23
|
+
it 'builds the path for the account from the id' do
|
|
24
|
+
account.path.should == '/accounts/123456'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'has web properties beneath it' do
|
|
28
|
+
Legato::Management::WebProperty.stubs(:for_account).returns('web_properties')
|
|
29
|
+
account.web_properties.should == 'web_properties'
|
|
30
|
+
Legato::Management::WebProperty.should have_received(:for_account).with(account)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'has profiles beneath it' do
|
|
34
|
+
Legato::Management::Profile.stubs(:for_account).returns('profiles')
|
|
35
|
+
account.profiles.should == 'profiles'
|
|
36
|
+
Legato::Management::Profile.should have_received(:for_account).with(account)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Legato::Management::Profile do
|
|
4
|
+
context "The Profile class" do
|
|
5
|
+
def self.subject_class_name
|
|
6
|
+
"profiles"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it_behaves_like "a management finder"
|
|
10
|
+
|
|
11
|
+
it 'creates a new profile instance from a hash of attributes' do
|
|
12
|
+
user = stub
|
|
13
|
+
profile = Legato::Management::Profile.new({"id" => 12345, "name" => "Profile 1"}, user)
|
|
14
|
+
profile.user.should == user
|
|
15
|
+
profile.id.should == 12345
|
|
16
|
+
profile.name.should == "Profile 1"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'returns an array of all profiles available to a user under an account' do
|
|
20
|
+
account = stub(:user => 'user', :path => 'accounts/12345')
|
|
21
|
+
Legato::Management::Profile.stubs(:all)
|
|
22
|
+
|
|
23
|
+
Legato::Management::Profile.for_account(account)
|
|
24
|
+
|
|
25
|
+
Legato::Management::Profile.should have_received(:all).with('user', 'accounts/12345/webproperties/~all/profiles')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'returns an array of all profiles available to a user under an web property' do
|
|
29
|
+
web_property = stub(:user => 'user', :path => 'accounts/~all/webproperties/12345')
|
|
30
|
+
Legato::Management::Profile.stubs(:all)
|
|
31
|
+
|
|
32
|
+
Legato::Management::Profile.for_web_property(web_property)
|
|
33
|
+
|
|
34
|
+
Legato::Management::Profile.should have_received(:all).with('user', 'accounts/~all/webproperties/12345/profiles')
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context "A Profile instance" do
|
|
39
|
+
it 'builds the path for the profile from the id' do
|
|
40
|
+
web_property = Legato::Management::Profile.new({"id" => 12345}, stub)
|
|
41
|
+
web_property.path.should == '/accounts/~all/webproperties/~all/profiles/12345'
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Legato::Management::WebProperty do
|
|
4
|
+
context "The WebProperty class" do
|
|
5
|
+
def self.subject_class_name
|
|
6
|
+
"web properties"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it_behaves_like "a management finder"
|
|
10
|
+
|
|
11
|
+
it 'creates a new web property instance from a hash of attributes' do
|
|
12
|
+
user = stub
|
|
13
|
+
web_property = Legato::Management::WebProperty.new({"id" => 12345, "name" => "WebProperty 1", "websiteUrl" => "http://google.com"}, user)
|
|
14
|
+
web_property.user.should == user
|
|
15
|
+
web_property.id.should == 12345
|
|
16
|
+
web_property.name.should == "WebProperty 1"
|
|
17
|
+
web_property.website_url.should == 'http://google.com'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'returns an array of all web properties available to a user under an account' do
|
|
21
|
+
account = stub(:user => 'user', :path => 'accounts/12345')
|
|
22
|
+
Legato::Management::WebProperty.stubs(:all)
|
|
23
|
+
Legato::Management::WebProperty.for_account(account)
|
|
24
|
+
Legato::Management::WebProperty.should have_received(:all).with('user', 'accounts/12345/webproperties')
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context "A WebProperty instance" do
|
|
29
|
+
it 'builds the path for the web_property from the id' do
|
|
30
|
+
web_property = Legato::Management::WebProperty.new({"id" => 123456}, stub)
|
|
31
|
+
web_property.path.should == '/accounts/~all/webproperties/123456'
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "Legato::Model" do
|
|
4
|
+
context "A Class extended with Legato::Model" do
|
|
5
|
+
def new_model_class
|
|
6
|
+
Class.new.tap do |klass|
|
|
7
|
+
klass.extend(Legato::Model)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
before :each do
|
|
12
|
+
@model = new_model_class
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'has a metric' do
|
|
16
|
+
@model.metrics :exits
|
|
17
|
+
@model.metrics.should == Legato::ListParameter.new(:metrics, [:exits])
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'has metrics' do
|
|
21
|
+
@model.metrics :exits, :pageviews
|
|
22
|
+
@model.metrics.should == Legato::ListParameter.new(:metrics, [:exits, :pageviews])
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'has a dimension' do
|
|
26
|
+
@model.dimensions :browser
|
|
27
|
+
@model.dimensions.should == Legato::ListParameter.new(:dimensions, [:browser])
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'has dimensions' do
|
|
31
|
+
@model.dimensions :browser, :city
|
|
32
|
+
@model.dimensions.should == Legato::ListParameter.new(:dimensions, [:browser, :city])
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context "with filters" do
|
|
36
|
+
before :each do
|
|
37
|
+
@block = lambda {}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'creates a class method' do
|
|
41
|
+
@model.filter :high, @block
|
|
42
|
+
@model.respond_to?(:high).should be_true
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'stores the filter' do
|
|
46
|
+
@model.filter :high, @block
|
|
47
|
+
@model.filters[:high].should == @block
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'returns a Query instance for a filter' do
|
|
51
|
+
query = stub(:apply_filter => "a query")
|
|
52
|
+
Legato::Query.stubs(:new).returns(query)
|
|
53
|
+
|
|
54
|
+
@model.filter :high, @block
|
|
55
|
+
@model.high('arg1').should == 'a query'
|
|
56
|
+
|
|
57
|
+
Legato::Query.should have_received(:new).with(@model)
|
|
58
|
+
query.should have_received(:apply_filter).with('arg1', @block)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# xit 'has an instance klass'
|
|
63
|
+
# xit 'sets an instance klass'
|
|
64
|
+
|
|
65
|
+
it 'has results' do
|
|
66
|
+
options = {}
|
|
67
|
+
profile = stub
|
|
68
|
+
query = stub(:results => "a query")
|
|
69
|
+
Legato::Query.stubs(:new).returns(query)
|
|
70
|
+
|
|
71
|
+
@model.results(profile, options).should == "a query"
|
|
72
|
+
|
|
73
|
+
Legato::Query.should have_received(:new).with(@model)
|
|
74
|
+
query.should have_received(:results).with(profile, options)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Legato::Query do
|
|
4
|
+
def self.it_defines_operators(*operators)
|
|
5
|
+
operators.each do |operator|
|
|
6
|
+
it "creates a method for the operator #{operator}" do
|
|
7
|
+
@query.respond_to?(operator).should be_true
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "returns a new filter for #{operator} to the set" do
|
|
11
|
+
Legato::Filter.stubs(:new).returns("a filter")
|
|
12
|
+
filter = @query.send(operator, :key, 2000)
|
|
13
|
+
Legato::Filter.should have_received(:new).with(:key, operator, 2000)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context "a query" do
|
|
19
|
+
before :each do
|
|
20
|
+
@klass = Class.new
|
|
21
|
+
@block = lambda {eql(:key, 1000)}
|
|
22
|
+
@klass.stubs(:filters).returns({:high => @block})
|
|
23
|
+
|
|
24
|
+
@query = Legato::Query.new(@klass)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'knows the parent class' do
|
|
28
|
+
@query.parent_klass.should == @klass
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'defaults to an empty filter set' do
|
|
32
|
+
@query.filters.to_params.should == Legato::FilterSet.new.to_params
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'has filters defined from the parent class' do
|
|
36
|
+
@query.respond_to?(:high).should be_true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "has filter methods that call apply with the given block" do
|
|
40
|
+
@query.stubs(:apply_filter)
|
|
41
|
+
@query.high('hi')
|
|
42
|
+
@query.should have_received(:apply_filter).with('hi', @block)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'does not load results by default' do
|
|
46
|
+
@query.loaded?.should == false
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "loads a collection of results" do
|
|
50
|
+
response = stub(:collection => [])
|
|
51
|
+
user = stub(:request => response)
|
|
52
|
+
@query.stubs(:profile => stub(:user => user))
|
|
53
|
+
|
|
54
|
+
@query.load
|
|
55
|
+
|
|
56
|
+
@query.loaded?.should be_true
|
|
57
|
+
@query.profile.user.should have_received(:request).with(@query)
|
|
58
|
+
response.should have_received(:collection)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "returns the collection" do
|
|
62
|
+
@query.stubs(:request_for_query).returns(stub(:collection => [1,2,3]))
|
|
63
|
+
@query.load
|
|
64
|
+
@query.collection.should == [1,2,3]
|
|
65
|
+
@query.to_a.should == [1,2,3]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "behaves like an enumerable delegating to the collection" do
|
|
69
|
+
collection = []
|
|
70
|
+
collection.stubs(:each)
|
|
71
|
+
@query.stubs(:collection).returns(collection)
|
|
72
|
+
@query.stubs(:loaded?).returns(true)
|
|
73
|
+
|
|
74
|
+
@query.each {}
|
|
75
|
+
|
|
76
|
+
collection.should have_received(:each)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'has a profile id after being given a profile' do
|
|
80
|
+
profile = stub(:id => '1234567890')
|
|
81
|
+
@query.stubs(:profile).returns(profile)
|
|
82
|
+
|
|
83
|
+
@query.profile_id.should == 'ga:1234567890'
|
|
84
|
+
|
|
85
|
+
profile.should have_received(:id)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'has no profile id by default' do
|
|
89
|
+
@query.stubs(:profile).returns(nil)
|
|
90
|
+
@query.profile_id.should be_nil
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it 'sets the profile and applies options, returns itself' do
|
|
94
|
+
@query.stubs(:profile=)
|
|
95
|
+
@query.stubs(:apply_options)
|
|
96
|
+
|
|
97
|
+
@query.results('profile').should == @query
|
|
98
|
+
|
|
99
|
+
@query.should have_received(:profile=).with('profile')
|
|
100
|
+
@query.should have_received(:apply_options).with({})
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context 'when applying filters' do
|
|
104
|
+
before :each do
|
|
105
|
+
@filter = Legato::Filter.new(:key, :eql, 1000)
|
|
106
|
+
@query.stubs(:eql).returns(@filter)
|
|
107
|
+
|
|
108
|
+
@filters = stub(:<<)
|
|
109
|
+
@query.stubs(:filters).returns(@filters)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'returns the query' do
|
|
113
|
+
@query.apply_filter(@block).should == @query
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'executes the block' do
|
|
117
|
+
@query.apply_filter(@block)
|
|
118
|
+
@query.should have_received(:eql).with(:key, 1000)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it 'accepts a profile as the first argument' do
|
|
122
|
+
profile = Legato::Management::Profile.new({}, stub)
|
|
123
|
+
@query.apply_filter(profile, @block)
|
|
124
|
+
@query.should have_received(:eql)
|
|
125
|
+
@query.profile.should == profile
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it 'accepts a profile as the last argument' do
|
|
129
|
+
profile = Legato::Management::Profile.new({}, stub)
|
|
130
|
+
block_with_arg = lambda {|count| eql(:key, count)}
|
|
131
|
+
@query.apply_filter(100, profile, block_with_arg)
|
|
132
|
+
@query.should have_received(:eql).with(:key, 100)
|
|
133
|
+
@query.profile.should == profile
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it 'does not override the existing profile if none is provide' do
|
|
137
|
+
@query.profile = Legato::Management::Profile.new({}, stub)
|
|
138
|
+
block_with_arg = lambda {|count| eql(:key, count)}
|
|
139
|
+
@query.apply_filter(100, block_with_arg)
|
|
140
|
+
@query.profile.should_not == nil
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it 'adds to the filter set' do
|
|
144
|
+
@query.apply_filter(@block)
|
|
145
|
+
|
|
146
|
+
@filters.should have_received(:<<).with(@filter)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'joins an array of filters with OR' do
|
|
150
|
+
block = lambda {|*browsers| browsers.map {|browser| eql(:browser, browser)}}
|
|
151
|
+
@filter.stubs(:join_character=)
|
|
152
|
+
|
|
153
|
+
@query.apply_filter('chrome', 'safari', block)
|
|
154
|
+
|
|
155
|
+
@filter.should have_received(:join_character=).with(Legato.and_join_character)
|
|
156
|
+
@filter.should have_received(:join_character=).with(Legato.or_join_character)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
context "when applying options" do
|
|
161
|
+
it "returns the query" do
|
|
162
|
+
@query.apply_options({}).should == @query
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "stores the order" do
|
|
166
|
+
@query.apply_options({:order => [:page_path]})
|
|
167
|
+
@query.order.should == Legato::ListParameter.new(:order, [:page_path])
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it 'replaces the order' do
|
|
171
|
+
@query.order = [:pageviews]
|
|
172
|
+
@query.apply_options({:order => [:page_path]})
|
|
173
|
+
@query.order.should == Legato::ListParameter.new(:order, [:page_path])
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it "does not replace order if option is omitted" do
|
|
177
|
+
@query.order = [:pageviews]
|
|
178
|
+
@query.apply_options({})
|
|
179
|
+
@query.order.should == Legato::ListParameter.new(:order, [:pageviews])
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it "moves :sort option into order" do
|
|
183
|
+
@query.apply_options({:sort => [:page_path]})
|
|
184
|
+
@query.order.should == Legato::ListParameter.new(:order, [:page_path])
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it "sets the limit" do
|
|
188
|
+
@query.apply_options({:limit => 100})
|
|
189
|
+
@query.limit.should == 100
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it "replaces the limit" do
|
|
193
|
+
@query.limit = 200
|
|
194
|
+
@query.apply_options({:limit => 100})
|
|
195
|
+
@query.limit.should == 100
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it "does not replace the limit if option is omitted" do
|
|
199
|
+
@query.limit = 200
|
|
200
|
+
@query.apply_options({})
|
|
201
|
+
@query.limit.should == 200
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "sets the offset" do
|
|
205
|
+
@query.apply_options({:offset => 100})
|
|
206
|
+
@query.offset.should == 100
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it "replaces the offset" do
|
|
210
|
+
@query.offset = 200
|
|
211
|
+
@query.apply_options({:offset => 100})
|
|
212
|
+
@query.offset.should == 100
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it "does not replace offset if option is omitted" do
|
|
216
|
+
@query.offset = 200
|
|
217
|
+
@query.apply_options({})
|
|
218
|
+
@query.offset.should == 200
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
context "with Time" do
|
|
222
|
+
before :each do
|
|
223
|
+
@now = Time.now
|
|
224
|
+
Time.stubs(:now).returns(@now)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it 'defaults the start date to 30 days ago' do
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
it "replaces the start date" do
|
|
231
|
+
@query.apply_options({:start_date => (@now-2000)})
|
|
232
|
+
@query.start_date.should == (@now-2000)
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it "does not replace the start date if option is omitted" do
|
|
236
|
+
@query.apply_options({})
|
|
237
|
+
Legato.format_time(@query.start_date).should == Legato.format_time(@now-Legato::Query::MONTH)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it "replaces the end date" do
|
|
241
|
+
@query.apply_options({:end_date => (@now+2000)})
|
|
242
|
+
@query.end_date.should == (@now+2000)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
it "does not replace the end date if option is omitted" do
|
|
246
|
+
@query.apply_options({})
|
|
247
|
+
Legato.format_time(@query.end_date).should == Legato.format_time(@now)
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
it_defines_operators :eql, :not_eql, :gt, :gte, :lt, :lte, :matches,
|
|
253
|
+
:does_not_match, :contains, :does_not_contain, :substring, :not_substring
|
|
254
|
+
|
|
255
|
+
context "as a hash of parameters" do
|
|
256
|
+
before :each do
|
|
257
|
+
@query.stubs(:metrics).returns(nil)
|
|
258
|
+
@query.stubs(:dimensions).returns(nil)
|
|
259
|
+
@query.stubs(:filters).returns(stub(:to_params => nil))
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it 'includes the profile id' do
|
|
263
|
+
@query.stubs(:profile_id).returns('ga:1234567890')
|
|
264
|
+
|
|
265
|
+
@query.to_params.should == {
|
|
266
|
+
'ids' => 'ga:1234567890',
|
|
267
|
+
'start-date' => Legato.format_time(Time.now-Legato::Query::MONTH),
|
|
268
|
+
'end-date' => Legato.format_time(Time.now)
|
|
269
|
+
}
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
it 'includes the start and end dates' do
|
|
273
|
+
now = Time.now
|
|
274
|
+
@query.start_date = now
|
|
275
|
+
@query.end_date = now
|
|
276
|
+
@query.to_params.should == {'start-date' => Legato.format_time(now), 'end-date' => Legato.format_time(now)}
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it 'includes the limit' do
|
|
280
|
+
@query.limit = 1000
|
|
281
|
+
@query.to_params['max-results'].should == 1000
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
it 'includes the offset' do
|
|
285
|
+
@query.offset = 50
|
|
286
|
+
@query.to_params['start-index'].should == 50
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it 'includes filters' do
|
|
290
|
+
filters = stub(:to_params => 'filter set parameters')
|
|
291
|
+
@query.stubs(:filters).returns(filters)
|
|
292
|
+
|
|
293
|
+
@query.to_params['filters'].should == 'filter set parameters'
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
it 'includes metrics' do
|
|
297
|
+
metrics = Legato::ListParameter.new(:metrics)
|
|
298
|
+
metrics.stubs(:to_params).returns({'metrics' => 'pageviews,exits'})
|
|
299
|
+
metrics.stubs(:empty?).returns(false)
|
|
300
|
+
@query.stubs(:metrics).returns(metrics)
|
|
301
|
+
|
|
302
|
+
@query.to_params['metrics'].should == 'pageviews,exits'
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
it 'includes dimensions' do
|
|
306
|
+
dimensions = Legato::ListParameter.new(:dimensions)
|
|
307
|
+
dimensions.stubs(:to_params).returns({'dimensions' => 'browser,country'})
|
|
308
|
+
dimensions.stubs(:empty?).returns(false)
|
|
309
|
+
@query.stubs(:dimensions).returns(dimensions)
|
|
310
|
+
|
|
311
|
+
@query.to_params['dimensions'].should == 'browser,country'
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
it 'includes order' do
|
|
315
|
+
order = Legato::ListParameter.new(:order)
|
|
316
|
+
order.stubs(:to_params).returns({'order' => 'pageviews'})
|
|
317
|
+
order.stubs(:empty?).returns(false)
|
|
318
|
+
@query.stubs(:order).returns(order)
|
|
319
|
+
|
|
320
|
+
@query.to_params['order'].should == 'pageviews'
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Legato::Response do
|
|
4
|
+
context "An instance of Response" do
|
|
5
|
+
before :each do
|
|
6
|
+
raw_body = File.read(File.dirname(__FILE__) + '/../../fixtures/simple_response.json')
|
|
7
|
+
|
|
8
|
+
@response = Legato::Response.new(stub(:body => raw_body))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it 'has a collection of OpenStruct instances' do
|
|
12
|
+
@response.collection.first.should == OpenStruct.new({:browser=>"Android Browser", :pageviews=>"93"})
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Legato::User do
|
|
4
|
+
context "an instance of Legato::User" do
|
|
5
|
+
before :each do
|
|
6
|
+
@access_token = stub
|
|
7
|
+
@user = Legato::User.new(@access_token)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'returns a response for a given query' do
|
|
11
|
+
@access_token.stubs(:get).returns('a response')
|
|
12
|
+
Legato::Response.stubs(:new)
|
|
13
|
+
|
|
14
|
+
@user.request(stub(:to_params => "params"))
|
|
15
|
+
|
|
16
|
+
Legato::Response.should have_received(:new).with('a response')
|
|
17
|
+
@access_token.should have_received(:get).with(Legato::User::URL, :params => "params")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'has accounts' do
|
|
21
|
+
Legato::Management::Account.stubs(:all)
|
|
22
|
+
@user.accounts
|
|
23
|
+
Legato::Management::Account.should have_received(:all).with(@user)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'has web_properties' do
|
|
27
|
+
Legato::Management::WebProperty.stubs(:all)
|
|
28
|
+
@user.web_properties
|
|
29
|
+
Legato::Management::WebProperty.should have_received(:all).with(@user)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'has profiles' do
|
|
33
|
+
Legato::Management::Profile.stubs(:all)
|
|
34
|
+
@user.profiles
|
|
35
|
+
Legato::Management::Profile.should have_received(:all).with(@user)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'bundler'
|
|
2
|
+
Bundler.setup(:test)
|
|
3
|
+
|
|
4
|
+
require 'rspec'
|
|
5
|
+
require 'mocha'
|
|
6
|
+
require 'bourne'
|
|
7
|
+
require 'vcr'
|
|
8
|
+
|
|
9
|
+
require File.expand_path('../../lib/legato', __FILE__)
|
|
10
|
+
|
|
11
|
+
Dir["./spec/support/**/*.rb"].each {|f| require f}
|
|
12
|
+
|
|
13
|
+
VCR.configure do |config|
|
|
14
|
+
config.cassette_library_dir = File.expand_path('../cassettes', __FILE__)
|
|
15
|
+
config.default_cassette_options = {:record => :new_episodes, :serialize_with => :json}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
RSpec.configure do |config|
|
|
19
|
+
config.mock_with :mocha
|
|
20
|
+
|
|
21
|
+
config.extend VCR::RSpec::Macros
|
|
22
|
+
config.include Support::Macros::OAuth
|
|
23
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
shared_examples_for "a management finder" do
|
|
2
|
+
it "returns an array of all #{subject_class_name} available to a user" do
|
|
3
|
+
JSON.stubs(:parse).returns({'items' => ['item1', 'item2']})
|
|
4
|
+
response = stub(:body => 'some json')
|
|
5
|
+
access_token = stub(:get => response)
|
|
6
|
+
user = stub(:access_token => access_token)
|
|
7
|
+
described_class.stubs(:new).returns('thing1', 'thing2')
|
|
8
|
+
|
|
9
|
+
described_class.all(user).should == ['thing1', 'thing2']
|
|
10
|
+
|
|
11
|
+
user.should have_received(:access_token)
|
|
12
|
+
access_token.should have_received(:get).with('https://www.googleapis.com/analytics/v3/management'+described_class.default_path)
|
|
13
|
+
response.should have_received(:body)
|
|
14
|
+
JSON.should have_received(:parse).with('some json')
|
|
15
|
+
described_class.should have_received(:new).with('item1', user)
|
|
16
|
+
described_class.should have_received(:new).with('item2', user)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Support
|
|
2
|
+
module Macros
|
|
3
|
+
module OAuth
|
|
4
|
+
def token
|
|
5
|
+
# fill me in if you add more tests here, use the rake task oauth:token, update vcr to :record => :all
|
|
6
|
+
"ya29.AHES6ZREobGegWLc3tyxuuQAkKF7lg071UgpTeLe_4jTcV35uW8"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def client
|
|
10
|
+
opts = {
|
|
11
|
+
:authorize_url => 'https://accounts.google.com/o/oauth2/auth',
|
|
12
|
+
:token_url => 'https://accounts.google.com/o/oauth2/token'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
OAuth2::Client.new('779170787975.apps.googleusercontent.com', 'mbCISoZiSwyVQIDEbLj4EeEc', opts) do |builder|
|
|
16
|
+
builder.use VCR::Middleware::Faraday
|
|
17
|
+
builder.adapter :net_http
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def access_token
|
|
22
|
+
OAuth2::AccessToken.new(client, token)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|