eeny-meeny 2.1.4 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rspec +3 -0
- data/.simplecov +16 -0
- data/.travis.yml +3 -7
- data/CHANGELOG.md +35 -0
- data/Gemfile +0 -4
- data/README.md +1 -1
- data/eeny-meeny.gemspec +5 -5
- data/lib/eeny-meeny/{experiment_helper.rb → helpers/experiment_helper.rb} +6 -0
- data/lib/eeny-meeny/middleware.rb +50 -23
- data/lib/eeny-meeny/models/cookie.rb +2 -2
- data/lib/eeny-meeny/models/encryptor.rb +2 -2
- data/lib/eeny-meeny/models/experiment.rb +17 -0
- data/lib/eeny-meeny/railtie.rb +8 -4
- data/lib/eeny-meeny/version.rb +1 -1
- data/lib/tasks/cookie.rake +1 -1
- data/spec/eeny-meeny/experiment_helper_spec.rb +1 -2
- data/spec/eeny-meeny/middleware_spec.rb +21 -2
- data/spec/eeny-meeny/models/cookie_spec.rb +0 -1
- data/spec/eeny-meeny/models/experiment_spec.rb +32 -2
- data/spec/eeny-meeny/models/variation_spec.rb +0 -1
- data/spec/fixtures/empty_experiments.yml +0 -0
- data/spec/fixtures/experiments.yml +10 -0
- data/spec/spec_helper.rb +6 -15
- data/spec/tasks/cookie_task_spec.rb +0 -1
- metadata +23 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: eb901520367109f3167e217522a3b712ae71167e04c0458d4dac2b0907b541bc
|
4
|
+
data.tar.gz: b360de703e230a8aef6fb7ec7211fe24aa2f79007bb2c3344591a452b40d26ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9e244e1ba2895921276b2fe070689a2694296ce8db150e0f9ddde380608d65e5cda63afe6e130981da0c7eed3e5e32eb67e28b021cfc38cbf8d931d23b4a8e3
|
7
|
+
data.tar.gz: e84d5450b37db881191650f259a9abe353d63e8ab8cbdda3c666932029ad78774281f8d99ea73491c74f1807d3aad7dce6908b678c779b888b1c79a32b7c3b2d
|
data/.rspec
ADDED
data/.simplecov
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'simplecov-rcov'
|
4
|
+
|
5
|
+
formatters = [
|
6
|
+
SimpleCov::Formatter::HTMLFormatter,
|
7
|
+
SimpleCov::Formatter::RcovFormatter
|
8
|
+
]
|
9
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(formatters)
|
10
|
+
SimpleCov.add_group('Lib', 'lib')
|
11
|
+
SimpleCov.add_group('Helpers', 'lib/eeny-meeny/helpers')
|
12
|
+
SimpleCov.add_group('Models', 'lib/eeny-meeny/models')
|
13
|
+
SimpleCov.add_group('Routing', 'lib/eeny-meeny/routing')
|
14
|
+
SimpleCov.add_group('Rake Tasks', 'lib/tasks')
|
15
|
+
SimpleCov.add_group('Specs', 'spec')
|
16
|
+
SimpleCov.start
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,38 @@
|
|
1
|
+
### 2.3.0 (2021-08-11)
|
2
|
+
|
3
|
+
Changes:
|
4
|
+
|
5
|
+
- Support Rails 6 (PR: #11).
|
6
|
+
- Remove cookies for previous experiment versions (PR: #12).
|
7
|
+
- Update Travis configuration to include Ruby version 2.6 to 2.7.
|
8
|
+
|
9
|
+
### 2.2.2 (2019-04-08)
|
10
|
+
|
11
|
+
Bugfixes:
|
12
|
+
|
13
|
+
- Handle scenario where EenyMeeny is configured with an empty experiments file (https://github.com/corthmann/eeny-meeny/issues/9)
|
14
|
+
|
15
|
+
Other Changes:
|
16
|
+
|
17
|
+
- Update development dependency "yard" in .gemspec file
|
18
|
+
|
19
|
+
### 2.2.1 (2018-09-09)
|
20
|
+
|
21
|
+
Changes:
|
22
|
+
|
23
|
+
- Fix `OpenSSL::Cipher::Cipher` deprecation warning in `EenyMeeny::Encryptor`.
|
24
|
+
- Update Travis configuration to include Ruby version 2.2 to 2.5.
|
25
|
+
|
26
|
+
### 2.2.0 (2018-07-24)
|
27
|
+
|
28
|
+
Features:
|
29
|
+
|
30
|
+
- Let `Eeny::Meeny::Middleware` remove deprecated experiment cookies (for undefined and inactive experiements)
|
31
|
+
|
32
|
+
Changes:
|
33
|
+
|
34
|
+
- Renamed `EenyMeeny::Cookie::COOKIE_PREFIX` to `EenyMeeny::Cookie::EXPERIMENT_PREFIX`
|
35
|
+
|
1
36
|
### 2.1.4 (2017-10-04)
|
2
37
|
|
3
38
|
Changes:
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,7 @@ eeny-meeny
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/eeny-meeny.svg)](https://badge.fury.io/rb/eeny-meeny)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/corthmann/eeny-meeny/badges/gpa.svg)](https://codeclimate.com/github/corthmann/eeny-meeny)
|
5
5
|
[![Test Coverage](https://codeclimate.com/github/corthmann/eeny-meeny/badges/coverage.svg)](https://codeclimate.com/github/corthmann/eeny-meeny/coverage)
|
6
|
-
[![Build Status](https://travis-ci.
|
6
|
+
[![Build Status](https://travis-ci.com/corthmann/eeny-meeny.svg?branch=master)](https://travis-ci.com/corthmann/eeny-meeny)
|
7
7
|
|
8
8
|
Installation
|
9
9
|
-------------
|
data/eeny-meeny.gemspec
CHANGED
@@ -3,7 +3,7 @@ require File.expand_path('../lib/eeny-meeny/version', __FILE__)
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'eeny-meeny'
|
5
5
|
s.version = EenyMeeny::VERSION.dup
|
6
|
-
s.date = '
|
6
|
+
s.date = '2021-08-11'
|
7
7
|
s.summary = "A simple split and smoke testing tool for Rails"
|
8
8
|
s.authors = ["Christian Orthmann"]
|
9
9
|
s.email = 'christian.orthmann@gmail.com'
|
@@ -13,12 +13,12 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.homepage = 'http://rubygems.org/gems/eeny-meeny'
|
14
14
|
s.license = 'MIT'
|
15
15
|
|
16
|
-
s.add_development_dependency('rake', '~>
|
16
|
+
s.add_development_dependency('rake', '~> 13')
|
17
17
|
s.add_development_dependency('rspec', '~> 3')
|
18
18
|
s.add_development_dependency('simplecov', '~> 0')
|
19
19
|
s.add_development_dependency('simplecov-rcov', '~> 0')
|
20
|
-
s.add_development_dependency('yard', '
|
21
|
-
s.add_development_dependency('rack-test', '~>
|
20
|
+
s.add_development_dependency('yard', '>= 0.9.11', '< 1.0.0')
|
21
|
+
s.add_development_dependency('rack-test', '~> 1')
|
22
22
|
s.add_runtime_dependency('rack', '>= 1.2.1', '< 3')
|
23
|
-
s.add_runtime_dependency('activesupport', '>= 3.0.0', '< 6.
|
23
|
+
s.add_runtime_dependency('activesupport', '>= 3.0.0', '< 6.2.0')
|
24
24
|
end
|
@@ -1,7 +1,13 @@
|
|
1
|
+
require 'active_support/concern'
|
1
2
|
require 'eeny-meeny/models/cookie'
|
2
3
|
require 'eeny-meeny/models/experiment'
|
3
4
|
|
4
5
|
module EenyMeeny::ExperimentHelper
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
helper_method :participates_in?, :smoke_test?
|
10
|
+
end
|
5
11
|
|
6
12
|
def participates_in?(experiment_id, variation_id: nil)
|
7
13
|
experiment = EenyMeeny::Experiment.find_by_id(experiment_id)
|
@@ -24,34 +24,15 @@ module EenyMeeny
|
|
24
24
|
query_parameters = query_hash(env)
|
25
25
|
now = Time.zone.now
|
26
26
|
new_cookies = {}
|
27
|
+
delete_cookies = find_deprecated_cookies(cookies, now)
|
27
28
|
# Prepare for experiments.
|
28
29
|
@experiments.each do |experiment|
|
29
30
|
# Skip inactive experiments
|
30
31
|
next unless experiment.active?(now)
|
31
|
-
|
32
|
-
cookie_name = EenyMeeny::Cookie.cookie_name(experiment)
|
33
|
-
has_experiment_trigger = EenyMeeny.config.query_parameters[:experiment] && query_parameters.key?(cookie_name)
|
34
|
-
# skip experiments that already have a cookie
|
35
|
-
next unless has_experiment_trigger || !cookies.key?(cookie_name)
|
36
|
-
cookie = if has_experiment_trigger
|
37
|
-
# Trigger experiment variation through query parameter.
|
38
|
-
EenyMeeny::Cookie.create_for_experiment_variation(experiment, query_parameters[cookie_name].to_sym, @cookie_config)
|
39
|
-
else
|
40
|
-
EenyMeeny::Cookie.create_for_experiment(experiment, @cookie_config)
|
41
|
-
end
|
42
|
-
# Set HTTP_COOKIE header to enable experiment on first pageview
|
43
|
-
env = add_or_replace_http_cookie(env, cookie)
|
44
|
-
new_cookies[cookie.name] = cookie
|
45
|
-
end
|
46
|
-
# Prepare smoke tests (if enabled through query parameters)
|
47
|
-
if EenyMeeny.config.query_parameters[:smoke_test]
|
48
|
-
if query_parameters.key?('smoke_test_id') && (query_parameters['smoke_test_id'] =~ /\A[A-Za-z_]+\z/)
|
49
|
-
# Set HTTP_COOKIE header to enable smoke test on first pageview
|
50
|
-
cookie = EenyMeeny::Cookie.create_for_smoke_test(query_parameters['smoke_test_id'], @cookie_config)
|
51
|
-
env = add_or_replace_http_cookie(env, cookie)
|
52
|
-
new_cookies[cookie.name] = cookie
|
53
|
-
end
|
32
|
+
env, new_cookies = prepare_experiment(env, cookies, new_cookies, query_parameters, experiment)
|
54
33
|
end
|
34
|
+
# Prepare smoke tests
|
35
|
+
env, new_cookies = prepare_smoke_test(env, new_cookies, query_parameters)
|
55
36
|
# Delegate to app
|
56
37
|
status, headers, body = @app.call(env)
|
57
38
|
response = Rack::Response.new(body, status, headers)
|
@@ -59,11 +40,57 @@ module EenyMeeny
|
|
59
40
|
new_cookies.each do |key, value|
|
60
41
|
response.set_cookie(key,value.to_h)
|
61
42
|
end
|
43
|
+
delete_cookies.each do |key, value|
|
44
|
+
response.delete_cookie(key, value: value, path: @cookie_config[:path], same_site: @cookie_config[:same_site])
|
45
|
+
end
|
62
46
|
response.finish
|
63
47
|
end
|
64
48
|
|
65
49
|
private
|
66
50
|
|
51
|
+
def find_deprecated_cookies(cookies, now)
|
52
|
+
deprecated_cookies = {}
|
53
|
+
cookies.each do |cookie_name, value|
|
54
|
+
# Skip any cookie that does not have the 'eeny_meeny_' prefix
|
55
|
+
next unless cookie_name.to_s.start_with?(EenyMeeny::Cookie::EXPERIMENT_PREFIX)
|
56
|
+
# Mark cookies that does not match any existing active experiment as 'deprecated'.
|
57
|
+
experiment = EenyMeeny::Experiment.find_by_cookie_name(cookie_name)
|
58
|
+
next if experiment && experiment.active?(now)
|
59
|
+
deprecated_cookies[cookie_name] = value
|
60
|
+
end
|
61
|
+
deprecated_cookies
|
62
|
+
end
|
63
|
+
|
64
|
+
def prepare_experiment(env, cookies, new_cookies, query_parameters, experiment)
|
65
|
+
# Trigger experiment through query parameters
|
66
|
+
cookie_name = EenyMeeny::Cookie.cookie_name(experiment)
|
67
|
+
has_experiment_trigger = EenyMeeny.config.query_parameters[:experiment] && query_parameters.key?(cookie_name)
|
68
|
+
# Skip experiments that already have a cookie
|
69
|
+
return env, new_cookies unless has_experiment_trigger || !cookies.key?(cookie_name)
|
70
|
+
cookie = if has_experiment_trigger
|
71
|
+
# Trigger experiment variation through query parameter.
|
72
|
+
EenyMeeny::Cookie.create_for_experiment_variation(experiment, query_parameters[cookie_name].to_sym, @cookie_config)
|
73
|
+
else
|
74
|
+
EenyMeeny::Cookie.create_for_experiment(experiment, @cookie_config)
|
75
|
+
end
|
76
|
+
# Set HTTP_COOKIE header to enable experiment on first pageview
|
77
|
+
env = add_or_replace_http_cookie(env, cookie)
|
78
|
+
new_cookies[cookie.name] = cookie
|
79
|
+
return env, new_cookies
|
80
|
+
end
|
81
|
+
|
82
|
+
def prepare_smoke_test(env, new_cookies, query_parameters)
|
83
|
+
# Skip if the EenyMeeny 'smoke test' query parameters configuration is disabled.
|
84
|
+
return env, new_cookies unless EenyMeeny.config.query_parameters[:smoke_test]
|
85
|
+
# Skip if no valid 'smoke_test_id' query parameter present
|
86
|
+
return env, new_cookies unless query_parameters.key?('smoke_test_id') && (query_parameters['smoke_test_id'] =~ /\A[A-Za-z_]+\z/)
|
87
|
+
# Set HTTP_COOKIE header to enable smoke test on first pageview
|
88
|
+
cookie = EenyMeeny::Cookie.create_for_smoke_test(query_parameters['smoke_test_id'], **@cookie_config)
|
89
|
+
env = add_or_replace_http_cookie(env, cookie)
|
90
|
+
new_cookies[cookie.name] = cookie
|
91
|
+
return env, new_cookies
|
92
|
+
end
|
93
|
+
|
67
94
|
def query_hash(env)
|
68
95
|
# Query Params are only relevant if EenyMeeny.config have them enabled.
|
69
96
|
return {} unless EenyMeeny.config.query_parameters[:experiment] || EenyMeeny.config.query_parameters[:smoke_test]
|
@@ -2,7 +2,7 @@ require 'rack'
|
|
2
2
|
|
3
3
|
module EenyMeeny
|
4
4
|
class Cookie
|
5
|
-
|
5
|
+
EXPERIMENT_PREFIX = 'eeny_meeny_'.freeze
|
6
6
|
SMOKE_TEST_PREFIX = 'smoke_test_'.freeze
|
7
7
|
|
8
8
|
attr_accessor :value
|
@@ -52,7 +52,7 @@ module EenyMeeny
|
|
52
52
|
|
53
53
|
def self.cookie_name(experiment)
|
54
54
|
return if experiment.nil?
|
55
|
-
|
55
|
+
EXPERIMENT_PREFIX+experiment.id.to_s+'_v'+experiment.version.to_s
|
56
56
|
end
|
57
57
|
|
58
58
|
def self.read(cookie_string)
|
@@ -92,7 +92,7 @@ module EenyMeeny
|
|
92
92
|
# Encrypts the given message with a random IV, then returns the ciphertext
|
93
93
|
# with the IV prepended.
|
94
94
|
def encrypt_message(message)
|
95
|
-
aes = OpenSSL::Cipher
|
95
|
+
aes = OpenSSL::Cipher.new(@cipher).encrypt
|
96
96
|
aes.key = @encryption_key
|
97
97
|
iv = aes.random_iv
|
98
98
|
aes.iv = iv
|
@@ -105,7 +105,7 @@ module EenyMeeny
|
|
105
105
|
# OpenSSL errors and returns nil. But this should never happen, as the
|
106
106
|
# verify method should catch all corrupted ciphertexts.
|
107
107
|
def decrypt_ciphertext(ciphertext)
|
108
|
-
aes = OpenSSL::Cipher
|
108
|
+
aes = OpenSSL::Cipher.new(@cipher).decrypt
|
109
109
|
aes.key = @encryption_key
|
110
110
|
iv = ciphertext[0, aes.iv_len]
|
111
111
|
aes.iv = iv
|
@@ -1,22 +1,39 @@
|
|
1
|
+
require 'eeny-meeny/models/cookie'
|
1
2
|
require 'eeny-meeny/models/variation'
|
2
3
|
require 'active_support/time'
|
3
4
|
require 'active_support/core_ext/enumerable'
|
4
5
|
|
5
6
|
module EenyMeeny
|
6
7
|
class Experiment
|
8
|
+
|
9
|
+
COOKIE_EXPERIMENT_ID_REGEX = Regexp.new(
|
10
|
+
"\\A#{EenyMeeny::Cookie::EXPERIMENT_PREFIX}(.+)_v(\\d+)\\z"
|
11
|
+
).freeze
|
12
|
+
|
7
13
|
attr_reader :id, :name, :version, :variations, :total_weight, :end_at, :start_at
|
8
14
|
|
9
15
|
def self.find_all
|
16
|
+
return [] unless EenyMeeny.config.experiments
|
10
17
|
EenyMeeny.config.experiments.map do |id, experiment|
|
11
18
|
new(id, **experiment)
|
12
19
|
end
|
13
20
|
end
|
14
21
|
|
15
22
|
def self.find_by_id(experiment_id)
|
23
|
+
return unless EenyMeeny.config.experiments
|
16
24
|
experiment = EenyMeeny.config.experiments[experiment_id.to_sym]
|
17
25
|
new(experiment_id, **experiment) if experiment
|
18
26
|
end
|
19
27
|
|
28
|
+
def self.find_by_cookie_name(cookie_name)
|
29
|
+
return unless cookie_name =~ COOKIE_EXPERIMENT_ID_REGEX
|
30
|
+
|
31
|
+
experiment = find_by_id($1)
|
32
|
+
return unless experiment && experiment.version.to_s == $2
|
33
|
+
|
34
|
+
experiment
|
35
|
+
end
|
36
|
+
|
20
37
|
def initialize(id, name: '', version: 1, variations: {}, start_at: nil, end_at: nil)
|
21
38
|
@id = id
|
22
39
|
@name = name
|
data/lib/eeny-meeny/railtie.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'eeny-meeny'
|
2
|
-
require 'eeny-meeny/experiment_helper'
|
3
2
|
require 'eeny-meeny/middleware'
|
3
|
+
require 'eeny-meeny/helpers/experiment_helper'
|
4
4
|
|
5
5
|
module EenyMeeny
|
6
6
|
class Railtie < Rails::Railtie
|
@@ -15,13 +15,17 @@ module EenyMeeny
|
|
15
15
|
config.secure = app.config.eeny_meeny[:secure] if app.config.eeny_meeny.key?(:secure)
|
16
16
|
config.query_parameters = app.config.eeny_meeny[:query_parameters] if app.config.eeny_meeny.key?(:query_parameters)
|
17
17
|
end
|
18
|
-
# Include Helpers in ActionController and ActionView
|
19
|
-
ActionController::Base.send :include, EenyMeeny::ExperimentHelper
|
20
|
-
ActionView::Base.send :include, EenyMeeny::ExperimentHelper
|
21
18
|
# Insert Middleware
|
22
19
|
app.middleware.insert_before ActionDispatch::Cookies, EenyMeeny::Middleware
|
23
20
|
end
|
24
21
|
|
22
|
+
config.to_prepare do
|
23
|
+
# Include Helpers in ActionController and ActionView
|
24
|
+
ActiveSupport.on_load(:action_controller_base) do
|
25
|
+
include EenyMeeny::ExperimentHelper
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
25
29
|
rake_tasks do
|
26
30
|
load 'tasks/cookie.rake'
|
27
31
|
end
|
data/lib/eeny-meeny/version.rb
CHANGED
data/lib/tasks/cookie.rake
CHANGED
@@ -38,7 +38,7 @@ namespace :eeny_meeny do
|
|
38
38
|
raise "Missing 'smoke_test_id' parameter" if (args['smoke_test_id'].nil? || args['smoke_test_id'].empty?)
|
39
39
|
smoke_test_id = args['smoke_test_id']
|
40
40
|
version = args['version'] || 1
|
41
|
-
cookie = EenyMeeny::Cookie.create_for_smoke_test(smoke_test_id, EenyMeeny.config.cookies.merge(version: version))
|
41
|
+
cookie = EenyMeeny::Cookie.create_for_smoke_test(smoke_test_id, **EenyMeeny.config.cookies.merge(version: version))
|
42
42
|
puts cookie
|
43
43
|
end
|
44
44
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'spec_helper'
|
2
1
|
require 'eeny-meeny/models/encryptor'
|
3
2
|
require 'eeny-meeny/middleware'
|
4
3
|
|
@@ -55,7 +54,7 @@ describe EenyMeeny::Middleware do
|
|
55
54
|
let(:request) { Rack::MockRequest.new(subject) }
|
56
55
|
|
57
56
|
before(:example) do
|
58
|
-
@original_request_cookies = 'test=abc;eeny_meeny_my_page_v1=on1tOQ5hiKdA0biVZVwvTUQcmkODacwdpi%2FedQJIYQz9KdWYAXqzCafF5Dqqa6xtHFBdXYVmz%2Bp4%2FigmKz4hBVYZbJU%2FMwBbvYG%2BIoBelk10PxwtyxbA%2BiDzFT4jZeiTkNOmZ3rp1Gzz74JjT4aocqB187p7SrpeM2jfyZ8ZKPOiZs6tXf0QoXkV%2BZbtxJLRPr5lgmGxslfM8vCIm1%2F0HQ%3D%3D;'
|
57
|
+
@original_request_cookies = 'test=abc;eeny_meeny_my_page_v1=on1tOQ5hiKdA0biVZVwvTUQcmkODacwdpi%2FedQJIYQz9KdWYAXqzCafF5Dqqa6xtHFBdXYVmz%2Bp4%2FigmKz4hBVYZbJU%2FMwBbvYG%2BIoBelk10PxwtyxbA%2BiDzFT4jZeiTkNOmZ3rp1Gzz74JjT4aocqB187p7SrpeM2jfyZ8ZKPOiZs6tXf0QoXkV%2BZbtxJLRPr5lgmGxslfM8vCIm1%2F0HQ%3D%3D;eeny_meeny_versioned_v3=UUgXwn3j0%2BOL2cpov4duTnuCJPc621yHd6GjuXpN0gnYLDASTsDpyk01CnFY5ZYCAo%2BgLO%2BwTbsYObP8dp30rA%3D%3D;'
|
59
58
|
@response = request.get('/test',
|
60
59
|
'CONTENT_TYPE' => 'text/plain',
|
61
60
|
'HTTP_COOKIE' => @original_request_cookies)
|
@@ -70,6 +69,26 @@ describe EenyMeeny::Middleware do
|
|
70
69
|
end
|
71
70
|
end
|
72
71
|
|
72
|
+
context 'and the request contains a cookie from an undefined experiment' do
|
73
|
+
let(:request) { Rack::MockRequest.new(subject) }
|
74
|
+
let(:cookie_value) { 'eeny_meeny_undefined_experiment_v1=thevaluedoesntmatter' }
|
75
|
+
let(:return_value) do
|
76
|
+
"#{cookie_value}; path=/; max-age=0; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Strict"
|
77
|
+
end
|
78
|
+
|
79
|
+
before(:example) do
|
80
|
+
@original_request_cookies = "test=abc;#{cookie_value};"
|
81
|
+
@response = request.get('/test',
|
82
|
+
'CONTENT_TYPE' => 'text/plain',
|
83
|
+
'HTTP_COOKIE' => @original_request_cookies)
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
it "instructs the browser to remove through the 'Set-Cookie' header on the response" do
|
88
|
+
expect(@response['Set-Cookie']).to include(return_value)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
73
92
|
context 'and given an experiment query parameter' do
|
74
93
|
let(:request) { Rack::MockRequest.new(initialize_app(secure: false)) }
|
75
94
|
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'spec_helper'
|
2
1
|
require 'eeny-meeny/models/experiment'
|
3
2
|
require 'eeny-meeny/models/variation'
|
4
3
|
|
@@ -158,7 +157,7 @@ describe EenyMeeny::Experiment do
|
|
158
157
|
it 'returns those experiments' do
|
159
158
|
instances = described_class.find_all
|
160
159
|
expect(instances).to be_a Array
|
161
|
-
expect(instances.size).to eq(
|
160
|
+
expect(instances.size).to eq(3)
|
162
161
|
instances.each do |instance|
|
163
162
|
expect(instance).to be_a EenyMeeny::Experiment
|
164
163
|
end
|
@@ -170,6 +169,12 @@ describe EenyMeeny::Experiment do
|
|
170
169
|
expect(described_class.find_all).to eq([])
|
171
170
|
end
|
172
171
|
end
|
172
|
+
|
173
|
+
context 'when EenyMeeny is configured with an empty experiments file', empty_experiments: true do
|
174
|
+
it 'returns an empty array' do
|
175
|
+
expect(described_class.find_all).to eq([])
|
176
|
+
end
|
177
|
+
end
|
173
178
|
end
|
174
179
|
|
175
180
|
describe '.find_by_id' do
|
@@ -192,6 +197,31 @@ describe EenyMeeny::Experiment do
|
|
192
197
|
expect(described_class.find_by_id(:experiment_missing)).to be_nil
|
193
198
|
end
|
194
199
|
end
|
200
|
+
|
201
|
+
context 'when EenyMeeny is configured with an empty experiments file', empty_experiments: true do
|
202
|
+
it 'returns nil' do
|
203
|
+
expect(described_class.find_by_id(:experiment_missing)).to be_nil
|
204
|
+
end
|
205
|
+
end
|
195
206
|
end
|
196
207
|
|
208
|
+
describe '.find_by_cookie_name', experiments: true do
|
209
|
+
context 'when the given cookie name matches a configured experiment' do
|
210
|
+
it 'returns the experiment' do
|
211
|
+
expect(described_class.find_by_cookie_name(:eeny_meeny_my_page_v1)).to be_a EenyMeeny::Experiment
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
context 'when the given cookie name does not match the experiment version' do
|
216
|
+
it 'returns the experiment' do
|
217
|
+
expect(described_class.find_by_cookie_name(:eeny_meeny_versioned_v2)).to be_nil
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context 'when the given cookie name does not match a configured experiment' do
|
222
|
+
it 'returns nil' do
|
223
|
+
expect(described_class.find_by_cookie_name(:eeny_meeny_undefined_experiment_v2)).to be_nil
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
197
227
|
end
|
File without changes
|
@@ -8,6 +8,16 @@
|
|
8
8
|
:new:
|
9
9
|
:name: New My Page
|
10
10
|
:weight: 0.98
|
11
|
+
:versioned:
|
12
|
+
:name: Versioned
|
13
|
+
:version: 3
|
14
|
+
:variations:
|
15
|
+
:old:
|
16
|
+
:name: Old Versioned Page
|
17
|
+
:weight: 0.02
|
18
|
+
:new:
|
19
|
+
:name: New Versioned Page
|
20
|
+
:weight: 0.98
|
11
21
|
:expired:
|
12
22
|
:name: Expired
|
13
23
|
:version: 1
|
data/spec/spec_helper.rb
CHANGED
@@ -1,28 +1,15 @@
|
|
1
1
|
require 'simplecov'
|
2
|
-
require 'simplecov-rcov'
|
3
|
-
require 'codeclimate-test-reporter'
|
4
2
|
require 'active_support/time'
|
5
|
-
|
6
|
-
SimpleCov.start do
|
7
|
-
formatter SimpleCov::Formatter::MultiFormatter.new([
|
8
|
-
SimpleCov::Formatter::HTMLFormatter,
|
9
|
-
SimpleCov::Formatter::RcovFormatter,
|
10
|
-
CodeClimate::TestReporter::Formatter])
|
11
|
-
add_group('EenyMeeny', 'lib/eeny-meeny')
|
12
|
-
add_group('Rake Tasks', 'lib/tasks')
|
13
|
-
add_group('Specs', 'spec')
|
14
|
-
end
|
15
|
-
|
16
3
|
require 'rspec'
|
17
4
|
require 'yaml'
|
18
5
|
require 'mock_rack_app'
|
19
|
-
|
20
6
|
require 'eeny-meeny'
|
21
7
|
|
22
8
|
RSpec.configure do |config|
|
23
9
|
config.run_all_when_everything_filtered = true
|
24
10
|
config.filter_run :focus
|
25
11
|
config.order = "random"
|
12
|
+
config.expose_dsl_globally = true
|
26
13
|
|
27
14
|
config.before(:suite) do
|
28
15
|
Time.zone = 'UTC'
|
@@ -36,5 +23,9 @@ RSpec.configure do |config|
|
|
36
23
|
config.experiments = YAML.load_file(File.join('spec','fixtures','experiments.yml'))
|
37
24
|
end
|
38
25
|
end
|
39
|
-
|
26
|
+
config.before(:each, empty_experiments: true) do
|
27
|
+
EenyMeeny.configure do |config|
|
28
|
+
config.experiments = YAML.load_file(File.join('spec','fixtures','empty_experiments.yml'))
|
29
|
+
end
|
30
|
+
end
|
40
31
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eeny-meeny
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christian Orthmann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '13'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '13'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,30 +70,36 @@ dependencies:
|
|
70
70
|
name: yard
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 0.9.11
|
76
|
+
- - "<"
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 1.0.0
|
76
79
|
type: :development
|
77
80
|
prerelease: false
|
78
81
|
version_requirements: !ruby/object:Gem::Requirement
|
79
82
|
requirements:
|
80
|
-
- - "
|
83
|
+
- - ">="
|
81
84
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
85
|
+
version: 0.9.11
|
86
|
+
- - "<"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 1.0.0
|
83
89
|
- !ruby/object:Gem::Dependency
|
84
90
|
name: rack-test
|
85
91
|
requirement: !ruby/object:Gem::Requirement
|
86
92
|
requirements:
|
87
93
|
- - "~>"
|
88
94
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
95
|
+
version: '1'
|
90
96
|
type: :development
|
91
97
|
prerelease: false
|
92
98
|
version_requirements: !ruby/object:Gem::Requirement
|
93
99
|
requirements:
|
94
100
|
- - "~>"
|
95
101
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
102
|
+
version: '1'
|
97
103
|
- !ruby/object:Gem::Dependency
|
98
104
|
name: rack
|
99
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,7 +129,7 @@ dependencies:
|
|
123
129
|
version: 3.0.0
|
124
130
|
- - "<"
|
125
131
|
- !ruby/object:Gem::Version
|
126
|
-
version: 6.
|
132
|
+
version: 6.2.0
|
127
133
|
type: :runtime
|
128
134
|
prerelease: false
|
129
135
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -133,13 +139,15 @@ dependencies:
|
|
133
139
|
version: 3.0.0
|
134
140
|
- - "<"
|
135
141
|
- !ruby/object:Gem::Version
|
136
|
-
version: 6.
|
142
|
+
version: 6.2.0
|
137
143
|
description:
|
138
144
|
email: christian.orthmann@gmail.com
|
139
145
|
executables: []
|
140
146
|
extensions: []
|
141
147
|
extra_rdoc_files: []
|
142
148
|
files:
|
149
|
+
- ".rspec"
|
150
|
+
- ".simplecov"
|
143
151
|
- ".travis.yml"
|
144
152
|
- CHANGELOG.md
|
145
153
|
- Gemfile
|
@@ -148,7 +156,7 @@ files:
|
|
148
156
|
- Rakefile
|
149
157
|
- eeny-meeny.gemspec
|
150
158
|
- lib/eeny-meeny.rb
|
151
|
-
- lib/eeny-meeny/experiment_helper.rb
|
159
|
+
- lib/eeny-meeny/helpers/experiment_helper.rb
|
152
160
|
- lib/eeny-meeny/middleware.rb
|
153
161
|
- lib/eeny-meeny/models/cookie.rb
|
154
162
|
- lib/eeny-meeny/models/encryptor.rb
|
@@ -166,6 +174,7 @@ files:
|
|
166
174
|
- spec/eeny-meeny/models/variation_spec.rb
|
167
175
|
- spec/eeny-meeny/routing/experiment_constraint_spec.rb
|
168
176
|
- spec/eeny-meeny/routing/smoke_test_constraint_spec.rb
|
177
|
+
- spec/fixtures/empty_experiments.yml
|
169
178
|
- spec/fixtures/experiments.yml
|
170
179
|
- spec/mock_rack_app.rb
|
171
180
|
- spec/spec_helper.rb
|
@@ -189,10 +198,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
189
198
|
- !ruby/object:Gem::Version
|
190
199
|
version: '0'
|
191
200
|
requirements: []
|
192
|
-
|
193
|
-
rubygems_version: 2.4.8
|
201
|
+
rubygems_version: 3.1.4
|
194
202
|
signing_key:
|
195
203
|
specification_version: 4
|
196
204
|
summary: A simple split and smoke testing tool for Rails
|
197
205
|
test_files: []
|
198
|
-
has_rdoc:
|