moses-vanity 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. data/.autotest +22 -0
  2. data/.gitignore +7 -0
  3. data/.rvmrc +3 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGELOG +374 -0
  6. data/Gemfile +28 -0
  7. data/MIT-LICENSE +21 -0
  8. data/README.rdoc +108 -0
  9. data/Rakefile +189 -0
  10. data/bin/vanity +16 -0
  11. data/doc/_config.yml +2 -0
  12. data/doc/_layouts/_header.html +34 -0
  13. data/doc/_layouts/page.html +47 -0
  14. data/doc/_metrics.textile +12 -0
  15. data/doc/ab_testing.textile +210 -0
  16. data/doc/configuring.textile +45 -0
  17. data/doc/contributing.textile +93 -0
  18. data/doc/credits.textile +23 -0
  19. data/doc/css/page.css +83 -0
  20. data/doc/css/print.css +43 -0
  21. data/doc/css/syntax.css +7 -0
  22. data/doc/email.textile +129 -0
  23. data/doc/experimental.textile +31 -0
  24. data/doc/faq.textile +8 -0
  25. data/doc/identity.textile +43 -0
  26. data/doc/images/ab_in_dashboard.png +0 -0
  27. data/doc/images/clear_winner.png +0 -0
  28. data/doc/images/price_options.png +0 -0
  29. data/doc/images/sidebar_test.png +0 -0
  30. data/doc/images/signup_metric.png +0 -0
  31. data/doc/images/vanity.png +0 -0
  32. data/doc/index.textile +91 -0
  33. data/doc/metrics.textile +231 -0
  34. data/doc/rails.textile +89 -0
  35. data/doc/site.js +27 -0
  36. data/generators/templates/vanity_migration.rb +53 -0
  37. data/generators/vanity_generator.rb +8 -0
  38. data/lib/generators/templates/vanity_migration.rb +53 -0
  39. data/lib/generators/vanity_generator.rb +15 -0
  40. data/lib/vanity.rb +36 -0
  41. data/lib/vanity/adapters/abstract_adapter.rb +140 -0
  42. data/lib/vanity/adapters/active_record_adapter.rb +248 -0
  43. data/lib/vanity/adapters/mock_adapter.rb +157 -0
  44. data/lib/vanity/adapters/mongodb_adapter.rb +178 -0
  45. data/lib/vanity/adapters/redis_adapter.rb +160 -0
  46. data/lib/vanity/backport.rb +26 -0
  47. data/lib/vanity/commands/list.rb +21 -0
  48. data/lib/vanity/commands/report.rb +64 -0
  49. data/lib/vanity/commands/upgrade.rb +34 -0
  50. data/lib/vanity/experiment/ab_test.rb +507 -0
  51. data/lib/vanity/experiment/base.rb +214 -0
  52. data/lib/vanity/frameworks.rb +16 -0
  53. data/lib/vanity/frameworks/rails.rb +318 -0
  54. data/lib/vanity/helpers.rb +66 -0
  55. data/lib/vanity/images/x.gif +0 -0
  56. data/lib/vanity/metric/active_record.rb +85 -0
  57. data/lib/vanity/metric/base.rb +244 -0
  58. data/lib/vanity/metric/google_analytics.rb +83 -0
  59. data/lib/vanity/metric/remote.rb +53 -0
  60. data/lib/vanity/playground.rb +396 -0
  61. data/lib/vanity/templates/_ab_test.erb +28 -0
  62. data/lib/vanity/templates/_experiment.erb +5 -0
  63. data/lib/vanity/templates/_experiments.erb +7 -0
  64. data/lib/vanity/templates/_metric.erb +14 -0
  65. data/lib/vanity/templates/_metrics.erb +13 -0
  66. data/lib/vanity/templates/_report.erb +27 -0
  67. data/lib/vanity/templates/_vanity.js.erb +20 -0
  68. data/lib/vanity/templates/flot.min.js +1 -0
  69. data/lib/vanity/templates/jquery.min.js +19 -0
  70. data/lib/vanity/templates/vanity.css +26 -0
  71. data/lib/vanity/templates/vanity.js +82 -0
  72. data/lib/vanity/version.rb +11 -0
  73. data/test/adapters/redis_adapter_test.rb +17 -0
  74. data/test/experiment/ab_test.rb +771 -0
  75. data/test/experiment/base_test.rb +150 -0
  76. data/test/experiments/age_and_zipcode.rb +19 -0
  77. data/test/experiments/metrics/cheers.rb +3 -0
  78. data/test/experiments/metrics/signups.rb +2 -0
  79. data/test/experiments/metrics/yawns.rb +3 -0
  80. data/test/experiments/null_abc.rb +5 -0
  81. data/test/metric/active_record_test.rb +277 -0
  82. data/test/metric/base_test.rb +293 -0
  83. data/test/metric/google_analytics_test.rb +104 -0
  84. data/test/metric/remote_test.rb +109 -0
  85. data/test/myapp/app/controllers/application_controller.rb +2 -0
  86. data/test/myapp/app/controllers/main_controller.rb +7 -0
  87. data/test/myapp/config/boot.rb +110 -0
  88. data/test/myapp/config/environment.rb +10 -0
  89. data/test/myapp/config/environments/production.rb +0 -0
  90. data/test/myapp/config/routes.rb +3 -0
  91. data/test/passenger_test.rb +43 -0
  92. data/test/playground_test.rb +26 -0
  93. data/test/rails_dashboard_test.rb +37 -0
  94. data/test/rails_helper_test.rb +36 -0
  95. data/test/rails_test.rb +389 -0
  96. data/test/test_helper.rb +145 -0
  97. data/vanity.gemspec +26 -0
  98. metadata +202 -0
