optimizely_server_side 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 145b5a0f2ef2177328463547242c89d2ed4ed033
4
- data.tar.gz: 9f91dde0bcdeac9263a8a9cdd1e5cd61dd63f094
3
+ metadata.gz: 52a8ee884cb6db767b45acb026984cb413f77dca
4
+ data.tar.gz: f674f904ce523f6003db14456367a47df57b48d2
5
5
  SHA512:
6
- metadata.gz: 71c7edd22820a695d10a3c99ace963614206af5bf0453d8b5819380dc0d0ac9f977c4200da8574c0458a9bb490e042a0ccd2debd659fdaef7ec65a0a475e2116
7
- data.tar.gz: adfc46a67cab06fc9b5cdb1529fcfc11bdac350a94d9260b0d59a0164f46e781d6223007b6e014e3eaae772d88cf046fd4c144b0a9a08639256f1e995b717927
6
+ metadata.gz: 42058be44f0bd1cc8ce1a16b6aae1e7aba342d558a4cc5f8dacf13a97a03f5c3751126cf4ba10839cc89a0701026f32213af3e777345051aa3650c22dc851068
7
+ data.tar.gz: 115f4e2b2ee276c8eb29b5160fd83074fc12b25aa01f5fcdaab5eb3400c7fcafad738f7fce52781095a96855f218aa6207dc0c7aa63c22567ee0aed0e5614b2a
data/.rspec CHANGED
@@ -1,2 +1,2 @@
1
- --format documentation
1
+ --format progress
2
2
  --color
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- optimizely_server_side (0.0.4)
4
+ optimizely_server_side (0.0.6)
5
5
  activesupport (~> 4.2, >= 4.2.6)
6
6
  optimizely-sdk (~> 0.1.1)
7
7
 
@@ -40,6 +40,8 @@ GEM
40
40
  rspec-core (~> 3.5.0)
41
41
  rspec-expectations (~> 3.5.0)
42
42
  rspec-mocks (~> 3.5.0)
43
+ rspec-collection_matchers (1.1.2)
44
+ rspec-expectations (>= 2.99.0.beta1)
43
45
  rspec-core (3.5.2)
44
46
  rspec-support (~> 3.5.0)
45
47
  rspec-expectations (3.5.0)
@@ -70,6 +72,7 @@ DEPENDENCIES
70
72
  codeclimate-test-reporter
71
73
  optimizely_server_side!
72
74
  rspec (~> 3.5)
75
+ rspec-collection_matchers (~> 1.1, >= 1.1.2)
73
76
  webmock (~> 2.1)
74
77
 
75
78
  BUNDLED WITH
