gaq 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +15 -0
- data/Guardfile +23 -0
- data/LICENSE.txt +22 -0
- data/README.md +102 -0
- data/Rakefile +1 -0
- data/gaq.gemspec +22 -0
- data/lib/gaq.rb +3 -0
- data/lib/gaq/class_cache.rb +32 -0
- data/lib/gaq/command_language.rb +145 -0
- data/lib/gaq/configuration.rb +159 -0
- data/lib/gaq/controller_facade.rb +15 -0
- data/lib/gaq/controller_handle.rb +93 -0
- data/lib/gaq/dsl_target.rb +51 -0
- data/lib/gaq/dsl_target_factory.rb +64 -0
- data/lib/gaq/flash_commands_adapter.rb +48 -0
- data/lib/gaq/interprets_config.rb +13 -0
- data/lib/gaq/railtie.rb +40 -0
- data/lib/gaq/snippet_renderer.rb +44 -0
- data/lib/gaq/version.rb +3 -0
- data/spec-dummy/.rspec +1 -0
- data/spec-dummy/README.rdoc +261 -0
- data/spec-dummy/Rakefile +7 -0
- data/spec-dummy/app/assets/images/rails.png +0 -0
- data/spec-dummy/app/assets/javascripts/application.js +13 -0
- data/spec-dummy/app/assets/stylesheets/application.css +13 -0
- data/spec-dummy/app/controllers/application_controller.rb +3 -0
- data/spec-dummy/app/controllers/integration_spec_controller.rb +22 -0
- data/spec-dummy/app/helpers/application_helper.rb +2 -0
- data/spec-dummy/app/views/integration_spec/view.erb +0 -0
- data/spec-dummy/app/views/layouts/application.html.erb +16 -0
- data/spec-dummy/config.ru +4 -0
- data/spec-dummy/config/application.rb +64 -0
- data/spec-dummy/config/boot.rb +6 -0
- data/spec-dummy/config/environment.rb +5 -0
- data/spec-dummy/config/environments/development.rb +26 -0
- data/spec-dummy/config/environments/production.rb +51 -0
- data/spec-dummy/config/environments/test_dynamic.rb +39 -0
- data/spec-dummy/config/environments/test_static.rb +38 -0
- data/spec-dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec-dummy/config/initializers/inflections.rb +15 -0
- data/spec-dummy/config/initializers/mime_types.rb +5 -0
- data/spec-dummy/config/initializers/secret_token.rb +7 -0
- data/spec-dummy/config/initializers/session_store.rb +8 -0
- data/spec-dummy/config/initializers/wrap_parameters.rb +10 -0
- data/spec-dummy/config/locales/en.yml +5 -0
- data/spec-dummy/config/routes.rb +8 -0
- data/spec-dummy/db/seeds.rb +7 -0
- data/spec-dummy/public/404.html +26 -0
- data/spec-dummy/public/422.html +26 -0
- data/spec-dummy/public/500.html +25 -0
- data/spec-dummy/public/favicon.ico +0 -0
- data/spec-dummy/public/robots.txt +5 -0
- data/spec-dummy/script/rails +6 -0
- data/spec-dummy/spec/common_spec_methods.rb +88 -0
- data/spec-dummy/spec/features/dynamic_config_spec.rb +21 -0
- data/spec-dummy/spec/features/next_request_spec.rb +27 -0
- data/spec-dummy/spec/features/presence_spec.rb +64 -0
- data/spec-dummy/spec/spec_helper.rb +41 -0
- data/spec/lib/gaq/class_cache_spec.rb +62 -0
- data/spec/lib/gaq/command_language_spec.rb +267 -0
- data/spec/lib/gaq/configuration_spec.rb +233 -0
- data/spec/lib/gaq/controller_facade_spec.rb +29 -0
- data/spec/lib/gaq/controller_handle_spec.rb +510 -0
- data/spec/lib/gaq/dsl_target_factory_spec.rb +163 -0
- data/spec/lib/gaq/dsl_target_spec.rb +87 -0
- data/spec/lib/gaq/flash_commands_adapter_spec.rb +116 -0
- data/spec/lib/gaq/interprets_config_spec.rb +37 -0
- data/spec/lib/gaq/snippet_renderer_spec.rb +60 -0
- metadata +159 -0
@@ -0,0 +1,233 @@
|
|
1
|
+
require 'gaq/configuration'
|
2
|
+
|
3
|
+
require 'gaq/interprets_config'
|
4
|
+
require 'active_support/string_inquirer'
|
5
|
+
|
6
|
+
module Gaq
|
7
|
+
describe Configuration do
|
8
|
+
let(:rails) { subject.rails_config }
|
9
|
+
|
10
|
+
describe "rails exposed config object" do
|
11
|
+
describe ".declare_variable" do
|
12
|
+
describe "variable setup" do
|
13
|
+
let(:variable) do
|
14
|
+
subject.variables.should have(1).variable
|
15
|
+
subject.variables["my_variable"]
|
16
|
+
end
|
17
|
+
|
18
|
+
it "sets up variable name and slot correctly" do
|
19
|
+
rails.declare_variable("my_variable", slot: 2)
|
20
|
+
|
21
|
+
variable.name.should be == "my_variable"
|
22
|
+
variable.slot.should be 2
|
23
|
+
end
|
24
|
+
|
25
|
+
it "default to scope code 3" do
|
26
|
+
rails.declare_variable("my_variable", slot: 1)
|
27
|
+
|
28
|
+
variable.scope.should be 3
|
29
|
+
end
|
30
|
+
|
31
|
+
it "correctly sets up scope, given as symbol" do
|
32
|
+
rails.declare_variable("my_variable", slot: 1, scope: :visitor)
|
33
|
+
|
34
|
+
variable.scope.should be 1
|
35
|
+
end
|
36
|
+
|
37
|
+
it "correctly sets up scope, given as Fixnum" do
|
38
|
+
rails.declare_variable("my_variable", slot: 1, scope: 1)
|
39
|
+
|
40
|
+
variable.scope.should be 1
|
41
|
+
end
|
42
|
+
|
43
|
+
it "complains about unknown scope" do
|
44
|
+
expect do
|
45
|
+
rails.declare_variable("my_variable", slot: 1, scope: //)
|
46
|
+
end.to raise_exception(Configuration::VariableException)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "complains about an invalid slot"
|
51
|
+
|
52
|
+
it "complains about a taken slot" do
|
53
|
+
rails.declare_variable("my_variable", slot: 1)
|
54
|
+
expect do
|
55
|
+
rails.declare_variable("my_other_variable", slot: 1)
|
56
|
+
end.to raise_exception Configuration::VariableException
|
57
|
+
end
|
58
|
+
|
59
|
+
it "complains about a taken name" do
|
60
|
+
rails.declare_variable("my_variable", slot: 1)
|
61
|
+
expect do
|
62
|
+
rails.declare_variable("my_variable", slot: 2)
|
63
|
+
end.to raise_exception Configuration::VariableException
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe ".additional_trackers=" do
|
68
|
+
it "complains about bad tracker names" do
|
69
|
+
pending "could not find out about that in the docs"
|
70
|
+
# probably, leading underscore is bad
|
71
|
+
end
|
72
|
+
|
73
|
+
it "makes tracker configs available" do
|
74
|
+
rails.additional_trackers = [:foo, :bar]
|
75
|
+
|
76
|
+
rails.tracker(:foo).should_not be rails.tracker(:bar)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "tolerates symbols as well as strings" do
|
80
|
+
rails.additional_trackers = [:foo, "bar"]
|
81
|
+
|
82
|
+
rails.tracker(:foo).should_not be rails.tracker(:bar)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "complains about name collision" do
|
86
|
+
expect { rails.additional_trackers = ["foo", "foo"] }.to raise_exception
|
87
|
+
end
|
88
|
+
|
89
|
+
it "complains about name collision even if symbol and string is used" do
|
90
|
+
expect { rails.additional_trackers = [:foo, "foo"] }.to raise_exception
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def find_tracker_config_by_name(name)
|
95
|
+
name = name.to_s unless name.nil?
|
96
|
+
result = subject.tracker_config(name)
|
97
|
+
result.should_not be_nil
|
98
|
+
result
|
99
|
+
end
|
100
|
+
|
101
|
+
describe ".tracker" do
|
102
|
+
it "complains about a non-existent tracker name" do
|
103
|
+
expect{ rails.tracker(:nonexistent) }.to raise_exception
|
104
|
+
end
|
105
|
+
|
106
|
+
it "returns something for a valid tracker name" do
|
107
|
+
rails.additional_trackers = [:foo]
|
108
|
+
|
109
|
+
rails.tracker(:foo).should_not be_nil
|
110
|
+
end
|
111
|
+
|
112
|
+
it "tolerates symbols as well as strings" do
|
113
|
+
rails.additional_trackers = [:foo]
|
114
|
+
|
115
|
+
rails.tracker(:foo).should be rails.tracker("foo")
|
116
|
+
end
|
117
|
+
|
118
|
+
it "delegates tracker setting setters to tracker configs" do
|
119
|
+
rails.additional_trackers = [:foo]
|
120
|
+
|
121
|
+
rails_tracker = rails.tracker(:foo)
|
122
|
+
rails_tracker.web_property_id = "web property id"
|
123
|
+
rails_tracker.track_pageview = :production
|
124
|
+
|
125
|
+
tracker_config = find_tracker_config_by_name(:foo)
|
126
|
+
tracker_config.web_property_id.should be == "web property id"
|
127
|
+
tracker_config.track_pageview.should be :production
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
it "delegates tracker setting setters to default tracker rails config object" do
|
132
|
+
rails.web_property_id = "bla"
|
133
|
+
|
134
|
+
default_tracker_config = find_tracker_config_by_name(nil)
|
135
|
+
|
136
|
+
default_tracker_config.web_property_id.should be == "bla"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe "tracker_config" do
|
141
|
+
it "returns nil when no tracker config by given name" do
|
142
|
+
subject.tracker_config('bogus').should be_nil
|
143
|
+
end
|
144
|
+
|
145
|
+
it "returns a different object per tracker name" do
|
146
|
+
rails.additional_trackers = [:foo, :bar]
|
147
|
+
|
148
|
+
subject.tracker_config('foo').should_not be subject.tracker_config('bar')
|
149
|
+
end
|
150
|
+
|
151
|
+
it "only accepts tracker names as strings" do
|
152
|
+
rails.additional_trackers = [:foo, :bar]
|
153
|
+
|
154
|
+
subject.tracker_config(:foo).should be_nil
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe "tracker_names" do
|
159
|
+
it "initially is [nil]" do
|
160
|
+
subject.tracker_names.should be == [nil]
|
161
|
+
end
|
162
|
+
|
163
|
+
context "after gaq.additional_trackers = [:foo, :bar]" do
|
164
|
+
before do
|
165
|
+
rails.additional_trackers = [:foo, :bar]
|
166
|
+
end
|
167
|
+
|
168
|
+
it "contains nil, 'foo' and 'bar'" do
|
169
|
+
subject.tracker_names.should have(3).tracker_names
|
170
|
+
subject.tracker_names.should include(nil)
|
171
|
+
subject.tracker_names.should include('foo')
|
172
|
+
subject.tracker_names.should include('bar')
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe "#render_ga_js?" do
|
178
|
+
let(:environment) do
|
179
|
+
ActiveSupport::StringInquirer.new(example.metadata[:env].to_s)
|
180
|
+
end
|
181
|
+
|
182
|
+
def result
|
183
|
+
subject.render_ga_js?(environment)
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
describe "this StringInquirer setup" do
|
188
|
+
it "works as expected", env: :development do
|
189
|
+
environment.should be_development
|
190
|
+
environment.should_not be_production
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context "with rails_config.render_ga_js = true or false" do
|
195
|
+
it "reports those values " do
|
196
|
+
rails.render_ga_js = true
|
197
|
+
result.should be == true
|
198
|
+
|
199
|
+
rails.render_ga_js = false
|
200
|
+
result.should be == false
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
context "with rails_config.render_ga_ja = some symbol" do
|
205
|
+
it "compares with given environment", env: :production do
|
206
|
+
rails.render_ga_js = :production
|
207
|
+
result.should be == true
|
208
|
+
|
209
|
+
rails.render_ga_js = :development
|
210
|
+
result.should be == false
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
context "with rails_config.render_ga_ja = Array of symbols" do
|
215
|
+
it "compares with given environment", env: :production do
|
216
|
+
rails.render_ga_js = [:production, :test]
|
217
|
+
result.should be == true
|
218
|
+
|
219
|
+
rails.render_ga_js = [:development, :test]
|
220
|
+
result.should be == false
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
context "with rails_config.render_ga_ja = callable object (for interpret_config)" do
|
225
|
+
it "passes it through" do
|
226
|
+
lmbda = ->{}
|
227
|
+
rails.render_ga_js = lmbda
|
228
|
+
result.should be lmbda
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'gaq/controller_facade'
|
2
|
+
|
3
|
+
module Gaq
|
4
|
+
describe ControllerFacade do
|
5
|
+
let(:flash) { Object.new }
|
6
|
+
let(:controller) do
|
7
|
+
Struct.new(:flash).new(flash)
|
8
|
+
end
|
9
|
+
|
10
|
+
subject do
|
11
|
+
described_class.new(controller)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#flash' do
|
15
|
+
it "returns controller's flash" do
|
16
|
+
subject.flash.should be(flash)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#evaluate_config_lambda' do
|
21
|
+
it "calls the lambda, passing controller, returning lambda result" do
|
22
|
+
lmbda = ->(*args) { args }
|
23
|
+
result = subject.evaluate_config_lambda(lmbda)
|
24
|
+
result.should have(1).item
|
25
|
+
result.first.should be(controller)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,510 @@
|
|
1
|
+
require 'gaq/controller_handle'
|
2
|
+
require 'gaq/configuration'
|
3
|
+
require 'gaq/class_cache'
|
4
|
+
|
5
|
+
RSpec::Matchers.define :command_segments do
|
6
|
+
match do |segments|
|
7
|
+
next false unless segments.is_a?(Array) and segments.length >= 1
|
8
|
+
first_segment = segments.first
|
9
|
+
command, tracker = first_segment.split('.', 2).reverse
|
10
|
+
|
11
|
+
(!@first_segment || first_segment == @first_segment) &&
|
12
|
+
(!@tracker_name || tracker.to_s == @tracker_name)
|
13
|
+
end
|
14
|
+
|
15
|
+
chain :starting_with do |first_segment|
|
16
|
+
@first_segment = first_segment
|
17
|
+
end
|
18
|
+
|
19
|
+
chain :for_tracker do |tracker_name|
|
20
|
+
@tracker_name = tracker_name.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
chain :for_default_tracker do
|
24
|
+
@tracker_name = ''
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "custom matcher" do
|
29
|
+
it "detects commands" do
|
30
|
+
[['foo']].should include(command_segments.starting_with('foo'))
|
31
|
+
[['foo']].should_not include(command_segments.starting_with('bar'))
|
32
|
+
[['tracker.foo']].should_not include(command_segments.starting_with('foo'))
|
33
|
+
[['tracker.foo']].should include(command_segments.starting_with('tracker.foo'))
|
34
|
+
|
35
|
+
[['foo']].should include(command_segments.for_default_tracker)
|
36
|
+
[['foo']].should_not include(command_segments.for_tracker('tracker'))
|
37
|
+
[['tracker.foo']].should include(command_segments.for_tracker('tracker'))
|
38
|
+
[['tracker.foo']].should_not include(command_segments.for_default_tracker)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module Gaq
|
43
|
+
describe ControllerHandle do
|
44
|
+
describe "#finalized_commands_as_segments" do
|
45
|
+
# This is more like an integration test. Many things are stubbed by real representatives,
|
46
|
+
# e.g. a real CommandLanguage object (because that's easier).
|
47
|
+
# The purpose of these examples is to assert what commands are rendered and what are
|
48
|
+
# placed in the flash, under different circumstances, namely,
|
49
|
+
# configurations and relevant data initially found in flash.
|
50
|
+
|
51
|
+
# Assertions are made against
|
52
|
+
# * #finalized_commands_as_segments results (see let(:result)) and
|
53
|
+
# * commands_pushed_to_flash
|
54
|
+
# Initial flash input is placed in
|
55
|
+
# * commands_from_flash
|
56
|
+
# For test convenience, all three use the same format, namely an array of commands
|
57
|
+
# represented as command segments. The language is used for the necessary conversion.
|
58
|
+
# Emptiness of commands_pushed_to_flash is automatically asserted unless the
|
59
|
+
# push_to_flash: true metadata is present.
|
60
|
+
|
61
|
+
# The result array is implicitly checked to comply to certain ordering assumptions (fex.
|
62
|
+
# a tracker must be initialized with _setAccount before anything else is done with it).
|
63
|
+
# See let(:result) for details.
|
64
|
+
|
65
|
+
let(:stubbed_controller_facade) { double "controller facade" }
|
66
|
+
|
67
|
+
let(:stubbed_language) do
|
68
|
+
# we use the actual implementation, given that this spec is at the highest level of all
|
69
|
+
result = CommandLanguage.new
|
70
|
+
CommandLanguage.declare_language_on(result)
|
71
|
+
CommandLanguage.define_transformations_on(result)
|
72
|
+
result
|
73
|
+
end
|
74
|
+
|
75
|
+
let(:stubbed_configuration) do
|
76
|
+
Configuration.new
|
77
|
+
end
|
78
|
+
|
79
|
+
# convenience. think "config.gaq", so rails_config.track_event would be config.gaq.track_event in the real world
|
80
|
+
let(:rails_config) { stubbed_configuration.rails_config }
|
81
|
+
|
82
|
+
let(:commands_from_flash) { [] }
|
83
|
+
let(:commands_pushed_to_flash) { [] }
|
84
|
+
|
85
|
+
let(:stubbed_flash_commands_adapter) do
|
86
|
+
result = double("flash_commands_adapter")
|
87
|
+
|
88
|
+
# for test convenience, convert between plain "segments" arrays and proper command objects
|
89
|
+
# this depends on features from language
|
90
|
+
|
91
|
+
result.stub(:commands_from_flash) do
|
92
|
+
stubbed_language.commands_from_flash_items(commands_from_flash)
|
93
|
+
end
|
94
|
+
|
95
|
+
result.stub(:<<) do |item|
|
96
|
+
item = stubbed_language.commands_to_flash_items([item]).first
|
97
|
+
commands_pushed_to_flash << item
|
98
|
+
end
|
99
|
+
|
100
|
+
result
|
101
|
+
end
|
102
|
+
|
103
|
+
after do
|
104
|
+
# automatically assert that nothing got pushed to flash storage unless metadata tagged
|
105
|
+
commands_pushed_to_flash.should be_empty \
|
106
|
+
unless example.metadata[:push_to_flash]
|
107
|
+
end
|
108
|
+
|
109
|
+
subject do
|
110
|
+
described_class.new(stubbed_controller_facade, stubbed_language, ClassCache.new, stubbed_configuration).tap do |result|
|
111
|
+
result.flash_commands_adapter = stubbed_flash_commands_adapter
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
let(:result) do
|
116
|
+
subject.finalized_commands_as_segments
|
117
|
+
end
|
118
|
+
|
119
|
+
let(:order_asserter_class) do
|
120
|
+
# We need to do a bunch of assertions that are hard to express in rspec proper.
|
121
|
+
# This class does the heavy lifting. It is tested below!
|
122
|
+
Class.new do
|
123
|
+
def initialize(result, context)
|
124
|
+
@result = result
|
125
|
+
@context = context
|
126
|
+
end
|
127
|
+
|
128
|
+
def do_the_assertions
|
129
|
+
## overall order assumptions
|
130
|
+
|
131
|
+
# renders _gat._anonymizeIp before any _trackPageview, _setCustomVar or _trackEvent"
|
132
|
+
any_occurrence_of('_anonymizeIp').should \
|
133
|
+
precede(any_occurrence_of('_trackPageview'))
|
134
|
+
any_occurrence_of('_anonymizeIp').should \
|
135
|
+
precede(any_occurrence_of('_setCustomVar'))
|
136
|
+
any_occurrence_of('_anonymizeIp').should \
|
137
|
+
precede(any_occurrence_of('_trackEvent'))
|
138
|
+
|
139
|
+
## per tracker order assumptions
|
140
|
+
|
141
|
+
# it rendes _setAccount before _trackPageview, _setCustomVar or _trackEvent
|
142
|
+
tracker_occurrences_of('_setAccount').should \
|
143
|
+
precede(tracker_occurrences_of('_trackPageview'))
|
144
|
+
tracker_occurrences_of('_setAccount').should \
|
145
|
+
precede(tracker_occurrences_of('_setCustomVar'))
|
146
|
+
tracker_occurrences_of('_setAccount').should \
|
147
|
+
precede(tracker_occurrences_of('_trackEvent'))
|
148
|
+
|
149
|
+
# it renders _setCustomVar before _trackEvent
|
150
|
+
tracker_occurrences_of('_setCustomVar').should \
|
151
|
+
precede(tracker_occurrences_of('_trackEvent'))
|
152
|
+
end
|
153
|
+
|
154
|
+
def self_test
|
155
|
+
@result = [
|
156
|
+
['cmd1'], ['cmd2'], ['tracker.cmd1'], ['tracker.cmd2'],
|
157
|
+
['cmd3'], ['cmd4'], ['tracker.cmd5']
|
158
|
+
]
|
159
|
+
|
160
|
+
tracker_occurrences_of('cmd1').should \
|
161
|
+
precede(tracker_occurrences_of('cmd2'))
|
162
|
+
|
163
|
+
tracker_occurrences_of('cmd2').should_not \
|
164
|
+
precede(tracker_occurrences_of('cmd1'))
|
165
|
+
|
166
|
+
any_occurrence_of('cmd3').should \
|
167
|
+
precede(any_occurrence_of('cmd4'))
|
168
|
+
|
169
|
+
any_occurrence_of('cmd4').should_not \
|
170
|
+
precede(any_occurrence_of('cmd3'))
|
171
|
+
|
172
|
+
any_occurrence_of('cmd3').should \
|
173
|
+
precede(any_occurrence_of('cmd5'))
|
174
|
+
|
175
|
+
any_occurrence_of('cmd5').should_not \
|
176
|
+
precede(any_occurrence_of('cmd3'))
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
def precede(following)
|
182
|
+
@context.satisfy do |preceding|
|
183
|
+
preceding.all? do |tracker_name, indices|
|
184
|
+
following_indices = following[tracker_name]
|
185
|
+
[*indices, -1].max < [*following_indices, 2**31].min
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def tracker_occurrences_of(command_name)
|
191
|
+
command_occurrences_with_matching_tracker_name(command_name) do |tracker_name|
|
192
|
+
tracker_name != :any
|
193
|
+
end
|
194
|
+
# preprocessed_result[command_name].select { |tracker_name, _| tracker_name != :any }
|
195
|
+
end
|
196
|
+
|
197
|
+
def any_occurrence_of(command_name)
|
198
|
+
command_occurrences_with_matching_tracker_name(command_name) do |tracker_name|
|
199
|
+
tracker_name == :any
|
200
|
+
end
|
201
|
+
# preprocessed_result[command_name].select { |tracker_name, _| tracker_name == :any }
|
202
|
+
end
|
203
|
+
|
204
|
+
def command_occurrences_with_matching_tracker_name(command_name)
|
205
|
+
analyzed_result[command_name].select { |tracker_name, _| yield tracker_name }
|
206
|
+
end
|
207
|
+
|
208
|
+
def analyzed_result
|
209
|
+
ar = Hash.new do |hash, command_name|
|
210
|
+
hash[command_name] = Hash.new { |h, tracker_name| h[tracker_name] = [] }
|
211
|
+
end
|
212
|
+
|
213
|
+
@result.map(&:first).each_with_index do |first_segment, index|
|
214
|
+
command_name, tracker_name = first_segment.split('.', 2).reverse
|
215
|
+
|
216
|
+
per_command = ar[command_name]
|
217
|
+
per_command[tracker_name] << index
|
218
|
+
per_command[:any] << index
|
219
|
+
end
|
220
|
+
|
221
|
+
ar
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "order asserter mechanism" do
|
227
|
+
# the order_asserter_class does heavy lifting and deserves being tested!
|
228
|
+
|
229
|
+
it "does what we expect" do
|
230
|
+
order_asserter_class.new(nil, self).self_test
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
after do
|
235
|
+
# automatically assert order assumptions for each example
|
236
|
+
order_asserter_class.new(result, self).do_the_assertions
|
237
|
+
# this way we don't forget.
|
238
|
+
end
|
239
|
+
|
240
|
+
let(:root_target) { subject.root_target }
|
241
|
+
|
242
|
+
shared_context declare_var: true do
|
243
|
+
before do
|
244
|
+
rails_config.declare_variable :var, scope: 3, slot: 0
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
context "without further configuration" do
|
249
|
+
it "returns _setAccount (unset wpi) and _trackPageview for default tracker" do
|
250
|
+
result.should have(2).items
|
251
|
+
result.should include(["_setAccount", "UA-XUNSET-S"])
|
252
|
+
result.should include(["_trackPageview"])
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
context "with config.gaq.anonymize_ip = true" do
|
257
|
+
before do
|
258
|
+
rails_config.anonymize_ip = true
|
259
|
+
end
|
260
|
+
|
261
|
+
it "renders '_gat._anonymizeIp" do
|
262
|
+
result.should include(["_gat._anonymizeIp"])
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
describe "default tracker configuration effect" do
|
267
|
+
before do
|
268
|
+
rails_config.web_property_id = 'UA-TEST23-5'
|
269
|
+
end
|
270
|
+
|
271
|
+
it "renders a correct _setAccount" do
|
272
|
+
result.should include(["_setAccount", 'UA-TEST23-5'])
|
273
|
+
end
|
274
|
+
|
275
|
+
it "renders a _trackPageview by default" do
|
276
|
+
result.should include(["_trackPageview"])
|
277
|
+
end
|
278
|
+
|
279
|
+
context "config.gaq.track_pageview = false" do
|
280
|
+
before do
|
281
|
+
rails_config.track_pageview = false
|
282
|
+
end
|
283
|
+
|
284
|
+
it "does not render anything for default tracker", pending: true do
|
285
|
+
# Currently, the default tracker _setAccount is always rendered.
|
286
|
+
# I'm undecided about that.
|
287
|
+
# If the implementation stays this way, I should assert
|
288
|
+
# _setAccount presence here instead.
|
289
|
+
result.should_not include command_segments.for_default_tracker
|
290
|
+
end
|
291
|
+
|
292
|
+
context "with a tracker command" do
|
293
|
+
before do
|
294
|
+
# this is really an arbitrary tracker command.
|
295
|
+
root_target.track_event 'category', 'action', 'label'
|
296
|
+
end
|
297
|
+
|
298
|
+
it "renders the _setAccount, but not a _trackPageview" do
|
299
|
+
result.should include(["_setAccount", 'UA-TEST23-5'])
|
300
|
+
result.should_not include(command_segments.starting_with('_trackPageview'))
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
describe "effect of tracker commands issued on default tracker" do
|
307
|
+
describe "gaq.track_event 'category', 'action', 'label'" do
|
308
|
+
before do
|
309
|
+
root_target.track_event 'category', 'action', 'label'
|
310
|
+
end
|
311
|
+
|
312
|
+
it "renders the _trackEvent" do
|
313
|
+
result.should include(["_trackEvent", "category", "action", "label"])
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
# more here when implemented...
|
318
|
+
end
|
319
|
+
|
320
|
+
describe "effect of tracker commands issued on default tracker .next_request" do
|
321
|
+
context "gaq.next_request.track_event 'category', 'action', 'label'", push_to_flash: true do
|
322
|
+
before do
|
323
|
+
root_target.next_request.track_event 'category', 'action', 'label'
|
324
|
+
end
|
325
|
+
|
326
|
+
it "does not render the _trackEvent" do
|
327
|
+
result.should_not include command_segments.starting_with('_trackEvent')
|
328
|
+
end
|
329
|
+
|
330
|
+
it "pushes the _trackEvent to flash storage" do
|
331
|
+
commands_pushed_to_flash.should be == [
|
332
|
+
["_trackEvent", "category", "action", "label"]
|
333
|
+
]
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
# more here when implemented...
|
338
|
+
end
|
339
|
+
|
340
|
+
context "with a variable declared", declare_var: true do
|
341
|
+
it "returns nothing in addition" do
|
342
|
+
result.should have(2).items
|
343
|
+
result.should include(["_setAccount", "UA-XUNSET-S"])
|
344
|
+
result.should include(["_trackPageview"])
|
345
|
+
end
|
346
|
+
|
347
|
+
context "after assigning to variable" do
|
348
|
+
before do
|
349
|
+
root_target.var = "blah"
|
350
|
+
end
|
351
|
+
|
352
|
+
it "renders the _setCustomVar" do
|
353
|
+
result.should include(["_setCustomVar", 0, "var", "blah", 3])
|
354
|
+
end
|
355
|
+
|
356
|
+
context "gaq.track_event 'category', 'action', 'label'" do
|
357
|
+
before(:each) do
|
358
|
+
root_target.track_event 'category', 'action', 'label'
|
359
|
+
end
|
360
|
+
|
361
|
+
it "renders the _trackEvent in addition, maintaining correct order" do
|
362
|
+
# order assertion is not here, see preamble.
|
363
|
+
result.should include(["_setCustomVar", 0, "var", "blah", 3])
|
364
|
+
result.should include(["_trackEvent", "category", "action", "label"])
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
context "after assigning to variable on gaq.next_request", push_to_flash: true do
|
370
|
+
before do
|
371
|
+
root_target.next_request.var = "blah"
|
372
|
+
end
|
373
|
+
|
374
|
+
it "does not render a _setCustomVar" do
|
375
|
+
result.should_not include(command_segments.starting_with('_setCustomVar'))
|
376
|
+
end
|
377
|
+
|
378
|
+
it "pushes the _setCustomVar onto the flash storage" do
|
379
|
+
commands_pushed_to_flash.should be == [
|
380
|
+
["_setCustomVar", 0, "var", "blah", 3]
|
381
|
+
]
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
context "with commands stored in flash" do
|
387
|
+
before do
|
388
|
+
commands_from_flash << ["_trackEvent", "last_cat", "last_action", "last_label"]
|
389
|
+
commands_from_flash << ["_setCustomVar", 0, "var", "blah", 3]
|
390
|
+
end
|
391
|
+
|
392
|
+
it "renders these" do
|
393
|
+
result.should include(["_setCustomVar", 0, "var", "blah", 3])
|
394
|
+
result.should include(["_trackEvent", "last_cat", "last_action", "last_label"])
|
395
|
+
end
|
396
|
+
|
397
|
+
context "gaq.next_request.track_event 'category', 'action', 'label'", push_to_flash: true do
|
398
|
+
before(:each) do
|
399
|
+
root_target.next_request.track_event 'category', 'action', 'label'
|
400
|
+
end
|
401
|
+
|
402
|
+
it "does not render that in addition" do
|
403
|
+
result.should_not include(["_trackEvent", "category", "action", "label"])
|
404
|
+
end
|
405
|
+
|
406
|
+
it "pushes that on the flash store instead" do
|
407
|
+
commands_pushed_to_flash.should be == [
|
408
|
+
["_trackEvent", "category", "action", "label"]
|
409
|
+
]
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
context "with a variable declared", declare_var: true do
|
414
|
+
context "after assigning to same variable again" do
|
415
|
+
before do
|
416
|
+
root_target.var = "blubb"
|
417
|
+
end
|
418
|
+
|
419
|
+
it "renders both _setCustomVar, in order" do
|
420
|
+
first_set_custom_var = ["_setCustomVar", 0, "var", "blah", 3]
|
421
|
+
second_set_custom_var = ["_setCustomVar", 0, "var", "blubb", 3]
|
422
|
+
|
423
|
+
result.should include(first_set_custom_var)
|
424
|
+
result.should include(second_set_custom_var)
|
425
|
+
result.index(first_set_custom_var).should be <
|
426
|
+
result.index(second_set_custom_var)
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
context "with a custom tracker" do
|
434
|
+
before do
|
435
|
+
rails_config.additional_trackers = ["foo"]
|
436
|
+
end
|
437
|
+
|
438
|
+
context "configured not to track pageviews" do
|
439
|
+
before do
|
440
|
+
rails_config.tracker(:foo).track_pageview = false
|
441
|
+
end
|
442
|
+
|
443
|
+
it "does not render any command for the additional tracker" do
|
444
|
+
result.should_not include(command_segments.for_tracker('foo'))
|
445
|
+
end
|
446
|
+
|
447
|
+
context "after gaq[:foo].track_event 'category', 'action', 'label'" do
|
448
|
+
before do
|
449
|
+
root_target["foo"].track_event 'category', 'action', 'label'
|
450
|
+
end
|
451
|
+
|
452
|
+
it "renders the proper _setAccount" do
|
453
|
+
result.should include(["foo._setAccount", "UA-XUNSET-S"])
|
454
|
+
end
|
455
|
+
|
456
|
+
it "does not render a _trackPageview for the tracker" do
|
457
|
+
result.should_not include(["foo._trackPageview"])
|
458
|
+
end
|
459
|
+
|
460
|
+
it "renders the _trackEvent" do
|
461
|
+
result.should include(["foo._trackEvent", "category", "action", "label"])
|
462
|
+
end
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
466
|
+
it "renders a _setAccount for the additional tracker" do
|
467
|
+
result.should include(['foo._setAccount', "UA-XUNSET-S"])
|
468
|
+
end
|
469
|
+
|
470
|
+
it "renders a _trackPageview for the tracker" do
|
471
|
+
result.should include(["foo._trackPageview"])
|
472
|
+
end
|
473
|
+
|
474
|
+
context "after gaq[:foo].track_event 'category', 'action', 'label'" do
|
475
|
+
before do
|
476
|
+
root_target["foo"].track_event 'category', 'action', 'label'
|
477
|
+
end
|
478
|
+
|
479
|
+
it "renders a _setAccount for the additional tracker" do
|
480
|
+
result.should include(['foo._setAccount', "UA-XUNSET-S"])
|
481
|
+
end
|
482
|
+
|
483
|
+
it "renders a _trackPageview for the tracker" do
|
484
|
+
result.should include(["foo._trackPageview"])
|
485
|
+
end
|
486
|
+
|
487
|
+
it "renders the _trackEvent" do
|
488
|
+
result.should include(["foo._trackEvent", "category", "action", "label"])
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
it "fails when an undeclared tracker is accessed from a target like gaq[:bogus]" do
|
494
|
+
expect {
|
495
|
+
root_target[:bogus]
|
496
|
+
}.to raise_exception
|
497
|
+
end
|
498
|
+
|
499
|
+
context "with commands stored in flash referencing a nonexistend tracker" do
|
500
|
+
before do
|
501
|
+
commands_from_flash << ["nonexistent._trackEvent", "last_cat", "last_action", "last_label"]
|
502
|
+
end
|
503
|
+
|
504
|
+
it "does not raise an exception" do
|
505
|
+
result
|
506
|
+
end
|
507
|
+
end
|
508
|
+
end
|
509
|
+
end
|
510
|
+
end
|