tupalo-vanity 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/CHANGELOG +243 -0
  2. data/Gemfile +24 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.rdoc +74 -0
  5. data/Rakefile +189 -0
  6. data/bin/vanity +69 -0
  7. data/lib/vanity.rb +36 -0
  8. data/lib/vanity/adapters/abstract_adapter.rb +135 -0
  9. data/lib/vanity/adapters/active_record_adapter.rb +304 -0
  10. data/lib/vanity/adapters/mock_adapter.rb +157 -0
  11. data/lib/vanity/adapters/mongodb_adapter.rb +162 -0
  12. data/lib/vanity/adapters/redis_adapter.rb +154 -0
  13. data/lib/vanity/backport.rb +26 -0
  14. data/lib/vanity/commands/list.rb +21 -0
  15. data/lib/vanity/commands/report.rb +64 -0
  16. data/lib/vanity/commands/upgrade.rb +34 -0
  17. data/lib/vanity/experiment/ab_test.rb +482 -0
  18. data/lib/vanity/experiment/base.rb +212 -0
  19. data/lib/vanity/frameworks/rails.rb +244 -0
  20. data/lib/vanity/helpers.rb +59 -0
  21. data/lib/vanity/metric/active_record.rb +83 -0
  22. data/lib/vanity/metric/base.rb +244 -0
  23. data/lib/vanity/metric/google_analytics.rb +83 -0
  24. data/lib/vanity/metric/remote.rb +53 -0
  25. data/lib/vanity/playground.rb +332 -0
  26. data/lib/vanity/templates/_ab_test.erb +28 -0
  27. data/lib/vanity/templates/_experiment.erb +5 -0
  28. data/lib/vanity/templates/_experiments.erb +7 -0
  29. data/lib/vanity/templates/_metric.erb +14 -0
  30. data/lib/vanity/templates/_metrics.erb +13 -0
  31. data/lib/vanity/templates/_report.erb +27 -0
  32. data/lib/vanity/templates/flot.min.js +1 -0
  33. data/lib/vanity/templates/jquery.min.js +19 -0
  34. data/lib/vanity/templates/vanity.css +26 -0
  35. data/lib/vanity/templates/vanity.js +82 -0
  36. data/lib/vanity/version.rb +11 -0
  37. data/test/experiment/ab_test.rb +700 -0
  38. data/test/experiment/base_test.rb +136 -0
  39. data/test/experiments/age_and_zipcode.rb +19 -0
  40. data/test/experiments/metrics/cheers.rb +3 -0
  41. data/test/experiments/metrics/signups.rb +2 -0
  42. data/test/experiments/metrics/yawns.rb +3 -0
  43. data/test/experiments/null_abc.rb +5 -0
  44. data/test/metric/active_record_test.rb +249 -0
  45. data/test/metric/base_test.rb +293 -0
  46. data/test/metric/google_analytics_test.rb +104 -0
  47. data/test/metric/remote_test.rb +108 -0
  48. data/test/myapp/app/controllers/application_controller.rb +2 -0
  49. data/test/myapp/app/controllers/main_controller.rb +7 -0
  50. data/test/myapp/config/boot.rb +110 -0
  51. data/test/myapp/config/environment.rb +10 -0
  52. data/test/myapp/config/environments/production.rb +0 -0
  53. data/test/myapp/config/routes.rb +3 -0
  54. data/test/passenger_test.rb +43 -0
  55. data/test/playground_test.rb +10 -0
  56. data/test/rails_test.rb +294 -0
  57. data/test/test_helper.rb +134 -0
  58. data/tupalo-vanity.gemspec +25 -0
  59. metadata +152 -0
