redis_analytics 0.1.0 → 0.6.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/CHANGELOG.md +12 -0
- data/CONTRIBUTING.md +33 -0
- data/Guardfile +10 -0
- data/README.md +105 -23
- data/Rakefile +3 -11
- data/TODO.md +12 -0
- data/bin/redis_analytics_dashboard +1 -1
- data/config.ru +13 -0
- data/lib/redis_analytics.rb +5 -1
- data/lib/redis_analytics/analytics.rb +17 -203
- data/lib/redis_analytics/api.rb +60 -0
- data/lib/redis_analytics/configuration.rb +47 -16
- data/lib/redis_analytics/dashboard.rb +28 -89
- data/lib/redis_analytics/dashboard/public/{favicon.ico → img/favicon.ico} +0 -0
- data/lib/redis_analytics/dashboard/public/javascripts/{bootstrap.min.js → vendor/bootstrap/bootstrap.min.js} +0 -0
- data/lib/redis_analytics/dashboard/public/javascripts/{jquery-1.9.1.min.js → vendor/jquery-1.9.1.min.js} +0 -0
- data/lib/redis_analytics/dashboard/public/javascripts/{jquery-jvectormap-1.2.2.min.js → vendor/jquery-jvectormap-1.2.2.min.js} +0 -0
- data/lib/redis_analytics/dashboard/public/javascripts/{jquery-jvectormap-world-mill-en.js → vendor/jquery-jvectormap-world-mill-en.js} +0 -0
- data/lib/redis_analytics/dashboard/public/javascripts/{morris.min.js → vendor/morris.min.js} +0 -0
- data/lib/redis_analytics/dashboard/public/javascripts/{raphael-min.js → vendor/raphael-min.js} +0 -0
- data/lib/redis_analytics/dashboard/views/activity.erb +7 -0
- data/lib/redis_analytics/dashboard/views/dialogs/unique_visits.erb +41 -0
- data/lib/redis_analytics/dashboard/views/dialogs/visits.erb +40 -0
- data/lib/redis_analytics/dashboard/views/footer.erb +1 -3
- data/lib/redis_analytics/dashboard/views/header.erb +17 -42
- data/lib/redis_analytics/dashboard/views/layout.erb +5 -22
- data/lib/redis_analytics/dashboard/views/visits.erb +38 -143
- data/lib/redis_analytics/dashboard/views/visits_js.erb +110 -247
- data/lib/redis_analytics/dashboard/views/widgets/bounce_rate.erb +3 -0
- data/lib/redis_analytics/dashboard/views/widgets/browsers_donut.erb +8 -0
- data/lib/redis_analytics/dashboard/views/widgets/first_visits.erb +3 -0
- data/lib/redis_analytics/dashboard/views/widgets/page_depth.erb +3 -0
- data/lib/redis_analytics/dashboard/views/widgets/referers_donut.erb +8 -0
- data/lib/redis_analytics/dashboard/views/widgets/total_page_views.erb +3 -0
- data/lib/redis_analytics/dashboard/views/widgets/total_visits.erb +3 -0
- data/lib/redis_analytics/dashboard/views/widgets/unique_visits_line.erb +26 -0
- data/lib/redis_analytics/dashboard/views/widgets/visit_duration.erb +3 -0
- data/lib/redis_analytics/dashboard/views/widgets/visit_spark.erb +23 -0
- data/lib/redis_analytics/dashboard/views/widgets/visitor_recency_slices.erb +39 -0
- data/lib/redis_analytics/dashboard/views/widgets/visits_area.erb +30 -0
- data/lib/redis_analytics/dashboard/views/widgets/visits_donut.erb +8 -0
- data/lib/redis_analytics/dashboard/views/widgets/world_map.erb +50 -0
- data/lib/redis_analytics/filter.rb +33 -0
- data/lib/redis_analytics/helpers.rb +36 -30
- data/lib/redis_analytics/metrics.rb +96 -0
- data/lib/redis_analytics/time_ext.rb +72 -2
- data/lib/redis_analytics/tracker.rb +13 -5
- data/lib/redis_analytics/version.rb +1 -1
- data/lib/redis_analytics/visit.rb +122 -0
- data/redis_analytics.gemspec +19 -14
- data/spec/lib/redis_analytics/analytics_spec.rb +59 -0
- data/spec/lib/redis_analytics/configuration_spec.rb +158 -0
- data/spec/lib/redis_analytics/dashboard_spec.rb +32 -0
- data/spec/lib/redis_analytics/filter_spec.rb +34 -0
- data/spec/lib/redis_analytics/tracker_spec.rb +20 -0
- data/spec/spec_helper.rb +13 -6
- data/spec/support/fakeredis.rb +1 -0
- data/wsd.png +0 -0
- metadata +268 -126
- data/lib/redis_analytics/config.ru +0 -10
- data/spec/redis_analytics_spec.rb +0 -57
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'date'
|
1
2
|
module TimeExtensions
|
2
3
|
%w[ round floor ceil ].each do |_method|
|
3
4
|
define_method _method do |*args|
|
@@ -6,14 +7,83 @@ module TimeExtensions
|
|
6
7
|
end
|
7
8
|
end
|
8
9
|
|
10
|
+
def end_of_year
|
11
|
+
Time.local(self.year, 12, 31, 23, 59, 59)
|
12
|
+
end
|
13
|
+
|
14
|
+
def beginning_of_year
|
15
|
+
Time.local(self.year, 1, 1, 0, 0, 0)
|
16
|
+
end
|
17
|
+
|
18
|
+
def end_of_month
|
19
|
+
Time.local(self.year, self.mon + 1, 1, 23, 59, 59) - 1.day
|
20
|
+
end
|
21
|
+
|
22
|
+
def beginning_of_month
|
23
|
+
Date.civil(self.year, self.mon, -1).to_time
|
24
|
+
end
|
25
|
+
|
26
|
+
def beginning_of_day
|
27
|
+
Time.local(self.year, self.mon, self.day, 0, 0, 0)
|
28
|
+
end
|
29
|
+
|
30
|
+
def end_of_day
|
31
|
+
Time.local(self.year, self.mon, self.day, 23, 59, 59)
|
32
|
+
end
|
33
|
+
|
34
|
+
def beginning_of_day
|
35
|
+
Time.local(self.year, self.mon, self.day, 0, 0, 0)
|
36
|
+
end
|
37
|
+
|
38
|
+
def end_of_hour
|
39
|
+
Time.local(self.year, self.mon, self.day, self.hour, 59, 59)
|
40
|
+
end
|
41
|
+
|
42
|
+
def beginning_of_hour
|
43
|
+
Time.local(self.year, self.mon, self.day, self.hour, 0, 0)
|
44
|
+
end
|
45
|
+
|
9
46
|
def end_of_minute
|
10
|
-
|
47
|
+
Time.local(self.year, self.mon, self.day, self.hour, self.min, 59)
|
11
48
|
end
|
12
49
|
|
13
50
|
def beginning_of_minute
|
14
|
-
|
51
|
+
Time.local(self.year, self.mon, self.day, self.hour, self.min, 0)
|
15
52
|
end
|
16
53
|
end
|
17
54
|
|
18
55
|
Time.send :include, TimeExtensions
|
19
56
|
|
57
|
+
module FixnumExtensions
|
58
|
+
|
59
|
+
def minute
|
60
|
+
self * 60
|
61
|
+
end
|
62
|
+
|
63
|
+
def hour
|
64
|
+
minute * 60
|
65
|
+
end
|
66
|
+
|
67
|
+
def day
|
68
|
+
hour * 24
|
69
|
+
end
|
70
|
+
|
71
|
+
def week
|
72
|
+
day * 7
|
73
|
+
end
|
74
|
+
|
75
|
+
def month
|
76
|
+
day * 30
|
77
|
+
end
|
78
|
+
|
79
|
+
def year
|
80
|
+
day * 365
|
81
|
+
end
|
82
|
+
|
83
|
+
def ago(time = Time.now)
|
84
|
+
time - self
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
Fixnum.send :include, FixnumExtensions
|
89
|
+
|
@@ -4,23 +4,31 @@ module Rack
|
|
4
4
|
|
5
5
|
def initialize(app)
|
6
6
|
@app = Rack::Builder.new do
|
7
|
+
|
8
|
+
if defined?(Dashboard) and RedisAnalytics.dashboard_endpoint
|
9
|
+
puts("WARNING: RedisAnalytics.dashboard_endpoint is set as \"/\"") if RedisAnalytics.dashboard_endpoint == '/'
|
10
|
+
map RedisAnalytics.dashboard_endpoint do
|
11
|
+
run Dashboard.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
7
15
|
map '/' do
|
8
16
|
run Analytics.new(app)
|
9
17
|
end
|
10
18
|
|
11
|
-
if defined?
|
12
|
-
map RedisAnalytics.
|
13
|
-
run
|
19
|
+
if defined?(Api) and RedisAnalytics.api_endpoint
|
20
|
+
map RedisAnalytics.api_endpoint do
|
21
|
+
run Api.new
|
14
22
|
end
|
15
23
|
end
|
24
|
+
|
16
25
|
end
|
17
26
|
end
|
18
27
|
|
19
28
|
def call(env)
|
20
29
|
@app.call(env)
|
21
30
|
end
|
22
|
-
|
31
|
+
|
23
32
|
end
|
24
33
|
end
|
25
34
|
end
|
26
|
-
|
@@ -0,0 +1,122 @@
|
|
1
|
+
module Rack
|
2
|
+
module RedisAnalytics
|
3
|
+
class Visit
|
4
|
+
include Metrics
|
5
|
+
|
6
|
+
# This class represents one unique visit
|
7
|
+
# User may have never visited the site
|
8
|
+
# User may have visited before but his visit is expired
|
9
|
+
# Everything counted here is unique for a visit
|
10
|
+
|
11
|
+
# helpers
|
12
|
+
def for_each_time_range(t)
|
13
|
+
RedisAnalytics.redis_key_timestamps.map{|x, y| t.strftime(x)}.each do |ts|
|
14
|
+
yield(ts)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def first_visit_info
|
19
|
+
cookie = @rack_request.cookies[RedisAnalytics.first_visit_cookie_name]
|
20
|
+
return cookie ? cookie.split('.') : []
|
21
|
+
end
|
22
|
+
|
23
|
+
def current_visit_info
|
24
|
+
cookie = @rack_request.cookies[RedisAnalytics.current_visit_cookie_name]
|
25
|
+
return cookie ? cookie.split('.') : []
|
26
|
+
end
|
27
|
+
|
28
|
+
# method used in analytics.rb to initialize visit
|
29
|
+
def initialize(request, response)
|
30
|
+
@t = Time.now
|
31
|
+
@redis_key_prefix = "#{RedisAnalytics.redis_namespace}:"
|
32
|
+
@rack_request = request
|
33
|
+
@rack_response = response
|
34
|
+
@first_visit_seq = first_visit_info[0] || current_visit_info[0]
|
35
|
+
@current_visit_seq = current_visit_info[1]
|
36
|
+
|
37
|
+
@first_visit_time = first_visit_info[1]
|
38
|
+
@last_visit_time = first_visit_info[2]
|
39
|
+
|
40
|
+
@page_view_seq_no = current_visit_info[2] || 0
|
41
|
+
@last_visit_start_time = current_visit_info[3]
|
42
|
+
@last_visit_end_time = current_visit_info[4]
|
43
|
+
end
|
44
|
+
|
45
|
+
# called from analytics.rb
|
46
|
+
def record
|
47
|
+
if @current_visit_seq
|
48
|
+
track("visit_time", @t.to_i - @last_visit_end_time.to_i)
|
49
|
+
else
|
50
|
+
@current_visit_seq ||= counter("visits")
|
51
|
+
track("visits", 1) # track core 'visit' metric
|
52
|
+
if @first_visit_seq
|
53
|
+
track("repeat_visits", 1)
|
54
|
+
else
|
55
|
+
@first_visit_seq ||= counter("unique_visits")
|
56
|
+
track("first_visits", 1)
|
57
|
+
track("unique_visits", @first_visit_seq)
|
58
|
+
end
|
59
|
+
exec_custom_methods('visit') # custom methods that are measured on a per-visit basis
|
60
|
+
end
|
61
|
+
exec_custom_methods('hit') # custom methods that are measured on a per-page-view (per-hit) basis
|
62
|
+
track("page_views", 1) # track core 'page_view' metric
|
63
|
+
track("second_page_views", 1) if @page_view_seq_no.to_i == 1 # @last_visit_start_time and (@last_visit_start_time.to_i == @last_visit_end_time.to_i)
|
64
|
+
@rack_response
|
65
|
+
end
|
66
|
+
|
67
|
+
def exec_custom_methods(type)
|
68
|
+
Metrics.public_instance_methods.each do |meth|
|
69
|
+
if m = meth.to_s.match(/^([a-z_]*)_(count|ratio)_per_#{type}$/)
|
70
|
+
begin
|
71
|
+
return_value = self.send(meth)
|
72
|
+
track(m.to_a[1], return_value) if return_value
|
73
|
+
rescue => e
|
74
|
+
warn "#{meth} resulted in an exception #{e}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# helpers
|
81
|
+
def counter(metric_name)
|
82
|
+
n = RedisAnalytics.redis_connection.incr("#{@redis_key_prefix}#{metric_name}")
|
83
|
+
# to debug, uncomment this line
|
84
|
+
# puts "COUNT #{metric_name} -> #{n}"
|
85
|
+
return n
|
86
|
+
end
|
87
|
+
|
88
|
+
def updated_current_visit_info
|
89
|
+
value = [@first_visit_seq.to_i, @current_visit_seq.to_i, @page_view_seq_no.to_i + 1, (@last_visit_start_time || @t).to_i, @t.to_i]
|
90
|
+
# to debug, uncomment this line
|
91
|
+
# puts "UPDATING VCN COOKIE -> #{value}"
|
92
|
+
expires = @t + (RedisAnalytics.visit_timeout.to_i * 60)
|
93
|
+
{:value => value.join('.'), :expires => expires}
|
94
|
+
end
|
95
|
+
|
96
|
+
def updated_first_visit_info
|
97
|
+
value = [@first_visit_seq.to_i, (@first_visit_time || @t).to_i, @t.to_i]
|
98
|
+
# to debug, uncomment this line
|
99
|
+
# puts "UPDATING RUCN COOKIE -> #{value}"
|
100
|
+
expires = @t + (60 * 60 * 24 * 5) # 5 hours
|
101
|
+
{:value => value.join('.'), :expires => expires}
|
102
|
+
end
|
103
|
+
|
104
|
+
def track(metric_name, metric_value)
|
105
|
+
n = 0
|
106
|
+
RedisAnalytics.redis_connection.hmset("#{@redis_key_prefix}#METRICS", metric_name, metric_value.class)
|
107
|
+
for_each_time_range(@t) do |ts|
|
108
|
+
key = "#{@redis_key_prefix}#{metric_name}:#{ts}"
|
109
|
+
if metric_value.is_a?(Fixnum)
|
110
|
+
n = RedisAnalytics.redis_connection.incrby(key, metric_value)
|
111
|
+
else
|
112
|
+
n = RedisAnalytics.redis_connection.zincrby(key, 1, metric_value)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
# to debug, uncomment this line
|
116
|
+
# puts "TRACK #{metric_name} -> #{n}"
|
117
|
+
return n
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
data/redis_analytics.gemspec
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
|
1
2
|
# -*- encoding: utf-8 -*-
|
2
3
|
$:.push File.expand_path("../lib", __FILE__)
|
3
4
|
require 'redis_analytics/version'
|
@@ -5,11 +6,11 @@ require 'redis_analytics/version'
|
|
5
6
|
Gem::Specification.new do |spec|
|
6
7
|
spec.name = "redis_analytics"
|
7
8
|
spec.version = Rack::RedisAnalytics::VERSION
|
8
|
-
spec.date = '
|
9
|
+
spec.date = Time.now.strftime('%Y-%m-%d')
|
9
10
|
spec.authors = ["Schubert Cardozo"]
|
10
11
|
spec.email = ["cardozoschubert@gmail.com"]
|
11
12
|
spec.homepage = "https://github.com/saturnine/redis_analytics"
|
12
|
-
spec.summary = %q{
|
13
|
+
spec.summary = %q{Fast and efficient web analytics for Rack apps}
|
13
14
|
spec.description = %q{A gem that provides a Redis based web analytics solution for your rack-compliant apps. It gives you detailed analytics about visitors, unique visitors, browsers, OS, visitor recency, traffic sources and more}
|
14
15
|
|
15
16
|
spec.rubyforge_project = "redis_analytics"
|
@@ -20,18 +21,22 @@ Gem::Specification.new do |spec|
|
|
20
21
|
spec.default_executable = 'redis_analytics_dashboard'
|
21
22
|
spec.require_paths = ["lib"]
|
22
23
|
|
23
|
-
spec.add_runtime_dependency('rack'
|
24
|
-
spec.add_runtime_dependency('redis'
|
25
|
-
spec.add_runtime_dependency('browser'
|
26
|
-
spec.add_runtime_dependency('sinatra'
|
27
|
-
spec.add_runtime_dependency('
|
28
|
-
spec.add_runtime_dependency('
|
29
|
-
spec.add_runtime_dependency('
|
30
|
-
|
31
|
-
spec.add_development_dependency('
|
32
|
-
spec.add_development_dependency('
|
33
|
-
spec.add_development_dependency('
|
34
|
-
spec.add_development_dependency('
|
24
|
+
spec.add_runtime_dependency('rack')
|
25
|
+
spec.add_runtime_dependency('redis')
|
26
|
+
spec.add_runtime_dependency('browser')
|
27
|
+
spec.add_runtime_dependency('sinatra')
|
28
|
+
spec.add_runtime_dependency('sinatra-assetpack')
|
29
|
+
spec.add_runtime_dependency('geoip')
|
30
|
+
spec.add_runtime_dependency('json')
|
31
|
+
|
32
|
+
spec.add_development_dependency('fakeredis')
|
33
|
+
spec.add_development_dependency('rake')
|
34
|
+
spec.add_development_dependency('rspec')
|
35
|
+
spec.add_development_dependency('guard-rspec')
|
36
|
+
spec.add_development_dependency('mocha')
|
37
|
+
spec.add_development_dependency('rack-test')
|
38
|
+
spec.add_development_dependency('simplecov')
|
39
|
+
spec.add_development_dependency('coveralls')
|
35
40
|
|
36
41
|
spec.required_ruby_version = '>= 1.9.2'
|
37
42
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rack::RedisAnalytics::Analytics do
|
4
|
+
|
5
|
+
subject(:app) {
|
6
|
+
Rack::Builder.app do
|
7
|
+
use Rack::RedisAnalytics::Analytics
|
8
|
+
run Proc.new { |env| [200, {'Content-Type' => 'text/html'}, "Hello!"] }
|
9
|
+
end
|
10
|
+
}
|
11
|
+
|
12
|
+
before(:each) do
|
13
|
+
clear_cookies
|
14
|
+
end
|
15
|
+
|
16
|
+
# Spec for Cookies
|
17
|
+
context "when a user makes 2 visits and the current visit cookie and first visit cookie are not expired" do
|
18
|
+
def cookie
|
19
|
+
last_response.original_headers['Set-Cookie']
|
20
|
+
end
|
21
|
+
it "should count as the same visit in the cookie" do
|
22
|
+
t1 = Time.now
|
23
|
+
Time.stubs(:now).returns(t1)
|
24
|
+
get '/'
|
25
|
+
cookie.should match("#{Rack::RedisAnalytics.current_visit_cookie_name}=1.1.1.#{t1.to_i}.#{t1.to_i}")
|
26
|
+
cookie.should match("#{Rack::RedisAnalytics.first_visit_cookie_name}=1.#{t1.to_i}.#{t1.to_i}")
|
27
|
+
t2 = t1 + 5 # just adding 5 seconds
|
28
|
+
Time.stubs(:now).returns(t2)
|
29
|
+
get '/'
|
30
|
+
cookie.should match("#{Rack::RedisAnalytics.current_visit_cookie_name}=1.1.2.#{t1.to_i}.#{t2.to_i}")
|
31
|
+
cookie.should match("#{Rack::RedisAnalytics.first_visit_cookie_name}=1.#{t1.to_i}.#{t2.to_i}")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "when a user makes 2 visits, but current visit cookie and first visit cookie are both non-existent" do
|
36
|
+
def cookie
|
37
|
+
last_response.original_headers['Set-Cookie']
|
38
|
+
end
|
39
|
+
it "should count as a separate and new visit in the cookie" do
|
40
|
+
t1 = Time.now
|
41
|
+
Time.stubs(:now).returns(t1)
|
42
|
+
get '/'
|
43
|
+
cookie.should match("#{Rack::RedisAnalytics.current_visit_cookie_name}=1.1.1.#{t1.to_i}.#{t1.to_i}")
|
44
|
+
cookie.should match("#{Rack::RedisAnalytics.first_visit_cookie_name}=1.#{t1.to_i}.#{t1.to_i}")
|
45
|
+
clear_cookies
|
46
|
+
|
47
|
+
t2 = t1 + 5 # just adding 5 seconds
|
48
|
+
Time.stubs(:now).returns(t2)
|
49
|
+
get '/'
|
50
|
+
cookie.should match("#{Rack::RedisAnalytics.current_visit_cookie_name}=2.2.1.#{t2.to_i}.#{t2.to_i}")
|
51
|
+
cookie.should match("#{Rack::RedisAnalytics.first_visit_cookie_name}=2.#{t2.to_i}.#{t2.to_i}")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when a user makes 2 visits, and visit cookie is expired but the returning user cookie exists" do
|
56
|
+
it "should count as a separate visit but not a new visit"
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rack::RedisAnalytics::Configuration do
|
4
|
+
|
5
|
+
context 'property redis_connection' do
|
6
|
+
subject(:connection) { Rack::RedisAnalytics.redis_connection }
|
7
|
+
it 'should not be nil' do
|
8
|
+
connection.should_not be_nil
|
9
|
+
end
|
10
|
+
it 'should be an instance of Redis' do
|
11
|
+
connection.instance_of? Redis
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'property redis_namespace' do
|
16
|
+
subject(:namespace) { Rack::RedisAnalytics.redis_namespace }
|
17
|
+
it 'should not be nil' do
|
18
|
+
namespace.should_not be_nil
|
19
|
+
end
|
20
|
+
it 'should have an default value' do
|
21
|
+
namespace.should be == "_ra_test_namespace"
|
22
|
+
end
|
23
|
+
it 'can be set to another value' do
|
24
|
+
namespace = "test_ra"
|
25
|
+
namespace.should be == "test_ra"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'property first_visit_cookie_name' do
|
30
|
+
subject(:return_cookie) { Rack::RedisAnalytics.first_visit_cookie_name }
|
31
|
+
it 'should not be nil' do
|
32
|
+
return_cookie.should_not be_nil
|
33
|
+
end
|
34
|
+
it 'should have an default value' do
|
35
|
+
return_cookie.should be == "_rucn"
|
36
|
+
end
|
37
|
+
it 'has an setter method' do
|
38
|
+
return_cookie = "rucn"
|
39
|
+
return_cookie.should be == "rucn"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'property current_visit_cookie_name' do
|
44
|
+
subject(:current_visit_cookie_name) { Rack::RedisAnalytics.current_visit_cookie_name }
|
45
|
+
it 'should not be nil' do
|
46
|
+
current_visit_cookie_name.should_not be_nil
|
47
|
+
end
|
48
|
+
it 'should have an default value' do
|
49
|
+
current_visit_cookie_name.should be == "_vcn"
|
50
|
+
end
|
51
|
+
it 'can be set to another value' do
|
52
|
+
current_visit_cookie_name = "test_vcn"
|
53
|
+
current_visit_cookie_name.should be == "test_vcn"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'property visit_timeout' do
|
58
|
+
subject(:visit_timeout) { Rack::RedisAnalytics.visit_timeout }
|
59
|
+
it 'should not be nil' do
|
60
|
+
visit_timeout.should_not be_nil
|
61
|
+
end
|
62
|
+
it 'should have an default value' do
|
63
|
+
visit_timeout.should be == 1
|
64
|
+
end
|
65
|
+
it 'can be set to another value' do
|
66
|
+
visit_timeout = 5
|
67
|
+
visit_timeout.should be == 5
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'property visitor_recency_slices' do
|
72
|
+
subject(:visitor_recency_slices) { Rack::RedisAnalytics.visitor_recency_slices }
|
73
|
+
it 'should not be nil' do
|
74
|
+
visitor_recency_slices.should_not be_nil
|
75
|
+
end
|
76
|
+
it 'should be an Array of Fixnum' do
|
77
|
+
visitor_recency_slices.instance_of? Array
|
78
|
+
visitor_recency_slices.each do |value|
|
79
|
+
value.instance_of? Fixnum
|
80
|
+
end
|
81
|
+
end
|
82
|
+
it 'can be set to another value' do
|
83
|
+
visitor_recency_slices = [3, 7, 9]
|
84
|
+
expect(visitor_recency_slices).to eq([3, 7, 9])
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'property default_range' do
|
89
|
+
subject(:default_range) { Rack::RedisAnalytics.default_range }
|
90
|
+
it 'should not be nil' do
|
91
|
+
default_range.should_not be_nil
|
92
|
+
end
|
93
|
+
it 'should be an symbol' do
|
94
|
+
default_range.instance_of? Symbol
|
95
|
+
end
|
96
|
+
it 'should have an value' do
|
97
|
+
default_range.should be == :day
|
98
|
+
end
|
99
|
+
it 'can be set to another value' do
|
100
|
+
default_range = :month
|
101
|
+
default_range.should be :month
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'property redis_key_timestamps' do
|
106
|
+
subject(:redis_key_timestamps) { Rack::RedisAnalytics.redis_key_timestamps }
|
107
|
+
it 'should not be nil' do
|
108
|
+
redis_key_timestamps.should_not be_nil
|
109
|
+
end
|
110
|
+
it 'should be an instance of Array' do
|
111
|
+
redis_key_timestamps.instance_of? Array
|
112
|
+
end
|
113
|
+
it 'can be set to another value' do
|
114
|
+
redis_key_timestamps = ['one', 'two']
|
115
|
+
expect(redis_key_timestamps).to eq(['one','two'])
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'property time_range_formats' do
|
120
|
+
subject(:time_range_formats) { Rack::RedisAnalytics.time_range_formats }
|
121
|
+
it 'should not be nil' do
|
122
|
+
time_range_formats.should_not be_nil
|
123
|
+
end
|
124
|
+
it 'should be an Array of Array' do
|
125
|
+
time_range_formats.instance_of? Array
|
126
|
+
time_range_formats.each do |range|
|
127
|
+
range.instance_of? Array
|
128
|
+
end
|
129
|
+
end
|
130
|
+
it 'can be set to another value' do
|
131
|
+
time_range_formats = "nothing"
|
132
|
+
expect(time_range_formats).to eq("nothing")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'method add_filter' do
|
137
|
+
subject(:filters) { Rack::RedisAnalytics.filters }
|
138
|
+
it 'should add a new filter' do
|
139
|
+
proc = Proc.new {}
|
140
|
+
Rack::RedisAnalytics.configure do |c|
|
141
|
+
c.add_filter(&proc)
|
142
|
+
end
|
143
|
+
filters[0].should be_an_instance_of Rack::RedisAnalytics::Filter
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'method add_path_filter' do
|
148
|
+
subject(:path_filters) { Rack::RedisAnalytics.path_filters }
|
149
|
+
it 'should add a new path filter' do
|
150
|
+
path = '/hello'
|
151
|
+
Rack::RedisAnalytics.configure do |c|
|
152
|
+
c.add_path_filter(path)
|
153
|
+
end
|
154
|
+
path_filters[0].should be_an_instance_of Rack::RedisAnalytics::PathFilter
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|