gaq 0.2.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.
- 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
|