@@ -0,0 +1,104 @@
1
+ require "test/test_helper"
2
+
3
+
4
+ context "Google Analytics" do
5
+
6
+ setup do
7
+ File.open "tmp/experiments/metrics/ga.rb", "w" do |f|
8
+ f.write <<-RUBY
9
+ metric "GA" do
10
+ google_analytics "UA2"
11
+ end
12
+ RUBY
13
+ end
14
+ end
15
+
16
+ GA_RESULT = Struct.new(:date, :pageviews, :visits)
17
+ GA_PROFILE = Struct.new(:web_property_id)
18
+
19
+ test "fail if Garb not available" do
20
+ File.open "tmp/experiments/metrics/ga.rb", "w" do |f|
21
+ f.write <<-RUBY
22
+ metric "GA" do
23
+ expects(:require).raises LoadError
24
+ google_analytics "UA2"
25
+ end
26
+ RUBY
27
+ end
28
+ assert_raise LoadError do
29
+ Vanity.playground.metrics
30
+ end
31
+ end
32
+
33
+ test "constructs a report" do
34
+ Vanity.playground.metrics
35
+ assert metric(:ga).report
36
+ end
37
+
38
+ test "default to pageviews metric" do
39
+ Vanity.playground.metrics
40
+ assert_equal [:pageviews], metric(:ga).report.metrics.elements
41
+ end
42
+
43
+ test "apply data dimension and sort" do
44
+ Vanity.playground.metrics
45
+ assert_equal [:date], metric(:ga).report.dimensions.elements
46
+ assert_equal [:date], metric(:ga).report.sort.elements
47
+ end
48
+
49
+ test "accept other metrics" do
50
+ File.open "tmp/experiments/metrics/ga.rb", "w" do |f|
51
+ f.write <<-RUBY
52
+ metric "GA" do
53
+ google_analytics "UA2", :visitors
54
+ end
55
+ RUBY
56
+ end
57
+ Vanity.playground.metrics
58
+ assert_equal [:visitors], metric(:ga).report.metrics.elements
59
+ end
60
+
61
+ test "does not support hooks" do
62
+ Vanity.playground.metrics
63
+ assert_raises RuntimeError do
64
+ metric(:ga).hook
65
+ end
66
+ end
67
+
68
+ test "should find matching profile" do
69
+ Vanity.playground.metrics
70
+ Garb::Profile.expects(:all).returns(Array.new(3) { |i| GA_PROFILE.new("UA#{i + 1}") })
71
+ metric(:ga).report.stubs(:send_request_for_body).returns(nil)
72
+ Garb::ReportResponse.stubs(:new).returns(mock(:results=>[]))
73
+ metric(:ga).values(Date.parse("2010-02-10"), Date.parse("2010-02-12"))
74
+ assert_equal "UA2", metric(:ga).report.profile.web_property_id
75
+ end
76
+
77
+ test "should map results from report" do
78
+ Vanity.playground.metrics
79
+ today = Date.today
80
+ response = mock(:results=>Array.new(3) { |i| GA_RESULT.new("2010021#{i}", i + 1) })
81
+ Garb::Profile.stubs(:all).returns([])
82
+ Garb::ReportResponse.expects(:new).returns(response)
83
+ metric(:ga).report.stubs(:send_request_for_body).returns(nil)
84
+ assert_equal [1,2,3], metric(:ga).values(Date.parse("2010-02-10"), Date.parse("2010-02-12"))
85
+ end
86
+
87
+ test "mapping GA metrics to single value" do
88
+ File.open "tmp/experiments/metrics/ga.rb", "w" do |f|
89
+ f.write <<-RUBY
90
+ metric "GA" do
91
+ google_analytics "UA2", :mapper=>lambda { |e| e.pageviews * e.visits }
92
+ end
93
+ RUBY
94
+ end
95
+ Vanity.playground.metrics
96
+ today = Date.today
97
+ response = mock(:results=>Array.new(3) { |i| GA_RESULT.new("2010021#{i}", i + 1, i + 1) })
98
+ Garb::Profile.stubs(:all).returns([])
99
+ Garb::ReportResponse.expects(:new).returns(response)
100
+ metric(:ga).report.stubs(:send_request_for_body).returns(nil)
101
+ assert_equal [1,4,9], metric(:ga).values(Date.parse("2010-02-10"), Date.parse("2010-02-12"))
102
+ end
103
+
104
+ end
@@ -0,0 +1,108 @@
1
+ require "test/test_helper"
2
+
3
+
4
+ context "Remote metrics" do
5
+ setup do
6
+ FileUtils.mkpath "tmp/config"
7
+ File.open "tmp/config/vanity.yml", "w" do |f|
8
+ f.write <<-RUBY
9
+ metrics:
10
+ sandbox: http://api.vanitydash.com/metrics/sandbox
11
+ RUBY
12
+ end
13
+ Dir.chdir "tmp" do
14
+ Vanity.playground.load!
15
+ end
16
+ end
17
+
18
+ test "load from configuration file" do
19
+ assert Vanity.playground.metrics[:sandbox]
20
+ end
21
+
22
+ test "create remote metric from configuration file" do
23
+ stub_request :post, /vanitydash/
24
+ metric(:sandbox).track!
25
+ assert_requested :post, /api\.vanitydash\.com/
26
+ end
27
+ end
28
+
29
+
30
+ context "Remote send" do
31
+ setup do
32
+ @metric = Vanity::Metric.new(Vanity.playground, :sandbox)
33
+ @metric.remote "http://api.vanitydash.com/metrics/sandbox"
34
+ Vanity.playground.metrics[:sandbox] = @metric
35
+ stub_request :post, /vanitydash/
36
+ end
37
+
38
+ test "remote send in sequence" do
39
+ Vanity.playground.track! :sandbox
40
+ Vanity.playground.track! :sandbox
41
+ assert_requested(:post, "http://api.vanitydash.com/metrics/sandbox", :times=>2)
42
+ end
43
+
44
+ test "remote sends url-encoded data" do
45
+ Vanity.playground.track! :sandbox, 12
46
+ assert_requested(:post, /api/) { |request| request.headers["Content-Type"] == "application/x-www-form-urlencoded" }
47
+ end
48
+
49
+ test "remote sends metric identifier" do
50
+ Vanity.playground.track! :sandbox, 12
51
+ assert_requested(:post, /api/) { |request| Rack::Utils.parse_query(request.body)["metric"] == "sandbox" }
52
+ end
53
+
54
+ test "remote sends RFC 2616 compliant time stamp" do
55
+ Vanity.playground.track! :sandbox, 12
56
+ assert_requested(:post, /api/) { |request| Time.httpdate(Rack::Utils.parse_query(request.body)["timestamp"]) }
57
+ end
58
+
59
+ test "remote sends array of values" do
60
+ Vanity.playground.track! :sandbox, [1,2,3]
61
+ assert_requested(:post, /api/) { |request| Rack::Utils.parse_query(request.body)["values[]"] == %w{1 2 3} }
62
+ end
63
+
64
+ test "remote sends default of 1" do
65
+ Vanity.playground.track! :sandbox
66
+ assert_requested(:post, /api/) { |request| Rack::Utils.parse_query(request.body)["values[]"] == "1" }
67
+ end
68
+
69
+ test "remote sends current identity" do
70
+ Vanity.context = Object.new
71
+ class << Vanity.context
72
+ def vanity_identity
73
+ "xkcd"
74
+ end
75
+ end
76
+ Vanity.playground.track! :sandbox, 12
77
+ assert_requested(:post, /api/) { |request| Rack::Utils.parse_query(request.body)["identity"] == "xkcd" }
78
+ end
79
+
80
+ test "remote sends with additional query parameters" do
81
+ @metric.remote "http://api.vanitydash.com/metrics/sandbox?ask=receive"
82
+ Vanity.playground.track! :sandbox, 12
83
+ assert_requested(:post, /api/) { |request| Rack::Utils.parse_query(request.body)["ask"] == "receive" }
84
+ end
85
+
86
+ test "remote send handles standard error" do
87
+ stub_request(:post, /api/).to_raise(StandardError)
88
+ Vanity.playground.track! :sandbox
89
+ stub_request(:post, /api/)
90
+ Vanity.playground.track! :sandbox
91
+ assert_requested(:post, /api/, :times=>2)
92
+ end
93
+
94
+ test "remote send handles timeout error" do
95
+ stub_request(:post, /api/).to_timeout
96
+ Vanity.playground.track! :sandbox
97
+ stub_request(:post, /api/)
98
+ Vanity.playground.track! :sandbox
99
+ assert_requested(:post, /api/, :times=>2)
100
+ end
101
+
102
+ test "remote does not send when metrics disabled" do
103
+ not_collecting!
104
+ Vanity.playground.track! :sandbox
105
+ Vanity.playground.track! :sandbox
106
+ assert_requested(:post, /api/, :times=>0)
107
+ end
108
+ end
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ end
@@ -0,0 +1,7 @@
1
+ class MainController < ApplicationController
2
+ def index
3
+ render :text=>"#{Vanity.playground.connection}\n#{Vanity.playground.connection.object_id}"
4
+ rescue Error=>ex
5
+ puts $!
6
+ end
7
+ end
@@ -0,0 +1,110 @@
1
+ # Don't change this file!
2
+ # Configure your app in config/environment.rb and config/environments/*.rb
3
+
4
+ RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
5
+
6
+ module Rails
7
+ class << self
8
+ def boot!
9
+ unless booted?
10
+ preinitialize
11
+ pick_boot.run
12
+ end
13
+ end
14
+
15
+ def booted?
16
+ defined? Rails::Initializer
17
+ end
18
+
19
+ def pick_boot
20
+ (vendor_rails? ? VendorBoot : GemBoot).new
21
+ end
22
+
23
+ def vendor_rails?
24
+ File.exist?("#{RAILS_ROOT}/vendor/rails")
25
+ end
26
+
27
+ def preinitialize
28
+ load(preinitializer_path) if File.exist?(preinitializer_path)
29
+ end
30
+
31
+ def preinitializer_path
32
+ "#{RAILS_ROOT}/config/preinitializer.rb"
33
+ end
34
+ end
35
+
36
+ class Boot
37
+ def run
38
+ load_initializer
39
+ Rails::Initializer.run(:set_load_path)
40
+ end
41
+ end
42
+
43
+ class VendorBoot < Boot
44
+ def load_initializer
45
+ require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
46
+ Rails::Initializer.run(:install_gem_spec_stubs)
47
+ Rails::GemDependency.add_frozen_gem_path
48
+ end
49
+ end
50
+
51
+ class GemBoot < Boot
52
+ def load_initializer
53
+ self.class.load_rubygems
54
+ load_rails_gem
55
+ require 'initializer'
56
+ end
57
+
58
+ def load_rails_gem
59
+ if version = self.class.gem_version
60
+ gem 'rails', version
61
+ else
62
+ gem 'rails'
63
+ end
64
+ rescue Gem::LoadError => load_error
65
+ $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
66
+ exit 1
67
+ end
68
+
69
+ class << self
70
+ def rubygems_version
71
+ Gem::RubyGemsVersion rescue nil
72
+ end
73
+
74
+ def gem_version
75
+ if defined? RAILS_GEM_VERSION
76
+ RAILS_GEM_VERSION
77
+ elsif ENV.include?('RAILS_GEM_VERSION')
78
+ ENV['RAILS_GEM_VERSION']
79
+ else
80
+ parse_gem_version(read_environment_rb)
81
+ end
82
+ end
83
+
84
+ def load_rubygems
85
+ min_version = '1.3.1'
86
+ require 'rubygems'
87
+ unless rubygems_version >= min_version
88
+ $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
89
+ exit 1
90
+ end
91
+
92
+ rescue LoadError
93
+ $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
94
+ exit 1
95
+ end
96
+
97
+ def parse_gem_version(text)
98
+ $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
99
+ end
100
+
101
+ private
102
+ def read_environment_rb
103
+ File.read("#{RAILS_ROOT}/config/environment.rb")
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ # All that for this:
110
+ Rails.boot!
@@ -0,0 +1,10 @@
1
+ require File.join(File.dirname(__FILE__), 'boot')
2
+
3
+ Rails::Initializer.run do |config|
4
+ config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
5
+ config.action_controller.session = { :key=>"_myapp_session", :secret=>"Stay hungry. Stay foolish. -- Steve Jobs" }
6
+ config.after_initialize do
7
+ $:.unshift File.dirname(__FILE__) + "/../../../lib/"
8
+ require "vanity"
9
+ end
10
+ end
File without changes
@@ -0,0 +1,3 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.connect "/", :controller=>:main, :action=>:index
3
+ end
@@ -0,0 +1,43 @@
1
+ require "test/test_helper"
2
+ require "phusion_passenger/spawn_manager"
3
+
4
+ class PassengerTest < Test::Unit::TestCase
5
+ def setup
6
+ super
7
+ ActiveRecord::Base.connection.disconnect! # Otherwise AR metric tests fail
8
+ @original = Vanity.playground.connection
9
+ File.unlink "test/myapp/config/vanity.yml" rescue nil
10
+ File.open("test/myapp/config/vanity.yml", "w") do |io|
11
+ io.write "production: #{Vanity.playground.connection}"
12
+ end
13
+ @server = PhusionPassenger::SpawnManager.new
14
+ @server.start
15
+ Thread.pass until @server.started?
16
+ app_root = File.expand_path("myapp", File.dirname(__FILE__))
17
+ @app = @server.spawn_application "app_root"=>app_root, "spawn_method"=>"smart-lv2"
18
+ end
19
+
20
+ def test_reconnect
21
+ sleep 0.1
22
+ case @app.listen_socket_type
23
+ when "tcp" ; socket = TCPSocket.new(*@app.listen_socket_name.split(":"))
24
+ when "unix"; socket = UNIXSocket.new(@app.listen_socket_name)
25
+ else fail
26
+ end
27
+ channel = PhusionPassenger::MessageChannel.new(socket)
28
+ request = {"REQUEST_PATH"=>"/", "REQUEST_METHOD"=>"GET", "QUERY_STRING"=>" "}
29
+ channel.write_scalar request.to_a.join("\0")
30
+ response = socket.read.split("\r\n\r\n").last
31
+ socket.close
32
+ conn, obj_id = response.split("\n")
33
+ assert_equal @original.to_s, conn
34
+ assert_not_equal @original.object_id.to_s, obj_id
35
+ end
36
+
37
+ def teardown
38
+ super
39
+ @server.stop
40
+ File.unlink "test/myapp/config/vanity.yml"
41
+ end
42
+
43
+ end
@@ -0,0 +1,10 @@
1
+ require "test/test_helper"
2
+
3
+ class PlaygroundTest < Test::Unit::TestCase
4
+
5
+ def test_has_one_global_instance
6
+ assert instance = Vanity.playground
7
+ assert_equal instance, Vanity.playground
8
+ end
9
+
10
+ end
@@ -0,0 +1,294 @@
1
+ require "test/test_helper"
2
+
3
+ class UseVanityController < ActionController::Base
4
+ attr_accessor :current_user
5
+
6
+ def index
7
+ render :text=>ab_test(:pie_or_cake)
8
+ end
9
+ end
10
+
11
+ # Pages accessible to everyone, e.g. sign in, community search.
12
+ class UseVanityTest < ActionController::TestCase
13
+ tests UseVanityController
14
+
15
+ def setup
16
+ super
17
+ metric :sugar_high
18
+ new_ab_test :pie_or_cake do
19
+ metrics :sugar_high
20
+ end
21
+ UseVanityController.class_eval do
22
+ use_vanity :current_user
23
+ end
24
+ end
25
+
26
+ def test_vanity_cookie_is_persistent
27
+ get :index
28
+ assert cookie = @response["Set-Cookie"].find { |c| c[/^vanity_id=/] }
29
+ assert expires = cookie[/vanity_id=[a-f0-9]{32}; path=\/; expires=(.*)(;|$)/, 1]
30
+ assert_in_delta Time.parse(expires), Time.now + 1.month, 1.minute
31
+ end
32
+
33
+ def test_vanity_cookie_default_id
34
+ get :index
35
+ assert cookies['vanity_id'] =~ /^[a-f0-9]{32}$/
36
+ end
37
+
38
+ def test_vanity_cookie_retains_id
39
+ @request.cookies['vanity_id'] = "from_last_time"
40
+ get :index
41
+ assert_equal "from_last_time", cookies['vanity_id']
42
+ end
43
+
44
+ def test_vanity_identity_set_from_cookie
45
+ @request.cookies['vanity_id'] = "from_last_time"
46
+ get :index
47
+ assert_equal "from_last_time", @controller.send(:vanity_identity)
48
+ end
49
+
50
+ def test_vanity_identity_set_from_user
51
+ @controller.current_user = mock("user", :id=>"user_id")
52
+ get :index
53
+ assert_equal "user_id", @controller.send(:vanity_identity)
54
+ end
55
+
56
+ def test_vanity_identity_with_no_user_model
57
+ UseVanityController.class_eval do
58
+ use_vanity nil
59
+ end
60
+ @controller.current_user = Object.new
61
+ get :index
62
+ assert cookies['vanity_id'] =~ /^[a-f0-9]{32}$/
63
+ end
64
+
65
+ def test_vanity_identity_set_with_block
66
+ UseVanityController.class_eval do
67
+ attr_accessor :project_id
68
+ use_vanity { |controller| controller.project_id }
69
+ end
70
+ @controller.project_id = "576"
71
+ get :index
72
+ assert_equal "576", @controller.send(:vanity_identity)
73
+ end
74
+
75
+ # query parameter filter
76
+
77
+ def test_redirects_and_loses_vanity_query_parameter
78
+ get :index, :foo=>"bar", :_vanity=>"567"
79
+ assert_redirected_to "/use_vanity?foo=bar"
80
+ end
81
+
82
+ def test_sets_choices_from_vanity_query_parameter
83
+ first = experiment(:pie_or_cake).alternatives.first
84
+ # experiment(:pie_or_cake).fingerprint(first)
85
+ 10.times do
86
+ @controller = nil ; setup_controller_request_and_response
87
+ get :index, :_vanity=>"aae9ff8081"
88
+ assert !experiment(:pie_or_cake).choose
89
+ assert experiment(:pie_or_cake).showing?(first)
90
+ end
91
+ end
92
+
93
+ def test_does_nothing_with_vanity_query_parameter_for_posts
94
+ first = experiment(:pie_or_cake).alternatives.first
95
+ post :index, :foo=>"bar", :_vanity=>"567"
96
+ assert_response :success
97
+ assert !experiment(:pie_or_cake).showing?(first)
98
+ end
99
+
100
+
101
+ # -- Load path --
102
+
103
+ def test_load_path
104
+ assert_equal File.expand_path("tmp/experiments"), load_rails(<<-RB)
105
+ initializer.after_initialize
106
+ $stdout << Vanity.playground.load_path
107
+ RB
108
+ end
109
+
110
+ def test_settable_load_path
111
+ assert_equal File.expand_path("tmp/predictions"), load_rails(<<-RB)
112
+ Vanity.playground.load_path = "predictions"
113
+ initializer.after_initialize
114
+ $stdout << Vanity.playground.load_path
115
+ RB
116
+ end
117
+
118
+ def test_absolute_load_path
119
+ assert_equal File.expand_path("/tmp/var"), load_rails(<<-RB)
120
+ Vanity.playground.load_path = "/tmp/var"
121
+ initializer.after_initialize
122
+ $stdout << Vanity.playground.load_path
123
+ RB
124
+ end
125
+
126
+
127
+ # -- Connection configuration --
128
+
129
+ def test_default_connection
130
+ assert_equal "redis://127.0.0.1:6379/0", load_rails(<<-RB)
131
+ initializer.after_initialize
132
+ $stdout << Vanity.playground.connection
133
+ RB
134
+ end
135
+
136
+ def test_connection_from_string
137
+ assert_equal "redis://192.168.1.1:6379/5", load_rails(<<-RB)
138
+ Vanity.playground.establish_connection "redis://192.168.1.1:6379/5"
139
+ initializer.after_initialize
140
+ $stdout << Vanity.playground.connection
141
+ RB
142
+ end
143
+
144
+ def test_connection_from_yaml
145
+ FileUtils.mkpath "tmp/config"
146
+ ENV["RAILS_ENV"] = "production"
147
+ File.open("tmp/config/vanity.yml", "w") do |io|
148
+ io.write <<-YML
149
+ production:
150
+ adapter: redis
151
+ host: somehost
152
+ database: 15
153
+ YML
154
+ end
155
+ assert_equal "redis://somehost:6379/15", load_rails(<<-RB)
156
+ initializer.after_initialize
157
+ $stdout << Vanity.playground.connection
158
+ RB
159
+ ensure
160
+ File.unlink "tmp/config/vanity.yml"
161
+ end
162
+
163
+ def test_connection_from_yaml_url
164
+ FileUtils.mkpath "tmp/config"
165
+ ENV["RAILS_ENV"] = "production"
166
+ File.open("tmp/config/vanity.yml", "w") do |io|
167
+ io.write <<-YML
168
+ production: redis://somehost/15
169
+ YML
170
+ end
171
+ assert_equal "redis://somehost:6379/15", load_rails(<<-RB)
172
+ initializer.after_initialize
173
+ $stdout << Vanity.playground.connection
174
+ RB
175
+ ensure
176
+ File.unlink "tmp/config/vanity.yml"
177
+ end
178
+
179
+ def test_connection_from_yaml_missing
180
+ FileUtils.mkpath "tmp/config"
181
+ ENV["RAILS_ENV"] = "development"
182
+ File.open("tmp/config/vanity.yml", "w") do |io|
183
+ io.write <<-YML
184
+ production:
185
+ adapter: redis
186
+ YML
187
+ end
188
+ assert_equal "No configuration for development", load_rails(<<-RB)
189
+ initializer.after_initialize
190
+ $stdout << (Vanity.playground.connection rescue $!.message)
191
+ RB
192
+ ensure
193
+ File.unlink "tmp/config/vanity.yml"
194
+ end
195
+
196
+ def test_connection_from_yaml_with_erb
197
+ FileUtils.mkpath "tmp/config"
198
+ ENV["RAILS_ENV"] = "production"
199
+ # Pass storage URL through environment like heroku does
200
+ ENV["REDIS_URL"] = "redis://somehost:6379/15"
201
+ File.open("tmp/config/vanity.yml", "w") do |io|
202
+ io.write <<-YML
203
+ production: <%= ENV['REDIS_URL'] %>
204
+ YML
205
+ end
206
+ assert_equal "redis://somehost:6379/15", load_rails(<<-RB)
207
+ initializer.after_initialize
208
+ $stdout << Vanity.playground.connection
209
+ RB
210
+ ensure
211
+ File.unlink "tmp/config/vanity.yml"
212
+ end
213
+
214
+ def test_connection_from_redis_yml
215
+ FileUtils.mkpath "tmp/config"
216
+ yml = File.open("tmp/config/redis.yml", "w")
217
+ yml << "development: internal.local:6379\n"
218
+ yml.flush
219
+ assert_equal "redis://internal.local:6379/0", load_rails(<<-RB)
220
+ initializer.after_initialize
221
+ $stdout << Vanity.playground.connection
222
+ RB
223
+ ensure
224
+ File.unlink yml.path
225
+ end
226
+
227
+ def test_collection_true_in_production_by_default
228
+ assert_equal "true", load_rails(<<-RB, "production")
229
+ initializer.after_initialize
230
+ $stdout << Vanity.playground.collecting?
231
+ RB
232
+ end
233
+
234
+ def test_collection_false_in_production_when_configured
235
+ assert_equal "false", load_rails(<<-RB, "production")
236
+ Vanity.playground.collecting = false
237
+ initializer.after_initialize
238
+ $stdout << Vanity.playground.collecting?
239
+ RB
240
+ end
241
+
242
+ def test_collection_false_in_development_by_default
243
+ assert_equal "false", load_rails(<<-RB, "development")
244
+ initializer.after_initialize
245
+ $stdout << Vanity.playground.collecting?
246
+ RB
247
+ end
248
+
249
+ def test_collection_true_in_development_when_configured
250
+ assert_equal "true", load_rails(<<-RB, "development")
251
+ Vanity.playground.collecting = true
252
+ initializer.after_initialize
253
+ $stdout << Vanity.playground.collecting?
254
+ RB
255
+ end
256
+
257
+ def test_collection_false_after_test!
258
+ assert_equal "false", load_rails(<<-RB, "production")
259
+ initializer.after_initialize
260
+ Vanity.playground.test!
261
+ $stdout << Vanity.playground.collecting?
262
+ RB
263
+ end
264
+
265
+
266
+ def load_rails(code, env = "production")
267
+ tmp = Tempfile.open("test.rb")
268
+ tmp.write <<-RB
269
+ $:.delete_if { |path| path[/gems\\/vanity-\\d/] }
270
+ $:.unshift File.expand_path("../lib")
271
+ RAILS_ROOT = File.expand_path(".")
272
+ RAILS_ENV = "#{env}"
273
+ require "initializer"
274
+ require "active_support"
275
+ Rails.configuration = Rails::Configuration.new
276
+ initializer = Rails::Initializer.new(Rails.configuration)
277
+ initializer.check_gem_dependencies
278
+ require "vanity"
279
+ RB
280
+ tmp.write code
281
+ tmp.flush
282
+ Dir.chdir "tmp" do
283
+ open("|ruby #{tmp.path}").read
284
+ end
285
+ rescue
286
+ tmp.close!
287
+ end
288
+
289
+
290
+ def teardown
291
+ super
292
+ UseVanityController.send(:filter_chain).clear
293
+ end
294
+ end