@@ -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
@@ -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 YAML.dump({ "production"=>DATABASE })
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,26 @@
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
+ def test_be_use_js
11
+ assert !Vanity.playground.using_js?
12
+ Vanity.playground.use_js!
13
+ assert Vanity.playground.using_js?
14
+ end
15
+
16
+ def test_chooses_path_sets_default
17
+ assert_equal Vanity.playground.add_participant_path, Vanity::Playground::DEFAULT_ADD_PARTICIPANT_PATH
18
+ end
19
+
20
+ def test_reconnects_with_existing_connection
21
+ Vanity.playground.establish_connection "mock:/"
22
+ Vanity.playground.reconnect!
23
+ assert_equal Vanity.playground.connection.to_s, "mock:/"
24
+ end
25
+
26
+ end
@@ -0,0 +1,37 @@
1
+ require "test/test_helper"
2
+
3
+ class VanityController < ActionController::Base
4
+ include Vanity::Rails::Dashboard
5
+ end
6
+
7
+ # Pages accessible to everyone, e.g. sign in, community search.
8
+ class RailsDashboardTest < ActionController::TestCase
9
+ tests VanityController
10
+
11
+ def setup
12
+ Vanity.playground.collecting = true
13
+ metric :sugar_high
14
+ new_ab_test :food do
15
+ alternatives :apple, :orange
16
+ metrics :sugar_high
17
+ identify { '1' }
18
+ end
19
+ end
20
+
21
+ def test_add_participant
22
+ xhr :post, :add_participant, :e => "food", :a => 0
23
+ assert_response :success
24
+ assert @response.body.blank?
25
+ end
26
+
27
+ def test_add_participant_no_params
28
+ xhr :post, :add_participant
29
+ assert_response :not_found
30
+ assert @response.body.blank?
31
+ end
32
+
33
+ def test_chooses
34
+ xhr :post, :chooses, :e => "food", :a => 0
35
+ assert_response :success
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ require "test/test_helper"
2
+
3
+ class RailsHelperTest < ActionView::TestCase
4
+ include Vanity::Rails::Helpers
5
+
6
+ def setup
7
+ super
8
+ metric :sugar_high
9
+ new_ab_test :pie_or_cake do
10
+ metrics :sugar_high
11
+ identify { '1' }
12
+ alternatives :pie, :cake
13
+ end
14
+ end
15
+
16
+ def test_ab_test_returns_one_of_the_alternatives
17
+ assert [:pie, :cake].include?(ab_test(:pie_or_cake))
18
+ end
19
+
20
+ def test_ab_test_using_js_returns_the_same_alternative
21
+ Vanity.playground.use_js!
22
+ result = ab_test(:pie_or_cake)
23
+ assert [:pie, :cake].include?(result)
24
+ 10.times do
25
+ assert result == ab_test(:pie_or_cake)
26
+ end
27
+ end
28
+
29
+ def test_vanity_track_url_for_returns_url_with_identity_and_metrics
30
+ assert_equal vanity_track_url_for("123", :sugar_high, :controller => "controller", :action => "action"), "/controller/action?_identity=123&amp;_track=sugar_high"
31
+ end
32
+
33
+ def test_vanity_tracking_image
34
+ assert_equal vanity_tracking_image("123", :sugar_high, options = {}), image_tag("/vanity/image?_identity=123&amp;_track=sugar_high", :width => "1px", :height => "1px", :alt => "")
35
+ end
36
+ end
@@ -0,0 +1,389 @@
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
+ if ::Rails.respond_to?(:application) # Rails 3 configuration
25
+ ::Rails.application.config.session_options[:domain] = '.foo.bar'
26
+ end
27
+ end
28
+
29
+ def test_chooses_sets_alternatives_for_rails_tests
30
+ experiment(:pie_or_cake).chooses(true)
31
+ get :index
32
+ assert_equal 'true', @response.body
33
+
34
+ experiment(:pie_or_cake).chooses(false)
35
+ get :index
36
+ assert_equal 'false', @response.body
37
+ end
38
+
39
+
40
+ def test_vanity_cookie_is_persistent
41
+ get :index
42
+ assert cookie = @response["Set-Cookie"].find { |c| c[/^vanity_id=/] }
43
+ assert expires = cookie[/vanity_id=[a-f0-9]{32}; path=\/; expires=(.*)(;|$)/, 1]
44
+ assert_in_delta Time.parse(expires), Time.now + 1.month, 1.minute
45
+ end
46
+
47
+ def test_vanity_cookie_default_id
48
+ get :index
49
+ assert cookies['vanity_id'] =~ /^[a-f0-9]{32}$/
50
+ end
51
+
52
+ def test_vanity_cookie_retains_id
53
+ @request.cookies['vanity_id'] = "from_last_time"
54
+ get :index
55
+ assert_equal "from_last_time", cookies['vanity_id']
56
+ end
57
+
58
+ def test_vanity_identity_set_from_cookie
59
+ @request.cookies['vanity_id'] = "from_last_time"
60
+ get :index
61
+ assert_equal "from_last_time", @controller.send(:vanity_identity)
62
+ end
63
+
64
+ def test_vanity_identity_set_from_user
65
+ @controller.current_user = mock("user", :id=>"user_id")
66
+ get :index
67
+ assert_equal "user_id", @controller.send(:vanity_identity)
68
+ end
69
+
70
+ def test_vanity_identity_with_no_user_model
71
+ UseVanityController.class_eval do
72
+ use_vanity nil
73
+ end
74
+ @controller.current_user = Object.new
75
+ get :index
76
+ assert cookies['vanity_id'] =~ /^[a-f0-9]{32}$/
77
+ end
78
+
79
+ def test_vanity_identity_set_with_block
80
+ UseVanityController.class_eval do
81
+ attr_accessor :project_id
82
+ use_vanity { |controller| controller.project_id }
83
+ end
84
+ @controller.project_id = "576"
85
+ get :index
86
+ assert_equal "576", @controller.send(:vanity_identity)
87
+ end
88
+
89
+ def test_vanity_identity_set_with_indentity_paramater
90
+ get :index, :_identity => "id_from_params"
91
+ assert_equal "id_from_params", @controller.send(:vanity_identity)
92
+
93
+ @request.cookies['vanity_id'] = "old_id"
94
+ get :index, :_identity => "id_from_params"
95
+ assert_equal "id_from_params", @controller.send(:vanity_identity)
96
+ assert cookies['vanity_id'], "id_from_params"
97
+ end
98
+
99
+ # query parameter filter
100
+
101
+ def test_redirects_and_loses_vanity_query_parameter
102
+ get :index, :foo=>"bar", :_vanity=>"567"
103
+ assert_redirected_to "/use_vanity?foo=bar"
104
+ end
105
+
106
+ def test_sets_choices_from_vanity_query_parameter
107
+ first = experiment(:pie_or_cake).alternatives.first
108
+ fingerprint = experiment(:pie_or_cake).fingerprint(first)
109
+ 10.times do
110
+ @controller = nil ; setup_controller_request_and_response
111
+ get :index, :_vanity => fingerprint
112
+ assert_equal experiment(:pie_or_cake).choose, experiment(:pie_or_cake).alternatives.first
113
+ assert experiment(:pie_or_cake).showing?(first)
114
+ end
115
+ end
116
+
117
+ def test_does_nothing_with_vanity_query_parameter_for_posts
118
+ experiment(:pie_or_cake).chooses(experiment(:pie_or_cake).alternatives.last.value)
119
+ first = experiment(:pie_or_cake).alternatives.first
120
+ fingerprint = experiment(:pie_or_cake).fingerprint(first)
121
+ post :index, :foo => "bar", :_vanity => fingerprint
122
+ assert_response :success
123
+ assert !experiment(:pie_or_cake).showing?(first)
124
+ end
125
+
126
+ def test_track_param_tracks_a_metric
127
+ get :index, :_identity => "123", :_track => "sugar_high"
128
+ assert_equal experiment(:pie_or_cake).alternatives[0].converted, 1
129
+ end
130
+
131
+ def test_cookie_domain_from_rails_configuration
132
+ get :index
133
+ assert_equal cookies["vanity_id"][:domain], '.foo.bar' if ::Rails.respond_to?(:application)
134
+ end
135
+
136
+ # -- Load path --
137
+
138
+ def test_load_path
139
+ assert_equal File.expand_path("tmp/experiments"), load_rails(<<-RB)
140
+ initializer.after_initialize
141
+ $stdout << Vanity.playground.load_path
142
+ RB
143
+ end
144
+
145
+ def test_settable_load_path
146
+ assert_equal File.expand_path("tmp/predictions"), load_rails(<<-RB)
147
+ Vanity.playground.load_path = "predictions"
148
+ initializer.after_initialize
149
+ $stdout << Vanity.playground.load_path
150
+ RB
151
+ end
152
+
153
+ def test_absolute_load_path
154
+ assert_equal File.expand_path("/tmp/var"), load_rails(<<-RB)
155
+ Vanity.playground.load_path = "/tmp/var"
156
+ initializer.after_initialize
157
+ $stdout << Vanity.playground.load_path
158
+ RB
159
+ end
160
+
161
+
162
+ # -- Connection configuration --
163
+
164
+ def test_default_connection
165
+ assert_equal "redis://127.0.0.1:6379/0", load_rails(<<-RB)
166
+ initializer.after_initialize
167
+ $stdout << Vanity.playground.connection
168
+ RB
169
+ end
170
+
171
+ def test_connection_from_string
172
+ assert_equal "redis://192.168.1.1:6379/5", load_rails(<<-RB)
173
+ Vanity.playground.establish_connection "redis://192.168.1.1:6379/5"
174
+ initializer.after_initialize
175
+ $stdout << Vanity.playground.connection
176
+ RB
177
+ end
178
+
179
+ def test_connection_from_yaml
180
+ FileUtils.mkpath "tmp/config"
181
+ ENV["RAILS_ENV"] = "production"
182
+ File.open("tmp/config/vanity.yml", "w") do |io|
183
+ io.write <<-YML
184
+ production:
185
+ adapter: redis
186
+ host: somehost
187
+ database: 15
188
+ YML
189
+ end
190
+ assert_equal "redis://somehost:6379/15", load_rails(<<-RB)
191
+ initializer.after_initialize
192
+ $stdout << Vanity.playground.connection
193
+ RB
194
+ ensure
195
+ File.unlink "tmp/config/vanity.yml"
196
+ end
197
+
198
+ def test_mongo_connection_from_yaml
199
+ FileUtils.mkpath "tmp/config"
200
+ File.open("tmp/config/vanity.yml", "w") do |io|
201
+ io.write <<-YML
202
+ mongodb:
203
+ adapter: mongodb
204
+ host: localhost
205
+ port: 27017
206
+ database: vanity_test
207
+ YML
208
+ end
209
+
210
+ assert_equal "mongodb://localhost:27017/vanity_test", load_rails(<<-RB, "mongodb")
211
+ initializer.after_initialize
212
+ $stdout << Vanity.playground.connection
213
+ RB
214
+ ensure
215
+ File.unlink "tmp/config/vanity.yml"
216
+ end
217
+
218
+ def test_mongodb_replica_set_connection
219
+ FileUtils.mkpath "tmp/config"
220
+ File.open("tmp/config/vanity.yml", "w") do |io|
221
+ io.write <<-YML
222
+ mongodb:
223
+ adapter: mongodb
224
+ hosts:
225
+ - localhost
226
+ port: 27017
227
+ database: vanity_test
228
+ YML
229
+ end
230
+
231
+ assert_equal "mongodb://localhost:27017/vanity_test", load_rails(<<-RB, "mongodb")
232
+ initializer.after_initialize
233
+ $stdout << Vanity.playground.connection
234
+ RB
235
+
236
+ assert_equal "Mongo::ReplSetConnection", load_rails(<<-RB, "mongodb")
237
+ initializer.after_initialize
238
+ $stdout << Vanity.playground.connection.mongo.class
239
+ RB
240
+ ensure
241
+ File.unlink "tmp/config/vanity.yml"
242
+ end
243
+
244
+ def test_connection_from_yaml_url
245
+ FileUtils.mkpath "tmp/config"
246
+ ENV["RAILS_ENV"] = "production"
247
+ File.open("tmp/config/vanity.yml", "w") do |io|
248
+ io.write <<-YML
249
+ production: redis://somehost/15
250
+ YML
251
+ end
252
+ assert_equal "redis://somehost:6379/15", load_rails(<<-RB)
253
+ initializer.after_initialize
254
+ $stdout << Vanity.playground.connection
255
+ RB
256
+ ensure
257
+ File.unlink "tmp/config/vanity.yml"
258
+ end
259
+
260
+ def test_connection_from_yaml_missing
261
+ FileUtils.mkpath "tmp/config"
262
+ File.open("tmp/config/vanity.yml", "w") do |io|
263
+ io.write <<-YML
264
+ production:
265
+ adapter: redis
266
+ YML
267
+ end
268
+ assert_equal "No configuration for development", load_rails(<<-RB, "development")
269
+ initializer.after_initialize
270
+ $stdout << (Vanity.playground.connection rescue $!.message)
271
+ RB
272
+ ensure
273
+ File.unlink "tmp/config/vanity.yml"
274
+ end
275
+
276
+ def test_connection_from_yaml_with_erb
277
+ FileUtils.mkpath "tmp/config"
278
+ ENV["RAILS_ENV"] = "production"
279
+ # Pass storage URL through environment like heroku does
280
+ ENV["REDIS_URL"] = "redis://somehost:6379/15"
281
+ File.open("tmp/config/vanity.yml", "w") do |io|
282
+ io.write <<-YML
283
+ production: <%= ENV['REDIS_URL'] %>
284
+ YML
285
+ end
286
+ assert_equal "redis://somehost:6379/15", load_rails(<<-RB)
287
+ initializer.after_initialize
288
+ $stdout << Vanity.playground.connection
289
+ RB
290
+ ensure
291
+ File.unlink "tmp/config/vanity.yml"
292
+ end
293
+
294
+ def test_connection_from_redis_yml
295
+ FileUtils.mkpath "tmp/config"
296
+ yml = File.open("tmp/config/redis.yml", "w")
297
+ yml << "production: internal.local:6379\n"
298
+ yml.flush
299
+ assert_equal "redis://internal.local:6379/0", load_rails(<<-RB)
300
+ initializer.after_initialize
301
+ $stdout << Vanity.playground.connection
302
+ RB
303
+ ensure
304
+ File.unlink yml.path
305
+ end
306
+
307
+ def test_collection_from_vanity_yaml
308
+ FileUtils.mkpath "tmp/config"
309
+ File.open("tmp/config/vanity.yml", "w") do |io|
310
+ io.write <<-YML
311
+ production:
312
+ collecting: false
313
+ YML
314
+ end
315
+ assert_equal "false", load_rails(<<-RB)
316
+ initializer.after_initialize
317
+ $stdout << Vanity.playground.collecting?
318
+ RB
319
+ ensure
320
+ File.unlink "tmp/config/vanity.yml"
321
+ end
322
+
323
+ def test_collection_true_in_production_by_default
324
+ assert_equal "true", load_rails(<<-RB, "production")
325
+ initializer.after_initialize
326
+ $stdout << Vanity.playground.collecting?
327
+ RB
328
+ end
329
+
330
+ def test_collection_false_in_production_when_configured
331
+ assert_equal "false", load_rails(<<-RB, "production")
332
+ Vanity.playground.collecting = false
333
+ initializer.after_initialize
334
+ $stdout << Vanity.playground.collecting?
335
+ RB
336
+ end
337
+
338
+ def test_collection_false_in_development_by_default
339
+ assert_equal "false", load_rails(<<-RB, "development")
340
+ initializer.after_initialize
341
+ $stdout << Vanity.playground.collecting?
342
+ RB
343
+ end
344
+
345
+ def test_collection_true_in_development_when_configured
346
+ assert_equal "true", load_rails(<<-RB, "development")
347
+ Vanity.playground.collecting = true
348
+ initializer.after_initialize
349
+ $stdout << Vanity.playground.collecting?
350
+ RB
351
+ end
352
+
353
+ def test_collection_false_after_test!
354
+ assert_equal "false", load_rails(<<-RB, "production")
355
+ initializer.after_initialize
356
+ Vanity.playground.test!
357
+ $stdout << Vanity.playground.collecting?
358
+ RB
359
+ end
360
+
361
+ def load_rails(code, env = "production")
362
+ tmp = Tempfile.open("test.rb")
363
+ tmp.write <<-RB
364
+ $:.delete_if { |path| path[/gems\\/vanity-\\d/] }
365
+ $:.unshift File.expand_path("../lib")
366
+ RAILS_ROOT = File.expand_path(".")
367
+ RAILS_ENV = ENV['RACK_ENV'] = "#{env}"
368
+ require "initializer"
369
+ require "active_support"
370
+ Rails.configuration = Rails::Configuration.new
371
+ initializer = Rails::Initializer.new(Rails.configuration)
372
+ initializer.check_gem_dependencies
373
+ require "vanity"
374
+ RB
375
+ tmp.write code
376
+ tmp.flush
377
+ Dir.chdir "tmp" do
378
+ open("|ruby #{tmp.path}").read
379
+ end
380
+ rescue
381
+ tmp.close!
382
+ end
383
+
384
+
385
+ def teardown
386
+ super
387
+ UseVanityController.send(:filter_chain).clear
388
+ end
389
+ end