data/Readme.md CHANGED
@@ -12,19 +12,20 @@ This is a wrapper on top of [Optimizely's](https://app.optimizely.com/projects)
12
12
 
13
13
  This gem solves few things:
14
14
 
15
- - **Syncing AB test config across different servers when you don't want to fetch config via REST endpoint or redis/memcache store**
15
+ - **Syncing A/B test config across different servers when you don't want to fetch config via REST endpoint or redis/memcache store**
16
16
 
17
17
  Yes, it's designed keeping performance in mind as we want to save a network overhead and a extra dependency.
18
18
 
19
19
  If you are using Optimizely you will be aware about the [datafile](http://developers.optimizely.com/server/reference/index.html#datafile). Once we make changes to the A/B test like change in percent distribution, start / pause a experiment this file get's updated.
20
20
 
21
- If you have 50 servers with 40 passenger / puma process these process needs to be updated. The Gem polls the config at regular interval and keeps the datafile cached across different process.
21
+ If you have 50 servers with 40 passenger / puma process each these process needs to be updated. The Gem polls the config at regular interval and keeps the datafile cached across different process.
22
22
 
23
23
  The config is stored in **Memory Store** . We use [Activesupport memory store](http://api.rubyonrails.org/classes/ActiveSupport/Cache/MemoryStore.html) for same.
24
24
 
25
- * **Some additional helpers**
25
+ * **Helper methods to better handle test and variations and handling fallbacks and experiment pause**
26
26
 
27
- Some more helpers exposed that can be exposed in views (.erbs) or PORO's. It avoids duplication of few activation settings.
27
+ Optimizely ruby sdk provides us way to know which variation to show. But what happens when the experiment is paused ? Or there is a error happening in config.
28
+ More details about this in below section of experiment config.
28
29
 
29
30
  ### Architecture
30
31
 
@@ -58,12 +59,13 @@ end
58
59
  `PROJECT_ID` is a id of your server side project at https://app.optimizely.com .
59
60
 
60
61
 
61
- Optimizely needs a visitor_id to track the unique user and server a constant experience.
62
+ Optimizely needs a `visitor_id` to track the unique user and server a constant experience.
62
63
 
63
64
  In your Application controller
64
65
 
65
66
  ```ruby
66
67
  class ApplicationController < ActionController::Base
68
+
67
69
  include OptimizelyServerSide::Support
68
70
 
69
71
  before_action :set_visitor_id
@@ -80,48 +82,98 @@ class ApplicationController < ActionController::Base
80
82
 
81
83
  ```
82
84
 
83
- Now in your views or models
85
+ ### Example usage
84
86
 
87
+ #### In your html.erb
85
88
 
86
89
  ```ruby
87
- experiment(EXPERIMENT_KEY) do |config|
90
+ # in any app/view/foo.html.erb
91
+ <% experiment(EXPERIMENT_KEY) do |config| %>
92
+ <% config.variation_one(VARIATION_ONE_KEY) do %>
93
+ <%= render partial: 'variation_one_experience'
94
+ <% end %>
95
+
96
+ <% config.variation_default(VARIATION_DEFAULT_KEY, primary: true) do %>
97
+ <%= render partial: 'variation_default_experience'
98
+ <% end %>
99
+ <% end %>
100
+ ```
88
101
 
89
- config.variation_one(VARIATION_ONE_KEY) do
90
- # Code for experience one. it can be html or a ruby code
91
- end
102
+ #### In your model or any PORO
92
103
 
93
- config.variation_two(VARIATION_TWO_KEY) do
94
- # Code for experience two. it can be html or a ruby code
95
- end
104
+ ```ruby
105
+ class Foo
106
+
107
+ include OptimizelyServerSide::Support
96
108
 
97
- config.variation_default(VARIATION_DEFAULT_KEY) do
98
- # Code for experience default. it can be html or a ruby code
99
- end
100
109
 
110
+ # This method is responsible from getting data from
111
+ # any other rest endpoint.
112
+ # Suppose you are doing a AB test on a new endpoint / data source.
113
+ def get_me_some_data
114
+ data = experiment(EXPERIMENT_KEY) do |config|
115
+
116
+ config.variation_one(VARIATION_ONE_KEY) do
117
+ HTTParty.get('http://from_source_a.com/users')
118
+ end
119
+
120
+ config.variation_default(VARIATION_TWO_KEY, primary: true) do
121
+ HTTParty.get('http://from_source_b.com/users')
122
+ end
123
+ end
124
+
125
+ end
101
126
  end
102
127
  ```
103
128
 
104
- `EXPERIMENT_KEY`: The experiment key that you will be getting while setting up your experiment from https://app.optimizely.com.
129
+ In the above examples:
130
+
131
+ `EXPERIMENT_KEY`: When you will set your experiment this key will be set up that time at https://app.optimizely.com.
105
132
 
106
- `VARIATION_ONE_KEY`: Key for Variation one. This will be also set when setting up experiment
133
+ `VARIATION_ONE_KEY`: Key for Variation one. This will be also set when setting up experiment.
107
134
 
108
- `VARIATION_TWO_KEY`: Key for Variation two. This will be also set when setting up experiment
135
+ `VARIATION_TWO_KEY`: Key for Variation two. This will be also set when setting up experiment.
109
136
 
110
137
  `VARIATION_DEFAULT_KEY`: Key for default experience. This will be also set when setting up experiment
111
138
 
139
+ `primary: true` : If you see above some variations are marked with `primary: true`. This enables handling the fallback capabilities of optimizely_server_side. If there is any error pulling datafile or experiment is paused the `primary` experience is served. Not setting primary won't give any experience during fallback times. We encourage setting it up.
140
+
112
141
  ![alt text](https://github.com/ankit8898/optimizely_server_side/blob/master/docs/screenshot.png "Logo Title Text 1")
113
142
 
114
- ### Testing
115
143
 
116
- Gem uses rspec for unit testing
144
+ ### Instrumentation
145
+
146
+ This is a trial feature and may or maynot exist in future version.
147
+
148
+ We have [ActiveSupport::Notifications](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html) hooked up for few places which are worth monitoring.
149
+
150
+
151
+ * When the datafile is fetched from cdn. In your application you can subscribe via below. This helps to monitor the time it takes from CDN fetch
117
152
 
118
153
  ```ruby
119
- bundle exec rspec .
154
+ ActiveSupport::Notifications.subscribe "oss.call_optimizely_cdn" do |name, started, finished, unique_id, data|
155
+ Rails.logger.info "GET Datafile from Optimizely CDN in #{(finished - started) * 1000} ms"
156
+ end
120
157
  ```
158
+ * Which variation is being served currently. In your application you can subscribe via below
159
+
160
+ ```ruby
121
161
 
162
+ ActiveSupport::Notifications.subscribe "oss.variation" do |name, started, finished, unique_id, data|
163
+ Rails.logger.info "GET Variation from OSS in #{(finished - started) * 1000} ms with variation key #{data[:variation]}"
164
+ end
122
165
  ```
123
- Finished in 0.28287 seconds (files took 1.3 seconds to load)
124
- 36 examples, 0 failures
166
+ ### Testing
167
+
168
+ Gem uses rspec for unit testing
169
+
170
+ ```ruby
171
+ $~/D/p/w/optimizely_server_side> rspec .
172
+ ......................................................
173
+
174
+ Finished in 0.12234 seconds (files took 0.5512 seconds to load)
175
+ 54 examples, 0 failures
176
+
125
177
  ```
126
178
 
127
179
  ### License
@@ -8,6 +8,7 @@ require 'optimizely_server_side/configuration'
8
8
  require 'optimizely_server_side/datafile_fetcher'
9
9
  require 'optimizely_server_side/experiment'
10
10
  require 'optimizely_server_side/optimizely_sdk'
11
+ require 'optimizely_server_side/variation'
11
12
  require 'optimizely_server_side/helpers/support'
12
13
 
13
14
  module OptimizelyServerSide
@@ -8,7 +8,7 @@ module OptimizelyServerSide
8
8
 
9
9
  attr_reader :content, :success
10
10
 
11
- def initialize(content:, success:)
11
+ def initialize(content: nil, success: false)
12
12
  @content = content
13
13
  @success = success
14
14
  end
@@ -16,6 +16,7 @@ module OptimizelyServerSide
16
16
  class << self
17
17
 
18
18
  # Fetch the Config from the specified source.
19
+ # Incase of any error or exception we goto the fallback data
19
20
  def fetch
20
21
  begin
21
22
  response = call_optimizely_cdn
@@ -2,36 +2,60 @@ module OptimizelyServerSide
2
2
  class Experiment
3
3
 
4
4
  def initialize(key)
5
- @another_key = key
6
- @store = {}
5
+ @selected_variation_key = key
6
+ @variations = []
7
7
  end
8
8
 
9
+ # Starts the experiment
9
10
  def start
10
11
  yield(self)
11
- self.compute
12
+ self.applicable_variation
12
13
  end
13
14
 
14
- def variation_one(key, &blk)
15
- @store[key] = blk
15
+ [
16
+ :variation_one,
17
+ :variation_two,
18
+ :variation_three,
19
+ :variation_default,
20
+ ].each do |variation|
21
+ define_method(variation) do |key, opts={}, &blk| # def variation_one(key, opts = {}, &blk)
22
+ add_variation(key, opts, &blk) # add_variation(key, opts, &blk)
23
+ end # end
16
24
  end
17
25
 
18
- def variation_two(key, &blk)
19
- @store[key] = blk
26
+ # Selects and calls the variation which is applicable
27
+ # In case of running test the applicable variation key is present
28
+ # In case of fallback / paused test we pick the primary variation
29
+ def applicable_variation
30
+ ActiveSupport::Notifications.instrument "oss.variation", variation: @another_key do
31
+ if @variations.any?(&variation_selector)
32
+ @variations.find(&variation_selector).call
33
+ else
34
+ primary_variation.call if primary_variation
35
+ end
36
+ end
20
37
  end
21
38
 
22
- def variation_three(key, &blk)
23
- @store[key] = blk
39
+ # Primary variation is where primary: true
40
+ def primary_variation
41
+ @primary_variation ||= @variations.find(&:primary)
24
42
  end
25
43
 
26
- def variation_default(key, &blk)
27
- @store[key] = blk
44
+ private
45
+
46
+ # Scope to query on selected variation
47
+ def variation_selector
48
+ ->(variation) { variation.key == @selected_variation_key }
28
49
  end
29
50
 
30
- def compute
31
- ActiveSupport::Notifications.instrument "variation.variation", variation: @another_key do
32
- if @store[@another_key]
33
- @store[@another_key].call
34
- end
51
+ # Add all the variation to the variations collection
52
+ def add_variation(key, opts = {}, &blk)
53
+ Variation.new(
54
+ key: key,
55
+ primary: opts[:primary] || false,
56
+ content: blk
57
+ ).tap do |variation_instance|
58
+ @variations << variation_instance
35
59
  end
36
60
  end
37
61
 
@@ -14,12 +14,11 @@ module OptimizelyServerSide
14
14
  # # Code related to variation two
15
15
  # end
16
16
  #
17
- # config.variation_default('variation_default_key') do
17
+ # config.variation_default('variation_default_key', primary: true) do
18
18
  # # We still want to keep our default experience
19
19
  # end
20
20
  #
21
21
  # end
22
-
23
22
  def experiment(experiment_key, &blk)
24
23
  variation_key = optimizely_sdk_project_instance(experiment_key)
25
24
  OptimizelyServerSide::Experiment.new(variation_key).start(&blk)
@@ -0,0 +1,23 @@
1
+ module OptimizelyServerSide
2
+ class Variation
3
+
4
+ # Class holding meta data about variation.
5
+ # content: The block / content of the variation
6
+ # Primary: If this is the primary variation. Primary is
7
+ # applicable in the cases of fallback / test is paused.
8
+
9
+ attr_reader :primary, :key
10
+
11
+ def initialize(primary: false, content: nil, key: nil)
12
+ @primary = primary
13
+ @key = key
14
+ @content = content
15
+ end
16
+
17
+ # Content is a block. Call is calling that block.
18
+ def call
19
+ @content.call
20
+ end
21
+
22
+ end
23
+ end
@@ -2,10 +2,10 @@ $:.push File.expand_path("../lib", __FILE__)
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'optimizely_server_side'
5
- s.version = '0.0.5'
5
+ s.version = '0.0.6'
6
6
  s.date = '2016-08-14'
7
7
  s.summary = "Optimizely server side. A wrapper on top of optimizely's ruby sdk for easy caching of server side config "
8
- s.description = "Optimizely server side. A AB test wrapper on top of optimizely's ruby sdk for easy caching of server side config and exposing few more utility helpers. Handling of fallbacks and marking primary experiments. "
8
+ s.description = "Optimizely server side. A A/B test wrapper on top of optimizely's ruby sdk for easy caching of server side config and exposing few more utility helpers. Handling of fallbacks and marking primary experiments. "
9
9
  s.authors = ["Ankit Gupta"]
10
10
  s.email = 'ankit.gupta8898@gmail.com'
11
11
  s.files = `git ls-files`.split("\n")
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
  'https://github.com/ankit8898/optimizely_server_side'
17
17
  s.license = 'MIT'
18
18
  s.add_development_dependency 'rspec', '~> 3.5'
19
+ s.add_development_dependency 'rspec-collection_matchers', '~> 1.1', '>= 1.1.2'
19
20
  s.add_development_dependency 'webmock', '~> 2.1'
20
21
  s.add_runtime_dependency 'optimizely-sdk' , '~> 0.1.1'
21
22
  s.add_runtime_dependency 'activesupport', '~> 4.2', '>= 4.2.6'
@@ -5,7 +5,7 @@ RSpec.describe OptimizelyServerSide::Experiment do
5
5
  subject { OptimizelyServerSide::Experiment.new(variation_key = 'variation_key_a') }
6
6
 
7
7
 
8
- describe '#compute' do
8
+ describe '#applicable_variation' do
9
9
 
10
10
  before do
11
11
 
@@ -22,7 +22,7 @@ RSpec.describe OptimizelyServerSide::Experiment do
22
22
  context 'when variation_key is present' do
23
23
 
24
24
  it 'should result variation b' do
25
- expect(subject.compute).to eq('experience a')
25
+ expect(subject.applicable_variation).to eq('experience a')
26
26
  end
27
27
 
28
28
  end
@@ -32,7 +32,7 @@ RSpec.describe OptimizelyServerSide::Experiment do
32
32
  subject { OptimizelyServerSide::Experiment.new(variation_key = '') }
33
33
 
34
34
  it 'should be nil' do
35
- expect(subject.compute).to be_nil
35
+ expect(subject.applicable_variation).to be_nil
36
36
  end
37
37
  end
38
38
 
@@ -43,9 +43,26 @@ RSpec.describe OptimizelyServerSide::Experiment do
43
43
 
44
44
  let(:blk) { Proc.new { 'Hello!'} }
45
45
 
46
- it 'returns a block passed' do
47
- expect(subject.variation_one('foo', &blk)).to eq(blk)
46
+ before do
47
+ @variation_instance = subject.variation_one('foo', &blk)
48
+ end
49
+
50
+ it 'returns a variation instance passed' do
51
+ expect(@variation_instance).to be_kind_of(OptimizelyServerSide::Variation)
52
+ end
53
+
54
+ it 'returns a key of foo' do
55
+ expect(@variation_instance.key).to eq('foo')
56
+ end
57
+
58
+ it 'returns a content with blk ' do
59
+ expect(@variation_instance.instance_variable_get(:@content)).to eq(blk)
60
+ end
61
+
62
+ it 'is not primary' do
63
+ expect(@variation_instance.primary).to be(false)
48
64
  end
65
+
49
66
  end
50
67
 
51
68
 
@@ -53,8 +70,24 @@ RSpec.describe OptimizelyServerSide::Experiment do
53
70
 
54
71
  let(:blk) { -> {OpenStruct.new } }
55
72
 
56
- it 'returns a block passed' do
57
- expect(subject.variation_two('foo', &blk)).to eq(blk)
73
+ before do
74
+ @variation_instance = subject.variation_two('foo', &blk)
75
+ end
76
+
77
+ it 'returns a variation instance passed' do
78
+ expect(@variation_instance).to be_kind_of(OptimizelyServerSide::Variation)
79
+ end
80
+
81
+ it 'returns a key of foo' do
82
+ expect(@variation_instance.key).to eq('foo')
83
+ end
84
+
85
+ it 'returns a content with blk ' do
86
+ expect(@variation_instance.instance_variable_get(:@content)).to eq(blk)
87
+ end
88
+
89
+ it 'is not primary' do
90
+ expect(@variation_instance.primary).to be(false)
58
91
  end
59
92
  end
60
93
 
@@ -62,12 +95,53 @@ RSpec.describe OptimizelyServerSide::Experiment do
62
95
 
63
96
  let(:blk) { Proc.new { 'Hello!'} }
64
97
 
65
- it 'returns a block passed' do
66
- expect(subject.variation_three('foo', &blk)).to eq(blk)
98
+ before do
99
+ @variation_instance = subject.variation_three('foo', &blk)
100
+ end
101
+
102
+ it 'returns a variation instance passed' do
103
+ expect(@variation_instance).to be_kind_of(OptimizelyServerSide::Variation)
104
+ end
105
+
106
+ it 'returns a key of foo' do
107
+ expect(@variation_instance.key).to eq('foo')
108
+ end
109
+
110
+ it 'returns a content with blk ' do
111
+ expect(@variation_instance.instance_variable_get(:@content)).to eq(blk)
112
+ end
113
+
114
+ it 'is not primary' do
115
+ expect(@variation_instance.primary).to be(false)
67
116
  end
68
117
  end
69
118
 
70
- describe '#store' do
119
+ describe '#variation_default' do
120
+
121
+ let(:blk) { -> {'<div><h1>Hello</h1></div>'} }
122
+
123
+ before do
124
+ @variation_instance = subject.variation_default('foo', primary: true, &blk)
125
+ end
126
+
127
+ it 'returns a variation instance passed' do
128
+ expect(@variation_instance).to be_kind_of(OptimizelyServerSide::Variation)
129
+ end
130
+
131
+ it 'returns a key of foo' do
132
+ expect(@variation_instance.key).to eq('foo')
133
+ end
134
+
135
+ it 'returns a content with blk ' do
136
+ expect(@variation_instance.instance_variable_get(:@content)).to eq(blk)
137
+ end
138
+
139
+ it 'is primary' do
140
+ expect(@variation_instance.primary).to be(true)
141
+ end
142
+ end
143
+
144
+ describe '#variations' do
71
145
 
72
146
  context 'key accepts regular strings' do
73
147
 
@@ -77,8 +151,16 @@ RSpec.describe OptimizelyServerSide::Experiment do
77
151
  subject.variation_one('foo', &string_lambda)
78
152
  end
79
153
 
80
- it 'has value as string' do
81
- expect(subject.instance_variable_get(:@store)).to eq({'foo' => string_lambda})
154
+ it 'holds collection of variations' do
155
+ expect(subject.instance_variable_get(:@variations)).to have(1).items
156
+ end
157
+
158
+ it 'is a type of Variation' do
159
+ expect(subject.instance_variable_get(:@variations)[0]).to be_kind_of(OptimizelyServerSide::Variation)
160
+ end
161
+
162
+ it 'is having the block content' do
163
+ expect(subject.instance_variable_get(:@variations)[0].call).to eq('I am a variation')
82
164
  end
83
165
 
84
166
  end
@@ -92,8 +174,12 @@ RSpec.describe OptimizelyServerSide::Experiment do
92
174
  subject.variation_one('foo', &some_method)
93
175
  end
94
176
 
95
- it 'has value as proc' do
96
- expect(subject.instance_variable_get(:@store)).to eq({'foo' => some_method})
177
+ it 'has content as proc' do
178
+ expect(subject.instance_variable_get(:@variations)[0].instance_variable_get(:@content)).to eq(some_method)
179
+ end
180
+
181
+ it 'has key' do
182
+ expect(subject.instance_variable_get(:@variations)[0].key).to eq('foo')
97
183
  end
98
184
 
99
185
  end
@@ -129,10 +215,72 @@ RSpec.describe OptimizelyServerSide::Experiment do
129
215
  subject.variation_three('foo_three', &string_blk)
130
216
  end
131
217
 
132
- it 'has value as proc' do
133
- expect(subject.instance_variable_get(:@store)).to eq({'foo' => some_method, 'foo_two' => some_html_block, 'foo_three' => string_blk})
218
+ it 'has all variations' do
219
+ expect(subject.instance_variable_get(:@variations)).to have(3).items
220
+ end
221
+
222
+ it 'has all variations of class Variation' do
223
+ expect(subject.instance_variable_get(:@variations)).to all(be_an(OptimizelyServerSide::Variation))
224
+ end
225
+
226
+ end
227
+ end
228
+
229
+
230
+ describe '#primary_variation' do
231
+
232
+ let(:some_method) { Proc.new {|n| n*2 } }
233
+
234
+ let(:some_html_block) do
235
+ -> { '<h1>Foo</h1>' }
236
+ end
237
+
238
+ let(:string_blk) { -> { 'Hello!'} }
239
+
240
+
241
+ context 'when nothing is marked as primary' do
242
+
243
+ before do
244
+ subject.variation_one('foo', &some_method)
245
+
246
+ subject.variation_two('foo_two', &some_html_block)
247
+
248
+ subject.variation_three('foo_three', &string_blk)
249
+ end
250
+
251
+ it { expect(subject.primary_variation).to be_nil }
252
+ end
253
+
254
+ context 'when one is marked as primary' do
255
+
256
+ before do
257
+ subject.variation_one('foo', &some_method)
258
+
259
+ subject.variation_two('foo_two',primary: true, &some_html_block)
260
+
261
+ subject.variation_three('foo_three', &string_blk)
134
262
  end
135
263
 
264
+ it { expect(subject.primary_variation).not_to be_nil }
265
+
266
+ it { expect(subject.primary_variation.call).to eq('<h1>Foo</h1>') }
136
267
  end
268
+
269
+
270
+ context 'when multiple are marked as primary' do
271
+
272
+ before do
273
+ subject.variation_one('foo', &some_method)
274
+
275
+ subject.variation_three('foo_two', primary: true, &some_html_block)
276
+
277
+ subject.variation_two('foo_three',primary: true, &string_blk)
278
+ end
279
+
280
+ it { expect(subject.primary_variation).not_to be_nil }
281
+
282
+ it { expect(subject.primary_variation.call).to eq('<h1>Foo</h1>') }
283
+ end
284
+
137
285
  end
138
286
  end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe OptimizelyServerSide::Variation do
4
+
5
+ describe '#primary' do
6
+
7
+ context 'when no primary is passed' do
8
+
9
+ subject { described_class.new }
10
+
11
+ it 'defaults to false' do
12
+ expect(subject.primary).to be(false)
13
+ end
14
+
15
+ end
16
+
17
+ context 'when primary is passed' do
18
+
19
+ subject { described_class.new(primary: true) }
20
+
21
+ it 'is as per passed' do
22
+ expect(subject.primary).to be(true)
23
+ end
24
+
25
+ end
26
+ end
27
+
28
+
29
+ describe '#content' do
30
+
31
+ context 'when no content is passed' do
32
+
33
+ subject { described_class.new }
34
+
35
+ it 'defaults to nil' do
36
+ expect(subject.instance_variable_get(:@content)).to be_nil
37
+ end
38
+
39
+ end
40
+
41
+ context 'when content is passed' do
42
+
43
+ let(:some_proc) { Proc.new { |n| "Hello #{n} world!"} }
44
+
45
+ subject { described_class.new(content: some_proc) }
46
+
47
+ it 'is as per passed' do
48
+ expect(subject.instance_variable_get(:@content)).to be(some_proc)
49
+ end
50
+
51
+ end
52
+ end
53
+
54
+ describe '#key' do
55
+
56
+ context 'when no key is passed' do
57
+
58
+ subject { described_class.new }
59
+
60
+ it 'defaults to nil' do
61
+ expect(subject.instance_variable_get(:@key)).to be_nil
62
+ end
63
+ end
64
+
65
+ context 'when key is passed' do
66
+
67
+
68
+ subject { described_class.new(key: 'ankit_test') }
69
+
70
+ it 'is as per passed' do
71
+ expect(subject.instance_variable_get(:@key)).to eq('ankit_test')
72
+ end
73
+ end
74
+ end
75
+ end
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,8 @@ CodeClimate::TestReporter.start
3
3
 
4
4
  require 'bundler/setup'
5
5
  require 'webmock/rspec'
6
+ require 'rspec/collection_matchers'
7
+
6
8
  Bundler.setup
7
9
 
8
10
  require 'optimizely_server_side'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: optimizely_server_side
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ankit Gupta
@@ -24,6 +24,26 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-collection_matchers
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 1.1.2
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '1.1'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.1.2
27
47
  - !ruby/object:Gem::Dependency
28
48
  name: webmock
29
49
  requirement: !ruby/object:Gem::Requirement
@@ -72,9 +92,9 @@ dependencies:
72
92
  - - ">="
73
93
  - !ruby/object:Gem::Version
74
94
  version: 4.2.6
75
- description: 'Optimizely server side. A AB test wrapper on top of optimizely''s ruby
76
- sdk for easy caching of server side config and exposing few more utility helpers. Handling
77
- of fallbacks and marking primary experiments. '
95
+ description: 'Optimizely server side. A A/B test wrapper on top of optimizely''s ruby
96
+ sdk for easy caching of server side config and exposing few more utility helpers.
97
+ Handling of fallbacks and marking primary experiments. '
78
98
  email: ankit.gupta8898@gmail.com
79
99
  executables: []
80
100
  extensions: []
@@ -96,6 +116,7 @@ files:
96
116
  - lib/optimizely_server_side/experiment.rb
97
117
  - lib/optimizely_server_side/helpers/support.rb
98
118
  - lib/optimizely_server_side/optimizely_sdk.rb
119
+ - lib/optimizely_server_side/variation.rb
99
120
  - optimizely_server_side.gemspec
100
121
  - spec/optimizely_server_side/cache_spec.rb
101
122
  - spec/optimizely_server_side/configuration_spec.rb
@@ -103,6 +124,7 @@ files:
103
124
  - spec/optimizely_server_side/experiment_spec.rb
104
125
  - spec/optimizely_server_side/helpers/support_spec.rb
105
126
  - spec/optimizely_server_side/optimizely_sdk_spec.rb
127
+ - spec/optimizely_server_side/variation_spec.rb
106
128
  - spec/optimizely_server_side_spec.rb
107
129
  - spec/spec_helper.rb
108
130
  homepage: https://github.com/ankit8898/optimizely_server_side
@@ -137,5 +159,6 @@ test_files:
137
159
  - spec/optimizely_server_side/experiment_spec.rb
138
160
  - spec/optimizely_server_side/helpers/support_spec.rb
139
161
  - spec/optimizely_server_side/optimizely_sdk_spec.rb
162
+ - spec/optimizely_server_side/variation_spec.rb
140
163
  - spec/optimizely_server_side_spec.rb
141
164
  - spec/spec_helper.rb